Quellcode durchsuchen

feat: 小说服务接口完善

hidewnd vor 1 Monat
Ursprung
Commit
ba4e0a830c
27 geänderte Dateien mit 883 neuen und 62 gelöschten Zeilen
  1. 2 0
      yt-common/src/main/java/com/ytpm/app/model/YtNovel.java
  2. 32 0
      yt-common/src/main/java/com/ytpm/app/model/YtNovelAdRecord.java
  3. 12 0
      yt-common/src/main/java/com/ytpm/app/model/YtNovelCategory.java
  4. 31 0
      yt-common/src/main/java/com/ytpm/app/model/YtNovelUser.java
  5. 2 1
      yt-common/src/main/java/com/ytpm/app/model/YtUser.java
  6. 1 2
      yt-common/src/main/java/com/ytpm/general/ResultTable.java
  7. 17 0
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/controller/AdController.java
  8. 3 3
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/controller/NovelController.java
  9. 392 0
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/controller/UserController.java
  10. 232 0
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/controller/WxController.java
  11. 20 0
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/dao/NovelAdRecordMapper.java
  12. 8 0
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/dao/NovelMapper.java
  13. 19 0
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/model/dto/UserStaticParam.java
  14. 26 0
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/model/param/NovelAdRecordParam.java
  15. 13 17
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/service/impl/AdServiceImpl.java
  16. 1 2
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/service/impl/NovelServiceImpl.java
  17. 1 2
      yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/service/impl/VisitorLoginServiceImpl.java
  18. 15 0
      yt-novel/yt-novel-service/src/main/resources/mapper/NovelAdRecordMapper.xml
  19. 6 0
      yt-novel/yt-novel-service/src/main/resources/mapper/NovelMapper.xml
  20. 2 1
      yt-question/yt-question-feign/src/main/java/com/ytpm/question/base/BaseFeign.java
  21. 5 1
      yt-question/yt-question-service/src/main/java/com/ytpm/question/controller/UserController.java
  22. 1 1
      yt-question/yt-question-service/src/main/java/com/ytpm/question/service/impl/VisitorLoginServiceImpl.java
  23. 13 7
      yt-risk/risk-feign/src/main/java/com/ytpm/feign/RiskFeign.java
  24. 4 3
      yt-risk/risk-feign/src/main/java/com/ytpm/feign/fallback/RiskFeignFallBack.java
  25. 5 4
      yt-risk/risk-manage/src/main/java/com/ytpm/controller/PublicApiController.java
  26. 5 4
      yt-risk/risk-manage/src/main/java/com/ytpm/service/RiskService.java
  27. 15 14
      yt-risk/risk-manage/src/main/java/com/ytpm/service/impl/RiskServiceImpl.java

+ 2 - 0
yt-common/src/main/java/com/ytpm/app/model/YtNovel.java

@@ -16,6 +16,8 @@ import java.util.Date;
 public class YtNovel {
     @ApiModelProperty("小说ID")
     private String novelId;
+    @ApiModelProperty("小说分类ID")
+    private String categoryId;
     @ApiModelProperty("小说名称")
     private String novelName;
     @ApiModelProperty("小说作者")

+ 32 - 0
yt-common/src/main/java/com/ytpm/app/model/YtNovelAdRecord.java

@@ -0,0 +1,32 @@
+package com.ytpm.app.model;
+
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author lih
+ * @date 2025-10-09 16:45
+ */
+@Data
+@ApiModel("用户广告观看记录")
+public class YtNovelAdRecord {
+
+    @ApiModelProperty("记录ID")
+    private String recordId;
+
+    @ApiModelProperty("用户ID")
+    private String userId;
+
+    @ApiModelProperty("该功能高记录ID")
+    private String adRecordId;
+
+    @ApiModelProperty("用时|秒")
+    private Long duration;
+
+    @ApiModelProperty("记录时间")
+    private Date recordTime;
+}

+ 12 - 0
yt-common/src/main/java/com/ytpm/app/model/YtNovelCategory.java

@@ -5,6 +5,8 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.util.Date;
+
 /**
  * @author lih
  * @date 2025-09-30 11:22
@@ -25,5 +27,15 @@ public class YtNovelCategory {
     @ApiModelProperty("排序号")
     private Integer sort;
 
+    @ApiModelProperty("删除标志|0未删除|1已删除")
+    private Integer deleted;
+
+    private String createBy;
+    private Date createTime;
+    private String updateBy;
+    private Date updateTime;
+
+    @ApiModelProperty("乐观锁ID")
+    private Integer revision;
 
 }

+ 31 - 0
yt-common/src/main/java/com/ytpm/app/model/YtNovelUser.java

@@ -1,10 +1,14 @@
 package com.ytpm.app.model;
 
 
+import com.ytpm.custom.CustomField;
 import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import java.math.BigDecimal;
+import java.util.List;
 /**
  * @author lih
  * @date 2025-09-30 09:38
@@ -14,5 +18,32 @@ import lombok.EqualsAndHashCode;
 @EqualsAndHashCode(callSuper = true)
 public class YtNovelUser extends YtUser {
 
+    @ApiModelProperty("总观看视频数")
+    private Integer totalVideo;
 
+    @ApiModelProperty("总收益")
+    private BigDecimal totalIncome;
+
+    @ApiModelProperty("红包余额")
+    private BigDecimal redPacketBalance;
+
+    @ApiModelProperty("红包总额")
+    private BigDecimal redPacketAmount;
+
+    @CustomField(node = 1)
+    @ApiModelProperty("积分余额")
+    private BigDecimal pointsBalance;
+
+    @ApiModelProperty("积分总额")
+    private BigDecimal pointsTotal;
+
+    @CustomField(node = 1)
+    @ApiModelProperty("提现总额")
+    private BigDecimal withdrawTotal;
+
+    @ApiModelProperty("体力")
+    private Integer power;
+
+    @ApiModelProperty("广告观看记录")
+    private List<YtNovelAdRecord> novelAdRecordList;
 }

+ 2 - 1
yt-common/src/main/java/com/ytpm/app/model/YtUser.java

@@ -154,5 +154,6 @@ public class YtUser extends PageMeta {
     @ApiModelProperty(value = "服务名")
     private String serviceName;
 
-
+    @ApiModelProperty(value = "体力不足提示语模板")
+    private String powerLimitTip;
 }

+ 1 - 2
yt-common/src/main/java/com/ytpm/general/ResultTable.java

@@ -57,9 +57,8 @@ public class ResultTable<T> implements Serializable {
      * 查询成功,返回实体
      *
      * @param pageInfo 分页插件返回实体
-     * @return
      */
-    public static <T> ResultTable resultTableOk(PageInfo<T> pageInfo) {
+    public static <T> ResultTable<T> resultTableOk(PageInfo<T> pageInfo) {
         //当前页
         int currentPage = pageInfo.getPageNum();
         //每页的数量

+ 17 - 0
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/controller/AdController.java

@@ -2,11 +2,14 @@ package com.ytpm.novel.controller;
 
 import com.ytpm.agent.view.AgentAdGroupStaticsVO;
 import com.ytpm.agent.view.AgentTopCountView;
+import com.ytpm.app.model.YtNovelAdRecord;
 import com.ytpm.app.param.DyzAdRecordParam;
 import com.ytpm.general.Result;
 import com.ytpm.middle.view.DashboardRankingListVO;
 import com.ytpm.middle.view.DashboardRevenueVO;
 import com.ytpm.middle.view.DashboardRiskVO;
+import com.ytpm.novel.dao.NovelAdRecordMapper;
+import com.ytpm.novel.model.param.NovelAdRecordParam;
 import com.ytpm.novel.service.AdService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -33,6 +36,9 @@ public class AdController {
     @Resource
     private AdService adService;
 
+    @Resource
+    private NovelAdRecordMapper novelAdRecordMapper;
+
     /**
      * 保存广告记录
      */
@@ -92,4 +98,15 @@ public class AdController {
     public List<AgentAdGroupStaticsVO> getAgentProfit(@RequestParam(name = "appIds") String appIds) {
         return adService.getAgentProfit(appIds);
     }
+
+    @ApiOperation("保存用户广告记录")
+    @PostMapping("/novel/record")
+    public Result<String> novelAdRecord(@RequestBody NovelAdRecordParam param){
+        YtNovelAdRecord record = new YtNovelAdRecord();
+        novelAdRecordMapper.insertNovelAdRecord(record);
+        return Result.resultOk("保存成功");
+    }
+
+
+
 }

+ 3 - 3
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/controller/NovelController.java

@@ -38,7 +38,7 @@ public class NovelController {
 
     @ApiOperation("获取小说列表")
     @PostMapping("/page")
-    public ResultTable<List<YtNovelDto>> queryNovelList(@RequestBody NovelPageParam param) {
+    public ResultTable<YtNovelDto> queryNovelList(@RequestBody NovelPageParam param) {
         return ResultTable.resultTableOk(novelService.selectNovelPage(param));
     }
 
@@ -55,13 +55,13 @@ public class NovelController {
         return Result.resultObjOk(novelService.selectNovelById(novelId,userId));
     }
 
-    @ApiOperation("获取书架小说列表")
+    @ApiOperation("获取用户书架列表")
     @GetMapping("/shelf/list")
     public Result<List<YtNovel>> queryNovelShelfList(@RequestParam("userId") String userId) {
         return Result.resultObjOk(novelService.selectNovelShelf(userId));
     }
 
-    @ApiOperation("保存书架")
+    @ApiOperation("更新用户书架列表")
     @PostMapping("/shelf/save")
     public Result<String> saveShelf(@RequestBody NovelShelfParam param) {
         return Result.resultObjOk(novelService.saveNovelShelf(param));

+ 392 - 0
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/controller/UserController.java

@@ -0,0 +1,392 @@
+package com.ytpm.novel.controller;
+
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.ytpm.advertise.enums.AdSourceTypeEnum;
+import com.ytpm.agent.enums.UserStatusEnum;
+import com.ytpm.agent.param.AdRecordListParam;
+import com.ytpm.agent.param.AuditCheckParam;
+import com.ytpm.agent.param.AuditUserParam;
+import com.ytpm.agent.view.AgentAuditCheckVO;
+import com.ytpm.app.model.YtDyzAdRecord;
+import com.ytpm.app.model.YtDyzLoginRecord;
+import com.ytpm.app.model.YtNovelUser;
+import com.ytpm.app.model.YtUser;
+import com.ytpm.app.param.AppQueryUserTodayTimeParam;
+import com.ytpm.app.param.AppUserParam;
+import com.ytpm.app.param.AppUserQueryParam;
+import com.ytpm.app.param.AppUserTodayBannedParam;
+import com.ytpm.app.param.YtAppUserListParam;
+import com.ytpm.app.view.HourCountView;
+import com.ytpm.app.view.YtAppUserListView;
+import com.ytpm.general.RepMessage;
+import com.ytpm.general.Result;
+import com.ytpm.general.ResultTable;
+import com.ytpm.novel.dao.AdRecordMapper;
+import com.ytpm.novel.dao.AppUserMapper;
+import com.ytpm.novel.dao.LoginRecordMapper;
+import com.ytpm.novel.dao.NovelAdRecordMapper;
+import com.ytpm.novel.model.dto.UserStaticParam;
+import com.ytpm.novel.redis.RedisService;
+import com.ytpm.risk.enums.BannedTypeEnum;
+import com.ytpm.risk.view.RiskConfigView;
+import com.ytpm.risk.view.RiskTemplateView;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @author lih
+ * @date 2025-10-09 14:24
+ */
+@Slf4j
+@RestController
+@RequestMapping("/user")
+public class UserController {
+    @Resource
+    private AppUserMapper appUserMapper;
+    @Resource
+    private LoginRecordMapper loginRecordMapper;
+    @Resource
+    private AdRecordMapper adRecordMapper;
+    @Resource
+    private NovelAdRecordMapper novelAdRecordMapper;
+
+    @Resource
+    private RedisService redisService;
+
+
+    @ApiOperation("根据应用ID查询当月注册用户")
+    @GetMapping("/getMonthRegistryUser")
+    public List<YtNovelUser> getMonthRegistryUser(@RequestParam("appIds") String appIds, @RequestParam("type") Integer type) {
+        return appUserMapper.getMonthRegistryUser(appIds, type);
+    }
+
+    /**
+     * 查询app 所有玩家
+     * 汇聚分库应用
+     */
+    @PostMapping("/queryAll")
+    public ResultTable<YtAppUserListView> queryAll(@RequestBody YtAppUserListParam param) {
+        //查询主应用
+        PageHelper.startPage(param.getPage(), param.getLimit());
+        List<YtAppUserListView> result = appUserMapper.queryAll(param);
+        String collect = result.stream().map(YtAppUserListView::getUserId).collect(Collectors.joining(","));
+        List<YtDyzAdRecord> adRecords = adRecordMapper.getByUserIds(collect);
+        List<YtDyzLoginRecord> dyzLogins = loginRecordMapper.getLoginRecordByIds(collect);
+        Map<String, List<YtDyzAdRecord>> userAdMap = adRecords.stream().collect(
+                Collectors.groupingBy(YtDyzAdRecord::getUserId));
+        Map<String, List<YtDyzLoginRecord>> loginMap = dyzLogins.stream().collect(
+                Collectors.groupingBy(YtDyzLoginRecord::getUserId));
+        setUserExtInfo(result, userAdMap, loginMap);
+        return ResultTable.resultTableOk(new PageInfo<>(result));
+    }
+
+    /**
+     * 设置视频记录和登录信息
+     */
+    private void setUserExtInfo(List<YtAppUserListView> result, Map<String, List<YtDyzAdRecord>> userAdMap,
+                                Map<String, List<YtDyzLoginRecord>> loginMap) {
+        for (YtAppUserListView user : result) {
+            if (loginMap.containsKey(user.getUserId())) {
+                user.setLoginRecordList(loginMap.get(user.getUserId()));
+            }
+            //获取今日收益 | 今日视频播放数
+            if (userAdMap.containsKey(user.getUserId())) {
+                List<YtDyzAdRecord> ytDyzAdRecords = userAdMap.get(user.getUserId());
+                List<YtDyzAdRecord> collect = ytDyzAdRecords.stream().filter(
+                        s -> DateUtil.isSameDay(DateUtil.date(), DateUtil.parseDate(s.getFinishTime()))).collect(Collectors.toList());
+                BigDecimal todayIncome = collect.stream().map(YtDyzAdRecord::getRevenue).reduce(BigDecimal.ZERO, BigDecimal::add);
+                user.setTodayVideo((int) collect.stream().filter(
+                        s -> s.getAdSourceType() == AdSourceTypeEnum.rewarded_video.getAdSourceType()).count());
+                user.setTodayIncome(todayIncome);
+                // 统计4天-今日收益=前三日收益
+                if (user.getNearlyIncome() != null && user.getNearlyIncome().compareTo(todayIncome) >= 0) {
+                    user.setNearlyIncome(user.getNearlyIncome().subtract(todayIncome));
+                }
+            } else {
+                user.setTodayIncome(BigDecimal.ZERO);
+                user.setTodayVideo(0);
+            }
+        }
+    }
+
+    @ApiOperation("根据时间统计收益")
+    @PostMapping("/getRevenueByTime")
+    public BigDecimal getRevenueByTime(@RequestBody YtAppUserListParam param) {
+        BigDecimal result = new BigDecimal(0);
+        BigDecimal dyzRevenue = adRecordMapper.getRevenueByTime(param);
+        if (Objects.nonNull(dyzRevenue)) {
+            result = result.add(dyzRevenue);
+        }
+        return result;
+    }
+
+    /**
+     * 主键查询用户信息
+     */
+    @GetMapping("/getUserInfo")
+    public Result<YtNovelUser> getUserInfo(@RequestParam("userId") String userId) {
+        YtNovelUser user = appUserMapper.selectPrimaryKey(userId);
+        user.setLoginRecordList(loginRecordMapper.getLoginRecords(userId));
+        user.setNovelAdRecordList(novelAdRecordMapper.selectToDayNovelRecode(userId));
+        return Result.resultObjOk(user);
+    }
+
+
+    /**
+     * 查询用户信息
+     */
+    @PostMapping("/getUserList")
+    public ResultTable<YtNovelUser> getUserList(@RequestBody AppUserParam param) {
+        List<YtNovelUser> userList = appUserMapper.getUserList(param);
+        if (CollUtil.isEmpty(userList)) {
+            userList = new ArrayList<>();
+        }
+        return ResultTable.resultTableOk(new PageInfo<>(userList));
+    }
+
+    @PostMapping("/getUserAll")
+    public ResultTable<YtNovelUser> getUserAll(@RequestBody AppUserParam param) {
+        List<YtNovelUser> userList = appUserMapper.getUserList(param);
+        return ResultTable.resultTableOk(new PageInfo<>(userList));
+    }
+
+    /**
+     * 修改用户信息
+     */
+    @PostMapping("/updateUserInfo")
+    public Result<?> updateUserInfo(@RequestBody YtUser ytUser) {
+        YtNovelUser novelUser = new YtNovelUser();
+        BeanUtil.copyProperties(ytUser, novelUser);
+        appUserMapper.updateUser(novelUser);
+        return Result.resultOk(RepMessage.MODIFY_SUCCESS);
+    }
+
+    /**
+     * 查询用户的广告记录
+     */
+    @GetMapping("/adRecords")
+    public ResultTable<YtDyzAdRecord> adRecords(@RequestParam(name = "userId", required = true) String userId,
+                                                @RequestParam(name = "adsourceType", required = false) Integer adsourceType) {
+        return ResultTable.resultTableOk(new PageInfo<>(adRecordMapper.getByUserId(userId, adsourceType)));
+    }
+
+    @PostMapping("/adRecords/page")
+    public ResultTable<YtDyzAdRecord> adRecordsPage(@RequestBody AdRecordListParam param) {
+        PageHelper.startPage(param.getPage(), param.getLimit());
+        List<YtDyzAdRecord> adrecords = adRecordMapper.getByUserByParam(param);
+        return ResultTable.resultTableOk(new PageInfo<>(adrecords));
+    }
+
+    /**
+     * 查询广告记录统计数
+     */
+    @GetMapping("/adRecords/count/month")
+    public Result<Integer> queryRecordMonthCount(@RequestParam(name = "userId") String userId,
+                                                 @RequestParam(name = "adSourceType", required = false) Integer adSourceType,
+                                                 @RequestParam(name = "startTime", required = false) String startTime) {
+        Date time;
+        // 统计起始时间为空,则默认查询当月信息
+        if (StrUtil.isEmpty(startTime)) {
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime(new Date());
+            calendar.set(Calendar.DAY_OF_MONTH, 1);
+            calendar.set(Calendar.HOUR_OF_DAY, 0);
+            calendar.set(Calendar.MINUTE, 0);
+            calendar.set(Calendar.SECOND, 0);
+            time = calendar.getTime();
+        } else {
+            time = DateUtil.parse(startTime, "yyyy-MM-dd HH:mm:ss");
+        }
+        return Result.resultObjOk(adRecordMapper.getRecordMonthCount(userId, adSourceType, time));
+    }
+
+    @PostMapping("/queryUserByTime")
+    public List<YtNovelUser> queryUserByTime(@RequestBody AppUserQueryParam appUserQueryParam) {
+        UserStaticParam param = new UserStaticParam(appUserQueryParam);
+        return appUserMapper.queryAllByTime(param);
+    }
+
+    @PostMapping("/queryUserByTodayTime")
+    public int[] queryUserByTodayTime(@RequestBody AppQueryUserTodayTimeParam appQueryUserTodayTimeParam) {
+        // 获取当前日期
+        LocalDate localDate = LocalDate.now();
+
+        // 构建当天起始时间段
+        LocalDateTime startOfDay = localDate.atStartOfDay();
+        LocalDateTime endOfDay = startOfDay.plusDays(1).minusSeconds(1);
+
+        Date startTime = Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
+        Date endTime = Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
+        UserStaticParam param = new UserStaticParam();
+        param.setStartTime(startTime);
+        param.setEndTime(endTime);
+        param.setAppIdList(appQueryUserTodayTimeParam.getAppIdList());
+        // 查询用户注册数据
+        List<HourCountView> hourCountViews = appUserMapper.countUsersByHour(param);
+        // 初始化每小时用户数量数组
+        int[] hourlyCounts = new int[24];
+        for (HourCountView hc : hourCountViews) {
+            if (hc.getHour() >= 0 && hc.getHour() < 24) {
+                hourlyCounts[hc.getHour()] = hc.getCount();
+            }
+        }
+        return hourlyCounts;
+    }
+
+    @PostMapping("/queryLoginRecords")
+    public List<String> queryLoginRecords(@RequestBody AppUserQueryParam appUserQueryParam) {
+        return loginRecordMapper.queryLoginCount(appUserQueryParam);
+    }
+
+    @GetMapping("/queryByOpenid")
+    public List<YtNovelUser> queryByOpenid(@RequestParam("openid") String openid) {
+        return appUserMapper.queryByOpenid(openid);
+    }
+
+    @PostMapping("/queryTodayBanned")
+    public List<YtNovelUser> queryTodayBanned(@RequestBody AppUserTodayBannedParam appUserTodayBannedParam) {
+        UserStaticParam param = new UserStaticParam(appUserTodayBannedParam);
+        return appUserMapper.queryTodayBanned(param);
+    }
+
+    @PostMapping("/unLockUser")
+    public void unLockUser(@RequestParam("userIds") String userIds) {
+        List<YtNovelUser> users = appUserMapper.queryByUserIds(userIds);
+        if (CollUtil.isNotEmpty(users)) {
+            appUserMapper.unlockUser(userIds);
+        }
+    }
+
+    @GetMapping("/lockUser")
+    public YtNovelUser lockUser(@RequestParam("userId") String userId, @RequestParam("userStatus") Integer userStatus) {
+        YtNovelUser dyzUser = appUserMapper.selectPrimaryKey(userId);
+        YtNovelUser newUser = new YtNovelUser();
+        newUser.setUserId(userId);
+        newUser.setUserStatus(userStatus);
+        newUser.setRiskReason(BannedTypeEnum.CHANNEL.getDesc() + "禁止登录");
+        if (Objects.nonNull(dyzUser)) {
+            appUserMapper.updateUser(newUser);
+            return dyzUser;
+        }
+        return null;
+    }
+
+    /**
+     * 批量审核用户是否满足风控规则
+     * 不满足风控规则的审核通过后直接封禁指定天数
+     */
+    @PostMapping("/batchAudit")
+    public void batchAudit(@RequestBody AuditCheckParam checkParam) {
+        AuditUserParam auditParam = checkParam.getAuditParam();
+        RiskTemplateView ecpmLimit = checkParam.getEcpmLimit();
+        RiskTemplateView revenueLimit = checkParam.getRevenueLimit();
+        //查询用户,指定应用激励视频的广告记录
+        List<AgentAuditCheckVO> auditList = new ArrayList<>();
+        List<AgentAuditCheckVO> auditCheckList = appUserMapper.queryTodayUserAd(auditParam);
+        if (CollUtil.isNotEmpty(auditCheckList)) {
+            auditList.addAll(auditCheckList);
+        }
+        Map<String, List<YtDyzAdRecord>> adRecordMap = auditList.stream().collect(
+                Collectors.toMap(AgentAuditCheckVO::getUserId, AgentAuditCheckVO::getAdRecordList));
+        checkRisk742(ecpmLimit, adRecordMap, auditParam);
+        checkRisk746(revenueLimit, adRecordMap, auditParam);
+    }
+
+    /**
+     * 校验默认风控规则742
+     */
+    private void checkRisk742(RiskTemplateView ecpmLimit, Map<String, List<YtDyzAdRecord>> adRecordMap, AuditUserParam auditParam) {
+        if (ecpmLimit.getEnabled() != 1) return;
+        Map<String, String> limitMap = ecpmLimit.getConfigList().stream().collect(
+                Collectors.toMap(RiskConfigView::getFieldName, RiskConfigView::getConfigVal));
+        int adCount = 0;
+        for (Map.Entry<String, List<YtDyzAdRecord>> entry : adRecordMap.entrySet()) {
+            adCount = CollUtil.isEmpty(entry.getValue()) ? adCount : entry.getValue().size();
+            ++adCount;
+            //判断当日观看视频数已经达到风控条件预设的视频数
+            int firstAdCount = Integer.parseInt(limitMap.get("firstAdCount"));
+            if (adCount >= firstAdCount) {
+                //过滤出ecpm值小于预设值的视频数
+                int ecpm = Integer.parseInt(limitMap.get("ecpm"));
+                long count = entry.getValue().stream().filter(
+                        s -> Objects.nonNull(s.getEcpm()) && (s.getEcpm().compareTo(BigDecimal.valueOf(ecpm))) < 0).count();
+                int exact = Math.toIntExact(count);
+                //判断小于预设值的视频数超出预设次数
+                int haveCount = Integer.parseInt(limitMap.get("haveCount"));
+                if (exact > haveCount) {//把风控不满足的用户记录redis 进行封禁
+                    checkLock(entry, auditParam);
+                }
+            }
+        }
+
+    }
+
+    /**
+     * 用户锁定操作
+     */
+    private void checkLock(Map.Entry<String, List<YtDyzAdRecord>> entry, AuditUserParam auditParam) {
+        log.error("执行对低价值用户{}的定时风控操作", entry.getKey());
+        if (auditParam.getEffectTime() == 0) { //立即锁定
+            lockUser(entry.getKey(), UserStatusEnum.RISK.getCode());
+            redisService.setTimeOutHoursStr("unlock_" + entry.getKey(), auditParam.getAppId(), auditParam.getBannedLimit() * 24L);
+        } else {//延迟锁定
+            redisService.setTimeOutHoursStr("lock_" + entry.getKey(), auditParam.getAppId(), auditParam.getEffectTime());
+            redisService.setTimeOutHoursStr("unlock_" + entry.getKey(), auditParam.getAppId(),
+                    auditParam.getBannedLimit() * 24L + auditParam.getEffectTime());
+        }
+    }
+
+    /**
+     * 校验默认风控规则746
+     */
+    private void checkRisk746(RiskTemplateView revenueLimit, Map<String, List<YtDyzAdRecord>> adRecordMap,
+                              AuditUserParam auditParam) {
+        if (revenueLimit.getEnabled() != 1) return;
+        Map<String, String> revenueMap = revenueLimit.getConfigList().stream().collect(
+                Collectors.toMap(RiskConfigView::getFieldName, RiskConfigView::getConfigVal));
+        for (Map.Entry<String, List<YtDyzAdRecord>> entry : adRecordMap.entrySet()) {
+            List<YtDyzAdRecord> revenues = entry.getValue().stream().filter(
+                            s -> Objects.nonNull(s.getRevenue()) && (s.getRevenue().compareTo(BigDecimal.ZERO)) > 0)
+                    .collect(Collectors.toList());
+            int incomeCount = 0;
+            incomeCount = CollUtil.isEmpty(revenues) ? incomeCount : entry.getValue().size();
+            //判断当日获得收益的广告达到预设数值,触发风控规则
+            int rewardCount = Integer.parseInt(revenueMap.get("rewardCount"));
+            if (incomeCount >= rewardCount) {
+                BigDecimal income = new BigDecimal(revenueMap.get("income"));
+                //获取最先的两条
+                BigDecimal reduce = revenues.stream().map(YtDyzAdRecord::getRevenue).reduce(BigDecimal.ZERO, BigDecimal::add);
+                if (reduce.compareTo(income) < 0) {
+                    checkLock(entry, auditParam);
+                }
+            }
+        }
+
+    }
+
+}

+ 232 - 0
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/controller/WxController.java

@@ -0,0 +1,232 @@
+package com.ytpm.novel.controller;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.ytpm.app.enums.AppTypeEnums;
+import com.ytpm.app.enums.LoginType;
+import com.ytpm.app.model.YtAppDefaultConfig;
+import com.ytpm.app.model.YtDyzPowerRecord;
+import com.ytpm.app.model.YtDyzUser;
+import com.ytpm.app.model.YtNovelUser;
+import com.ytpm.app.param.AppConfigUpdateParam;
+import com.ytpm.app.param.WxLoginParam;
+import com.ytpm.app.view.WxDefaultConfig;
+import com.ytpm.app.view.WxLoginResult;
+import com.ytpm.app.view.WxUserInfo;
+import com.ytpm.feign.RiskFeign;
+import com.ytpm.general.RepMessage;
+import com.ytpm.general.Result;
+import com.ytpm.general.StatusCode;
+import com.ytpm.novel.dao.AppUserMapper;
+import com.ytpm.novel.service.AppUserService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+
+@Slf4j
+@RestController
+@RequestMapping("/wx")
+@Api(tags = "微信开放能力模块")
+public class WxController {
+    private final static String GRANT_TYPE = "authorization_code";
+
+    @Resource
+    private AppUserMapper appUserMapper;
+    @Resource
+    private RiskFeign riskFeign;
+    @Resource
+    private AppUserService appUserService;
+
+    @PostMapping("/login")
+    @ApiOperation("微信登录")
+    @Transactional
+    public Result<YtNovelUser> wxLogin(@RequestBody WxLoginParam param, HttpServletRequest request) {
+        if (StrUtil.isEmpty(param.getDeviceId())) {
+            log.warn("[wx login validate]deviceId is empty!");
+            // 尝试从phoneJson中获取
+            if (StrUtil.isNotEmpty(param.getPhoneJson())) {
+                JSONObject phoneJson = JSONObject.parseObject(param.getPhoneJson());
+                if (phoneJson.get("device_basic") != null) {
+                    String deviveId = phoneJson.getJSONObject("device_basic").getString("device_id");
+                    param.setDeviceId(deviveId);
+                }
+            }
+        }
+        //根据应用获取配置调用微信接口登录
+        WxDefaultConfig defaultConfig = appUserMapper.getDefaultConfig(param.getAppType());
+        if (Objects.isNull(defaultConfig)) {
+            return new Result<>(StatusCode.ACCESS_ERR, "微信登录失败,未找到相应配置!");
+        }
+        param.setAppId(defaultConfig.getPlatformAppId());
+        WxLoginResult loginResult = getWechatLoginInfo(param.getWxCode(), param.getAppType(), defaultConfig.getAppId(), defaultConfig.getSecret());
+        if (Objects.isNull(loginResult) || StrUtil.isBlank(loginResult.getOpenid())) {
+            return new Result<>(StatusCode.ACCESS_ERR, "微信登录失败,请刷新授权码!");
+        }
+        WxUserInfo wxUserInfo = getWechatUserInfo(loginResult.getAccess_token(), loginResult.getOpenid());
+        if (Objects.isNull(wxUserInfo)) {
+            return new Result<>(StatusCode.ACCESS_ERR, "微信用户登录失败");
+        }
+        param.setLoginIp(getClientIp(request));
+        YtNovelUser old = appUserService.crudForNewTrans(param, wxUserInfo, loginResult);
+        old.setLoginType(LoginType.WX);
+        //调用风控服务校验默认风控配置
+        old.setRiskCode("313");
+        Result<?> result = riskFeign.checkRisk(old);
+        if (result.getCode() != 200) {
+            return new Result<>(StatusCode.ACCESS_ERR, result.getMessage());
+        }
+        return Result.resultOk(RepMessage.LOGIN_SUCCESS, old);
+    }
+
+    private String getClientIp(HttpServletRequest request) {
+        String xfHeader = request.getHeader("X-Forwarded-For");
+        if (xfHeader == null) {
+            return request.getRemoteAddr();
+        }
+        return xfHeader.split(",")[0]; // 可能会有多个IP,这里取第一个逗号前的IP
+    }
+
+    /**
+     * 获取微信用户信息
+     */
+    private WxUserInfo getWechatUserInfo(String accessToken, String openid) {
+        // 根据token和openid 获取用户信息
+        String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
+        String curUser = HttpUtil.get(userInfoUrl);
+        WxUserInfo wxUserInfo = JSON.parseObject(curUser, WxUserInfo.class);
+        log.error("获取的用户信息:{}", wxUserInfo);
+        return wxUserInfo;
+    }
+
+    /**
+     * 微信登录
+     */
+    private WxLoginResult getWechatLoginInfo(String wxCode, int appType, String appId, String secret) {
+
+        String wxLoginUrl;
+        if (AppTypeEnums.QNJZ.getCode() == appType) {
+            wxLoginUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
+                    + appId + "&secret=" + secret + "&code=" + wxCode + "&grant_type=" + GRANT_TYPE;
+        } else {
+            wxLoginUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId
+                    + "&secret=" + secret + "&code=" + wxCode + "&grant_type=" + GRANT_TYPE;
+        }
+        //拿到授权码 请求微信登录返回access_token
+        String result = HttpUtil.get(wxLoginUrl);
+        WxLoginResult loginResult = JSON.parseObject(result, WxLoginResult.class);
+        log.error("授权码获取的登录结果:{}", loginResult);
+        return loginResult;
+    }
+
+    @ApiOperation("获取微信默认配置项")
+    @GetMapping("/defaultConfig")
+    public Result<WxDefaultConfig> getWxDefaultConfig(int appType) {
+        WxDefaultConfig config = appUserMapper.getDefaultConfig(appType);
+        if (Objects.isNull(config)) {
+            return Result.resultErr("应用类型有误!");
+        }
+        return Result.resultObjOk(config);
+    }
+
+    @ApiOperation("体力增加")
+    @GetMapping("/addPower")
+    @Transactional(rollbackFor = Exception.class)
+    public Result<YtDyzUser> addPower(@RequestParam("userId") String userId) {
+        appUserMapper.addOnePower(userId);
+        YtDyzPowerRecord record = new YtDyzPowerRecord();
+        record.setUserId(userId);
+        record.setRecordId(IdUtil.fastSimpleUUID());
+        record.setAddTime(new Date());
+        record.setType(1);
+        record.setRemark("增加体力");
+        appUserMapper.addPowerRecord(record);
+        return Result.resultOk(RepMessage.ADD_SUCCESS);
+    }
+
+    @ApiOperation("保存应用默认配置")
+    @PostMapping("/saveAppConfig")
+    public Result<String> saveAppConfig(@RequestBody YtAppDefaultConfig defaultConfig) {
+        appUserMapper.saveAppConfig(defaultConfig);
+        return Result.resultOk(RepMessage.SAVE_SUCCESS);
+    }
+
+    @ApiOperation("修改应用默认配置")
+    @PostMapping("/updateAppConfig")
+    public Result<String> updateAppConfig(@RequestBody YtAppDefaultConfig defaultConfig) {
+        appUserMapper.updateAppConfig(defaultConfig);
+        return Result.resultOk(RepMessage.SAVE_SUCCESS);
+    }
+
+    @ApiOperation("同步子应用默认配置")
+    @PostMapping("/updateAppsConfig")
+    public void updateAppsConfig(@RequestBody AppConfigUpdateParam param){
+        if (CollUtil.isNotEmpty(param.getApps()) && param.getDefaultConfig() != null) {
+            String appIds = String.join(",", param.getApps());
+            List<WxDefaultConfig> configs = appUserMapper.getConfigByIds(appIds);
+            YtAppDefaultConfig updateInfo = param.getDefaultConfig();
+            for (WxDefaultConfig config : configs) {
+                YtAppDefaultConfig appConfig = new YtAppDefaultConfig();
+                BeanUtils.copyProperties(config, appConfig);
+                if(StrUtil.isNotEmpty(updateInfo.getTakuAppId())) {
+                    appConfig.setTakuAppId(updateInfo.getTakuAppId());
+                }
+                if(StrUtil.isNotEmpty(updateInfo.getTakuKey())) {
+                    appConfig.setTakuKey(updateInfo.getTakuKey());
+                }
+                if(StrUtil.isNotEmpty(updateInfo.getTakuBannerPid())) {
+                    appConfig.setTakuBannerPid(updateInfo.getTakuBannerPid());
+                }
+                if(StrUtil.isNotEmpty(updateInfo.getTakuNativePid())) {
+                    appConfig.setTakuNativePid(updateInfo.getTakuNativePid());
+                }
+                if(StrUtil.isNotEmpty(updateInfo.getTakuRewardPid())) {
+                    appConfig.setTakuRewardPid(updateInfo.getTakuRewardPid());
+                }
+                if(StrUtil.isNotEmpty(updateInfo.getTakuInterstitialPid())) {
+                    appConfig.setTakuInterstitialPid(updateInfo.getTakuInterstitialPid());
+                }
+                appUserMapper.updateAppConfig(appConfig);
+            }
+        }
+    }
+
+    @ApiOperation("根据APP_ID获取配置")
+    @GetMapping("/getConfigs")
+    public List<WxDefaultConfig> getConfigs(@RequestParam(name = "appIds") String appIds) {
+        List<WxDefaultConfig> configs = new ArrayList<>();
+        List<WxDefaultConfig> dyzConfigs = appUserMapper.getConfigByIds(appIds);
+        if (CollUtil.isNotEmpty(dyzConfigs)) {
+            configs.addAll(dyzConfigs);
+        }
+        return configs;
+    }
+
+    @ApiOperation("删除默认配置")
+    @GetMapping("/delDefaultConfig")
+    public void delDefaultConfig(@RequestParam(name = "appId") String appId) {
+        List<WxDefaultConfig> dyzConfig = appUserMapper.getConfigByIds(appId);
+        if (CollUtil.isNotEmpty(dyzConfig)) {
+            appUserMapper.delByAppId(appId);
+        }
+    }
+}

+ 20 - 0
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/dao/NovelAdRecordMapper.java

@@ -0,0 +1,20 @@
+package com.ytpm.novel.dao;
+
+
+import com.ytpm.app.model.YtNovelAdRecord;
+import org.apache.ibatis.annotations.Param;
+import org.mapstruct.Mapper;
+
+import java.util.List;
+
+/**
+ * @author lih
+ * @date 2025-10-09 16:56
+ */
+@Mapper
+public interface NovelAdRecordMapper {
+
+    List<YtNovelAdRecord> selectToDayNovelRecode(@Param("userId") String userId);
+
+    void insertNovelAdRecord(@Param("param") YtNovelAdRecord adRecord);
+}

+ 8 - 0
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/dao/NovelMapper.java

@@ -2,6 +2,7 @@ package com.ytpm.novel.dao;
 
 
 import com.ytpm.app.model.YtNovel;
+import com.ytpm.app.model.YtNovelCategory;
 import com.ytpm.app.model.YtNovelChapter;
 import com.ytpm.app.model.YtNovelShelf;
 import com.ytpm.app.model.YtNovelReadRecord;
@@ -60,4 +61,11 @@ public interface NovelMapper {
      *  更新用户书架
      */
     void updateNovelShelf(YtNovelShelf shelf);
+
+
+    /**
+     * 查询小说分类列表
+     */
+    List<YtNovelCategory> selectCategoryList();
+
 }

+ 19 - 0
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/model/dto/UserStaticParam.java

@@ -1,8 +1,12 @@
 package com.ytpm.novel.model.dto;
 
 
+import com.ytpm.app.param.AppUserQueryParam;
+import com.ytpm.app.param.AppUserTodayBannedParam;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.util.Date;
 import java.util.List;
@@ -12,6 +16,8 @@ import java.util.List;
  * @date 2025-09-30 10:01
  */
 @Data
+@NoArgsConstructor
+@AllArgsConstructor
 public class UserStaticParam {
     @ApiModelProperty("开始时间(可选)")
     private Date startTime;
@@ -24,4 +30,17 @@ public class UserStaticParam {
     private List<String> appIdList;
 
     private List<Integer> adSourceTypes;
+
+    public UserStaticParam(AppUserQueryParam queryParam) {
+        this.startTime = queryParam.getStartTime();
+        this.endTime = queryParam.getEndTime();
+        this.appIdList = queryParam.getAppIdList();
+    }
+
+    public UserStaticParam(AppUserTodayBannedParam queryParam) {
+        this.startTime = queryParam.getStartTime();
+        this.endTime = queryParam.getEndTime();
+        this.userIdList = queryParam.getUserIdList();
+
+    }
 }

+ 26 - 0
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/model/param/NovelAdRecordParam.java

@@ -0,0 +1,26 @@
+package com.ytpm.novel.model.param;
+
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 用户广告记录参数
+ * @author lih
+ * @date 2025-10-09 16:34
+ */
+@Data
+public class NovelAdRecordParam implements Serializable {
+
+    @ApiModelProperty("用户ID")
+    private String userId;
+
+    @ApiModelProperty("广告记录ID")
+    private String adRecordId;
+
+    @ApiModelProperty("耗时")
+    private Long duration;
+
+}

+ 13 - 17
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/service/impl/AdServiceImpl.java

@@ -12,7 +12,6 @@ import com.ytpm.agent.view.AgentTopCountView;
 import com.ytpm.app.model.YtDyzAdRecord;
 import com.ytpm.app.model.YtNovelUser;
 import com.ytpm.app.param.DyzAdRecordParam;
-import com.ytpm.app.view.WxDefaultConfig;
 import com.ytpm.feign.RiskFeign;
 import com.ytpm.general.RepMessage;
 import com.ytpm.general.Result;
@@ -80,22 +79,19 @@ public class AdServiceImpl implements AdService {
         saveRecordAndChangeUser(param, user);
         //调用风控广告校验
         if (AdSourceTypeEnum.rewarded_video.getAdSourceType() == param.getAdSourceType()) {
-            WxDefaultConfig config = appUserMapper.getDefaultConfigByAppId(user.getAppId());
-            String format = StrUtil.emptyToDefault(config.getTaskLimitTip(), "当前设备完成任务次数过多,请{}后重试!");
-//            user.setPowerLimitTip(format);
-//            Result<?> result = riskFeign.checkAdRisk(user);
-//            if (result.getCode() != 200) {
-//                Result<Object> resultObj = new Result<>(StatusCode.ACCESS_ERR, getTipsMsg());
-//                // 766处理
-//                if ("766".contains(result.getMessage())) {
-//                    resultObj.setData(result.getMessage());
-//                } else if (result.getCode() == StatusCode.ACCESS_RISK_ERROR && StrUtil.isNotBlank(result.getMessage())) {
-//                    // 体力不再获取处理
-//                    resultObj.setMessage(result.getMessage());
-//                    resultObj.setData("767");
-//                }
-//                return resultObj;
-//            }
+            Result<?> result = riskFeign.checkAdRisk(user);
+            if (result.getCode() != 200) {
+                Result<Object> resultObj = new Result<>(StatusCode.ACCESS_ERR, getTipsMsg());
+                if ("766".contains(result.getMessage())) {
+                    // 成本收益限制处理返回值 766
+                    resultObj.setData(result.getMessage());
+                } else if (result.getCode() == StatusCode.ACCESS_RISK_ERROR && StrUtil.isNotBlank(result.getMessage())) {
+                    // 体力上限限制处理返回值 767/768
+                    resultObj.setMessage(result.getMessage());
+                    resultObj.setData("767");
+                }
+                return resultObj;
+            }
         }
         return Result.resultOk(RepMessage.SAVE_SUCCESS);
     }

+ 1 - 2
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/service/impl/NovelServiceImpl.java

@@ -29,7 +29,6 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
@@ -141,6 +140,6 @@ public class NovelServiceImpl implements NovelService {
 
     @Override
     public List<YtNovelCategory> selectCategoryList() {
-        return Collections.emptyList();
+        return novelMapper.selectCategoryList();
     }
 }

+ 1 - 2
yt-novel/yt-novel-service/src/main/java/com/ytpm/novel/service/impl/VisitorLoginServiceImpl.java

@@ -10,7 +10,6 @@ import com.ytpm.agent.enums.AdRecordEnum;
 import com.ytpm.agent.enums.UserStatusEnum;
 import com.ytpm.app.enums.LoginType;
 import com.ytpm.app.model.YtDyzLoginRecord;
-import com.ytpm.app.model.YtDyzUser;
 import com.ytpm.app.model.YtNovelUser;
 import com.ytpm.app.model.YtUser;
 import com.ytpm.app.param.DyzAdRecordParam;
@@ -182,7 +181,7 @@ public class VisitorLoginServiceImpl extends AbstractLoginService {
 
     @Override
     protected Result<?> remoteCheckLoginRisk(YtUser ytUser) {
-        return riskFeign.checkLoginRisk((YtDyzUser) ytUser);
+        return riskFeign.checkLoginRisk(ytUser);
     }
 
     /**

+ 15 - 0
yt-novel/yt-novel-service/src/main/resources/mapper/NovelAdRecordMapper.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ytpm.novel.dao.NovelAdRecordMapper">
+    <insert id="insertNovelAdRecord">
+        insert into yt_novel_ad_record(record_id, user_id, ad_record_id, duration, record_time)
+        values (#{param.recordId}, #{param.userId}, #{param.adRecordId}, #{param.duration}, #{param.recordTime})
+    </insert>
+
+    <select id="selectToDayNovelRecode" resultType="com.ytpm.app.model.YtNovelAdRecord">
+        select record_id, user_id, ad_record_id, duration, record_time
+        from yt_novel_ad_record
+        where user_id = #{userId}
+        order by record_time desc
+    </select>
+</mapper>

+ 6 - 0
yt-novel/yt-novel-service/src/main/resources/mapper/NovelMapper.xml

@@ -115,5 +115,11 @@
         <foreach collection="novelIds" item="id" open="and n.novel_id in (" separator="," close=")">#{id}</foreach>
 
     </select>
+    <select id="selectCategoryList" resultType="com.ytpm.app.model.YtNovelCategory">
+        select category_id, category_name, category_desc, sort, create_by, create_time, update_by, update_time
+        from yt_novel_category ync
+        where ync.deleted=0
+        order by ync.sort
+    </select>
 
 </mapper>

+ 2 - 1
yt-question/yt-question-feign/src/main/java/com/ytpm/question/base/BaseFeign.java

@@ -8,6 +8,7 @@ import com.ytpm.agent.view.AgentTopCountView;
 import com.ytpm.app.model.YtAppDefaultConfig;
 import com.ytpm.app.model.YtDyzAdRecord;
 import com.ytpm.app.model.YtDyzUser;
+import com.ytpm.app.model.YtUser;
 import com.ytpm.app.param.AppConfigUpdateParam;
 import com.ytpm.app.param.AppQueryUserTodayTimeParam;
 import com.ytpm.app.param.AppUserParam;
@@ -59,7 +60,7 @@ public interface BaseFeign {
     ResultTable<YtDyzUser> getUserAll(@RequestBody AppUserParam param);
 
     @PostMapping("/user/updateUserInfo")
-    Result<?> updateUserInfo(@RequestBody YtDyzUser dyzUser);
+    Result<?> updateUserInfo(@RequestBody YtUser dyzUser);
 
     @GetMapping("/user/adRecords")
     ResultTable<YtDyzAdRecord> adRecords(@RequestParam(name = "userId", required = true) String userId,

+ 5 - 1
yt-question/yt-question-service/src/main/java/com/ytpm/question/controller/UserController.java

@@ -1,5 +1,6 @@
 package com.ytpm.question.controller;
 
+import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
@@ -16,6 +17,7 @@ import com.ytpm.agent.view.AgentAuditCheckVO;
 import com.ytpm.app.model.YtDyzAdRecord;
 import com.ytpm.app.model.YtDyzLoginRecord;
 import com.ytpm.app.model.YtDyzUser;
+import com.ytpm.app.model.YtUser;
 import com.ytpm.app.param.AppQueryUserTodayTimeParam;
 import com.ytpm.app.param.AppUserParam;
 import com.ytpm.app.param.AppUserQueryParam;
@@ -223,7 +225,9 @@ public class UserController {
      * 修改用户信息
      */
     @PostMapping("/updateUserInfo")
-    public Result<?> updateUserInfo(@RequestBody YtDyzUser dyzUser) {
+    public Result<?> updateUserInfo(@RequestBody YtUser ytUser) {
+        YtDyzUser dyzUser = new YtDyzUser();
+        BeanUtil.copyProperties(ytUser, dyzUser);
         appUserMapper.updateUser(dyzUser);
         return Result.resultOk(RepMessage.MODIFY_SUCCESS);
     }

+ 1 - 1
yt-question/yt-question-service/src/main/java/com/ytpm/question/service/impl/VisitorLoginServiceImpl.java

@@ -191,7 +191,7 @@ public class VisitorLoginServiceImpl extends AbstractLoginService {
 
     @Override
     protected Result<?> remoteCheckLoginRisk(YtUser ytUser) {
-        return riskFeign.checkLoginRisk((YtDyzUser) ytUser);
+        return riskFeign.checkLoginRisk(ytUser);
     }
 
     /**

+ 13 - 7
yt-risk/risk-feign/src/main/java/com/ytpm/feign/RiskFeign.java

@@ -1,6 +1,7 @@
 package com.ytpm.feign;
 
 import com.ytpm.app.model.YtDyzUser;
+import com.ytpm.app.model.YtUser;
 import com.ytpm.feign.fallback.RiskFeignFallBack;
 import com.ytpm.general.Result;
 import org.springframework.cloud.openfeign.FeignClient;
@@ -11,18 +12,23 @@ import org.springframework.web.bind.annotation.RequestParam;
 
 @FeignClient(name = "risk-manage", fallback = RiskFeignFallBack.class)
 public interface RiskFeign {
+
     @PostMapping("/public/checkRisk")
-    Result<?> checkRisk(@RequestBody YtDyzUser ytDyzUser);
+    Result<?> checkRisk(@RequestBody YtUser ytDyzUser);
+
     @PostMapping("/public/checkAdRisk")
-    Result<?> checkAdRisk(@RequestBody YtDyzUser ytDyzUser);
+    Result<?> checkAdRisk(@RequestBody YtUser ytDyzUser);
+
     @PostMapping("/public/checkAdRisk/766")
-    Result<?> checkAdRisk766(@RequestBody YtDyzUser ytDyzUser);
+    Result<?> checkAdRisk766(@RequestBody YtUser ytDyzUser);
+
     @GetMapping("/public/addDeblockingRecord")
     void addBlockingRecord(@RequestParam("userId")String userId);
+
+    @PostMapping("/public/checkLoginRisk")
+    Result<?> checkLoginRisk(YtUser old);
+
+    @Deprecated
     @PostMapping("/public/checkRegRisk")
     Result<?> checkRegRisk(@RequestBody YtDyzUser ytDyzUser);
-    @PostMapping("/public/checkLoginRisk")
-    Result<?> checkLoginRisk(YtDyzUser old);
-    @PostMapping("/public/checkVisitorLogin")
-    Result<?> checkVisitorLogin(YtDyzUser old);
 }

+ 4 - 3
yt-risk/risk-feign/src/main/java/com/ytpm/feign/fallback/RiskFeignFallBack.java

@@ -1,6 +1,7 @@
 package com.ytpm.feign.fallback;
 
 import com.ytpm.app.model.YtDyzUser;
+import com.ytpm.app.model.YtUser;
 import com.ytpm.feign.RiskFeign;
 import com.ytpm.general.RepMessage;
 import com.ytpm.general.Result;
@@ -14,12 +15,12 @@ import org.springframework.web.bind.annotation.RequestBody;
 @Component
 public abstract class RiskFeignFallBack implements RiskFeign {
     @Override
-    public Result<?> checkRisk(@RequestBody YtDyzUser ytDyzUser) {
+    public Result<?> checkRisk(@RequestBody YtUser ytDyzUser) {
         return new Result<>(StatusCode.ACCESS_ERR, RepMessage.TOKEN_EXPIRE);
     }
 
     @Override
-    public Result<?> checkAdRisk(@RequestBody YtDyzUser ytDyzUser) {
+    public Result<?> checkAdRisk(@RequestBody YtUser ytDyzUser) {
         return new Result<>(StatusCode.ACCESS_ERR, RepMessage.TOKEN_EXPIRE);
     }
 
@@ -29,7 +30,7 @@ public abstract class RiskFeignFallBack implements RiskFeign {
     }
 
     @Override
-    public Result<?> checkLoginRisk(@RequestBody YtDyzUser ytDyzUser) {
+    public Result<?> checkLoginRisk(@RequestBody YtUser ytDyzUser) {
         return new Result<>(StatusCode.ACCESS_ERR, RepMessage.TOKEN_EXPIRE);
     }
 }

+ 5 - 4
yt-risk/risk-manage/src/main/java/com/ytpm/controller/PublicApiController.java

@@ -1,6 +1,7 @@
 package com.ytpm.controller;
 
 import com.ytpm.app.model.YtDyzUser;
+import com.ytpm.app.model.YtUser;
 import com.ytpm.general.Result;
 import com.ytpm.risk.view.RiskTemplateView;
 import com.ytpm.service.RiskService;
@@ -36,7 +37,7 @@ public class PublicApiController {
      */
     @ApiOperation("登录检查默认风控配置")
     @PostMapping("/checkRisk")
-    public Result<?> checkRisk(@RequestBody YtDyzUser dyzUser){
+    public Result<?> checkRisk(@RequestBody YtUser dyzUser){
         return riskService.checkRisk(dyzUser);
     }
 
@@ -62,7 +63,7 @@ public class PublicApiController {
      */
     @ApiOperation("校验广告的默认风控配置")
     @PostMapping("/checkAdRisk")
-    public Result<?> checkAdRisk(@RequestBody YtDyzUser dyzUser){
+    public Result<?> checkAdRisk(@RequestBody YtUser dyzUser){
        return riskService.checkAdRisk(dyzUser);
     }
 
@@ -71,7 +72,7 @@ public class PublicApiController {
      */
     @ApiOperation("校验广告的默认风控配置")
     @PostMapping("/checkAdRisk/766")
-    public Result<?> checkAdRisk766(@RequestBody YtDyzUser dyzUser){
+    public Result<?> checkAdRisk766(@RequestBody YtUser dyzUser){
        return riskService.checkAdRisk766(dyzUser);
     }
 
@@ -98,7 +99,7 @@ public class PublicApiController {
 
     @ApiOperation("校验登录风控配置")
     @PostMapping("/checkLoginRisk")
-    public Result<?> checkLoginRisk(@RequestBody YtDyzUser dyzUser){
+    public Result<?> checkLoginRisk(@RequestBody YtUser dyzUser){
         return riskService.checkLoginRisk(dyzUser);
     }
 }

+ 5 - 4
yt-risk/risk-manage/src/main/java/com/ytpm/service/RiskService.java

@@ -3,6 +3,7 @@ package com.ytpm.service;
 import com.ytpm.agent.model.YtPlatformBanned;
 import com.ytpm.agent.view.AgentUserInfo;
 import com.ytpm.app.model.YtDyzUser;
+import com.ytpm.app.model.YtUser;
 import com.ytpm.general.Result;
 import com.ytpm.general.ResultTable;
 import com.ytpm.risk.param.RiskBannedListParam;
@@ -82,7 +83,7 @@ public interface RiskService {
     /**
      * 登录检查默认风控配置
      */
-    Result<?> checkRisk(YtDyzUser dyzUser);
+    Result<?> checkRisk(YtUser dyzUser);
 
     /**
      * 根据appId查询应用配置模版
@@ -97,7 +98,7 @@ public interface RiskService {
     /**
      * 校验广告的默认风控配置
      */
-    Result<?> checkAdRisk(YtDyzUser dyzUser);
+    Result<?> checkAdRisk(YtUser dyzUser);
 
     List<YtPlatformBanned> queryBannedRecord(Date startTime,Date endTime,List<String> appIdList);
 
@@ -126,10 +127,10 @@ public interface RiskService {
     /**
      * 校验登录风控配置
      */
-    Result<?> checkLoginRisk(YtDyzUser dyzUser);
+    Result<?> checkLoginRisk(YtUser dyzUser);
 
     /**
      * 校验用户广告风控 766
      */
-    Result<?> checkAdRisk766(YtDyzUser dyzUser);
+    Result<?> checkAdRisk766(YtUser dyzUser);
 }

+ 15 - 14
yt-risk/risk-manage/src/main/java/com/ytpm/service/impl/RiskServiceImpl.java

@@ -27,6 +27,7 @@ import com.ytpm.app.enums.LoginType;
 import com.ytpm.app.model.YtDyzAdRecord;
 import com.ytpm.app.model.YtDyzLoginRecord;
 import com.ytpm.app.model.YtDyzUser;
+import com.ytpm.app.model.YtUser;
 import com.ytpm.custom.CustomField;
 import com.ytpm.dao.AppMapper;
 import com.ytpm.dao.DictMapper;
@@ -390,7 +391,7 @@ public class RiskServiceImpl implements RiskService {
      * 登录检查默认风控配置
      */
     @Override
-    public Result<?> checkRisk(YtDyzUser dyzUser) {
+    public Result<?> checkRisk(YtUser dyzUser) {
         //查询当前用户今日有被解封则直接放行
         List<RiskDeblockingListView> vo = riskManageMapper.queryTodayDeblock(dyzUser.getUserId());
         if(CollUtil.isNotEmpty(vo)){
@@ -414,7 +415,7 @@ public class RiskServiceImpl implements RiskService {
     /**
      * 校验风控规则322
      */
-    private void checkRisk322(YtDyzUser dyzUser) {
+    private void checkRisk322(YtUser dyzUser) {
         RiskTemplateView view = configMapper.getByCode("322");
         //根据用户所属应用查询该应用母包openid查询用户信息
         YtApp ytApp = appMapper.selectRiskApp(dyzUser.getAppId());
@@ -448,7 +449,7 @@ public class RiskServiceImpl implements RiskService {
      *  ipPrefix IP前?段为4
      *  ipSameCount 同IP登录数量为>2
      */
-    private void checkDefaultRiskConfig(YtDyzUser dyzUser, List<RiskConfigView> configList) {
+    private void checkDefaultRiskConfig(YtUser dyzUser, List<RiskConfigView> configList) {
         //封装配置值map
         Map<String, String> configMap = configList.stream().collect(
                 Collectors.toMap(RiskConfigView::getFieldName, RiskConfigView::getConfigVal));
@@ -500,7 +501,7 @@ public class RiskServiceImpl implements RiskService {
      * 校验广告的默认风控配置
      */
     @Override
-    public Result<?> checkAdRisk(YtDyzUser dyzUser) {
+    public Result<?> checkAdRisk(YtUser dyzUser) {
         //查询当前用户今日有被解封则直接放行
         long start = System.currentTimeMillis();
         List<RiskDeblockingListView> vo = riskManageMapper.queryTodayDeblock(dyzUser.getUserId());
@@ -551,7 +552,7 @@ public class RiskServiceImpl implements RiskService {
      * 校验默认风控规则768
      * {hourCount}小时内,获得奖励的激励视频数>{hourTaskLimit}
      */
-    private void checkRisk768(YtDyzUser dyzUser, List<YtDyzAdRecord> adRecords) {
+    private void checkRisk768(YtUser dyzUser, List<YtDyzAdRecord> adRecords) {
         RiskTemplateView riskTempView = configMapper.getByCode(dyzUser.getAppId() + "-768");
         if (riskTempView == null || riskTempView.getEnabled() != 1) return;
         Map<String, String> riskConfigMap = getRsihConfigMap(riskTempView);
@@ -577,7 +578,7 @@ public class RiskServiceImpl implements RiskService {
      * 校验默认风控规则767
      * {monthCount}月内,获得奖励的激励视频数>{monthTaskLimit}
      */
-    private void checkRisk767(YtDyzUser dyzUser, List<YtDyzAdRecord> adRecords, YtPlatformUserApp userApp) {
+    private void checkRisk767(YtUser dyzUser, List<YtDyzAdRecord> adRecords, YtPlatformUserApp userApp) {
         RiskTemplateView riskTempView = configMapper.getByCode(dyzUser.getAppId() + "-767");
         if (riskTempView == null || riskTempView.getEnabled() != 1) return;
         Map<String, String> riskConfigMap = getRsihConfigMap(riskTempView);
@@ -645,7 +646,7 @@ public class RiskServiceImpl implements RiskService {
      * 校验默认风控规则766
      * 当日用户获得{}个获得奖励的激励视频,近期前{}个获得奖励的激励视频平均收益<{}
      */
-    private void checkRisk766(YtDyzUser dyzUser, List<YtDyzAdRecord> adRecords) {
+    private void checkRisk766(YtUser dyzUser, List<YtDyzAdRecord> adRecords) {
         RiskTemplateView riskTempView = configMapper.getByCode(dyzUser.getAppId() + "-766");
         if (riskTempView == null || riskTempView.getEnabled() != 1) return;
         Map<String, String> rsihConfigMap = getRsihConfigMap(riskTempView);
@@ -683,7 +684,7 @@ public class RiskServiceImpl implements RiskService {
     /**
      * 校验默认风控规则746
      */
-    private void checkRisk746(YtDyzUser dyzUser, List<YtDyzAdRecord> records) {
+    private void checkRisk746(YtUser dyzUser, List<YtDyzAdRecord> records) {
         RiskTemplateView revenue = configMapper.getByCode(dyzUser.getAppId()+"-746");
         if (revenue == null || revenue.getEnabled() != 1) return;
         Map<String, String> revenueMap = revenue.getConfigList().stream().collect(
@@ -709,7 +710,7 @@ public class RiskServiceImpl implements RiskService {
     /**
      * 校验默认风控规则742
      */
-    private void checkRisk742(YtDyzUser dyzUser,List<YtDyzAdRecord> records) {
+    private void checkRisk742(YtUser dyzUser,List<YtDyzAdRecord> records) {
         RiskTemplateView ecpmLimit= configMapper.getByCode(dyzUser.getAppId()+"-742");
         if(ecpmLimit == null || ecpmLimit.getEnabled()!=1)return;
         Map<String, String> limitMap = ecpmLimit.getConfigList().stream().collect(
@@ -738,7 +739,7 @@ public class RiskServiceImpl implements RiskService {
     /**
      * 风控锁定用户
      */
-    private void riskLockUser(YtDyzUser dyzUser,String riskCode, String tempName, String errMsg) {
+    private void riskLockUser(YtUser dyzUser,String riskCode, String tempName, String errMsg) {
         //增加用户风控记录
         RiskBannedParam param = new RiskBannedParam();
         param.setUserId(dyzUser.getUserId());
@@ -753,7 +754,7 @@ public class RiskServiceImpl implements RiskService {
         YtApp app = appMapper.selectRiskApp(dyzUser.getAppId());
         YtPlatformUserApp appInfo = appMapper.selectParentApp(app.getSuperiorId());
         scheduledExecutorService.schedule(()->{
-            YtDyzUser next = new YtDyzUser();
+            YtUser next = new YtUser();
             next.setUserId(dyzUser.getUserId());
             next.setUserStatus(UserStatusEnum.LOCK.getCode());
             next.setRiskCode(riskCode);
@@ -1014,7 +1015,7 @@ public class RiskServiceImpl implements RiskService {
      * 校验登录风控规则
      */
     @Override
-    public Result<?> checkLoginRisk(YtDyzUser dyzUser) {
+    public Result<?> checkLoginRisk(YtUser dyzUser) {
         long start = System.currentTimeMillis();
         // 20250908 移除游客登陆校验
 //        // 游客登陆风控校验
@@ -1104,7 +1105,7 @@ public class RiskServiceImpl implements RiskService {
      * 原生(信息流)+ 开屏广告 + 横幅对应 总预估收益 小于 阈值时,校验失败
      * @param dyzUser 该设备同应用的最新一条注册用户信息
      */
-    private boolean checkVisitorRisk(YtDyzUser dyzUser) {
+    private boolean checkVisitorRisk(YtUser dyzUser) {
         RiskTemplateView view = configMapper.getByCode(dyzUser.getAppId() + "-344");
         RiskTemplateView view2 = configMapper.getByCode(dyzUser.getAppId() + "-345");
 
@@ -1179,7 +1180,7 @@ public class RiskServiceImpl implements RiskService {
     }
 
     @Override
-    public Result<?> checkAdRisk766(YtDyzUser dyzUser) {
+    public Result<?> checkAdRisk766(YtUser dyzUser) {
         long start = System.currentTimeMillis();
         YtPlatformUserApp userApp;
         if (dyzUser.getIosId()!=null) {