ct 4 dias atrás
pai
commit
00bebe354c
34 arquivos alterados com 1554 adições e 30 exclusões
  1. 8 8
      fs-common/src/main/java/com/fs/common/utils/luckyDraw/LotteryUtil.java
  2. 5 0
      fs-service/src/main/java/com/fs/aiChat/mapper/InterestAiChatSessionMapper.java
  3. 17 0
      fs-service/src/main/java/com/fs/aiChat/param/InterestAiMessage.java
  4. 1 1
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseRewardRoundServiceImpl.java
  5. 120 0
      fs-service/src/main/java/com/fs/his/config/AppPageConfig.java
  6. 12 0
      fs-service/src/main/java/com/fs/his/domain/FsIntegralCart.java
  7. 11 0
      fs-service/src/main/java/com/fs/his/domain/FsIntegralOrder.java
  8. 50 0
      fs-service/src/main/java/com/fs/his/domain/FsUserActiveLog.java
  9. 30 0
      fs-service/src/main/java/com/fs/his/dto/ActiveConfigDTO.java
  10. 6 0
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralCartMapper.java
  11. 4 7
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralGoodsMapper.java
  12. 2 0
      fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderItemMapper.java
  13. 68 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserActiveLogMapper.java
  14. 26 0
      fs-service/src/main/java/com/fs/his/param/AddGoodsIntoCartParam.java
  15. 17 0
      fs-service/src/main/java/com/fs/his/param/GetFsIntegralCartDetailsParm.java
  16. 14 0
      fs-service/src/main/java/com/fs/his/param/GetFsIntegralCartListParam.java
  17. 1 0
      fs-service/src/main/java/com/fs/his/service/IFsStoreOrderService.java
  18. 70 0
      fs-service/src/main/java/com/fs/his/service/IFsUserActiveLogService.java
  19. 224 11
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralCartServiceImpl.java
  20. 5 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  21. 257 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserActiveLogServiceImpl.java
  22. 50 0
      fs-service/src/main/java/com/fs/his/vo/FsIntegralGoodsVo.java
  23. 43 0
      fs-service/src/main/java/com/fs/his/vo/GetCartGoodsDetailsVo.java
  24. 37 0
      fs-service/src/main/java/com/fs/his/vo/GetFsIntegralCartDetailsVo.java
  25. 63 0
      fs-service/src/main/java/com/fs/his/vo/GetFsIntegralCartListVo.java
  26. 31 3
      fs-service/src/main/resources/mapper/his/FsIntegralCartMapper.xml
  27. 6 0
      fs-service/src/main/resources/mapper/his/FsIntegralGoodsMapper.xml
  28. 6 0
      fs-service/src/main/resources/mapper/his/FsStoreOrderItemMapper.xml
  29. 100 0
      fs-service/src/main/resources/mapper/his/FsUserActiveLogMapper.xml
  30. 7 0
      fs-service/src/main/resources/mapper/his/InterestAiChatSessionMapper.xml
  31. 9 0
      fs-user-app/src/main/java/com/fs/app/controller/CommonController.java
  32. 98 0
      fs-user-app/src/main/java/com/fs/app/controller/FsIntegralCartController.java
  33. 35 0
      fs-user-app/src/main/java/com/fs/app/controller/aiChat/controller/AiDoctorController.java
  34. 121 0
      fs-user-app/src/main/java/com/fs/app/controller/aiChat/controller/InterestAiController.java

+ 8 - 8
fs-common/src/main/java/com/fs/common/utils/luckyDraw/LotteryUtil.java

@@ -20,16 +20,16 @@ public class LotteryUtil {
         double total = prizes.stream().mapToDouble(Prize::getProbability).sum();
 
         // [0, total) 之间取随机数
-//        double random = ThreadLocalRandom.current().nextDouble() * total;
+        double random = ThreadLocalRandom.current().nextDouble() * total;
 
 //        // 逐步累加找到落点
-//        double sum = 0;
-//        for (Prize prize : prizes) {
-//            sum += prize.getProbability();
-//            if (random < sum) {
-//                return prize;
-//            }
-//        }
+        double sum = 0;
+        for (Prize prize : prizes) {
+            sum += prize.getProbability();
+            if (random < sum) {
+                return prize;
+            }
+        }
 
         // 理论上不会到这里
         return prizes.get(prizes.size() - 1);

+ 5 - 0
fs-service/src/main/java/com/fs/aiChat/mapper/InterestAiChatSessionMapper.java

@@ -5,6 +5,7 @@ import com.fs.aiChat.domain.DoctorAiChatLog;
 import com.fs.aiChat.domain.InterestAiChatMsg;
 import com.fs.aiChat.domain.InterestAiSession;
 import com.fs.aiChat.domain.SessionRoleInfo;
+import com.fs.aiChat.param.InterestAiMessage;
 import com.fs.his.domain.FsInterestAiMsg;
 import com.fs.his.domain.FsInterestAiRole;
 import com.fs.his.domain.FsInterestAiSession;
@@ -56,4 +57,8 @@ public interface InterestAiChatSessionMapper extends BaseMapper<DoctorAiChatLog>
 
 
     FsInterestAiRole selectFsInterestAiRoleByRoleId(Long roleId);
+
+    Integer selectSessionIdByUserAndRole(@Param("userId") Long userId, @Param("roleId") Integer roleId);
+
+    Integer selectAiMsgBySessionIdAndMsg(InterestAiMessage message);
 }

+ 17 - 0
fs-service/src/main/java/com/fs/aiChat/param/InterestAiMessage.java

@@ -1,7 +1,10 @@
 package com.fs.aiChat.param;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 
+import java.util.Date;
+
 @Data
 public class InterestAiMessage {
     Long userId;
@@ -11,5 +14,19 @@ public class InterestAiMessage {
     String roleName;
     String message;
     Long sessionId;
+    @JsonFormat(
+            pattern = "yyyy/MM/dd HH:mm:ss",
+            shape = JsonFormat.Shape.STRING
+    )
+    Date startTime;
+    @JsonFormat(
+            pattern = "yyyy/MM/dd HH:mm:ss",
+            shape = JsonFormat.Shape.STRING
+    )
+    Date endTime;
+
+    String deviceId;
+    Long isRefresh;
+    String beginTime;
 //    Integer isWelcome;
 }

+ 1 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsCourseRewardRoundServiceImpl.java

@@ -256,7 +256,7 @@ public class FsCourseRewardRoundServiceImpl extends ServiceImpl<FsCourseRewardRo
         rewardRound.setActualRewards(String.valueOf(auctual));
         if (result.get("code").equals(200)){
             insertFsCourseRewardRound(rewardRound);
-            return R.ok("芳华币+"+auctual);
+            return R.ok("积分币+"+auctual);
         }else {
             return result;
         }

+ 120 - 0
fs-service/src/main/java/com/fs/his/config/AppPageConfig.java

@@ -0,0 +1,120 @@
+package com.fs.his.config;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class AppPageConfig implements Serializable {
+
+    /**
+     * 主页面配置
+     */
+    private MainPage mainPage;
+
+    /**
+     * 子页面配置
+     */
+    private SubPage subPage;
+
+    @Data
+    public static class MainPage {
+        /**
+         * 健康
+         */
+        private String health;
+
+        /**
+         * 精选
+         */
+        private String featured;
+
+        /**
+         * 优选
+         */
+        private String preferred;
+    }
+
+    @Data
+    public static class SubPage {
+
+        /**
+         * 健康模块子页面
+         */
+        private Health health;
+
+        /**
+         * 精选模块子页面
+         */
+        private Featured featured;
+
+        /**
+         * 优选模块子页面
+         */
+        private Preferred preferred;
+    }
+
+    @Data
+    public static class Health {
+        /**
+         * 医疗服务
+         */
+        private String medicalService;
+
+        /**
+         * 健康管理
+         */
+        private String healthManagement;
+
+        /**
+         * 名家讲堂
+         */
+        private String famousLecture;
+
+        /**
+         * 学习中心
+         */
+        private String learningCenter;
+    }
+
+    @Data
+    public static class Featured {
+        /**
+         * 短视频
+         */
+        private String shortVideo;
+        private String shortVideoH5Url;
+
+        /**
+         * 直播
+         */
+        private String live;
+        private String liveH5Url;
+
+        /**
+         * 短剧
+         */
+        private String shortDrama;
+        private String shortDramaH5Url;
+
+        /**
+         * 游戏
+         */
+        private String game;
+        private String gameH5Url;
+
+        /**
+         * 任务广场
+         */
+        private String taskSquare;
+        private String taskSquareH5Url;
+    }
+
+    @Data
+    public static class Preferred {
+        /**
+         * 现金 + 积分购买
+         */
+        private String cashAndPointsPurchase;
+    }
+}

+ 12 - 0
fs-service/src/main/java/com/fs/his/domain/FsIntegralCart.java

@@ -4,13 +4,20 @@ import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 @TableName("fs_integral_cart")
 @Data
+@Builder
+@NoArgsConstructor      // 无参构造
+@AllArgsConstructor
 public class FsIntegralCart {
     /**
      * 主键ID
@@ -51,4 +58,9 @@ public class FsIntegralCart {
      */
     @TableField(exist = false)
     private Boolean addToExist;
+
+    @ApiModelProperty("是否选中:1是,0否")
+    @TableField("is_selected")
+    private Boolean isSelected;
+
 }

+ 11 - 0
fs-service/src/main/java/com/fs/his/domain/FsIntegralOrder.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -130,4 +131,14 @@ public class FsIntegralOrder
     private Integer deliveryStatus;
 
     private String deliveryType;
+
+
+    @ApiModelProperty("购物车中的商品信息(多个)")
+    private String itemCartJson;
+    @ApiModelProperty("购物车中的商品对应积分(多个)")
+    private String integralByCart;
+    @ApiModelProperty("购物车中对应的商品编码(多个)")
+    private String barCodeCart;
+    @ApiModelProperty("商品对应的数量(多个)")
+    private String quantityCart;
 }

+ 50 - 0
fs-service/src/main/java/com/fs/his/domain/FsUserActiveLog.java

@@ -0,0 +1,50 @@
+package com.fs.his.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 活动签到记录对象 fs_user_active_log
+ *
+ * @author fs
+ * @date 2025-09-23
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsUserActiveLog extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 活动名称 */
+    @Excel(name = "活动名称")
+    private String activeName;
+
+    /** 用户uid */
+    @Excel(name = "用户uid")
+    private Long userId;
+
+    /** 获得积分 */
+    @Excel(name = "获得积分")
+    private Long number;
+
+    /** 剩余积分 */
+    @Excel(name = "剩余积分")
+    private Long balance;
+
+    /** 签到说明 */
+    @Excel(name = "签到说明")
+    private String title;
+
+    @Excel(name = "创建时间")
+    private Date createTime;
+     @Excel(name = "修改时间")
+    private Date updateTime;
+
+
+
+}

+ 30 - 0
fs-service/src/main/java/com/fs/his/dto/ActiveConfigDTO.java

@@ -0,0 +1,30 @@
+package com.fs.his.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Data
+public class ActiveConfigDTO implements Serializable {
+
+
+    /** 活动名称 */
+    private String activeName;
+
+    /** 活动开始时间 */
+    private LocalDate activeStartTime;
+
+    /** 活动结束时间 */
+    private LocalDate activeEndTime;
+
+    /** 消费达标条件 */
+    private BigDecimal moneyTerm;
+
+    /** 活动奖励 */
+    private Long activeReward;
+
+    /** 是否开启(1 开启,0 关闭) */
+    private String isOpen;
+}

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

@@ -2,7 +2,9 @@ package com.fs.his.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.his.domain.FsIntegralCart;
+import com.fs.his.param.GetFsIntegralCartListParam;
 import com.fs.his.vo.FsIntegralCartVO;
+import com.fs.his.vo.GetFsIntegralCartListVo;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -35,4 +37,8 @@ public interface FsIntegralCartMapper extends BaseMapper<FsIntegralCart> {
      * @return  删除数量
      */
     int deleteCartByGoodsId(@Param("goodsId") Long goodsId);
+
+    List<GetFsIntegralCartListVo> getFsIntegralCartList(@Param("param") GetFsIntegralCartListParam param, @Param("aLong") Long aLong, @Param("cartId") List<Long> cartId);
+
+    int updateQuantityAtomically(@Param("userId") Long userId, @Param("goodsId") Long goodsId, @Param("addQuantity") Integer addQuantity, @Param("maxQuantity") int maxQuantity);
 }

+ 4 - 7
fs-service/src/main/java/com/fs/his/mapper/FsIntegralGoodsMapper.java

@@ -2,17 +2,12 @@ package com.fs.his.mapper;
 
 import com.fs.his.domain.FsIntegralGoods;
 import com.fs.his.param.FsIntegralGoodsListUParam;
-import com.fs.his.vo.FsGoodsVO;
-import com.fs.his.vo.FsIntegralGoodsChooseVO;
-import com.fs.his.vo.FsIntegralGoodsListUVO;
-import com.fs.his.vo.FsIntegralGoodsListVO;
+import com.fs.his.vo.*;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * 积分商品Mapper接口
@@ -111,4 +106,6 @@ public interface FsIntegralGoodsMapper
      * 根据id集合查询积分商品列表
      */
     List<FsGoodsVO> getFsGoodsVOListByIds(@Param("goodsIds") List<Long> goodsIds);
+
+    List<FsIntegralGoodsVo> selectAllByGoodsIds(@Param("goodsIds") Set<Long> goodsIds);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderItemMapper.java

@@ -78,4 +78,6 @@ public interface FsStoreOrderItemMapper
     List<FsStoreOrderItem> selectFsStoreOrderItemListByItemIds(@Param("itemIds") List<Long> itemIds);
 
     BigDecimal selectPayPriceByYear(@Param("userId") String userId);
+
+    BigDecimal selectPayPriceAll(@Param("userId") Long userId);
 }

+ 68 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserActiveLogMapper.java

@@ -0,0 +1,68 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsUserActiveLog;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 活动签到记录Mapper接口
+ *
+ * @author fs
+ * @date 2025-09-23
+ */
+public interface FsUserActiveLogMapper extends BaseMapper<FsUserActiveLog>{
+    /**
+     * 查询活动签到记录
+     *
+     * @param id 活动签到记录主键
+     * @return 活动签到记录
+     */
+    FsUserActiveLog selectFsUserActiveLogById(Long id);
+
+    /**
+     * 查询活动签到记录列表
+     *
+     * @param fsUserActiveLog 活动签到记录
+     * @return 活动签到记录集合
+     */
+    List<FsUserActiveLog> selectFsUserActiveLogList(FsUserActiveLog fsUserActiveLog);
+
+    /**
+     * 新增活动签到记录
+     *
+     * @param fsUserActiveLog 活动签到记录
+     * @return 结果
+     */
+    int insertFsUserActiveLog(FsUserActiveLog fsUserActiveLog);
+
+    /**
+     * 修改活动签到记录
+     *
+     * @param fsUserActiveLog 活动签到记录
+     * @return 结果
+     */
+    int updateFsUserActiveLog(FsUserActiveLog fsUserActiveLog);
+
+    /**
+     * 删除活动签到记录
+     *
+     * @param id 活动签到记录主键
+     * @return 结果
+     */
+    int deleteFsUserActiveLogById(Long id);
+
+    /**
+     * 批量删除活动签到记录
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsUserActiveLogByIds(Long[] ids);
+
+    FsUserActiveLog selectTodayIsSign(Long userId);
+
+    List<FsUserActiveLog> selectByUserAndDateRange(@Param("userId") Long userId,@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
+}

+ 26 - 0
fs-service/src/main/java/com/fs/his/param/AddGoodsIntoCartParam.java

@@ -0,0 +1,26 @@
+package com.fs.his.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class AddGoodsIntoCartParam {
+
+    @NotNull(message = "积分商品ID不能为空")
+    @ApiModelProperty("积分商品ID")
+    private Long goodsId;
+
+    @Max(value = 99, message = "单商品最多添加99件")
+    @Min(value = 1, message = "商品数量至少为1")
+    @NotNull(message = "商品数量不能为空")
+    @ApiModelProperty("商品数量")
+    private Integer quantity;
+
+    @NotNull(message = "是否选中:1是,0否,不能为空")
+    @ApiModelProperty("是否选中:1是,0否")
+    private Boolean isSelected;
+}

+ 17 - 0
fs-service/src/main/java/com/fs/his/param/GetFsIntegralCartDetailsParm.java

@@ -0,0 +1,17 @@
+package com.fs.his.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class GetFsIntegralCartDetailsParm {
+    @ApiModelProperty("收货地址ID")
+    private Long addressId;
+
+    @NotNull(message = "购物车ID不能为空")
+    @ApiModelProperty("购物车ID")
+    private List<Long> cartId;
+}

+ 14 - 0
fs-service/src/main/java/com/fs/his/param/GetFsIntegralCartListParam.java

@@ -0,0 +1,14 @@
+package com.fs.his.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class GetFsIntegralCartListParam {
+    @ApiModelProperty("商品名称")
+    private String goodsName;
+    @ApiModelProperty(value = "当前页,默认为1")
+    private Integer pageNum = 1;
+    @ApiModelProperty(value = "页容量,默认为10")
+    private Integer pageSize = 10;
+}

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

@@ -281,4 +281,5 @@ public interface IFsStoreOrderService
 
     BigDecimal selectPayPriceByYear(String userId);
 
+    BigDecimal selectPayPriceAll(Long userId);
 }

+ 70 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserActiveLogService.java

@@ -0,0 +1,70 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserActiveLog;
+
+import java.util.List;
+
+/**
+ * 活动签到记录Service接口
+ *
+ * @author fs
+ * @date 2025-09-23
+ */
+public interface IFsUserActiveLogService extends IService<FsUserActiveLog>{
+    /**
+     * 查询活动签到记录
+     *
+     * @param id 活动签到记录主键
+     * @return 活动签到记录
+     */
+    FsUserActiveLog selectFsUserActiveLogById(Long id);
+
+    /**
+     * 查询活动签到记录列表
+     *
+     * @param fsUserActiveLog 活动签到记录
+     * @return 活动签到记录集合
+     */
+    List<FsUserActiveLog> selectFsUserActiveLogList(FsUserActiveLog fsUserActiveLog);
+
+    /**
+     * 新增活动签到记录
+     *
+     * @param fsUserActiveLog 活动签到记录
+     * @return 结果
+     */
+    int insertFsUserActiveLog(FsUserActiveLog fsUserActiveLog);
+
+    /**
+     * 修改活动签到记录
+     *
+     * @param fsUserActiveLog 活动签到记录
+     * @return 结果
+     */
+    int updateFsUserActiveLog(FsUserActiveLog fsUserActiveLog);
+
+    /**
+     * 批量删除活动签到记录
+     *
+     * @param ids 需要删除的活动签到记录主键集合
+     * @return 结果
+     */
+    int deleteFsUserActiveLogByIds(Long[] ids);
+
+    /**
+     * 删除活动签到记录信息
+     *
+     * @param id 活动签到记录主键
+     * @return 结果
+     */
+    int deleteFsUserActiveLogById(Long id);
+
+    Long userActiveLogSign(FsUser fsUser);
+
+    R getUserActiveLog(FsUser fsUser);
+
+    boolean getUserActiveWindow(FsUser fsUser);
+}

+ 224 - 11
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralCartServiceImpl.java

@@ -1,28 +1,40 @@
 package com.fs.his.service.impl;
 
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
-import com.fs.his.domain.FsIntegralCart;
-import com.fs.his.domain.FsIntegralGoods;
-import com.fs.his.domain.FsUser;
-import com.fs.his.mapper.FsIntegralCartMapper;
-import com.fs.his.mapper.FsIntegralGoodsMapper;
-import com.fs.his.mapper.FsUserMapper;
+import com.fs.common.exception.ServiceException;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.spring.SpringUtils;
+import com.fs.core.utils.OrderCodeUtils;
+import com.fs.his.domain.*;
+import com.fs.his.mapper.*;
+import com.fs.his.param.AddGoodsIntoCartParam;
+import com.fs.his.param.CreateOrderFromCartParm;
+import com.fs.his.param.GetFsIntegralCartDetailsParm;
+import com.fs.his.param.GetFsIntegralCartListParam;
 import com.fs.his.service.IFsIntegralCartService;
-import com.fs.his.vo.FsIntegralCartVO;
+import com.fs.his.service.IFsUserIntegralLogsService;
+import com.fs.his.vo.*;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import javax.validation.constraints.NotNull;
 import java.time.LocalDateTime;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Service
@@ -32,6 +44,14 @@ public class FsIntegralCartServiceImpl extends ServiceImpl<FsIntegralCartMapper,
     private FsIntegralGoodsMapper goodsMapper;
     @Resource
     private FsUserMapper userMapper;
+    @Autowired
+    private FsUserAddressMapper fsUserAddressMapper;
+    @Autowired
+    private FsIntegralGoodsMapper fsIntegralGoodsMapper;
+    @Autowired
+    private FsIntegralOrderMapper fsIntegralOrderMapper;
+    @Autowired
+    IFsUserIntegralLogsService integralLogsService;
 
     /**
      * 添加或修改购物车
@@ -123,4 +143,197 @@ public class FsIntegralCartServiceImpl extends ServiceImpl<FsIntegralCartMapper,
         params.put("ids", ids);
         return baseMapper.getCartsByMap(params);
     }
+
+    @Override
+    public List<GetFsIntegralCartListVo> getFsIntegralCartList(GetFsIntegralCartListParam param, Long aLong) {
+        return baseMapper.getFsIntegralCartList(param, aLong, null);
+    }
+
+    /**
+     * 获取用户购物车详情页
+     *
+     * @param param
+     * @param userId
+     * @return
+     */
+    @Override
+    public GetFsIntegralCartDetailsVo getFsIntegralCartDetails(GetFsIntegralCartDetailsParm param, Long userId) {
+        List<GetFsIntegralCartListVo> cartListVoList = baseMapper.getFsIntegralCartList(new GetFsIntegralCartListParam(), userId, param.getCartId());
+        GetFsIntegralCartDetailsVo vos = new GetFsIntegralCartDetailsVo();
+        ArrayList<GetCartGoodsDetailsVo> goodsDetailsVos = new ArrayList<>();
+        for (GetFsIntegralCartListVo listVo : cartListVoList) {
+            GetCartGoodsDetailsVo cartListVo = new GetCartGoodsDetailsVo();
+            BeanUtils.copyProperties(listVo, cartListVo);
+            cartListVo.setGoodsIntegralTotal(listVo.getGoodsIntegral() * listVo.getQuantity());
+            goodsDetailsVos.add(cartListVo);
+        }
+        if (ObjectUtils.isNotEmpty(param.getAddressId())) {
+            FsUserAddress address = fsUserAddressMapper.selectFsUserAddressByAddressId(param.getAddressId());
+            vos.setUserName(address.getRealName());
+            vos.setUserAddress(address.getProvince() + address.getCity() + address.getDistrict() + address.getDetail());
+            vos.setUserPhone(address.getPhone());
+            vos.setAddressId(address.getAddressId());
+        }
+        vos.setUserId(cartListVoList.get(0).getUserId());
+        vos.setUserIntegral(cartListVoList.get(0).getUserIntegral());
+        vos.setGoodsIntegralTotal(goodsDetailsVos.stream().filter(n -> ObjectUtils.isNotEmpty(n.getGoodsIntegralTotal())).mapToLong(GetCartGoodsDetailsVo::getGoodsIntegralTotal).sum());
+        vos.setGoodsDetailsVoList(goodsDetailsVos);
+        return vos;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addGoodsIntoCart(AddGoodsIntoCartParam param, Long userId) {
+        // 查询现有购物车项
+        FsIntegralCart existingCart = baseMapper.selectOne(Wrappers.<FsIntegralCart>lambdaQuery().eq(FsIntegralCart::getUserId, userId).eq(FsIntegralCart::getGoodsId, param.getGoodsId()));
+        int finalQuantity;
+        // 查询商品最新状态
+        FsIntegralGoods freshGoods = fsIntegralGoodsMapper.selectFsIntegralGoodsByGoodsId(param.getGoodsId());
+        if (freshGoods == null || freshGoods.getStatus() != 1) {
+            try {
+                int deleteCount = baseMapper.delete(Wrappers.<FsIntegralCart>lambdaQuery().eq(FsIntegralCart::getUserId, userId).eq(FsIntegralCart::getGoodsId, param.getGoodsId()));
+                log.info("清除下架商品,userId:{}, goodsId:{},清除数量:{}", userId, param.getGoodsId(), deleteCount);
+            } catch (Exception e) {
+                log.error("清除下架商品失败,userId:{}, goodsId:{}", userId, param.getGoodsId(), e);
+            }
+            throw new ServiceException(String.format("商品[名称:%d]不存在或已下架", freshGoods.getGoodsName()));
+        }
+        int maxAllowed = Math.min((int) freshGoods.getStock().longValue(), 99);
+        if (existingCart != null) {
+            // 先做校验
+            finalQuantity = existingCart.getCartNum() + param.getQuantity();
+            if (finalQuantity > maxAllowed) {
+                if (existingCart.getCartNum() >= maxAllowed) {
+                    throw new ServiceException(String.format("商品已达最大购买数量%d件", maxAllowed));
+                }
+                int canAdd = maxAllowed - existingCart.getCartNum();
+                throw new ServiceException(String.format("最多还能购买%d件", canAdd));
+            }
+            int affectedRows = baseMapper.updateQuantityAtomically(userId, param.getGoodsId(), param.getQuantity(), maxAllowed);
+            if (affectedRows == 0) {
+                throw new ServiceException("添加失败,请重试");
+            }
+            return true;
+        } else {
+            // 新增购物车
+            if (param.getQuantity() > maxAllowed && param.getQuantity() > freshGoods.getStock()) {
+                throw new ServiceException(String.format("最多可购买%d件", freshGoods.getStock()));
+            }
+            try {
+                FsIntegralCart newCart = FsIntegralCart.builder().userId(userId).goodsId(param.getGoodsId()).cartNum(param.getQuantity()).isSelected(param.getIsSelected()).build();
+                return this.save(newCart);
+            } catch (DuplicateKeyException e) {
+                log.info("购物车并发插入,转为更新,userId:{}, goodsId:{}", userId, param.getGoodsId());
+                int affectedRows = baseMapper.updateQuantityAtomically(userId, param.getGoodsId(), param.getQuantity(), maxAllowed);
+                return affectedRows > 0;
+            }
+        }
+    }
+
+    /**
+     * 从购物车生成订单,兑换按钮(走的以前逻辑,没有重新设计)
+     *
+     * @param param
+     * @param userId
+     * @return
+     */
+    @Override
+    public R createOrderFromCart(CreateOrderFromCartParm param, Long userId) {
+        RedissonClient redissonClient = SpringUtils.getBean(RedissonClient.class);
+        String lockKey = "fsIntegralCartOrderCreate:" + userId;
+        RLock lock = redissonClient.getLock(lockKey);
+        try {
+            // 尝试获取锁,最多等待3秒,持有锁时间最多30秒
+            boolean isLocked = lock.tryLock(3, 10, TimeUnit.SECONDS);
+            if (!isLocked) {
+                return R.error("系统繁忙,请稍后再试");
+            }
+            FsUser user = userMapper.selectFsUserByUserId(userId);
+            FsUserAddress address = fsUserAddressMapper.selectFsUserAddressByAddressId(param.getAddressId());
+            List<FsIntegralGoodsVo> fsIntegralGoods = fsIntegralGoodsMapper.selectAllByGoodsIds(new HashSet<>(param.getGoodsId()));
+            List<FsIntegralCart> existingCart = baseMapper.selectList(Wrappers.<FsIntegralCart>lambdaQuery().eq(FsIntegralCart::getUserId, userId).in(FsIntegralCart::getGoodsId, param.getGoodsId()));
+            Map<Long, Integer> collect = existingCart.stream().collect(Collectors.groupingBy(FsIntegralCart::getGoodsId, Collectors.summingInt(FsIntegralCart::getCartNum)));
+            StringBuilder quantity = new StringBuilder();
+            for (FsIntegralGoodsVo fsIntegralGood : fsIntegralGoods) {
+                Integer integer = collect.get(fsIntegralGood.getGoodsId());
+                if (fsIntegralGood.getStock() < integer) {
+                    throw new ServiceException(String.format("%d库存不足,兑换失败", fsIntegralGood.getGoodsName()));
+                }
+                if (fsIntegralGood.getStatus() != 1) {
+                    this.remove(Wrappers.<FsIntegralCart>lambdaQuery().eq(FsIntegralCart::getUserId, userId).eq(FsIntegralCart::getGoodsId, fsIntegralGood.getGoodsId()));
+                    log.info("清除下架商品,userId:{}, goodsId:{}", userId, fsIntegralGood.getGoodsId());
+                    throw new ServiceException(String.format("商品[名称:%d]已下架,兑换失败", fsIntegralGood.getGoodsName()));
+                }
+                fsIntegralGood.setIntegralByNum(integer * fsIntegralGood.getIntegral());
+                fsIntegralGood.setQuantity(integer);
+                if (quantity.length() > 0) {
+                    quantity.append(",");
+                }
+                quantity.append(ObjectUtils.isNotEmpty(integer) ? integer : "0");
+            }
+            // 商品总的积分
+            Long goodsIntegral = fsIntegralGoods.stream().filter(n -> ObjectUtils.isNotEmpty(n.getIntegralByNum())).mapToLong(FsIntegralGoodsVo::getIntegralByNum).sum();
+            if (user.getIntegral() < goodsIntegral) {
+                throw new ServiceException("用户积分不足,兑换失败");
+            }
+            String barCode = fsIntegralGoods.stream().map(FsIntegralGoodsVo::getBarCode).collect(Collectors.joining(","));
+            String Integral = fsIntegralGoods.stream().map(m -> m.getIntegral().toString()).collect(Collectors.joining(","));
+            String orderSn = OrderCodeUtils.getOrderSn();
+            if (StringUtils.isEmpty(orderSn)) {
+                throw new ServiceException("订单生成失败,请重试");
+            }
+            FsIntegralOrder order = new FsIntegralOrder();
+            order.setOrderCode(orderSn);
+            order.setUserId(user.getUserId());
+            order.setStatus(1);
+            order.setBarCodeCart(barCode);
+            order.setIntegral(goodsIntegral.toString());
+            order.setIntegralByCart(Integral);
+            order.setItemCartJson(ObjectUtils.isNotEmpty(fsIntegralGoods) ? JSONUtil.toJsonStr(fsIntegralGoods) : null);
+            order.setUserName(address.getRealName());
+            order.setUserAddress(address.getProvince() + address.getCity() + address.getDistrict() + address.getDetail());
+            order.setUserPhone(address.getPhone());
+            order.setCreateTime(new Date());
+            order.setQuantityCart(quantity.toString());
+            if (fsIntegralOrderMapper.insertFsIntegralOrder(order) > 0) {
+                //写入日志
+                FsUser userMap = new FsUser();
+                userMap.setUserId(user.getUserId());
+                // 可消费积分
+                long consumer = user.getIntegral() - user.getWithdrawIntegral();
+                if (consumer < goodsIntegral) {
+                    // 扣除完可消费积分后,剩余的积分
+                    long extra = goodsIntegral - consumer;
+                    // 可提现积分扣除 剩余积分
+                    Long withdrawIntegral = user.getWithdrawIntegral() - extra;
+                    userMap.setIntegral(withdrawIntegral);
+                    userMap.setWithdrawIntegral(withdrawIntegral);
+                } else {
+                    userMap.setIntegral(user.getIntegral() - goodsIntegral);
+                }
+                userMapper.updateFsUser(userMap);
+                FsUserIntegralLogs logs = new FsUserIntegralLogs();
+                logs.setIntegral(-goodsIntegral);
+                logs.setUserId(order.getUserId());
+                logs.setBalance(userMap.getIntegral());
+                logs.setLogType(5);
+                logs.setBusinessId(order.getOrderId().toString());
+                logs.setCreateTime(new Date());
+                logs.setNickName(user.getNickName());
+                logs.setPhone(user.getPhone());
+                integralLogsService.insertFsUserIntegralLogs(logs);
+                //清空购物车对应商品
+                this.remove(Wrappers.<FsIntegralCart>lambdaQuery().eq(FsIntegralCart::getUserId, userId).in(FsIntegralCart::getGoodsId, param.getGoodsId()));
+                return R.ok("兑换成功").put("order", order);
+            } else {
+                return R.error("订单创建失败");
+            }
+        } catch (Exception e) {
+            return R.error(e.getMessage());
+        } finally {
+            if (lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+    }
 }

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

@@ -4626,4 +4626,9 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
         return fsStoreOrderItemMapper.selectPayPriceByYear(userId);
     }
 
+    @Override
+    public BigDecimal selectPayPriceAll(Long userId){
+        return fsStoreOrderItemMapper.selectPayPriceAll(userId);
+    }
+
 }

+ 257 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserActiveLogServiceImpl.java

@@ -0,0 +1,257 @@
+package com.fs.his.service.impl;
+
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.core.domain.R;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.DateUtils;
+import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserActiveLog;
+import com.fs.his.domain.FsUserIntegralLogs;
+import com.fs.his.dto.ActiveConfigDTO;
+import com.fs.his.mapper.FsUserActiveLogMapper;
+import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.service.IFsStoreOrderService;
+import com.fs.his.service.IFsUserActiveLogService;
+import com.fs.his.service.IFsUserIntegralLogsService;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.service.ISysConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 活动签到记录Service业务层处理
+ *
+ * @author fs
+ * @date 2025-09-23
+ */
+@Service
+public class FsUserActiveLogServiceImpl extends ServiceImpl<FsUserActiveLogMapper, FsUserActiveLog> implements IFsUserActiveLogService {
+    @Autowired
+    private IFsStoreOrderService storeOrderService;
+    @Autowired
+    private ISysConfigService configService;
+    @Autowired
+    private IFsUserIntegralLogsService userIntegralLogsService;
+    @Autowired
+    private FsUserMapper userMapper;
+    @Autowired
+    private FsUserActiveLogMapper userActiveLogMapper;
+    /**
+     * 查询活动签到记录
+     *
+     * @param id 活动签到记录主键
+     * @return 活动签到记录
+     */
+    @Override
+    public FsUserActiveLog selectFsUserActiveLogById(Long id)
+    {
+        return baseMapper.selectFsUserActiveLogById(id);
+    }
+
+    /**
+     * 查询活动签到记录列表
+     *
+     * @param fsUserActiveLog 活动签到记录
+     * @return 活动签到记录
+     */
+    @Override
+    public List<FsUserActiveLog> selectFsUserActiveLogList(FsUserActiveLog fsUserActiveLog)
+    {
+        return baseMapper.selectFsUserActiveLogList(fsUserActiveLog);
+    }
+
+    /**
+     * 新增活动签到记录
+     *
+     * @param fsUserActiveLog 活动签到记录
+     * @return 结果
+     */
+    @Override
+    public int insertFsUserActiveLog(FsUserActiveLog fsUserActiveLog)
+    {
+        fsUserActiveLog.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsUserActiveLog(fsUserActiveLog);
+    }
+
+    /**
+     * 修改活动签到记录
+     *
+     * @param fsUserActiveLog 活动签到记录
+     * @return 结果
+     */
+    @Override
+    public int updateFsUserActiveLog(FsUserActiveLog fsUserActiveLog)
+    {
+        fsUserActiveLog.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateFsUserActiveLog(fsUserActiveLog);
+    }
+
+    /**
+     * 批量删除活动签到记录
+     *
+     * @param ids 需要删除的活动签到记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserActiveLogByIds(Long[] ids)
+    {
+        return baseMapper.deleteFsUserActiveLogByIds(ids);
+    }
+
+    /**
+     * 删除活动签到记录信息
+     *
+     * @param id 活动签到记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserActiveLogById(Long id)
+    {
+        return baseMapper.deleteFsUserActiveLogById(id);
+    }
+
+    @Transactional
+    @Override
+    public Long userActiveLogSign(FsUser fsUser) {
+        //获取活动配置
+        SysConfig sysConfig= configService.selectConfigByConfigKey("active.config");
+        ActiveConfigDTO activeConfigDTO = JSONUtil.toBean(sysConfig.getConfigValue(), ActiveConfigDTO.class);
+        if ("0".equals(activeConfigDTO.getIsOpen())){
+            throw new CustomException("活动未开启");
+        }
+        // 判断今天是否在活动期间
+        LocalDate today = LocalDate.now();
+        if (today.isBefore(activeConfigDTO.getActiveStartTime())
+                || today.isAfter(activeConfigDTO.getActiveEndTime())) {
+            throw new CustomException("当前不在活动期间");
+        }
+        //查询用户消费额是否满足活动要求
+        BigDecimal totalPay = storeOrderService.selectPayPriceAll(fsUser.getUserId());
+        if (totalPay == null || totalPay.compareTo(activeConfigDTO.getMoneyTerm()) < 0) {
+            throw new CustomException("总消费金额未达到参与活动条件");
+        }
+        FsUserActiveLog userActiveLog = userActiveLogMapper.selectTodayIsSign(fsUser.getUserId());
+        if (userActiveLog!=null){
+            throw new CustomException("您今天已经领取过了");
+        }
+        //写入积分记录和活动记录表
+        FsUserActiveLog fsUserActiveLog = new FsUserActiveLog();
+        fsUserActiveLog.setActiveName(activeConfigDTO.getActiveName());
+        fsUserActiveLog.setTitle("活动奖励");
+        fsUserActiveLog.setNumber(activeConfigDTO.getActiveReward());
+        fsUserActiveLog.setBalance(fsUser.getIntegral());
+        fsUserActiveLog.setUserId(fsUser.getUserId());
+        fsUserActiveLog.setCreateTime(new Date());
+        baseMapper.insertFsUserActiveLog(fsUserActiveLog);
+        FsUserIntegralLogs logs = new FsUserIntegralLogs();
+        logs.setIntegral(activeConfigDTO.getActiveReward());
+        //logs.setBusinessType(fsUserActiveLog);
+        logs.setUserId(fsUser.getUserId());
+        logs.setBalance(fsUser.getIntegral());
+        logs.setLogType(25);
+        logs.setBusinessId(fsUserActiveLog.getId().toString());
+        logs.setCreateTime(new Date());
+        logs.setNickName(fsUser.getNickName());
+        logs.setPhone(fsUser.getPhone());
+        userIntegralLogsService.insertFsUserIntegralLogs(logs);
+        //用户积分增加
+        FsUser userMap =new  FsUser();
+        userMap.setIntegral(fsUser.getIntegral()+activeConfigDTO.getActiveReward());
+        userMap.setUserId(fsUser.getUserId());
+        //userMap.setSignNum(userSignNum);
+        Integer res =userMapper.updateFsUser(userMap);
+        if(res==0) {
+            throw new CustomException("签到失败");
+        }
+        return activeConfigDTO.getActiveReward();
+    }
+
+    @Override
+    public R getUserActiveLog(FsUser fsUser) {
+        SysConfig sysConfig = configService.selectConfigByConfigKey("active.config");
+        ActiveConfigDTO activeConfigDTO = JSONUtil.toBean(sysConfig.getConfigValue(), ActiveConfigDTO.class);
+
+        LocalDate start = activeConfigDTO.getActiveStartTime();
+        LocalDate end = activeConfigDTO.getActiveEndTime();
+
+        // 查询用户在活动期间的签到记录
+        List<FsUserActiveLog> logs = userActiveLogMapper.selectByUserAndDateRange(
+                fsUser.getUserId(),
+                LocalDateTime.of(start, LocalTime.MIN),
+                LocalDateTime.of(end, LocalTime.MAX)
+        );
+
+        // 转成 map,key=日期字符串,value=签到记录
+        Map<String, FsUserActiveLog> logMap = logs.stream()
+                .collect(Collectors.toMap(
+                        l -> l.getCreateTime().toInstant()
+                                .atZone(ZoneId.systemDefault())
+                                .toLocalDate()
+                                .toString(),
+                        Function.identity(),
+                        (a, b) -> a
+                ));
+
+        // 每天的签到状态
+        DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("d");
+        List<Map<String, Object>> days = new ArrayList<>();
+        for (LocalDate d = start; !d.isAfter(end); d = d.plusDays(1)) {
+            FsUserActiveLog log = logMap.get(d.toString());
+            Map<String, Object> day = new HashMap<>();
+            day.put("date",  d.format(dayFormatter));
+            day.put("isSign", log != null);
+            day.put("number", log != null&&log.getNumber()!=null ? log.getNumber() : activeConfigDTO.getActiveReward());
+            day.put("title", log != null ? log.getTitle() : "");
+            days.add(day);
+        }
+
+        Map<String, Object> result = new HashMap<>();
+        result.put("activeName", activeConfigDTO.getActiveName());
+        result.put("activeStartTime", start);
+        result.put("activeEndTime", end);
+        result.put("days", days);
+
+        return R.ok(result);
+    }
+
+    @Override
+    public boolean getUserActiveWindow(FsUser fsUser) {
+        //获取活动配置
+        SysConfig sysConfig= configService.selectConfigByConfigKey("active.config");
+        ActiveConfigDTO activeConfigDTO = JSONUtil.toBean(sysConfig.getConfigValue(), ActiveConfigDTO.class);
+        if ("0".equals(activeConfigDTO.getIsOpen())){
+            return false;
+        }
+        // 判断今天是否在活动期间
+        LocalDate today = LocalDate.now();
+        if (today.isBefore(activeConfigDTO.getActiveStartTime())
+                || today.isAfter(activeConfigDTO.getActiveEndTime())) {
+            return false;
+        }
+        //查询用户消费额是否满足活动要求
+        BigDecimal totalPay = storeOrderService.selectPayPriceAll(fsUser.getUserId());
+        if (totalPay == null || totalPay.compareTo(activeConfigDTO.getMoneyTerm()) < 0) {
+            return false;
+        }
+        //查询用户当天是否签到过
+        FsUserActiveLog userActiveLog = userActiveLogMapper.selectTodayIsSign(fsUser.getUserId());
+        if (userActiveLog!=null){
+            return false;
+        }
+        return true;
+    }
+
+
+}

+ 50 - 0
fs-service/src/main/java/com/fs/his/vo/FsIntegralGoodsVo.java

@@ -0,0 +1,50 @@
+package com.fs.his.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class FsIntegralGoodsVo {
+    private Long goodsId;
+
+    @ApiModelProperty("封面图")
+    private String imgUrl;
+
+    @ApiModelProperty("组图")
+    private String images;
+
+    @ApiModelProperty("商品名称")
+    private String goodsName;
+
+    @ApiModelProperty("原价")
+    private BigDecimal otPrice;
+
+    @ApiModelProperty("商品分类")
+    private Long goodsType;
+
+    @ApiModelProperty("状态")
+    private Long status;
+
+    @ApiModelProperty("单个商品积分")
+    private Long integral;
+
+    @ApiModelProperty("排序")
+    private Long sort;
+
+    @ApiModelProperty("库存")
+    private Long stock;
+
+    @ApiModelProperty("详情")
+    private String descs;
+
+    @ApiModelProperty("产品编码")
+    private String barCode;
+
+    @ApiModelProperty("加上数量的商品积分")
+    private Long integralByNum;
+
+    @ApiModelProperty("商品数量")
+    private Integer quantity;
+}

+ 43 - 0
fs-service/src/main/java/com/fs/his/vo/GetCartGoodsDetailsVo.java

@@ -0,0 +1,43 @@
+package com.fs.his.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class GetCartGoodsDetailsVo {
+    @ApiModelProperty("购物车ID")
+    private Long cartId;
+
+    @ApiModelProperty("商品id")
+    private Long goodsId;
+
+    @ApiModelProperty("封面图")
+    private String imgUrl;
+
+    @ApiModelProperty("组图")
+    private String images;
+
+    @ApiModelProperty("商品名称")
+    private String goodsName;
+
+    @ApiModelProperty("状态")
+    private Long status;
+
+    @ApiModelProperty("商品所需积分")
+    private Long goodsIntegral;
+
+    @ApiModelProperty("详情")
+    private String descs;
+
+    @ApiModelProperty("商品数量")
+    private Integer quantity;
+
+    @ApiModelProperty("是否选中:1是,0否")
+    private Integer isSelected;
+
+    @ApiModelProperty("创建时间(加入购物车时间)")
+    private String createTime;
+
+    @ApiModelProperty("商品所需积分之和")
+    private Long goodsIntegralTotal;
+}

+ 37 - 0
fs-service/src/main/java/com/fs/his/vo/GetFsIntegralCartDetailsVo.java

@@ -0,0 +1,37 @@
+package com.fs.his.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class GetFsIntegralCartDetailsVo {
+
+    @ApiModelProperty("地址id")
+    private Long addressId;
+
+    @ApiModelProperty("用户id")
+    private Long userId;
+
+    @ApiModelProperty("用户名称")
+    private String userName;
+
+    @ApiModelProperty("用户电话")
+    private String userPhone;
+
+    @ApiModelProperty("用户地址")
+    private String userAddress;
+
+    @ApiModelProperty("所有商品所需积分之和")
+    private Long goodsIntegralTotal;
+
+    @ApiModelProperty("用户的芳华币总数")
+    private BigDecimal userIntegral;
+
+    @ApiModelProperty("商品信息")
+    private List<GetCartGoodsDetailsVo> goodsDetailsVoList;
+
+
+}

+ 63 - 0
fs-service/src/main/java/com/fs/his/vo/GetFsIntegralCartListVo.java

@@ -0,0 +1,63 @@
+package com.fs.his.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class GetFsIntegralCartListVo {
+    @ApiModelProperty("主键ID")
+    private Long cartId;
+
+    @ApiModelProperty("用户ID")
+    private Long userId;
+
+    @ApiModelProperty("积分商品ID")
+    private Long goodsId;
+
+    @ApiModelProperty("封面图")
+    private String imgUrl;
+
+    @ApiModelProperty("组图")
+    private String images;
+
+    @ApiModelProperty("商品名称")
+    private String goodsName;
+
+    @ApiModelProperty("原价")
+    private BigDecimal otPrice;
+
+    @ApiModelProperty("商品分类")
+    private Long goodsType;
+
+    @ApiModelProperty("状态")
+    private Long status;
+
+    @ApiModelProperty("商品所需积分")
+    private Long goodsIntegral;
+
+    @ApiModelProperty("库存")
+    private Long stock;
+
+    @ApiModelProperty("详情")
+    private String descs;
+
+    @ApiModelProperty("产品编码")
+    private String barCode;
+
+    @ApiModelProperty("商品数量")
+    private Integer quantity;
+
+    @ApiModelProperty("用户的芳华币总数")
+    private BigDecimal userIntegral;
+
+    @ApiModelProperty("是否选中:1是,0否")
+    private Integer isSelected;
+
+    @ApiModelProperty("创建时间(加入购物车时间)")
+    private String createTime;
+
+    @ApiModelProperty("更新时间")
+    private String updateTime;
+}

+ 31 - 3
fs-service/src/main/resources/mapper/his/FsIntegralCartMapper.xml

@@ -12,7 +12,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             cash,
             cart_num,
             create_time,
-            update_time
+            update_time,
+            is_selected
         ) values (
             #{userId},
             #{goodsId},
@@ -20,7 +21,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{cash},
             #{cartNum},
             #{createTime},
-            #{updateTime}
+            #{updateTime},
+            #{isSelected}
         )
         on duplicate key update
             integral = values(integral),
@@ -36,6 +38,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 </otherwise>
             </choose>
     </insert>
+    <update id="updateQuantityAtomically">
+        UPDATE fs_integral_cart
+        SET quantity = LEAST(quantity + #{addQuantity}, #{maxQuantity}),
+            is_selected = 1,
+            update_time = NOW()
+        WHERE user_id = #{userId} AND goods_id = #{goodsId} AND quantity <![CDATA[<]]> #{maxQuantity}
+    </update>
 
     <select id="getCartCountByMap" resultType="java.lang.Integer">
         select
@@ -65,7 +74,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             ig.stock,
             ic.cart_num,
             ic.create_time,
-            ic.update_time
+            ic.update_time,
+            ic.is_selected
         from fs_integral_cart ic
         inner join fs_integral_goods ig on ig.goods_id = ic.goods_id
         <where>
@@ -80,6 +90,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             </if>
         </where>
     </select>
+    <select id="getFsIntegralCartList" resultType="com.fs.his.vo.GetFsIntegralCartListVo">
+        select fc.*,fg.*,fg.integral as goodsIntegral,fu.integral as userIntegral
+        from fs_integral_cart fc
+        left join fs_integral_goods fg on fc.goods_id = fg.goods_id
+        left join fs_user fu on fu.user_id = fc.user_id
+        <where>
+            <if test="aLong != null">
+                fc.user_id = #{aLong}
+            </if>
+            <if test="param.goodsName != null and param.goodsName != ''">
+                and fg.goods_name like concat('%', #{param.goodsName}, '%')
+            </if>
+            <if test="cartId != null and cartId.size() > 0">
+                and fc.cart_id in
+                <foreach collection="cartId" item="cartId" open="(" close=")" separator=",">#{cartId}</foreach>
+            </if>
+        </where>
+    </select>
 
     <delete id="deleteCartByGoodsId">
         delete from fs_integral_cart where goods_id = #{goodsId}

+ 6 - 0
fs-service/src/main/resources/mapper/his/FsIntegralGoodsMapper.xml

@@ -173,4 +173,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{goodsId}
         </foreach>
     </select>
+    <select id="selectAllByGoodsIds" resultType="com.fs.his.vo.FsIntegralGoodsVo">
+        select * from fs_integral_goods where goods_id in
+        <foreach item="goodsIds" collection="goodsIds" open="(" separator="," close=")">
+            #{goodsIds}
+        </foreach>
+    </select>
 </mapper>

+ 6 - 0
fs-service/src/main/resources/mapper/his/FsStoreOrderItemMapper.xml

@@ -55,6 +55,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         AND pay_time >= CONCAT(YEAR(CURDATE()), '-01-01')
         AND pay_time &lt; DATE_ADD(CONCAT(YEAR(CURDATE()), '-01-01'), INTERVAL 1 YEAR);
     </select>
+    <select id="selectPayPriceAll" resultType="java.math.BigDecimal">
+        SELECT SUM(pay_price) AS total_pay
+        FROM fs_store_order
+        WHERE status != 1 and status != -2
+          AND user_id = #{userId}
+    </select>
 
     <insert id="insertFsStoreOrderItem" parameterType="FsStoreOrderItem" useGeneratedKeys="true" keyProperty="itemId">
         insert into fs_store_order_item

+ 100 - 0
fs-service/src/main/resources/mapper/his/FsUserActiveLogMapper.xml

@@ -0,0 +1,100 @@
+<?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.fs.his.mapper.FsUserActiveLogMapper">
+
+    <resultMap type="FsUserActiveLog" id="FsUserActiveLogResult">
+        <result property="id"    column="id"    />
+        <result property="activeName"    column="active_name"    />
+        <result property="userId"    column="user_id"    />
+        <result property="number"    column="number"    />
+        <result property="balance"    column="balance"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="title"    column="title"    />
+    </resultMap>
+
+    <sql id="selectFsUserActiveLogVo">
+        select id, active_name, user_id, number, balance, create_time, update_time, title from fs_user_active_log
+    </sql>
+
+    <select id="selectFsUserActiveLogList" parameterType="FsUserActiveLog" resultMap="FsUserActiveLogResult">
+        <include refid="selectFsUserActiveLogVo"/>
+        <where>
+            <if test="activeName != null  and activeName != ''"> and active_name like concat('%', #{activeName}, '%')</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="number != null "> and number = #{number}</if>
+            <if test="balance != null "> and balance = #{balance}</if>
+            <if test="title != null  and title != ''"> and title = #{title}</if>
+        </where>
+    </select>
+
+    <select id="selectFsUserActiveLogById" parameterType="Long" resultMap="FsUserActiveLogResult">
+        <include refid="selectFsUserActiveLogVo"/>
+        where id = #{id}
+    </select>
+    <select id="selectTodayIsSign" resultType="com.fs.his.domain.FsUserActiveLog">
+        SELECT *
+        FROM fs_user_active_log
+        WHERE user_id = #{userId}
+          AND DATE(create_time) = CURDATE();
+    </select>
+    <select id="selectByUserAndDateRange" resultType="com.fs.his.domain.FsUserActiveLog">
+        SELECT *
+        FROM fs_user_active_log
+        WHERE user_id = #{userId}
+        AND create_time &gt;= #{startTime}
+        AND create_time &lt; #{endTime} + INTERVAL 1 DAY;
+
+    </select>
+
+    <insert id="insertFsUserActiveLog" parameterType="FsUserActiveLog">
+        insert into fs_user_active_log
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="activeName != null">active_name,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="number != null">number,</if>
+            <if test="balance != null">balance,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="title != null and title != ''">title,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="activeName != null">#{activeName},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="number != null">#{number},</if>
+            <if test="balance != null">#{balance},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="title != null and title != ''">#{title},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFsUserActiveLog" parameterType="FsUserActiveLog">
+        update fs_user_active_log
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="activeName != null">active_name = #{activeName},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="number != null">number = #{number},</if>
+            <if test="balance != null">balance = #{balance},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="title != null and title != ''">title = #{title},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFsUserActiveLogById" parameterType="Long">
+        delete from fs_user_active_log where id = #{id}
+    </delete>
+
+    <delete id="deleteFsUserActiveLogByIds" parameterType="String">
+        delete from fs_user_active_log where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 7 - 0
fs-service/src/main/resources/mapper/his/InterestAiChatSessionMapper.xml

@@ -136,6 +136,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         inner join fs_interest_ai_role t3 on t3.role_id = t2.role_id
         where t2.session_id = #{sessionId}
     </select>
+    <select id="selectSessionIdByUserAndRole" resultType="java.lang.Integer">
+        select session_id from fs_interest_ai_session where user_id = #{userId} and role_id = #{roleId} limit 1
+    </select>
+    <select id="selectAiMsgBySessionIdAndMsg" resultType="java.lang.Integer">
+         <![CDATA[ select count(1) from fs_interest_ai_msg where session_id = #{sessionId} and content = #{message}
+                                                             and begin_time = #{beginTime}]]>
+    </select>
 
     <insert id="insertFsInterestAiSession" parameterType="FsInterestAiSession" useGeneratedKeys="true" keyProperty="sessionId">
         insert into fs_interest_ai_session

+ 9 - 0
fs-user-app/src/main/java/com/fs/app/controller/CommonController.java

@@ -41,6 +41,7 @@ import com.fs.event.TemplateEvent;
 import com.fs.event.TemplateListenEnum;
 import com.fs.event.WeixinTemplateService;
 import com.fs.framework.config.ServerConfig;
+import com.fs.his.config.AppPageConfig;
 import com.fs.his.config.FsSmsConfig;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
@@ -728,4 +729,12 @@ public class CommonController {
 	public R exchangDetail(@RequestBody Map<String,Object> params){
 		return userService.exchangDetail(params);
 	}
+
+	@ApiOperation("获取ios支付开关")
+	@GetMapping("/getAppPageConfig")
+	public R getAppPageConfig(){
+		String json = configService.selectConfigByKey("app.pageConfig");
+		AppPageConfig config = JSONUtil.toBean(json, AppPageConfig.class);
+		return R.ok().put("appPageConfig",config);
+	}
 }

+ 98 - 0
fs-user-app/src/main/java/com/fs/app/controller/FsIntegralCartController.java

@@ -0,0 +1,98 @@
+package com.fs.app.controller;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.app.annotation.Login;
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsIntegralCart;
+import com.fs.his.param.AddGoodsIntoCartParam;
+import com.fs.his.param.CreateOrderFromCartParm;
+import com.fs.his.param.GetFsIntegralCartDetailsParm;
+import com.fs.his.param.GetFsIntegralCartListParam;
+import com.fs.his.service.IFsIntegralCartService;
+import com.fs.his.vo.GetFsIntegralCartDetailsVo;
+import com.fs.his.vo.GetFsIntegralCartListVo;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 积分购物车表 前端控制器
+ * </p>
+ *
+ * @author chenshiyi
+ * @since 2026-01-13
+ */
+@RestController
+@RequestMapping("/app/integralCart")
+public class FsIntegralCartController extends AppBaseController {
+
+    @Autowired
+    private IFsIntegralCartService fsIntegralCartService;
+
+
+    @Login
+    @ApiOperation("获取用户购物车列表")
+    @PostMapping("/getFsIntegralCartList")
+    public R getFsIntegralCartList(@RequestBody GetFsIntegralCartListParam param) {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        Long aLong = Long.valueOf(getUserId());
+        List<GetFsIntegralCartListVo> list = fsIntegralCartService.getFsIntegralCartList(param, aLong);
+        PageInfo<GetFsIntegralCartListVo> listPageInfo = new PageInfo<>(list);
+        return R.ok().put("data", listPageInfo);
+    }
+
+    @Login
+    @ApiOperation("获取用户购物车详情页")
+    @PostMapping("/getFsIntegralCartDetails")
+    public R getFsIntegralCartDetails(@RequestBody GetFsIntegralCartDetailsParm param) {
+        Long userId = Long.valueOf(getUserId());
+        GetFsIntegralCartDetailsVo list = fsIntegralCartService.getFsIntegralCartDetails(param, userId);
+        return R.ok().put("data", list);
+    }
+
+    @Login
+    @ApiOperation("添加商品到购物车")
+    @PostMapping("/addGoodsIntoCart")
+    public R addGoodsIntoCart(@RequestBody AddGoodsIntoCartParam param) {
+        Long aLong = Long.valueOf(getUserId());
+        Boolean b = fsIntegralCartService.addGoodsIntoCart(param, aLong);
+        return b ? R.ok("添加商品成功") : R.error("添加商品失败");
+    }
+
+
+    @Login
+    @ApiOperation("修改购物车商品数量")
+    @PutMapping("/putGoodsQuantityFromCart")
+    public R putGoodsQuantityFromCart(@RequestParam Integer quantity, @RequestParam Long cartId) {
+        Long aLong = Long.valueOf(getUserId());
+        FsIntegralCart cart = FsIntegralCart.builder().id(cartId).cartNum(quantity).build();
+        Boolean b = fsIntegralCartService.update(cart, Wrappers.<FsIntegralCart>lambdaQuery().eq(FsIntegralCart::getUserId, aLong).eq(FsIntegralCart::getId, cartId));
+        return b ? R.ok("修改商品成功") : R.error("修改商品失败");
+    }
+
+
+    @Login
+    @ApiOperation("删除购物车商品")
+    @DeleteMapping("/deleteGoodsFromCart/{cartIds}")
+    public R deleteGoodsFromCart(@PathVariable List<Long> cartIds) {
+        Long aLong = Long.valueOf(getUserId());
+        Boolean b = fsIntegralCartService.remove(Wrappers.<FsIntegralCart>lambdaQuery().eq(FsIntegralCart::getUserId, aLong).in(FsIntegralCart::getId, cartIds));
+        return b ? R.ok("删除商品成功") : R.error("删除商品失败");
+    }
+
+
+    @Login
+    @RepeatSubmit
+    @ApiOperation("从购物车生成订单(兑换按钮)")
+    @PostMapping("/createOrderFromCart")
+    public R createOrderFromCart(@RequestBody CreateOrderFromCartParm param) {
+        Long aLong = Long.valueOf(getUserId());
+        return fsIntegralCartService.createOrderFromCart(param, aLong);
+    }
+}

+ 35 - 0
fs-user-app/src/main/java/com/fs/app/controller/aiChat/controller/AiDoctorController.java

@@ -0,0 +1,35 @@
+package com.fs.app.controller.aiChat.controller;
+
+import com.fs.aiChat.domain.DoctorAiChatMsg;
+import com.fs.aiChat.vo.DoctorAiVO;
+import com.fs.common.core.domain.R;
+import com.fs.his.service.IHisDoctorAiChatSessionService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+@RequestMapping(value="/app/aiDoctor")
+@Api(tags = "AI医生")
+public class AiDoctorController {
+    @Autowired
+    private IHisDoctorAiChatSessionService doctorAiChatSessionService;
+    @ApiOperation(value = "历史会话")
+    @PostMapping("/chatListByUser")
+    public R chatListByUser(DoctorAiVO doctorAiVO) {
+        List<DoctorAiChatMsg> doctorAiChatMsgs = doctorAiChatSessionService.selectDoctorAiChatSessionListByUser(doctorAiVO);
+        return R.ok().put("data", doctorAiChatMsgs);
+    }
+
+//    @ApiOperation(value = "AI医生列表")
+//    @PostMapping("/doctorList")
+//    public R chatByUser(DoctorAiVO doctorAiVO) {
+//        String chat = doctorAiChatSessionService.chatByUser(doctorAiVO);
+//        return R.ok().put("data", chat);
+//    }
+}

+ 121 - 0
fs-user-app/src/main/java/com/fs/app/controller/aiChat/controller/InterestAiController.java

@@ -0,0 +1,121 @@
+package com.fs.app.controller.aiChat.controller;
+
+import com.fs.aiChat.domain.InterestAiChatMsg;
+import com.fs.aiChat.domain.InterestAiSession;
+import com.fs.aiChat.domain.SessionRoleInfo;
+import com.fs.aiChat.mapper.InterestAiChatSessionMapper;
+import com.fs.aiChat.param.InterestAiMessage;
+import com.fs.app.controller.AppBaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.his.domain.FsInterestAiSession;
+import com.fs.his.service.IHisInterestAiChatSessionService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+@RestController
+@RequestMapping(value = "/app/fsInterestAi")
+@Api(tags = "兴趣AI")
+public class InterestAiController extends AppBaseController {
+
+    @Autowired
+    private IHisInterestAiChatSessionService interestAiChatSessionService;
+
+    @Autowired
+    InterestAiChatSessionMapper interestAiChatSessionMapper;
+
+    /**
+     * 创建会话
+     *
+     * @param fsInterestAiSession
+     * @return
+     */
+    @PostMapping("/createSession")
+    @ApiOperation(value = "创建会话")
+    public R createSession(@RequestBody FsInterestAiSession fsInterestAiSession) {
+        FsInterestAiSession session = interestAiChatSessionService.createSession(fsInterestAiSession);
+        return R.ok().put("data", session);
+    }
+
+    /**
+     * 根据当前用户获取用户与所有AI角色的会话列表
+     *
+     * @param session
+     * @return
+     */
+    @GetMapping(value = "/getAllRolesListByUserId")
+    @ApiOperation(value = "根据当前用户获取用户的会话列表")
+    public R getAllRolesListByUserId(InterestAiSession session) {
+        String userId = getUserId();
+        log.info("拿到userId" + userId);
+        if (null != session && session.getUserId() == null) {
+            session.setUserId(Long.valueOf(userId));
+        }
+        startPage();
+        List<InterestAiSession> list = interestAiChatSessionService.getAllRolesListByUserId(session);
+        return R.ok().put("data", list);
+    }
+
+    /**
+     * 根据会话id获取会话的详细信息
+     *
+     * @param sessionId
+     * @return
+     */
+    @GetMapping(value = "/getSessionDetailInfoBySessionIdAndRoleId/{sessionId}/{roleId}")
+    @ApiOperation(value = "根据会话id获取会话的详细信息")
+    public R getSessionDetailInfoBySessionIdAndRoleId(@PathVariable(name = "sessionId") String sessionId,
+                                                      @PathVariable(name = "roleId") Long roleId) {
+
+
+        List<InterestAiChatMsg> chatList = new ArrayList<>();
+        SessionRoleInfo roleInfo = null;
+        if (null != roleId) {
+            roleInfo = interestAiChatSessionService.getSessionRoleInfoByRoleId(roleId);
+        }
+
+        if (StringUtils.isNotBlank(sessionId)) {
+            chatList = interestAiChatSessionService.getSessionChatList(sessionId);
+        }
+        return R.ok().put("roleInfo", roleInfo).put("chatList", chatList);
+    }
+
+    /**
+     * 获取推荐角色列表
+     *
+     * @return
+     */
+    @GetMapping(value = "/getRecommendRoleList")
+    @ApiOperation(value = "获取推荐角色列表")
+    public R getRecommendRoleList() {
+        String userId = getUserId();
+        List<SessionRoleInfo> roleList = interestAiChatSessionService.getRecommendRoleList(userId);
+        return R.ok().put("list", roleList);
+    }
+
+    @PostMapping(value = "/getAiJsonMsgCount")
+    @ApiOperation(value = "获取推荐角色列表")
+    public R getAiJsonMsgCount(@RequestBody InterestAiMessage message) {
+        Integer sessionId = interestAiChatSessionMapper.selectSessionIdByUserAndRole(message.getUserId(),message.getRoleId().intValue());
+        if (null == sessionId) {
+            return R.ok().put("count", 0);
+        }else{
+            message.setSessionId(Long.valueOf(sessionId));
+            Date time = message.getStartTime();
+            String dateString = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, time);
+            message.setBeginTime(dateString);
+            int count = interestAiChatSessionMapper.selectAiMsgBySessionIdAndMsg(message);
+            return R.ok().put("count", count);
+        }
+    }
+
+}