Просмотр исходного кода

积分商品添加运费模板,积分任务修改

yuhongqi 1 неделя назад
Родитель
Сommit
5d51fe2fb6
23 измененных файлов с 372 добавлено и 43 удалено
  1. 26 4
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  2. 2 1
      fs-service/src/main/java/com/fs/course/vo/CourseStatisticsUserDetailVO.java
  3. 7 1
      fs-service/src/main/java/com/fs/his/config/IntegralConfig.java
  4. 1 0
      fs-service/src/main/java/com/fs/his/constant/IntegralTaskConstants.java
  5. 3 0
      fs-service/src/main/java/com/fs/his/domain/FsIntegralGoods.java
  6. 2 0
      fs-service/src/main/java/com/fs/his/enums/FsUserIntegralLogTypeEnum.java
  7. 13 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralCartServiceImpl.java
  8. 20 1
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java
  9. 13 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserIntegralLogsServiceImpl.java
  10. 6 1
      fs-service/src/main/java/com/fs/his/service/impl/IntegralTaskServiceImpl.java
  11. 9 0
      fs-service/src/main/java/com/fs/his/utils/IntegralConfigHelper.java
  12. 126 0
      fs-service/src/main/java/com/fs/his/utils/IntegralShippingRegionValidator.java
  13. 3 1
      fs-service/src/main/java/com/fs/his/utils/IntegralTaskScopeHelper.java
  14. 3 0
      fs-service/src/main/java/com/fs/his/vo/FsIntegralGoodsVo.java
  15. 4 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderParam.java
  16. 70 28
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  17. 1 1
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderVO.java
  18. 17 0
      fs-service/src/main/resources/db/changelog/changes/20260613-live-user-add-is-del.sql
  19. 20 0
      fs-service/src/main/resources/db/changelog/dictData/dict_data_update.sql
  20. 1 0
      fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  21. 5 1
      fs-service/src/main/resources/mapper/his/FsIntegralGoodsMapper.xml
  22. 11 4
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  23. 9 0
      fs-user-app/src/main/java/com/fs/app/controller/IntegralController.java

+ 26 - 4
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -55,6 +55,7 @@ import com.fs.course.vo.*;
 import com.fs.course.vo.newfs.*;
 import com.fs.enums.ExceptionCodeEnum;
 import com.fs.his.config.AppConfig;
+import com.fs.his.config.IntegralConfig;
 import com.fs.his.domain.*;
 import com.fs.his.mapper.FsCouponMapper;
 import com.fs.his.mapper.FsUserCouponMapper;
@@ -66,6 +67,7 @@ import com.fs.his.service.IFsUserIntegralLogsService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.service.IFsUserWxService;
 import com.fs.his.utils.ConfigUtil;
+import com.fs.his.utils.IntegralConfigHelper;
 import com.fs.his.vo.OptionsVO;
 import com.fs.hisStore.domain.FsStoreProductScrm;
 import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
@@ -2537,15 +2539,19 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
      * @return 处理结果
      */
     private R sendIntegralReward(FsCourseSendRewardUParam param, FsUser user, FsCourseWatchLog log, CourseConfig config) {
+        Integer answerIntegral = resolveFinishCourseIntegral(param.getVideoId(), config);
+        if (answerIntegral == null || answerIntegral <= 0) {
+            return R.error("完课积分未配置");
+        }
         // 更新用户积分
         FsUser userMap = new FsUser();
         userMap.setUserId(user.getUserId());
-        userMap.setIntegral(user.getIntegral() + config.getAnswerIntegral());
+        userMap.setIntegral(user.getIntegral() + answerIntegral);
         fsUserMapper.updateFsUser(userMap);
 
         // 记录积分日志
         FsUserIntegralLogs integralLogs = new FsUserIntegralLogs();
-        integralLogs.setIntegral(config.getAnswerIntegral().longValue());
+        integralLogs.setIntegral(answerIntegral.longValue());
         integralLogs.setUserId(user.getUserId());
         integralLogs.setBalance(userMap.getIntegral());
         integralLogs.setLogType(17);
@@ -2556,7 +2562,7 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         //更新看课记录的奖励类型
         log.setRewardType(config.getRewardType());
         courseWatchLogMapper.updateFsCourseWatchLog(log);
-        logger.info("发放奖励====================》看课记录,{}", log);
+        logger.info("发放奖励====================》看课记录,{}, integral={}", log, answerIntegral);
 
         // 红德堂不要积分转红包
         if (CloudHostUtils.hasCloudHostName("弘德堂") || CloudHostUtils.hasCloudHostName("恒春来")) {
@@ -2574,7 +2580,7 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
         redPacketLog.setCompanyUserId(param.getCompanyUserId());
         redPacketLog.setCreateTime(new Date());
-        redPacketLog.setAmount(BigDecimal.valueOf(config.getAnswerIntegral()).divide(BigDecimal.valueOf(1000)));
+        redPacketLog.setAmount(BigDecimal.valueOf(answerIntegral).divide(BigDecimal.valueOf(1000)));
         redPacketLog.setRemark("点播答题领取积分转");
         redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
         redPacketLog.setPeriodId(param.getPeriodId());
@@ -2582,6 +2588,22 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         return R.ok("积分奖励发放成功").put("rewardType", config.getRewardType());
     }
 
+    /**
+     * 完课/答题积分:关联商品(转化素材)用 integralCommentProduct,未关联用 integralComment(后台完课评价积分)。
+     */
+    private Integer resolveFinishCourseIntegral(Long videoId, CourseConfig config) {
+        IntegralConfig integralConfig = IntegralConfigHelper.load(configService);
+        FsUserCourseVideo video = videoId == null ? null
+                : fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
+        if (video != null && Integer.valueOf(1).equals(video.getIsProduct())) {
+            return integralConfig.getIntegralCommentProduct();
+        }
+        if (integralConfig.getIntegralComment() != null) {
+            return integralConfig.getIntegralComment();
+        }
+        return config != null ? config.getAnswerIntegral() : null;
+    }
+
     @Override
     public List<FsUserCourseVideoPageListVO> pageListCourseVideo(UserCourseVideoPageParam param) {
         List<FsUserCourseVideoPageListVO> courseVideoPageListVOList = fsUserCourseVideoMapper.selectFsUserCourseVideoPageList(param);

+ 2 - 1
fs-service/src/main/java/com/fs/course/vo/CourseStatisticsUserDetailVO.java

@@ -15,7 +15,8 @@ import java.math.BigDecimal;
 @Data
 public class CourseStatisticsUserDetailVO implements Serializable {
     private static final long serialVersionUID = 1L;
-    /** 用户ID */
+    /** 会员ID(fs_user.user_id) */
+    @Excel(name = "会员ID")
     private Long userId;
     @Excel(name = "用户名称")
     private String userName;

+ 7 - 1
fs-service/src/main/java/com/fs/his/config/IntegralConfig.java

@@ -36,14 +36,20 @@ public class IntegralConfig implements Serializable {
     private Integer integralInviteDailyLimit;
     /** 分享单日上限次数(APP+小程序合计) */
     private Integer integralShareDailyLimit;
+    /** 分享首页视频获得积分 */
+    private Integer integralShareHomeVideo;
+    /** 分享首页视频单日上限次数 */
+    private Integer integralShareHomeVideoDailyLimit;
     /** 观看课程单日上限次数 */
     private Integer integralCourseDailyLimit;
     /** 浏览商城单日上限次数 */
     private Integer integralProductDailyLimit;
     /** 浏览商城所需秒数 */
     private Integer integralProductBrowseSeconds;
-    /** 点播课留言积分 */
+    /** 点播课留言积分(非转化素材/未关联商品) */
     private Integer integralComment;
+    /** 点播课留言积分(转化素材/关联商品) */
+    private Integer integralCommentProduct;
     /** 积分有效天数 */
     private Integer integralExpireDays;
     /** 积分有效期功能上线日(历史积分迁移基准) yyyy-MM-dd */

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

@@ -15,6 +15,7 @@ public final class IntegralTaskConstants {
     public static final String TASK_DOWNLOAD_APP = "DOWNLOAD_APP";
     public static final String TASK_INVITE = "INVITE";
     public static final String TASK_SHARE = "SHARE";
+    public static final String TASK_SHARE_HOME_VIDEO = "SHARE_HOME_VIDEO";
     public static final String TASK_COURSE = "COURSE";
     public static final String TASK_BROWSE_MALL = "BROWSE_MALL";
     public static final String TASK_INVITED = "INVITED";

+ 3 - 0
fs-service/src/main/java/com/fs/his/domain/FsIntegralGoods.java

@@ -73,6 +73,9 @@ public class FsIntegralGoods extends BaseEntity
     /** 可见范围 app,mini */
     private String visibleScope;
 
+    /** 运费模板ID */
+    private Integer tempId;
+
     @TableField(exist = false)
     private String appId;
 

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

@@ -41,6 +41,8 @@ public enum FsUserIntegralLogTypeEnum {
     TYPE_31(31, "购物积分退款扣除"),
     TYPE_32(32, "首次完成购物"),
     TYPE_33(33, "内容留言积分"),
+    TYPE_34(34, "管理员后台扣除"),
+    TYPE_35(35, "分享首页视频积分"),
     ;
 
 

+ 13 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralCartServiceImpl.java

@@ -18,6 +18,7 @@ import com.fs.his.param.GetFsIntegralCartDetailsParm;
 import com.fs.his.param.GetFsIntegralCartListParam;
 import com.fs.his.service.IFsIntegralCartService;
 import com.fs.his.service.IFsUserIntegralLogsService;
+import com.fs.his.utils.IntegralShippingRegionValidator;
 import com.fs.his.vo.*;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
@@ -63,6 +64,9 @@ public class FsIntegralCartServiceImpl extends ServiceImpl<FsIntegralCartMapper,
     @Autowired
     IFsUserIntegralLogsService integralLogsService;
 
+    @Autowired
+    private IntegralShippingRegionValidator integralShippingRegionValidator;
+
     /**
      * 添加或修改购物车
      *
@@ -257,10 +261,14 @@ public class FsIntegralCartServiceImpl extends ServiceImpl<FsIntegralCartMapper,
             }
             FsUser user = fsUserMapper.selectFsUserByUserId(userId);
             FsUserAddress address = fsUserAddressMapper.selectFsUserAddressByAddressId(param.getAddressId());
+            if (address == null) {
+                throw new ServiceException("地址不存在");
+            }
             List<FsIntegralGoodsVo> fsIntegralGoods = fsIntegralGoodsMapper.selectAllByGoodsIds(new HashSet<>(param.getGoodsId()));
             List<FsIntegralCart> existingCart = fsIntegralCartMapper.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();
+            List<Integer> tempIds = new ArrayList<>();
             for (FsIntegralGoodsVo fsIntegralGood : fsIntegralGoods) {
                 Integer integer = collect.get(fsIntegralGood.getGoodsId());
                 if (fsIntegralGood.getStock() < integer) {
@@ -271,6 +279,7 @@ public class FsIntegralCartServiceImpl extends ServiceImpl<FsIntegralCartMapper,
                     log.info("清除下架商品,userId:{}, goodsId:{}", userId, fsIntegralGood.getGoodsId());
                     throw new ServiceException(String.format("商品[名称:%d]已下架,兑换失败", fsIntegralGood.getGoodsName()));
                 }
+                tempIds.add(fsIntegralGood.getTempId());
                 fsIntegralGood.setIntegralByNum(integer * fsIntegralGood.getIntegral());
                 fsIntegralGood.setQuantity(integer);
                 if (quantity.length() > 0) {
@@ -278,6 +287,10 @@ public class FsIntegralCartServiceImpl extends ServiceImpl<FsIntegralCartMapper,
                 }
                 quantity.append(ObjectUtils.isNotEmpty(integer) ? integer : "0");
             }
+            String shippingError = integralShippingRegionValidator.checkError(address.getCityIds(), tempIds);
+            if (shippingError != null) {
+                throw new ServiceException(shippingError);
+            }
             // 商品总的积分
             Long goodsIntegral = fsIntegralGoods.stream().filter(n -> ObjectUtils.isNotEmpty(n.getIntegralByNum())).mapToLong(FsIntegralGoodsVo::getIntegralByNum).sum();
             if (user.getIntegral() < goodsIntegral) {

+ 20 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java

@@ -49,6 +49,7 @@ import com.fs.his.mapper.*;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.utils.ConfigUtil;
+import com.fs.his.utils.IntegralShippingRegionValidator;
 import com.fs.his.utils.PhoneUtil;
 import com.fs.his.utils.RedisCacheUtil;
 import com.fs.his.vo.*;
@@ -136,6 +137,9 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
     @Autowired
     private IFsIntegralCartService cartService;
 
+    @Autowired
+    private IntegralShippingRegionValidator integralShippingRegionValidator;
+
     @Autowired
     @Qualifier("erpOrderServiceImpl")
     private IErpOrderService gyOrderService;
@@ -345,6 +349,11 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
         if (integralGoods.getStatus() == 0) {
             return R.error("商品已经停售,请联系客户进行处理!");
         }
+        String shippingError = integralShippingRegionValidator.checkError(
+                address.getCityIds(), Collections.singletonList(integralGoods.getTempId()));
+        if (shippingError != null) {
+            return R.error(shippingError);
+        }
 
         // 减库存
         if (fsIntegralGoodsMapper.subStock(integralGoods.getGoodsId(), 1) <= 0) {
@@ -496,6 +505,7 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
         long totalIntegral = 0L;
         BigDecimal totalCash = BigDecimal.ZERO;
         List<FsIntegralGoods> goodsItem = new ArrayList<>();
+        List<Integer> tempIds = new ArrayList<>();
         for (FsIntegralCart cart : carts) {
             FsIntegralGoods integralGoods = fsIntegralGoodsMapper.selectFsIntegralGoodsByGoodsId(cart.getGoodsId());
             if (Objects.isNull(integralGoods)) {
@@ -507,7 +517,16 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
             if (integralGoods.getStatus() == 0) {
                 return R.error(integralGoods.getGoodsName() + "商品已经停售,请联系客户进行处理!");
             }
-
+            tempIds.add(integralGoods.getTempId());
+            goodsItem.add(integralGoods);
+        }
+        String shippingError = integralShippingRegionValidator.checkError(address.getCityIds(), tempIds);
+        if (shippingError != null) {
+            throw new CustomException(shippingError);
+        }
+        goodsItem.clear();
+        for (FsIntegralCart cart : carts) {
+            FsIntegralGoods integralGoods = fsIntegralGoodsMapper.selectFsIntegralGoodsByGoodsId(cart.getGoodsId());
             // 减库存
             if (fsIntegralGoodsMapper.subStock(integralGoods.getGoodsId(), cart.getCartNum()) <= 0) {
                 throw new CustomException("库存不足");

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

@@ -3,6 +3,8 @@ package com.fs.his.service.impl;
 import cn.hutool.json.JSONUtil;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
+import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.his.config.IntegralConfig;
 import com.fs.his.domain.FsIntegralCount;
 import com.fs.his.domain.FsUser;
@@ -55,6 +57,8 @@ public class FsUserIntegralLogsServiceImpl implements IFsUserIntegralLogsService
     private FsUserNewTaskMapper fsUserNewTaskMapper;
     @Autowired
     private FsUserIntegralBatchMapper fsUserIntegralBatchMapper;
+    @Autowired
+    private FsUserCourseVideoMapper fsUserCourseVideoMapper;
     /**
      * 查询积分记录
      *
@@ -422,6 +426,15 @@ public class FsUserIntegralLogsServiceImpl implements IFsUserIntegralLogsService
                     integralNum = config.getIntegralComment();
                     logsType = FsUserIntegralLogTypeEnum.TYPE_33;
                     break;
+                case 35: // 分享首页视频积分
+                    integralLogs = fsUserIntegralLogsMapper.selectFsUserIntegralLogsByUserIdAndLogType(
+                            param.getUserId(), param.getLogType(), LocalDate.now());
+                    if (integralLogs.size() >= config.getIntegralShareHomeVideoDailyLimit()) {
+                        return R.error("今日分享首页视频积分已达上限");
+                    }
+                    integralNum = config.getIntegralShareHomeVideo();
+                    logsType = FsUserIntegralLogTypeEnum.TYPE_35;
+                    break;
                 default:
                     return R.error("积分类型错误,联系管理员");
             }

+ 6 - 1
fs-service/src/main/java/com/fs/his/service/impl/IntegralTaskServiceImpl.java

@@ -287,8 +287,13 @@ public class IntegralTaskServiceImpl implements IIntegralTaskService {
         tasks.add(buildDailyTask(IntegralTaskConstants.TASK_SHARE, "分享得积分",
                 config.getIntegralShare(), shareCount, config.getIntegralShareDailyLimit(), taskDisplayScope));
 
+        int shareHomeVideoCount = countTodayLog(userId, 35);
+        tasks.add(buildDailyTask(IntegralTaskConstants.TASK_SHARE_HOME_VIDEO, "分享首页视频",
+                config.getIntegralShareHomeVideo(), shareHomeVideoCount,
+                config.getIntegralShareHomeVideoDailyLimit(), taskDisplayScope));
+
         int courseCount = countTodayLog(userId, 10);
-        tasks.add(buildDailyTask(IntegralTaskConstants.TASK_COURSE, "学习首页课程",
+        tasks.add(buildDailyTask(IntegralTaskConstants.TASK_COURSE, "观看首页视频60秒",
                 config.getIntegralCourse(), courseCount, config.getIntegralCourseDailyLimit(), taskDisplayScope));
 
         int browseCount = countTodayLog(userId, 13);

+ 9 - 0
fs-service/src/main/java/com/fs/his/utils/IntegralConfigHelper.java

@@ -37,6 +37,12 @@ public final class IntegralConfigHelper {
         if (config.getIntegralShareDailyLimit() == null) {
             config.setIntegralShareDailyLimit(5);
         }
+        if (config.getIntegralShareHomeVideo() == null) {
+            config.setIntegralShareHomeVideo(10);
+        }
+        if (config.getIntegralShareHomeVideoDailyLimit() == null) {
+            config.setIntegralShareHomeVideoDailyLimit(5);
+        }
         if (config.getIntegralCourseDailyLimit() == null) {
             config.setIntegralCourseDailyLimit(5);
         }
@@ -49,6 +55,9 @@ public final class IntegralConfigHelper {
         if (config.getIntegralComment() == null) {
             config.setIntegralComment(100);
         }
+        if (config.getIntegralCommentProduct() == null) {
+            config.setIntegralCommentProduct(150);
+        }
         if (config.getIntegralExpireDays() == null) {
             config.setIntegralExpireDays(90);
         }

+ 126 - 0
fs-service/src/main/java/com/fs/his/utils/IntegralShippingRegionValidator.java

@@ -0,0 +1,126 @@
+package com.fs.his.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fs.common.core.domain.entity.SysDictData;
+import com.fs.common.utils.StringUtils;
+import com.fs.hisStore.domain.FsShippingTemplatesRegionScrm;
+import com.fs.hisStore.domain.FsShippingTemplatesScrm;
+import com.fs.hisStore.dto.RegionInfoDTO;
+import com.fs.hisStore.service.IFsCityScrmService;
+import com.fs.hisStore.service.IFsShippingTemplatesRegionScrmService;
+import com.fs.hisStore.service.IFsShippingTemplatesScrmService;
+import com.fs.system.service.ISysDictTypeService;
+import org.apache.commons.collections.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * 积分订单运费模板配送范围校验(受 store_mall_func dict_sort=2 开关控制)
+ */
+@Component
+public class IntegralShippingRegionValidator {
+
+    private static final Logger log = LoggerFactory.getLogger(IntegralShippingRegionValidator.class);
+
+    public static final String ERROR_MSG = "该区域暂无库存不可兑换";
+
+    private static final String STORE_MALL_FUNC = "store_mall_func";
+    /** 字典 dict_sort=2:创建积分订单是否校验运费模板 */
+    private static final long DICT_SORT_CHECK_INTEGRAL_SHIPPING = 2L;
+
+    @Autowired
+    private ISysDictTypeService sysDictTypeService;
+    @Autowired
+    private IFsCityScrmService fsCityService;
+    @Autowired
+    private IFsShippingTemplatesScrmService shippingTemplatesService;
+    @Autowired
+    private IFsShippingTemplatesRegionScrmService shippingTemplatesRegionService;
+
+    public boolean isCheckEnabled() {
+        List<SysDictData> dictList = sysDictTypeService.selectDictDataByType(STORE_MALL_FUNC);
+        if (dictList == null || dictList.isEmpty()) {
+            return false;
+        }
+        return dictList.stream()
+                .filter(item -> "0".equals(item.getStatus()))
+                .filter(item -> item.getDictSort() != null && DICT_SORT_CHECK_INTEGRAL_SHIPPING == item.getDictSort())
+                .anyMatch(item -> "1".equals(StringUtils.trimToEmpty(item.getDictValue())));
+    }
+
+    /**
+     * @return 校验失败时的错误文案;通过返回 null
+     */
+    public String checkError(String cityId, Collection<? extends Number> tempIds) {
+        if (!isCheckEnabled()) {
+            return null;
+        }
+        if (StringUtils.isBlank(cityId)) {
+            return null;
+        }
+        List<Long> templateIds = tempIds == null ? null : tempIds.stream()
+                .filter(Objects::nonNull)
+                .map(Number::longValue)
+                .distinct()
+                .collect(Collectors.toList());
+        if (CollectionUtils.isEmpty(templateIds)) {
+            return null;
+        }
+
+        List<String> citys = fsCityService.resolveShippingMatchCityIds(cityId);
+        String tempIdStr = StringUtils.join(templateIds, ",");
+        List<FsShippingTemplatesScrm> shippingTemplatesList = shippingTemplatesService.selectFsShippingTemplatesByIds(tempIdStr);
+        List<FsShippingTemplatesRegionScrm> shippingTemplatesRegionList =
+                shippingTemplatesRegionService.selectFsShippingTemplatesRegionListByTempIdsAndCityIds(
+                        tempIdStr, StringUtils.join(citys, ","));
+
+        boolean isQg = false;
+        if (CollectionUtils.isEmpty(shippingTemplatesRegionList)
+                && CollectionUtils.isNotEmpty(shippingTemplatesList)
+                && shippingTemplatesList.size() < 2) {
+            List<RegionInfoDTO> regionList = JSONObject.parseArray(
+                    shippingTemplatesList.get(0).getRegionInfo(),
+                    RegionInfoDTO.class
+            );
+            if (regionList != null && !regionList.isEmpty()) {
+                RegionInfoDTO regionDTO = regionList.get(0);
+                if ("默认全国".equals(regionDTO.getRegionName())) {
+                    isQg = true;
+                }
+            }
+        }
+
+        if (CollectionUtils.isNotEmpty(shippingTemplatesList)
+                && CollectionUtils.isEmpty(shippingTemplatesRegionList)
+                && !isQg) {
+            log.warn("积分订单运费模板区域不匹配,cityId={}, tempIds={}", cityId, tempIdStr);
+            return ERROR_MSG;
+        }
+
+        if (CollectionUtils.isEmpty(shippingTemplatesRegionList)) {
+            return null;
+        }
+
+        for (Long tempId : templateIds) {
+            boolean templateExists = shippingTemplatesList != null
+                    && shippingTemplatesList.stream().anyMatch(t -> tempId.equals(t.getId()));
+            if (!templateExists) {
+                continue;
+            }
+            boolean regionMatched = shippingTemplatesRegionList.stream()
+                    .anyMatch(r -> tempId.equals(r.getTempId()));
+            if (!regionMatched && !isQg) {
+                log.warn("积分商品运费模板区域不匹配,tempId={}, cityId={}", tempId, cityId);
+                return ERROR_MSG;
+            }
+        }
+        return null;
+    }
+}

+ 3 - 1
fs-service/src/main/java/com/fs/his/utils/IntegralTaskScopeHelper.java

@@ -29,6 +29,7 @@ public final class IntegralTaskScopeHelper {
         map.put(IntegralTaskConstants.TASK_FIRST_PURCHASE, "app,mini");
         map.put(IntegralTaskConstants.TASK_INVITED, "app,mini");
         map.put(IntegralTaskConstants.TASK_SHARE, "app,mini");
+        map.put(IntegralTaskConstants.TASK_SHARE_HOME_VIDEO, "app,mini");
         map.put(IntegralTaskConstants.TASK_COURSE, "app");
         map.put(IntegralTaskConstants.TASK_BROWSE_MALL, "app,mini");
         map.put(IntegralTaskConstants.TASK_INVITE, "app,mini");
@@ -48,6 +49,7 @@ public final class IntegralTaskScopeHelper {
         Map<String, String> map = new LinkedHashMap<>();
         applyTaskScopeToLogType(map, taskScopes, IntegralTaskConstants.TASK_SIGN, "1");
         applyTaskScopeToLogType(map, taskScopes, IntegralTaskConstants.TASK_SHARE, "3");
+        applyTaskScopeToLogType(map, taskScopes, IntegralTaskConstants.TASK_SHARE_HOME_VIDEO, "34");
         applyTaskScopeToLogType(map, taskScopes, IntegralTaskConstants.TASK_COURSE, "10");
         applyTaskScopeToLogType(map, taskScopes, IntegralTaskConstants.TASK_BROWSE_MALL, "13");
         applyTaskScopeToLogType(map, taskScopes, IntegralTaskConstants.TASK_INVITE, "18");
@@ -56,7 +58,7 @@ public final class IntegralTaskScopeHelper {
         applyTaskScopeToLogType(map, taskScopes, IntegralTaskConstants.TASK_DOWNLOAD_APP, "28");
         applyTaskScopeToLogType(map, taskScopes, IntegralTaskConstants.TASK_FIRST_PURCHASE, "32");
         map.put("33", "app,mini");
-        for (int i = 1; i <= 33; i++) {
+        for (int i = 1; i <= 34; i++) {
             map.putIfAbsent(String.valueOf(i), "app,mini");
         }
         return map;

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

@@ -50,4 +50,7 @@ public class FsIntegralGoodsVo {
 
     @ApiModelProperty("需支付金额")
     private BigDecimal cash;
+
+    @ApiModelProperty("运费模板ID")
+    private Integer tempId;
 }

+ 4 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderParam.java

@@ -19,8 +19,12 @@ public class FsStoreOrderParam extends BaseEntity implements Serializable
     /** 多个订单号搜索(逗号分隔字符串,用于GET请求) */
     private String orderCodeList;
 
+    /** 微信昵称(fs_user.nick_name) */
     private String nickname;
 
+    /** 商品分类名称(fs_store_product_category_scrm.cate_name) */
+    private String cateName;
+
     private String phone;
 
     private String userPhone;

+ 70 - 28
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -238,6 +238,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     private static final String STORE_MALL_FUNC = "store_mall_func";
     /** 字典 dict_sort=1:是否展示直播中奖订单 */
     private static final long DICT_SORT_SHOW_LIVE_LOTTERY_ORDER = 1L;
+    /** 字典 dict_sort=3:是否发送到货通知 */
+    private static final long DICT_SORT_SEND_ARRIVAL_NOTICE = 3L;
 
     Logger logger = LoggerFactory.getLogger(getClass());
     @Autowired
@@ -538,6 +540,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
 
     /** 同一企微账号 + 外部联系人,一天内只发一次支付成功消息 */
     private static final String PAY_SUCCESS_MSG_CONTACT_REDIS_KEY = "fs:pay:success:msg:contact:";
+    private static final String ARRIVAL_NOTICE_MSG_REDIS_KEY = "fs:arrival:notice:msg:send:";
     @PostConstruct
     public void initErpServiceMap() {
         erpServiceMap = new HashMap<>();
@@ -2946,6 +2949,11 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     .templateType(TemplateListenEnum.TYPE_3.getValue())
                     .build();
             publisher.publishEvent(new TemplateEvent(this, templateBean));
+
+            // 到货通知:开关开启时异步推送企微消息
+            final Long arrivalNoticeOrderId = order.getId();
+            CompletableFuture.runAsync(() -> sendExpressInfoToWx(arrivalNoticeOrderId));
+
             return R.ok("操作成功");
         } else {
             return R.error("非法操作");
@@ -7826,6 +7834,56 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         }
     }
 
+
+
+
+    private String buildArrivalNoticeContent(FsStoreOrderScrm order) {
+        String productName = resolveOrderProductNames(order);
+        if (StringUtils.isBlank(productName)) {
+            productName = "商品";
+        }
+        String deliveryId = StringUtils.isNotBlank(order.getDeliveryId()) ? order.getDeliveryId() : "";
+        return "您好,您的包裹【" + productName + "】已签收,请及时确认收货;\n"
+                + " 物流单号为:" + deliveryId + "\n"
+                + "\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39";
+    }
+
+    private String resolveOrderProductNames(FsStoreOrderScrm order) {
+        if (order == null || StringUtils.isBlank(order.getItemJson())) {
+            return null;
+        }
+        try {
+            com.alibaba.fastjson.JSONArray itemArray = JSON.parseArray(order.getItemJson());
+            if (itemArray == null || itemArray.isEmpty()) {
+                return null;
+            }
+            List<String> names = new ArrayList<>();
+            for (int i = 0; i < itemArray.size(); i++) {
+                JSONObject item = itemArray.getJSONObject(i);
+                if (item == null) {
+                    continue;
+                }
+                String name = item.getString("productName");
+                if (StringUtils.isBlank(name) && StringUtils.isNotBlank(item.getString("jsonInfo"))) {
+                    JSONObject jsonInfo = JSON.parseObject(item.getString("jsonInfo"));
+                    if (jsonInfo != null) {
+                        name = jsonInfo.getString("productName");
+                    }
+                }
+                if (StringUtils.isNotBlank(name) && !names.contains(name)) {
+                    names.add(name);
+                }
+            }
+            if (names.isEmpty()) {
+                return null;
+            }
+            return String.join("、", names);
+        } catch (Exception e) {
+            log.warn("解析订单商品名失败, orderId={}, error={}", order.getId(), e.getMessage());
+            return null;
+        }
+    }
+
     /**
      * 支付成功后向用户发送感谢文案及配图(Redis 去重,防止支付回调重试重复发送)。
      */
@@ -8021,42 +8079,26 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                                         case 1:
                                             break;
                                         case 2:
-                                            sBuilder.append("您好,您有一个包裹正在准备发货,请耐心等待;\n");
+                                            String shipProductName = resolveOrderProductNames(order);
+                                            if (StringUtils.isBlank(shipProductName)) {
+                                                shipProductName = "商品";
+                                            }
+                                            sBuilder.append("您好,您的包裹【").append(shipProductName).append("】正在准备发货,请耐心等待;\n");
                                             if (order.getDeliveryId() != null && !order.getDeliveryId().isEmpty()) {
                                                 sBuilder.append(" 物流单号为:").append(order.getDeliveryId()).append("\n");
                                             }
                                             sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
                                             break;
                                         case 3:
-                                            String lastFourNumber = "";
-                                            if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue()) || order.getDeliverySn().equals(ShipperCodeEnum.ZTO.getValue())) {
-                                                if("恒春来".equals(cloudHostProper.getCompanyName())
-                                                        && ObjectUtil.isNotEmpty(lastFourNumber = order.getVirtualPhone())){
-                                                    if (lastFourNumber.contains("-")) {
-                                                        lastFourNumber = lastFourNumber.length() >= 4 ? lastFourNumber.substring(lastFourNumber.length() - 4) : lastFourNumber;
-                                                    }else{
-                                                        lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
-                                                    }
-                                                }
-                                                // 原逻辑
-                                                else if ((lastFourNumber = order.getUserPhone()).length() == 11) {
-                                                    lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
-                                                }
+                                            String productNamess = resolveOrderProductNames(order);
+                                            if (StringUtils.isBlank(productNamess)) {
+                                                productNamess = "商品";
                                             }
-                                            ExpressInfoDTO express = expressService.getExpressInfo(order.getOrderCode(), order.getDeliverySn(), order.getDeliveryId(), lastFourNumber);
-                                            if (express != null && "211".equals(express.getStateEx())) {
-                                                sBuilder.append("这边查询到您有一个包裹 ");
-                                                if (express.getTraces() != null && !express.getTraces().isEmpty()) {
-                                                    List<com.fs.hisStore.dto.TracesDTO> traces = express.getTraces();
-                                                    TracesDTO tracesDTO = traces.get(traces.size() - 1);
-                                                    sBuilder.append(" 在").append(tracesDTO.getAcceptTime()).append("已经送到了\n");
-                                                    sBuilder.append(" 物流单号为:").append(order.getDeliveryId()).append("\n");
-                                                    sBuilder.append("物流信息:").append(tracesDTO.getAcceptStation()).append("\n");
-                                                } else {
-                                                    sBuilder.append(" 已经送到了\n");
-                                                }
-                                                sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
+                                            sBuilder.append("您好,您的包裹【").append(productNamess).append("】已签收,请及时确认收货;\n");
+                                            if (order.getDeliveryId() != null && !order.getDeliveryId().isEmpty()) {
+                                                sBuilder.append(" 物流单号为:").append(order.getDeliveryId()).append("\n");
                                             }
+                                            sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
                                             break;
                                         case 4:
                                         case 5:

+ 1 - 1
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderVO.java

@@ -60,7 +60,7 @@ public class FsStoreOrderVO implements Serializable
     private String realName;
 
     @TableField(exist = false)
-    @Excel(name = "用户昵称")
+    @Excel(name = "微信昵称")
     private String userNickName;
 
     /** 用户电话 */

+ 17 - 0
fs-service/src/main/resources/db/changelog/changes/20260613-live-user-add-is-del.sql

@@ -270,6 +270,23 @@ ALTER TABLE company_user
     ADD COLUMN expiration_time DATETIME DEFAULT NULL COMMENT '账号过期时间';
 --rollback ALTER TABLE company_user DROP COLUMN expiration_time;
 
+--changeset yhq:20260715-fs-integral-goods-add-temp-id
+--preconditions onFail:MARK_RAN
+--precondition-sql-check expectedResult:1 SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'fs_integral_goods'
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'fs_integral_goods' AND column_name = 'temp_id'
+ALTER TABLE `fs_integral_goods`
+    ADD COLUMN `temp_id` INT NULL DEFAULT NULL COMMENT '运费模板ID' AFTER `visible_scope`;
+--rollback ALTER TABLE fs_integral_goods DROP COLUMN temp_id;
+
+--changeset yhq:20260715-sys-integral-log-type-share-home-video
+--preconditions onFail:MARK_RAN
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM sys_dict_data WHERE dict_type = 'sys_integral_log_type' AND dict_value = '34'
+INSERT INTO `sys_dict_data`
+(`dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+VALUES
+    (34, '分享首页视频积分', '34', 'sys_integral_log_type', NULL, 'default', 'N', '0', 'admin', NOW(), '', NULL, NULL);
+--rollback DELETE FROM sys_dict_data WHERE dict_type = 'sys_integral_log_type' AND dict_value = '34';
+
 --changeset sgw:20260714-qw_work_task_video_id
 --preconditions onFail:MARK_RAN
 --precondition-sql-check expectedResult:1 SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'qw_work_task'

+ 20 - 0
fs-service/src/main/resources/db/changelog/dictData/dict_data_update.sql

@@ -131,3 +131,23 @@ VALUES
     (3, '二维码Y坐标', '1160', 'qr_code_embed_position', '', 'default', 'N', '0', 'admin', NOW(), '', NULL, '二维码距主图顶部像素,sort就是id不能变');
 --rollback DELETE FROM sys_dict_data WHERE dict_type = 'qr_code_embed_position';
 --rollback DELETE FROM sys_dict_type WHERE dict_type = 'qr_code_embed_position';
+
+--changeset yhq:20260715-store-mall-func-integral-shipping-check
+--preconditions onFail:MARK_RAN
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM sys_dict_data WHERE dict_type = 'store_mall_func' AND dict_sort = 2
+INSERT INTO `sys_dict_data`
+(`dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+VALUES
+    (2, '创建积分订单是否校验运费模板', '0', 'store_mall_func', '', 'info', 'Y', '0', 'admin', NOW(), '', NULL, '值为1时创建积分订单校验收货地址是否在商品运费模板范围内,不在则提示该区域暂无库存不可兑换,默认0不校验,sort就是id不能变');
+--rollback DELETE FROM sys_dict_data WHERE dict_type = 'store_mall_func' AND dict_sort = 2;
+
+--changeset yhq:20260715-sys-integral-log-type-share-home-video
+--preconditions onFail:MARK_RAN
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM sys_dict_data WHERE dict_type = 'sys_integral_log_type' AND dict_value = '35'
+INSERT INTO `sys_dict_data`
+(`dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+VALUES
+    (35, '分享首页视频积分', '35', 'sys_integral_log_type', NULL, 'default', 'N', '0', 'admin', NOW(), '', NULL, NULL);
+--rollback DELETE FROM sys_dict_data WHERE dict_type = 'sys_integral_log_type' AND dict_value = '35';
+
+

+ 1 - 0
fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -41,6 +41,7 @@
         <result property="isFirst"    column="is_first"    />
         <result property="courseIntroImg"    column="course_intro_img"    />
         <result property="courseCouponId"    column="course_coupon_id"    />
+        <result property="isProduct"    column="is_product"    />
     </resultMap>
 
     <sql id="selectFsUserCourseVideoVo">

+ 5 - 1
fs-service/src/main/resources/mapper/his/FsIntegralGoodsMapper.xml

@@ -21,10 +21,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="barCode"    column="bar_code"    />
         <result property="appIds"    column="app_ids"    />
         <result property="visibleScope"    column="visible_scope"    />
+        <result property="tempId"    column="temp_id"    />
     </resultMap>
 
     <sql id="selectFsIntegralGoodsVo">
-        select goods_id, img_url, images,bar_code, goods_name, ot_price, goods_type, status, integral, cash, sort, stock, descs, create_time,app_ids,visible_scope from fs_integral_goods
+        select goods_id, img_url, images,bar_code, goods_name, ot_price, goods_type, status, integral, cash, sort, stock, descs, create_time,app_ids,visible_scope,temp_id from fs_integral_goods
     </sql>
 
     <select id="selectFsIntegralGoodsList" parameterType="FsIntegralGoods" resultMap="FsIntegralGoodsResult">
@@ -63,6 +64,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="barCode != null">bar_code,</if>
             <if test="appIds != null">app_ids,</if>
             <if test="visibleScope != null">visible_scope,</if>
+            <if test="tempId != null">temp_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="goodsId != null">#{goodsId},</if>
@@ -81,6 +83,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="barCode != null">#{barCode},</if>
             <if test="appIds != null">#{appIds},</if>
             <if test="visibleScope != null">#{visibleScope},</if>
+            <if test="tempId != null">#{tempId},</if>
          </trim>
     </insert>
 
@@ -102,6 +105,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="barCode != null">bar_code = #{barCode},</if>
             <if test="appIds != null">app_ids = #{appIds},</if>
             <if test="visibleScope != null">visible_scope = #{visibleScope},</if>
+            temp_id = #{tempId,jdbcType=INTEGER},
         </trim>
         where goods_id = #{goodsId}
     </update>

+ 11 - 4
fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml

@@ -1836,7 +1836,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 and o.delivery_id =#{maps.deliveryId}
             </if>
             <if test="maps.nickname != null and  maps.nickname !=''">
-                and u.nickname like CONCAT('%',#{maps.nickname},'%')
+                and us.nickname like CONCAT('%',#{maps.nickname},'%')
             </if>
             <if test="maps.realName != null and  maps.realName !=''">
                 and o.real_name like CONCAT('%',#{maps.realName},'%')
@@ -2018,7 +2018,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 and o.delivery_id =#{maps.deliveryId}
             </if>
             <if test="maps.nickname != null and  maps.nickname !=''">
-                and u.nickname like CONCAT('%',#{maps.nickname},'%')
+                and u.nick_name like CONCAT('%',#{maps.nickname},'%')
+            </if>
+            <if test="maps.cateName != null and maps.cateName != ''">
+                and fspc.cate_name like CONCAT('%',#{maps.cateName},'%')
             </if>
             <if test="maps.realName != null and  maps.realName !=''">
                 and o.real_name like CONCAT('%',#{maps.realName},'%')
@@ -2187,9 +2190,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             LEFT JOIN fs_store_order_df df on df.order_id=o.id
 
         </if>
-        <if test = "maps.productName != null and  maps.productName !=  '' ">
+        <if test="(maps.productName != null and maps.productName != '') or (maps.cateName != null and maps.cateName != '')">
             left join fs_store_order_item_scrm oi on o.id = oi.order_id
             left join fs_store_product_scrm fsp on fsp.product_id = oi.product_id
+            left join fs_store_product_category_scrm fspc on fspc.cate_id = fsp.cate_id
         </if>
         <if test="(maps.appId != null and maps.appId != '') or (maps.bankTransactionId != null and  maps.bankTransactionId !='') or (maps.payCode != null and maps.payCode != '')">
             LEFT JOIN (
@@ -2237,7 +2241,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 and o.delivery_id =#{maps.deliveryId}
             </if>
             <if test="maps.nickname != null and  maps.nickname !=''">
-                and u.nickname like CONCAT('%',#{maps.nickname},'%')
+                and u.nick_name like CONCAT('%',#{maps.nickname},'%')
+            </if>
+            <if test="maps.cateName != null and maps.cateName != ''">
+                and fspc.cate_name like CONCAT('%',#{maps.cateName},'%')
             </if>
             <if test="maps.realName != null and  maps.realName !=''">
                 and o.real_name like CONCAT('%',#{maps.realName},'%')

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

@@ -285,6 +285,15 @@ public class IntegralController extends  AppBaseController {
         return userIntegralLogsService.addIntegralTemplate(fsUserAddIntegralTemplateParam);
     }
 
+    @Login
+    @ApiOperation("分享首页视频获取积分")
+    @PostMapping("/shareHomeVideo")
+    public R shareHomeVideo(@RequestBody FsUserAddIntegralTemplateParam fsUserAddIntegralTemplateParam){
+        fsUserAddIntegralTemplateParam.setUserId(Long.parseLong(getUserId()));
+        fsUserAddIntegralTemplateParam.setLogType(FsUserIntegralLogTypeEnum.TYPE_35.getValue());
+        return userIntegralLogsService.addIntegralTemplate(fsUserAddIntegralTemplateParam);
+    }
+
     @Login
     @ApiOperation("添加或修改购物车")
     @PostMapping("/addOrUpdateCart")