ct пре 1 недеља
родитељ
комит
a63b9d042d

+ 2 - 0
fs-service/src/main/java/com/fs/his/config/IntegralConfig.java

@@ -28,4 +28,6 @@ public class IntegralConfig implements Serializable {
     private Integer integralSubscriptCourse;//付费课程订阅积分比例
     private Integer downloadAppIntegral; // 首次下载app获取积分
     private Integer integralPlayGame; // 首次下载app获取积分
+    private Integer integralArticle; // 观看文章(图文)一篇
+    private Integer integralArticleTime; // 观看文章(图文)一篇  多少秒算已看完
 }

+ 1 - 0
fs-service/src/main/java/com/fs/his/enums/FsUserIntegralLogTypeEnum.java

@@ -39,6 +39,7 @@ public enum FsUserIntegralLogTypeEnum {
 //    TYPE_27(27, "积分订单取消退回积分"),
     TYPE_28(28, "首次下载APP获取积分"),
     TYPE_29(29,"玩游戏获取积分"),
+    TYPE_30(30,"阅读文章获取积分")
     ;
 
 

+ 4 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserIntegralLogsMapper.java

@@ -37,6 +37,9 @@ public interface FsUserIntegralLogsMapper
      */
     public List<FsUserIntegralLogs> selectFsUserIntegralLogsList(FsUserIntegralLogs fsUserIntegralLogs);
 
+
+    Long selectFsUserIntegralLogsListCOUNT(FsUserIntegralLogs fsUserIntegralLogs);
+
     /**
      * 新增积分记录
      *
@@ -139,4 +142,5 @@ public interface FsUserIntegralLogsMapper
     Long selectH5VideoIntegralCount(@Param("userId") Long userId,@Param("videoId") Long videoId);
 
     List<FsUserIntegralLogs> selectFsUserIntegralLogsByUserIdAndLogType(@Param("userId") Long userId, @Param("logType") Integer logType, @Param("date") LocalDate date);
+
 }

+ 6 - 0
fs-service/src/main/java/com/fs/his/service/IFsArticleService.java

@@ -1,6 +1,8 @@
 package com.fs.his.service;
 
 import java.util.List;
+
+import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsArticle;
 import com.fs.his.param.FsArticleListUParam;
 import com.fs.his.vo.FsArticleListUVO;
@@ -68,4 +70,8 @@ public interface IFsArticleService
     int updateFsArticleViews(Long articleId);
 
     List<FsArticleListVO> selectFsArticleListVO(FsArticle fsArticle);
+
+    R finishView(Long userId, Long articleId);
+
+    R queryFinishViewStatus(Long userId, Long articleId);
 }

+ 58 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsArticleServiceImpl.java

@@ -1,16 +1,25 @@
 package com.fs.his.service.impl;
 
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.DateUtils;
+import com.fs.his.enums.FsUserIntegralLogTypeEnum;
 import com.fs.his.param.FsArticleListUParam;
+import com.fs.his.param.FsUserAddIntegralTemplateParam;
+import com.fs.his.service.IFsUserIntegralLogsService;
 import com.fs.his.vo.FsArticleListUVO;
 import com.fs.his.vo.FsArticleListVO;
-import com.fs.his.vo.FsArticleVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.his.mapper.FsArticleMapper;
 import com.fs.his.domain.FsArticle;
 import com.fs.his.service.IFsArticleService;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * 文章Service业务层处理
@@ -23,6 +32,10 @@ public class FsArticleServiceImpl implements IFsArticleService
 {
     @Autowired
     private FsArticleMapper fsArticleMapper;
+    @Autowired
+    private  RedisCache redisCache;
+    @Autowired
+    private IFsUserIntegralLogsService userIntegralLogsService;
 
     /**
      * 查询文章
@@ -112,4 +125,48 @@ public class FsArticleServiceImpl implements IFsArticleService
     public List<FsArticleListVO> selectFsArticleListVO(FsArticle fsArticle) {
         return fsArticleMapper.selectFsArticleListVO(fsArticle);
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R finishView(Long userId, Long articleId) {
+        //1.添加积分
+        // 先检查今天是否已领取
+        String today = DateUtils.getDate(); // 格式:2026-03-02
+        String finishViewKey = String.format("article:integral:%s:%s:%s", userId, articleId, today);
+        boolean success = redisCache.setIfAbsent(finishViewKey, "1", getSecondsUntilMidnight(), TimeUnit.SECONDS);
+        // 检查今天是否已领取
+        if (!success) {
+            return R.error("今日已领取该文章积分,明天再来吧");
+        }
+        FsUserAddIntegralTemplateParam param = new FsUserAddIntegralTemplateParam();
+        param.setUserId(userId);
+        param.setLogType(FsUserIntegralLogTypeEnum.TYPE_30.getValue());
+        param.setBusinessId(articleId.toString());
+        try {
+            R r = userIntegralLogsService.addIntegralTemplate(param);
+            if (!r.get("code").equals("200")) {
+                redisCache.deleteObject(finishViewKey);
+                return R.error("阅读文章领取积分失败:" + r.get("msg"));
+            }
+        } catch (Exception e) {
+            // 异常时删除缓存,允许用户重试
+            redisCache.deleteObject(finishViewKey);
+            return R.error("阅读文章领取积分失败");
+        }
+        return R.ok();
+    }
+
+    @Override
+    public R queryFinishViewStatus(Long userId, Long articleId) {
+        String today = DateUtils.getDate(); // 格式:2026-03-02
+        String finishViewKey = String.format("article:integral:%s:%s:%s", userId, articleId, today);
+        boolean isView = redisCache.hasKey(finishViewKey);
+        return R.ok().put("isView", isView ? 1 : 0);
+    }
+
+    private long getSecondsUntilMidnight() {
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime midnight = now.toLocalDate().plusDays(1).atStartOfDay();
+        return ChronoUnit.SECONDS.between(now, midnight);
+    }
 }

+ 5 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserIntegralLogsServiceImpl.java

@@ -394,6 +394,11 @@ public class FsUserIntegralLogsServiceImpl implements IFsUserIntegralLogsService
                     integralNum = param.getPoints() * config.getIntegralSubscriptCourse();
                     logsType = FsUserIntegralLogTypeEnum.TYPE_24;
                     break;
+                case 30: //阅读文章获取积分
+                    integralNum = config.getIntegralArticle();
+                    logsType = FsUserIntegralLogTypeEnum.TYPE_30;
+                    param.setRemark(DateUtils.getTime() + FsUserIntegralLogTypeEnum.TYPE_30.getDesc() + " " +integralNum);
+                    break;
                 default:
                     return R.error("积分类型错误,联系管理员");
             }

+ 14 - 0
fs-service/src/main/resources/mapper/his/FsUserIntegralLogsMapper.xml

@@ -33,6 +33,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
     </select>
 
+    <select id="selectFsUserIntegralLogsListCOUNT" resultType="java.lang.Long">
+        select count(*) from fs_user_integral_logs
+        <where>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="logType != null  and logType != ''"> and log_type = #{logType}</if>
+            <if test="integral != null "> and integral = #{integral}</if>
+            <if test="balance != null "> and balance = #{balance}</if>
+            <if test="businessId != null  and businessId != ''"> and business_id = #{businessId}</if>
+            <if test="createTime != null "> and create_time = #{createTime}</if>
+            <if test="businessType != null "> and business_type = #{businessType}</if>
+        </where>
+    </select>
+
     <select id="selectFsUserIntegralLogsById" parameterType="Long" resultMap="FsUserIntegralLogsResult">
         <include refid="selectFsUserIntegralLogsVo"/>
         where id = #{id}
@@ -47,6 +60,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </if>
     </select>
 
+
     <insert id="insertFsUserIntegralLogs" parameterType="FsUserIntegralLogs" useGeneratedKeys="true" keyProperty="id">
         insert into fs_user_integral_logs
         <trim prefix="(" suffix=")" suffixOverrides=",">

+ 31 - 1
fs-user-app/src/main/java/com/fs/app/controller/ArticleController.java

@@ -1,7 +1,9 @@
 package com.fs.app.controller;
 
 
+import com.fs.app.annotation.Login;
 import com.fs.app.utils.JwtUtils;
+import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsArticle;
 import com.fs.his.domain.FsArticleCate;
@@ -34,7 +36,7 @@ import java.util.Map;
 @Api("文章接口")
 @RestController
 @RequestMapping(value="/app/article")
-public class ArticleController {
+public class ArticleController extends AppBaseController{
 	@Autowired
     JwtUtils jwtUtils;
 	@Autowired
@@ -76,4 +78,32 @@ public class ArticleController {
 		return R.ok().put("data",article);
 	}
 
+	@Login
+	@ApiOperation("文章阅读完成")
+	@GetMapping("/finishView")
+	@RepeatSubmit
+	public R finishView(@RequestParam("articleId")Long articleId){
+		String userId;
+        try {
+            userId = getUserId();
+        } catch (Exception e) {
+            return R.error("获取用户信息错误,请重新登录!");
+        }
+		return articleService.finishView(Long.valueOf(userId),articleId);
+	}
+
+	@Login
+	@ApiOperation("查询今日文章阅读是否完成")
+	@GetMapping("/queryFinishViewStatus")
+	public R queryFinishViewStatus(@RequestParam("articleId")Long articleId){
+		String userId;
+		try {
+			userId = getUserId();
+		} catch (Exception e) {
+			return R.error("获取用户信息错误,请重新登录!");
+		}
+
+		return articleService.queryFinishViewStatus(Long.valueOf(userId),articleId);
+	}
+
 }