Browse Source

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_java

caoliqin 2 days ago
parent
commit
acad7eedea
59 changed files with 2051 additions and 529 deletions
  1. 37 14
      fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java
  2. 50 10
      fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchLogController.java
  3. 27 0
      fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java
  4. 5 0
      fs-admin/src/main/java/com/fs/his/task/Task.java
  5. 55 0
      fs-admin/src/main/java/com/fs/live/controller/OrderController.java
  6. 25 1
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseRedPacketLogController.java
  7. 7 1
      fs-company/src/main/java/com/fs/company/controller/live/LiveDataController.java
  8. 6 7
      fs-service/src/main/java/com/fs/course/mapper/FsCourseRedPacketLogMapper.java
  9. 6 2
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  10. 24 24
      fs-service/src/main/java/com/fs/course/param/FsCourseRedPacketLogParam.java
  11. 18 20
      fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java
  12. 19 5
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java
  13. 19 6
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java
  14. 13 6
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodDaysServiceImpl.java
  15. 4 2
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  16. 3 1
      fs-service/src/main/java/com/fs/course/vo/FsCourseRedPacketLogListPVO.java
  17. 4 1
      fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java
  18. 8 0
      fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogStatisticsListVO.java
  19. 3 0
      fs-service/src/main/java/com/fs/his/domain/FsUser.java
  20. 2 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java
  21. 2 0
      fs-service/src/main/java/com/fs/his/service/IFsUserService.java
  22. 8 2
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java
  23. 6 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  24. 17 17
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreProductScrmMapper.java
  25. 10 0
      fs-service/src/main/java/com/fs/hisStore/mapper/MergedOrderMapper.java
  26. 4 0
      fs-service/src/main/java/com/fs/hisStore/service/IMergedOrderService.java
  27. 26 0
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductScrmServiceImpl.java
  28. 6 1
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserAddressScrmServiceImpl.java
  29. 55 11
      fs-service/src/main/java/com/fs/hisStore/service/impl/MergedOrderServiceImpl.java
  30. 37 0
      fs-service/src/main/java/com/fs/live/enums/LiveGoodsAddErrorEnum.java
  31. 85 0
      fs-service/src/main/java/com/fs/live/param/MergedOrderQueryParam.java
  32. 96 2
      fs-service/src/main/java/com/fs/live/service/impl/LiveGoodsServiceImpl.java
  33. 27 1
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  34. 195 0
      fs-service/src/main/java/com/fs/live/vo/MergedOrderVO.java
  35. 2 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
  36. 3 2
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
  37. 2 1
      fs-service/src/main/java/com/fs/sop/domain/QwSopTemp.java
  38. 3 0
      fs-service/src/main/java/com/fs/sop/domain/QwSopTempRules.java
  39. 19 0
      fs-service/src/main/java/com/fs/sop/mapper/QwSopTempRulesMapper.java
  40. 2 0
      fs-service/src/main/java/com/fs/sop/service/IQwSopTempContentService.java
  41. 1 0
      fs-service/src/main/java/com/fs/sop/service/IQwSopTempDayService.java
  42. 2 0
      fs-service/src/main/java/com/fs/sop/service/IQwSopTempRulesService.java
  43. 6 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempContentServiceImpl.java
  44. 7 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempDayServiceImpl.java
  45. 7 2
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempRulesServiceImpl.java
  46. 111 35
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java
  47. 3 1
      fs-service/src/main/resources/application-druid-cfryt.yml
  48. 438 345
      fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml
  49. 6 1
      fs-service/src/main/resources/mapper/course/FsUserCoursePeriodDaysMapper.xml
  50. 3 0
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  51. 1 1
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  52. 1 0
      fs-service/src/main/resources/mapper/hisStore/FsUserAddressScrmMapper.xml
  53. 403 0
      fs-service/src/main/resources/mapper/hisStore/MergedOrderMapper.xml
  54. 3 3
      fs-service/src/main/resources/mapper/live/LiveDataMapper.xml
  55. 2 2
      fs-service/src/main/resources/mapper/qw/CustomerTransferApprovalMapper.xml
  56. 9 1
      fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml
  57. 92 0
      fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java
  58. 15 0
      fs-user-app/src/main/java/com/fs/app/controller/IntegralController.java
  59. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/store/AddressScrmController.java

+ 37 - 14
fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java

@@ -1,8 +1,6 @@
 package com.fs.course.controller;
 
-import java.util.ArrayList;
-import java.util.List;
-
+import java.util.*;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.fs.common.core.domain.R;
@@ -23,14 +21,7 @@ import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -87,13 +78,42 @@ public class FsCourseRedPacketLogController extends BaseController
 
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {
-            FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsCourseRedPacketLogListPVO.getPeriodId().longValue());
-            fsCourseRedPacketLogListPVO.setPeriodName(fsUserCoursePeriod.getPeriodName());
+            if (ObjectUtil.isNotEmpty(fsCourseRedPacketLogListPVO.getPeriodId())){
+                FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsCourseRedPacketLogListPVO.getPeriodId().longValue());
+                fsCourseRedPacketLogListPVO.setPeriodName(fsUserCoursePeriod.getPeriodName());
+            }
             fsCourseRedPacketLogListPVO.setPhone(PhoneUtil.decryptAutoPhoneMk(fsCourseRedPacketLogListPVO.getPhone()));
         }
         return R.ok().put("data",new PageInfo<>(list));
     }
 
+    /**
+     * 查询短链课程看课记录列表分页
+     * 与上面请求方式不同,list集合数据在get传输掉包
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseRedPacketLog:pageList')")
+    @PostMapping("/pageList")
+    public R pageList(@RequestBody FsCourseRedPacketLogParam fsCourseRedPacketLog)
+    {
+
+        if (fsCourseRedPacketLog.getPhoneMk() != null && fsCourseRedPacketLog.getPhoneMk() != "") {
+            fsCourseRedPacketLog.setPhone(encryptPhone(fsCourseRedPacketLog.getPhoneMk()));
+        }
+
+        PageHelper.startPage(fsCourseRedPacketLog.getPageNum(), fsCourseRedPacketLog.getPageSize());
+
+        List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
+        for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {
+            if (ObjectUtil.isNotEmpty(fsCourseRedPacketLogListPVO.getPeriodId())){
+                FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsCourseRedPacketLogListPVO.getPeriodId().longValue());
+                fsCourseRedPacketLogListPVO.setPeriodName(fsUserCoursePeriod.getPeriodName());
+            }
+            fsCourseRedPacketLogListPVO.setPhone(PhoneUtil.decryptAutoPhoneMk(fsCourseRedPacketLogListPVO.getPhone()));
+        }
+
+        return R.ok().put("data", new PageInfo<>(list));
+    }
+
     /**
      * 导出短链课程看课记录列表
      */
@@ -107,7 +127,10 @@ public class FsCourseRedPacketLogController extends BaseController
         }
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {
-
+            if (ObjectUtil.isNotEmpty(fsCourseRedPacketLogListPVO.getPeriodId())){
+                FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsCourseRedPacketLogListPVO.getPeriodId().longValue());
+                fsCourseRedPacketLogListPVO.setPeriodName(fsUserCoursePeriod.getPeriodName());
+            }
             fsCourseRedPacketLogListPVO.setPhone(PhoneUtil.decryptAutoPhoneMk(fsCourseRedPacketLogListPVO.getPhone()));
         }
         ExcelUtil<FsCourseRedPacketLogListPVO> util = new ExcelUtil<FsCourseRedPacketLogListPVO>(FsCourseRedPacketLogListPVO.class);

+ 50 - 10
fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchLogController.java

@@ -2,7 +2,10 @@ package com.fs.course.controller;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
+import cn.hutool.core.collection.CollectionUtil;
 import com.fs.common.constant.HttpStatus;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
@@ -55,20 +58,31 @@ public class FsCourseWatchLogController extends BaseController
      * 查询短链课程看课记录列表
      */
     @PreAuthorize("@ss.hasPermi('course:courseWatchLog:list')")
-    @PostMapping("/list")
-    public R list(@RequestBody FsCourseWatchLogListParam param)
+    @GetMapping("/list")
+    public TableDataInfo list(FsCourseWatchLogListParam param)
     {
-        if(param.getPageNum() == null) {
-            param.setPageNum(1);
-        }
-        if(param.getPageSize() == null) {
-            param.setPageSize(10);
+        startPage();
+        if(CollectionUtil.isNotEmpty(param.getUserIds())){
+            param.setUserIds(param.getUserIds().stream()
+                    .filter(userId -> userId != null && userId.startsWith("user_"))
+                    .map(userId -> userId.substring(5))
+                    .collect(Collectors.toList())
+            );
         }
-        PageHelper.startPage(param.getPageNum(), param.getPageSize());
-
         List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogListVO(param);
+        return getDataTable(list);
+    }
 
-        return R.ok().put("data",new PageInfo<>(list));
+    /**
+     * 查询短链课程看课记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseWatchLog:pageList')")
+    @PostMapping("/pageList")
+    public R pageList(@RequestBody FsCourseWatchLogListParam param)
+    {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogListVO(param);
+        return R.ok().put("data", new PageInfo<>(list));
     }
 
     @GetMapping("/qwWatchLogAllStatisticsList")
@@ -120,6 +134,32 @@ public class FsCourseWatchLogController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 会员看课统计导出
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseWatchLog:statisticsExport')")
+    @Log(title = "会员看课统计导出", businessType = BusinessType.EXPORT)
+    @PostMapping("/statisticsExport")
+    public AjaxResult statisticsExport(@RequestBody FsCourseWatchLogStatisticsListParam param)
+    {
+
+        // 如果看指定用户就不用设置公司
+        if(param.getCompanyId() == null){
+            if(param.getUserId() == null) {
+                throw new CustomException("查看公司或者用户必填!");
+            }
+        }
+        if (param.getSTime()==null||param.getETime()==null){
+            throw new CustomException("必须选择开始时间和结束时间!");
+        }
+
+        List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVONew(param);
+
+        ExcelUtil<FsCourseWatchLogStatisticsListVO> util = new ExcelUtil<FsCourseWatchLogStatisticsListVO>(FsCourseWatchLogStatisticsListVO.class);
+        return util.exportExcel(list, "会员看课统计");
+    }
+
+
     /**
      * 导出短链课程看课记录列表
      */

+ 27 - 0
fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java

@@ -89,6 +89,33 @@ public class QwFsCourseWatchLogController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 会员看课统计导出
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseWatchLog:statisticsExport')")
+    @Log(title = "企微看课统计导出", businessType = BusinessType.EXPORT)
+    @PostMapping("/statisticsExport")
+    public AjaxResult statisticsExport(@RequestBody FsCourseWatchLogStatisticsListParam param)
+    {
+
+        if (param.getSTime()==null||param.getETime()==null){
+            throw new CustomException("必须选择开始时间和结束时间!");
+        }
+
+        param.setSendType(2); //企微
+        List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVO(param);
+        if("济南联志健康".equals(signProjectName)){
+            FsCourseWatchLogStatisticsListVO totalData = fsCourseWatchLogService.getTotalDataAddItem(param);
+            list.add(totalData);
+        }
+
+        ExcelUtil<FsCourseWatchLogStatisticsListVO> util = new ExcelUtil<FsCourseWatchLogStatisticsListVO>(FsCourseWatchLogStatisticsListVO.class);
+
+        return util.exportExcel(list, "企微看课统计");
+    }
+
+
+
     @GetMapping("/getSignProjectName")
     public R getSignProjectName(){
         return R.ok().put("signProjectName", signProjectName);

+ 5 - 0
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -244,6 +244,11 @@ public class Task {
             String value = (String) cacheMap.get(key);
             //获取sessionId
             Long sessionId = Long.parseLong(key);
+            try {
+                Thread.sleep(800);
+            } catch (Exception e) {
+                log.error("定时消息处理异常,会话id:{},文本:{}",sessionId,value,e);
+            }
             try {
                 if (value != null && !value.isEmpty()) {
                     FastGptChatSession chatSession = fastGptChatSessionMapper.selectFastGptChatSessionBySessionId(sessionId);

+ 55 - 0
fs-admin/src/main/java/com/fs/live/controller/OrderController.java

@@ -0,0 +1,55 @@
+package com.fs.live.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ParseUtils;
+import com.fs.his.utils.PhoneUtil;
+import com.fs.hisStore.service.IMergedOrderService;
+import com.fs.live.param.MergedOrderQueryParam;
+import com.fs.live.vo.MergedOrderVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 合并订单Controller
+ *
+ * @author fs
+ * @date 2025-01-XX
+ */
+@Api("合并订单管理")
+@RestController
+@RequestMapping("/order")
+public class OrderController extends BaseController
+{
+    @Autowired
+    private IMergedOrderService mergedOrderService;
+
+    /**
+     * 查询合并订单列表
+     */
+    @ApiOperation("查询合并订单列表")
+    @GetMapping("/list")
+    public TableDataInfo list(MergedOrderQueryParam param)
+    {
+        startPage();
+        List<MergedOrderVO> list = mergedOrderService.selectMergedOrderList(param);
+        for (MergedOrderVO vo : list) {
+            vo.setUserPhone(ParseUtils.parsePhone(vo.getUserPhone()));
+            vo.setPhone(ParseUtils.parsePhone(vo.getPhone()));
+            vo.setSalesPhone(ParseUtils.parsePhone(vo.getSalesPhone()));
+            vo.setUserAddress(ParseUtils.parseAddress(vo.getUserAddress()));
+        }
+        return getDataTable(list);
+    }
+}

+ 25 - 1
fs-company/src/main/java/com/fs/company/controller/course/FsCourseRedPacketLogController.java

@@ -13,10 +13,12 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseRedPacketLog;
+import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.mapper.FsUserCourseMapper;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.param.FsCourseRedPacketLogParam;
 import com.fs.course.service.IFsCourseRedPacketLogService;
+import com.fs.course.service.IFsUserCoursePeriodService;
 import com.fs.course.vo.FsCourseRedPacketLogListPVO;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
@@ -51,6 +53,9 @@ public class FsCourseRedPacketLogController extends BaseController
     private TokenService tokenService;
     @Autowired
     private ISysConfigService configService;
+
+    @Autowired
+    private IFsUserCoursePeriodService fsUserCoursePeriodService;
     /**
      * 查询短链课程看课记录列表
      */
@@ -73,6 +78,10 @@ public class FsCourseRedPacketLogController extends BaseController
 
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {
+            if (ObjectUtil.isNotEmpty(fsCourseRedPacketLogListPVO.getPeriodId())){
+                FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsCourseRedPacketLogListPVO.getPeriodId().longValue());
+                fsCourseRedPacketLogListPVO.setPeriodName(fsUserCoursePeriod.getPeriodName());
+            }
 
             fsCourseRedPacketLogListPVO.setPhone(PhoneUtil.decryptAutoPhoneMk(fsCourseRedPacketLogListPVO.getPhone()));
         }
@@ -96,6 +105,10 @@ public class FsCourseRedPacketLogController extends BaseController
 
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {
+            if (ObjectUtil.isNotEmpty(fsCourseRedPacketLogListPVO.getPeriodId())){
+                FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsCourseRedPacketLogListPVO.getPeriodId().longValue());
+                fsCourseRedPacketLogListPVO.setPeriodName(fsUserCoursePeriod.getPeriodName());
+            }
             fsCourseRedPacketLogListPVO.setPhone(PhoneUtil.decryptAutoPhoneMk(fsCourseRedPacketLogListPVO.getPhone()));
         }
         return getDataTable(list);
@@ -115,6 +128,10 @@ public class FsCourseRedPacketLogController extends BaseController
 
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVONew(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {
+            if (ObjectUtil.isNotEmpty(fsCourseRedPacketLogListPVO.getPeriodId())){
+                FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsCourseRedPacketLogListPVO.getPeriodId().longValue());
+                fsCourseRedPacketLogListPVO.setPeriodName(fsUserCoursePeriod.getPeriodName());
+            }
             fsCourseRedPacketLogListPVO.setPhone(PhoneUtil.decryptAutoPhoneMk(fsCourseRedPacketLogListPVO.getPhone()));
         }
         return getDataTable(list);
@@ -136,7 +153,10 @@ public class FsCourseRedPacketLogController extends BaseController
         }
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {
-
+            if (ObjectUtil.isNotEmpty(fsCourseRedPacketLogListPVO.getPeriodId())){
+                FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsCourseRedPacketLogListPVO.getPeriodId().longValue());
+                fsCourseRedPacketLogListPVO.setPeriodName(fsUserCoursePeriod.getPeriodName());
+            }
             fsCourseRedPacketLogListPVO.setPhone(PhoneUtil.decryptAutoPhoneMk(fsCourseRedPacketLogListPVO.getPhone()));
         }
         ExcelUtil<FsCourseRedPacketLogListPVO> util = new ExcelUtil<FsCourseRedPacketLogListPVO>(FsCourseRedPacketLogListPVO.class);
@@ -158,6 +178,10 @@ public class FsCourseRedPacketLogController extends BaseController
         }
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {
+            if (ObjectUtil.isNotEmpty(fsCourseRedPacketLogListPVO.getPeriodId())){
+                FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsCourseRedPacketLogListPVO.getPeriodId().longValue());
+                fsCourseRedPacketLogListPVO.setPeriodName(fsUserCoursePeriod.getPeriodName());
+            }
             fsCourseRedPacketLogListPVO.setPhone(PhoneUtil.decryptAutoPhoneMk(fsCourseRedPacketLogListPVO.getPhone()));
         }
         ExcelUtil<FsCourseRedPacketLogListPVO> util = new ExcelUtil<FsCourseRedPacketLogListPVO>(FsCourseRedPacketLogListPVO.class);

+ 7 - 1
fs-company/src/main/java/com/fs/company/controller/live/LiveDataController.java

@@ -22,6 +22,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -99,7 +100,12 @@ public class LiveDataController extends BaseController
     @GetMapping("/exportLiveUserDetail")
     public AjaxResult exportLiveUserDetail(@RequestParam Long liveId, HttpServletRequest request) {
         CompanyUser user = tokenService.getLoginUser(request).getUser();
-        List<LiveUserDetailExportVO> list = liveDataService.exportLiveUserDetail(liveId,user.getCompanyId(),user.getUserId());
+        List<LiveUserDetailExportVO> list = new ArrayList<>();
+        if ("00".equals(user.getUserType())) {
+            liveDataService.getLiveUserDetailListBySql(liveId, user.getCompanyId(), null);
+        } else {
+            list = liveDataService.exportLiveUserDetail(liveId,user.getCompanyId(),user.getUserId());
+        }
         if (list == null || list.isEmpty()) {
             return AjaxResult.error("未找到用户详情数据");
         }

+ 6 - 7
fs-service/src/main/java/com/fs/course/mapper/FsCourseRedPacketLogMapper.java

@@ -107,14 +107,13 @@ public interface FsCourseRedPacketLogMapper
     List<FsCourseRedPacketLogListPVO> selectRedPacketLogListVO(@Param("maps") FsCourseRedPacketLogParam param);
 
     @Select({"<script> " +
-            "select l.*,v.title,u.nick_name as fsNickName,u.avatar as fsAvatar,u.phone,cu.nick_name company_user_name,c.company_name,qu.qw_user_name,fuc.course_name,cd.dept_name,u.phone as phoneNumber   from fs_course_red_packet_log l  \n" +
+            "select l.*,v.title,u.nick_name as fsNickName,u.avatar as fsAvatar,u.phone,cu.nick_name company_user_name,c.company_name,qu.qw_user_name,fuc.course_name,u.phone as phoneNumber,cu.dept_id   from fs_course_red_packet_log l  \n" +
             "left join fs_user_course_video v on v.video_id = l.video_id \n" +
             "left join fs_user u on u.user_id = l.user_id \n" +
             "left join fs_user_course fuc on fuc.course_id = l.course_id \n" +
             "left join company_user cu on cu.user_id=l.company_user_id \n" +
-            "left join company c on c.company_id=l.company_id \n" +
-            "LEFT JOIN qw_user qu on qu.id= l.qw_user_id  " +
-            "LEFT JOIN company_dept cd on cd.dept_id= cu.dept_id  " +
+            "left join company c on c.company_id=cu.company_id \n" +
+            "LEFT JOIN qw_user qu on qu.id= l.qw_user_id  \n" +
             "where 1=1   " +
             "<if test = ' maps.userId !=null '> and l.user_id = #{maps.userId} </if>" +
             "<if test = ' maps.watchLogId !=null '> and l.watch_log_id = #{maps.watchLogId} </if>" +
@@ -130,10 +129,10 @@ public interface FsCourseRedPacketLogMapper
             "<if test = ' maps.qwUserId !=null '> and l.qw_user_id = #{maps.qwUserId} </if>" +
             "<if test=\"maps.sTime != null \">  and DATE(l.create_time) &gt;= DATE(#{maps.sTime})</if>\n" +
             "<if test=\"maps.eTime != null \">  and DATE(l.create_time) &lt;= DATE(#{maps.eTime})</if>\n" +
-            "            <if test=\"maps.companyUserIds != null and !maps.companyUserIds.isEmpty()\">\n" +
+            "<if test=\"maps.userIds != null and maps.userIds.size() > 0\">\n" +
             "                AND l.company_user_id IN\n" +
-            "                <foreach collection='maps.companyUserIds' item='item' open='(' separator=',' close=')'>\n" +
-            "                    #{item}\n" +
+            "                <foreach collection=\"maps.userIds\" open=\"(\" close=\")\" separator=\",\" item=\"item\">\n" +
+            "                    ${item}\n" +
             "                </foreach>\n" +
             "            </if>" +
             " order by l.log_id desc  "+

+ 6 - 2
fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java

@@ -265,10 +265,10 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
             "       and  send_type= #{sendType} " +
             "</if>\n" +
             "<if test= 'sTime != null '> " +
-            "       and DATE(o.create_time) &gt;= DATE(#{sTime})\n" +
+            "       and o.create_time &gt;= #{sTime}\n" +
             "</if>\n" +
             "<if test='eTime != null '> " +
-            "      and DATE(o.create_time) &lt;= DATE(#{eTime})\n" +
+            "      and o.create_time &lt; DATE_ADD(#{eTime}, INTERVAL 1 DAY)\n" +
             "</if>" +
             "<if test ='sendType != 1 and nickName !=null and nickName!=\"\"'>\n" +
             "   and qu.qw_user_name like concat( #{nickName}, '%')\n" +
@@ -295,6 +295,10 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
             "</script>"})
     List<FsCourseWatchLogStatisticsListVO> selectFsCourseWatchLogStatisticsListVO(FsCourseWatchLogStatisticsListParam param);
 
+    List<FsCourseWatchLogStatisticsListVO> selectFsCourseWatchLogStatisticsListVO_COUNT(FsCourseWatchLogStatisticsListParam param);
+
+
+
     @Select({"<script> " +
             " \tselect \n" +
             "\t'总合计' as qw_user_name,\n" +

+ 24 - 24
fs-service/src/main/java/com/fs/course/param/FsCourseRedPacketLogParam.java

@@ -1,15 +1,15 @@
 package com.fs.course.param;
 
-import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 
-import java.util.ArrayList;
+import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 @Data
-public class FsCourseRedPacketLogParam {
+public class FsCourseRedPacketLogParam implements Serializable {
 
     private Long userId;
 
@@ -43,31 +43,31 @@ public class FsCourseRedPacketLogParam {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date sTime;
 
-    @TableField(exist = false)
-    private List<String> companyUserIds=new ArrayList<>();
-
     private Integer pageNum;
     private Integer pageSize;
 
-    public List<String> getCompanyUserIds() {
-        if (companyUserIds == null || companyUserIds.isEmpty()) {
-            return companyUserIds;
-        }
+    private List<String> userIds;
 
-        // 直接在原始列表上修改
-        for (int i = 0; i < companyUserIds.size(); i++) {
-            String id = companyUserIds.get(i);
-            if (id != null) {
-                if (id.startsWith("dept_")) {
-                    companyUserIds.set(i, id.substring(5));
-                } else if (id.startsWith("company_")) {
-                    companyUserIds.set(i, id.substring(8));
-                } else if (id.startsWith("user_")) {
-                    companyUserIds.set(i, id.substring(5));
-                }
-            }
+    public List<String> getUserIds() {
+        if (userIds == null || userIds.isEmpty()) {
+            return userIds;
         }
-        return companyUserIds;
-    }
 
+        return userIds.stream()
+                .map(id -> {
+                    if (id == null) {
+                        return null;
+                    }
+                    // 去除前缀
+                    if (id.startsWith("dept_")) {
+                        return "0";
+                    } else if (id.startsWith("company_")) {
+                        return "0";
+                    } else if (id.startsWith("user_")) {
+                        return id.substring(5);
+                    }
+                    return "0";
+                })
+                .collect(Collectors.toList());
+    }
 }

+ 18 - 20
fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java

@@ -1,13 +1,12 @@
 package com.fs.course.param;
 
-import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 @Data
 public class FsCourseWatchLogListParam implements Serializable {
@@ -110,31 +109,30 @@ public class FsCourseWatchLogListParam implements Serializable {
     private List<Long> deptIds;
     private String ids;
 
-
     private Integer pageNum;
     private Integer pageSize;
-
-    @TableField(exist = false)
-    private List<String> userIds = new ArrayList<>();
+    private List<String> userIds;
 
     public List<String> getUserIds() {
         if (userIds == null || userIds.isEmpty()) {
             return userIds;
         }
 
-        // 直接在原始列表上修改
-        for (int i = 0; i < userIds.size(); i++) {
-            String id = userIds.get(i);
-            if (id != null) {
-                if (id.startsWith("dept_")) {
-                    userIds.set(i, id.substring(5));
-                } else if (id.startsWith("company_")) {
-                    userIds.set(i, id.substring(8));
-                } else if (id.startsWith("user_")) {
-                    userIds.set(i, id.substring(5));
-                }
-            }
-        }
-        return userIds;
+        return userIds.stream()
+                .map(id -> {
+                    if (id == null) {
+                        return null;
+                    }
+                    // 去除前缀
+                    if (id.startsWith("dept_")) {
+                        return "0";
+                    } else if (id.startsWith("company_")) {
+                        return "0";
+                    } else if (id.startsWith("user_")) {
+                        return id.substring(5);
+                    }
+                    return "0";
+                })
+                .collect(Collectors.toList());
     }
 }

+ 19 - 5
fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java

@@ -3,16 +3,16 @@ package com.fs.course.service.impl;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.company.cache.ICompanyDeptCacheService;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyMoneyLogs;
 import com.fs.company.mapper.CompanyMapper;
@@ -62,6 +62,8 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
 
     @Autowired
     private ISysConfigService configService;
+    @Autowired
+    private ICompanyDeptCacheService companyDeptCacheService;
     /**
      * 查询短链课程看课记录
      *
@@ -162,7 +164,19 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
 
     @Override
     public List<FsCourseRedPacketLogListPVO> selectFsCourseRedPacketLogListVO(FsCourseRedPacketLogParam fsCourseRedPacketLog) {
-        return fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
+        List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
+        // 应用到每个对象
+        if(CollectionUtil.isNotEmpty(list)){
+            list.forEach(item -> {
+                if(item.getDeptId() != null) {
+                    String deptNameById = companyDeptCacheService.getDeptNameById(item.getDeptId());
+                    if(StringUtils.isNotBlank(deptNameById)) {
+                        item.setDeptName(deptNameById);
+                    }
+                }
+            });
+        }
+        return list;
     }
 
     @Override

+ 19 - 6
fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.course.service.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.json.JSONUtil;
@@ -13,6 +14,7 @@ import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.DictUtils;
 import com.fs.common.utils.date.DateUtil;
 import com.fs.company.cache.ICompanyCacheService;
+import com.fs.company.cache.ICompanyDeptCacheService;
 import com.fs.company.cache.ICompanyUserCacheService;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
@@ -138,6 +140,9 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
     @Autowired
     private FsTagUpdateService fsTagUpdateService;
 
+    @Autowired
+    private ICompanyDeptCacheService companyDeptCacheService;
+
     /**
      * 查询短链课程看课记录
      *
@@ -677,12 +682,20 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
                 ));
 
         // 遍历并赋值
-        fsCourseWatchLogListVOS.forEach(vo -> {
-            String periodName = periodIdToNameMap.get(vo.getPeriodId());
-            if (periodName != null) {
-                vo.setPeriodIdName(periodName);
-            }
-        });
+        if(CollectionUtil.isNotEmpty(fsCourseWatchLogListVOS)){
+            fsCourseWatchLogListVOS.forEach(vo -> {
+                String periodName = periodIdToNameMap.get(vo.getPeriodId());
+                if (periodName != null) {
+                    vo.setPeriodIdName(periodName);
+                }
+                if(vo.getDeptId() != null) {
+                    String deptNameById = companyDeptCacheService.getDeptNameById(vo.getDeptId());
+                    if(com.fs.common.utils.StringUtils.isNotBlank(deptNameById)) {
+                        vo.setDeptName(deptNameById);
+                    }
+                }
+            });
+        }
 
         return fsCourseWatchLogListVOS;
     }

+ 13 - 6
fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodDaysServiceImpl.java

@@ -198,11 +198,13 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
             day.setVideoId(e);
             day.setCreateTime(new Date());
             // 默认开启今天及以后的两天
-            LocalDate compareDay = LocalDate.now().plusDays(1);
-            if(day.getDayDate().isBefore(compareDay)){
+            LocalDateTime compareDayTime = LocalDateTime.now();
+            if(compareDayTime.isAfter(day.getStartDateTime()) && compareDayTime.isBefore(day.getEndDateTime())){
                 day.setStatus(1);
-            } else {
+            } else if(compareDayTime.isBefore(day.getStartDateTime())){
                 day.setStatus(0);
+            } else {
+                day.setStatus(2);
             }
             return day;
         }).collect(Collectors.toList());
@@ -326,17 +328,20 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
         LocalDateTime tempStartDateTime = source.getStartDateTime();
         LocalDateTime tempEndDateTime = source.getEndDateTime();
         LocalDateTime tempLastJoinTime = source.getLastJoinTime();
+        Integer status = source.getStatus();
 
         // 将目标数据赋给源
         source.setDayDate(target.getDayDate());
         source.setLesson(target.getLesson());
         source.setStartDateTime(target.getStartDateTime());
         source.setEndDateTime(target.getEndDateTime());
+        source.setStatus(target.getStatus());
         source.setLastJoinTime(target.getLastJoinTime());
 
         // 将保存的源数据赋给目标
         target.setDayDate(tempDayDate);
         target.setLesson(tempLesson);
+        target.setStatus(status);
         target.setStartDateTime(tempStartDateTime);
         target.setEndDateTime(tempEndDateTime);
         target.setLastJoinTime(tempLastJoinTime);
@@ -440,11 +445,13 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
         day.setEndDateTime(LocalDateTime.of(day.getDayDate(), day.getEndDateTime().toLocalTime()));
         day.setLastJoinTime(LocalDateTime.of(day.getDayDate(), day.getLastJoinTime().toLocalTime()));
         // 默认开启今天及以后的两天,为进行中
-        LocalDate compareDay = LocalDate.now().plusDays(1);
-        if(day.getDayDate().isBefore(compareDay)){
+        LocalDateTime compareDayTime = LocalDateTime.now();
+        if(compareDayTime.isAfter(day.getStartDateTime()) && compareDayTime.isBefore(day.getEndDateTime())){
             day.setStatus(1);
-        } else {
+        } else if(compareDayTime.isBefore(day.getStartDateTime())){
             day.setStatus(0);
+        } else {
+            day.setStatus(2);
         }
         updateById(day);
         return R.ok();

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

@@ -288,8 +288,10 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
             fsUserCourseVideo.setListingStartTime(null);
             fsUserCourseVideo.setListingEndTime(null);
         }
-        String videoRedisKey = "h5user:video:duration:" + fsUserCourseVideo.getVideoId();
-        redisCache.setCacheObject(videoRedisKey, fsUserCourseVideo.getDuration());
+        String videoRedisKey1 = "h5user:video:duration:" + fsUserCourseVideo.getVideoId();
+        redisCache.setCacheObject(videoRedisKey1, fsUserCourseVideo.getDuration());
+        String videoRedisKey2 = "h5wxuser:video:duration:" + fsUserCourseVideo.getVideoId();
+        redisCache.setCacheObject(videoRedisKey2, fsUserCourseVideo.getDuration());
         return fsUserCourseVideoMapper.updateFsUserCourseVideo(fsUserCourseVideo);
     }
 

+ 3 - 1
fs-service/src/main/java/com/fs/course/vo/FsCourseRedPacketLogListPVO.java

@@ -23,7 +23,7 @@ public class FsCourseRedPacketLogListPVO extends BaseEntity
 
     @Excel(name = "会员id")
     private Long userId;
-
+    @Excel(name = "会员名称")
     private String fsNickName;
 
     private String fsAvatar;
@@ -101,4 +101,6 @@ public class FsCourseRedPacketLogListPVO extends BaseEntity
     @Excel(name = "播放时长")
     private String duration;
 
+    private Long deptId;
+    private Long companyId;
 }

+ 4 - 1
fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java

@@ -85,6 +85,9 @@ public class FsCourseWatchLogListVO extends BaseEntity
     @Excel(name = "所属销售")
     private String companyUserName;
 
+    @Excel(name = "销售部门")
+    private String deptName;
+
     @Excel(name = "所属sop任务")
     private String sopId;
 
@@ -137,5 +140,5 @@ public class FsCourseWatchLogListVO extends BaseEntity
      */
     private Long imMsgSendDetailId;
 
-
+    private Long deptId;
 }

+ 8 - 0
fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogStatisticsListVO.java

@@ -11,27 +11,35 @@ public class FsCourseWatchLogStatisticsListVO {
 
 
     private Integer project;
+
     @Excel(name = "项目名称")
     private String projectName;
 
     private Long courseId;
+
     @Excel(name = "课程名称")
     private String courseName;
 
     private Long videoId;
+
     @Excel(name = "小节名称")
     private String videoName;
 
     @Excel(name = "看课中")
     private String type1;
+
     @Excel(name = "已完课")
     private String type2;
+
     @Excel(name = "待看课")
     private String type3;
+
     @Excel(name = "看课中断")
     private String type4;
+
     @Excel(name = "上线数")
     private Long onLineNum;
+
     @Excel(name = "企业微信员工名称")
     private String qwUserName;
 

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

@@ -183,6 +183,9 @@ public class FsUser extends BaseEntity
     /** 推广上级用户ID */
     private Long spreadUserId;
 
+    /** app登录后不为null(表示是否下载app) */
+    private String historyApp;
+
     public void setNickName(String nickname)
     {
         if(StringUtils.isNotEmpty(nickname)){

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

@@ -469,4 +469,6 @@ public interface FsUserMapper
     void updateUserOrderCountAndAmount(@Param("userId") Long userId, @Param("amount") BigDecimal amount);
 
     List<FsUser> selectFsUserListByPhone(String phone);
+
+    void updatePasswordByPhone(@Param("password")String password, @Param("encryptPhone")String encryptPhone);
 }

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

@@ -230,4 +230,6 @@ public interface IFsUserService
     HisFsUserVO getHisUserIntegralWithLogs(FsUser fsUser);
 
     List<FsUser> selectFsUserListByPhone(String phone);
+
+    R updatePasswordByPhone(String password, String encryptPhone);
 }

+ 8 - 2
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java

@@ -380,15 +380,21 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
 
         if(fsIntegralOrderMapper.insertFsIntegralOrder(order)>0){
             if (order.getPayType() != 2) {
+                // 验证积分是否足够,防止出现负数
+                long remainingIntegral = user.getIntegral() - totalIntegral;
+                if (remainingIntegral < 0) {
+                    throw new CustomException("积分不足,无法创建订单");
+                }
+                
                 //写入日志
                 FsUser userMap=new FsUser();
                 userMap.setUserId(user.getUserId());
-                userMap.setIntegral(user.getIntegral()-totalIntegral);
+                userMap.setIntegral(remainingIntegral);
                 fsUserMapper.updateFsUser(userMap);
                 FsUserIntegralLogs logs = new FsUserIntegralLogs();
                 logs.setIntegral(-totalIntegral);
                 logs.setUserId(order.getUserId());
-                logs.setBalance(userMap.getIntegral());
+                logs.setBalance(remainingIntegral);
                 logs.setLogType(5);
                 logs.setBusinessId(order.getOrderId().toString());
                 logs.setCreateTime(new Date());

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

@@ -1566,4 +1566,10 @@ public class FsUserServiceImpl implements IFsUserService {
         return fsUserMapper.selectFsUserListByPhone(phone);
     }
 
+    @Override
+    public R updatePasswordByPhone(String password, String encryptPhone) {
+        fsUserMapper.updatePasswordByPhone(password, encryptPhone);
+        return R.ok();
+    }
+
 }

+ 17 - 17
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreProductScrmMapper.java

@@ -75,8 +75,8 @@ public interface FsStoreProductScrmMapper
      */
     public int deleteFsStoreProductByIds(Long[] productIds);
     @Select({"<script> " +
-            "select p.*,pc.cate_name, fs_store.store_name from fs_store_product_scrm p left join fs_store_product_category_scrm pc on p.cate_id=pc.cate_id  " +
-            "left join fs_store on fs_store.store_id = p.store_id " +
+            "select p.*,pc.cate_name, fs.store_name from fs_store_product_scrm p left join fs_store_product_category_scrm pc on p.cate_id=pc.cate_id  " +
+            "left join fs_store fs on fs.store_id = p.store_id " +
             "where 1=1 " +
             "<if test = 'maps.productName != null and  maps.productName !=\"\"    '> " +
             "and p.product_name like CONCAT('%',#{maps.productName},'%') " +
@@ -97,53 +97,53 @@ public interface FsStoreProductScrmMapper
             "and p.store_id = #{maps.storeId} " +
             "</if>"+
             "<if test = 'maps.storeIds != null '>" +
-            "and store_id in " +
+            "and p.store_id in " +
             "<foreach collection='maps.storeIds'  item='item' index='index'  open='(' separator=',' close=')'> #{item} </foreach>" +
             "</if>" +
             "<if test = 'maps.isAudit != null '> " +
             "and p.is_audit = #{maps.isAudit} " +
             "</if>" +
             "<if test='maps.drugRegCertNo != null and maps.drugRegCertNo != \"\"'>" +
-            "            AND drug_reg_cert_no LIKE CONCAT('%', #{maps.drugRegCertNo}, '%')" +
+            "    AND p.drug_reg_cert_no LIKE CONCAT('%', #{maps.drugRegCertNo}, '%')" +
             "</if>" +
             "<if test='maps.commonName != null and maps.commonName != \"\"'>" +
-            "    AND common_name LIKE CONCAT('%', #{maps.commonName}, '%')" +
+            "    AND p.common_name LIKE CONCAT('%', #{maps.commonName}, '%')" +
             "</if>" +
             "<if test='maps.dosageForm != null and maps.dosageForm != \"\"'>" +
-            "    AND dosage_form LIKE CONCAT('%', #{maps.dosageForm}, '%')" +
+            "    AND p.dosage_form LIKE CONCAT('%', #{maps.dosageForm}, '%')" +
             "</if>" +
             "<if test='maps.unitPrice != null and maps.unitPrice != \"\"'>" +
-            "    AND unit_price = #{maps.unitPrice}" +
+            "    AND p.unit_price = #{maps.unitPrice}" +
             "</if>" +
             "<if test='maps.batchNumber != null and maps.batchNumber != \"\"'>" +
-            "    AND batch_number LIKE CONCAT('%', #{maps.batchNumber}, '%')" +
+            "    AND p.batch_number LIKE CONCAT('%', #{maps.batchNumber}, '%')" +
             "</if>" +
             "<if test='maps.mah != null and maps.mah != \"\"'>" +
-            "    AND mah LIKE CONCAT('%', #{maps.mah}, '%')" +
+            "    AND p.mah LIKE CONCAT('%', #{maps.mah}, '%')" +
             "</if>" +
             "<if test='maps.mahAddress != null and maps.mahAddress != \"\"'>" +
-            "    AND mah_address LIKE CONCAT('%', #{maps.mahAddress}, '%')" +
+            "    AND p.mah_address LIKE CONCAT('%', #{maps.mahAddress}, '%')" +
             "</if>" +
             "<if test='maps.manufacturer != null and maps.manufacturer != \"\"'>" +
-            "    AND manufacturer LIKE CONCAT('%', #{maps.manufacturer}, '%')" +
+            "    AND p.manufacturer LIKE CONCAT('%', #{maps.manufacturer}, '%')" +
             "</if>" +
             "<if test='maps.manufacturerAddress != null and maps.manufacturerAddress != \"\"'>" +
-            "    AND manufacturer_address LIKE CONCAT('%', #{maps.manufacturerAddress}, '%')" +
+            "    AND p.manufacturer_address LIKE CONCAT('%', #{maps.manufacturerAddress}, '%')" +
             " </if>" +
             " <if test='maps.indications != null and maps.indications != \"\"'>" +
-            "     AND indications LIKE CONCAT('%', #{maps.indications}, '%')" +
+            "     AND p.indications LIKE CONCAT('%', #{maps.indications}, '%')" +
             " </if>" +
             " <if test='maps.dosage != null and maps.dosage != \"\"'>" +
-            "     AND dosage LIKE CONCAT('%', #{maps.dosage}, '%')" +
+            "     AND p.dosage LIKE CONCAT('%', #{maps.dosage}, '%')" +
             " </if>" +
             " <if test='maps.adverseReactions != null and maps.adverseReactions != \"\"'>" +
-            "     AND adverse_reactions LIKE CONCAT('%', #{maps.adverseReactions}, '%')" +
+            "     AND p.adverse_reactions LIKE CONCAT('%', #{maps.adverseReactions}, '%')" +
             " </if>" +
             " <if test='maps.contraindications != null and maps.contraindications != \"\"'>" +
-            "     AND contraindications LIKE CONCAT('%', #{maps.contraindications}, '%')" +
+            "     AND p.contraindications LIKE CONCAT('%', #{maps.contraindications}, '%')" +
             " </if>" +
             " <if test='maps.precautions != null and maps.precautions != \"\"'>" +
-            "     AND precautions LIKE CONCAT('%', #{maps.precautions}, '%')" +
+            "     AND p.precautions LIKE CONCAT('%', #{maps.precautions}, '%')" +
             " </if>"+
             " order by p.product_id desc "+
             "</script>"})

+ 10 - 0
fs-service/src/main/java/com/fs/hisStore/mapper/MergedOrderMapper.java

@@ -2,6 +2,8 @@ package com.fs.hisStore.mapper;
 
 import com.fs.hisStore.param.FsMyStoreOrderQueryParam;
 import com.fs.hisStore.vo.FsMergedOrderListQueryVO;
+import com.fs.live.param.MergedOrderQueryParam;
+import com.fs.live.vo.MergedOrderVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
@@ -15,6 +17,14 @@ import java.util.List;
  */
 public interface MergedOrderMapper
 {
+    /**
+     * 查询合并的订单列表(销售订单+商城订单+直播订单)
+     *
+     * @param param 查询参数
+     * @return 合并后的订单列表
+     */
+    List<MergedOrderVO> selectMergedOrderList(@Param("maps") MergedOrderQueryParam param);
+
     /**
      * 查询合并的订单列表(商城订单+直播订单)
      *

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

@@ -2,6 +2,8 @@ package com.fs.hisStore.service;
 
 import com.fs.hisStore.param.FsMyStoreOrderQueryParam;
 import com.fs.hisStore.vo.FsMergedOrderListQueryVO;
+import com.fs.live.param.MergedOrderQueryParam;
+import com.fs.live.vo.MergedOrderVO;
 
 import java.util.List;
 
@@ -20,5 +22,7 @@ public interface IMergedOrderService
      * @return 合并后的订单列表
      */
     List<FsMergedOrderListQueryVO> selectMergedOrderListVO(FsMyStoreOrderQueryParam param);
+
+    List<MergedOrderVO> selectMergedOrderList(MergedOrderQueryParam param);
 }
 

+ 26 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductScrmServiceImpl.java

@@ -1514,12 +1514,38 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
         FsStoreProductScrm fsStoreProductScrm = fsStoreProductMapper.selectFsStoreProductById(productId);
         if (fsStoreProductScrm == null) return R.error("商品不存在");
 
+        // 查询原商品的规格属性与属性值
+        List<FsStoreProductAttrScrm> attrList = fsStoreProductAttrMapper.selectFsStoreProductAttrByProductId(productId);
+        List<FsStoreProductAttrValueScrm> attrValueList = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueByProductId(productId);
+
         FsStoreProductScrm copy = new FsStoreProductScrm();
         BeanUtils.copyProperties(fsStoreProductScrm, copy);
         copy.setProductId(null);
         copy.setIsAudit("0");
         fsStoreProductMapper.insertFsStoreProduct(copy);
 
+        // 复制规格属性
+        if (attrList != null && !attrList.isEmpty()) {
+            for (FsStoreProductAttrScrm attr : attrList) {
+                FsStoreProductAttrScrm newAttr = new FsStoreProductAttrScrm();
+                BeanUtils.copyProperties(attr, newAttr);
+                newAttr.setId(null);
+                newAttr.setProductId(copy.getProductId());
+                fsStoreProductAttrMapper.insertFsStoreProductAttr(newAttr);
+            }
+        }
+
+        // 复制属性值
+        if (attrValueList != null && !attrValueList.isEmpty()) {
+            for (FsStoreProductAttrValueScrm val : attrValueList) {
+                FsStoreProductAttrValueScrm newVal = new FsStoreProductAttrValueScrm();
+                BeanUtils.copyProperties(val, newVal);
+                newVal.setId(null);
+                newVal.setProductId(copy.getProductId());
+                fsStoreProductAttrValueMapper.insertFsStoreProductAttrValue(newVal);
+            }
+        }
+
         return R.ok();
 
     }

+ 6 - 1
fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserAddressScrmServiceImpl.java

@@ -68,7 +68,12 @@ public class FsUserAddressScrmServiceImpl implements IFsUserAddressScrmService
     {
         fsUserAddress.setDetail(fsUserAddress.getDetail().trim());
         fsUserAddress.setCreateTime(DateUtils.getNowDate());
-        return fsUserAddressMapper.insertFsUserAddress(fsUserAddress);
+        int result = fsUserAddressMapper.insertFsUserAddress(fsUserAddress);
+        // 将自增id赋值给addressId字段
+        if (result > 0 && fsUserAddress.getId() != null) {
+            fsUserAddress.setAddressId(fsUserAddress.getId());
+        }
+        return result;
     }
 
     /**

+ 55 - 11
fs-service/src/main/java/com/fs/hisStore/service/impl/MergedOrderServiceImpl.java

@@ -9,15 +9,14 @@ import com.fs.hisStore.param.FsMyStoreOrderQueryParam;
 import com.fs.hisStore.service.IMergedOrderService;
 import com.fs.hisStore.vo.FsMergedOrderListQueryVO;
 import com.fs.hisStore.vo.FsStoreOrderItemVO;
+import com.fs.live.param.MergedOrderQueryParam;
+import com.fs.live.vo.MergedOrderVO;
 import com.fs.store.config.StoreConfig;
 import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.List;
+import java.util.*;
 
 /**
  * 合并订单Service实现类
@@ -31,27 +30,72 @@ public class MergedOrderServiceImpl implements IMergedOrderService
     @Autowired
     private MergedOrderMapper mergedOrderMapper;
 
+    /*
+     * 后端合并
+     * */
+    @Override
+    public List<MergedOrderVO> selectMergedOrderList(MergedOrderQueryParam param)
+    {
+        List<MergedOrderVO> list = mergedOrderMapper.selectMergedOrderList(param);
+
+        // 处理商品JSON
+        for (MergedOrderVO vo : list)
+        {
+            if (StringUtils.isNotEmpty(vo.getItemJson()))
+            {
+                try
+                {
+                    JSONArray jsonArray = JSONUtil.parseArray(vo.getItemJson());
+                    if (jsonArray != null && jsonArray.size() > 0)
+                    {
+                        vo.setItems(jsonArray);
+                    }
+                }
+                catch (Exception e)
+                {
+                    // JSON解析失败,忽略
+                }
+            }
+        }
+
+        return list;
+    }
+
+
     @Autowired
     private ISysConfigService configService;
 
+    /*
+     * 小程序合并
+     * */
     @Override
     public List<FsMergedOrderListQueryVO> selectMergedOrderListVO(FsMyStoreOrderQueryParam param)
     {
         List<FsMergedOrderListQueryVO> list = mergedOrderMapper.selectMergedOrderListVO(param);
-        
+
         for (FsMergedOrderListQueryVO vo : list)
         {
+
             // 处理商品JSON
             if (StringUtils.isNotEmpty(vo.getItemJson()))
             {
-                JSONArray jsonArray = JSONUtil.parseArray(vo.getItemJson());
-                List<FsStoreOrderItemVO> items = JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
-                if (items != null && items.size() > 0)
-                {
+                List<FsStoreOrderItemVO> items = new ArrayList<>();
+                if (2 == vo.getOrderType()) {
+                    FsStoreOrderItemVO bean = JSONUtil.toBean(vo.getItemJson(), FsStoreOrderItemVO.class);
+                    items.add(bean);
                     vo.setItems(items);
+                }else {
+                    JSONArray jsonArray = JSONUtil.parseArray(vo.getItemJson());
+                    items = JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
+                    if (items != null && items.size() > 0)
+                    {
+                        vo.setItems(items);
+                    }
                 }
+
+
             }
-            
+
             // 处理是否可以申请售后
             vo.setIsAfterSales(0);
             if (vo.getStatus() != null && vo.getStatus().equals(OrderInfoEnum.STATUS_3.getValue()))
@@ -83,7 +127,7 @@ public class MergedOrderServiceImpl implements IMergedOrderService
                 vo.setIsAfterSales(1);
             }
         }
-        
+
         return list;
     }
 }

+ 37 - 0
fs-service/src/main/java/com/fs/live/enums/LiveGoodsAddErrorEnum.java

@@ -0,0 +1,37 @@
+package com.fs.live.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 直播商品添加失败原因枚举
+ *
+ * @author fs
+ * @date 2025-01-XX
+ */
+@Getter
+@AllArgsConstructor
+public enum LiveGoodsAddErrorEnum {
+
+    /**
+     * 未上架
+     */
+    NOT_SHELVED("未上架"),
+
+    /**
+     * 未审核
+     */
+    NOT_AUDITED("未审核"),
+
+    /**
+     * 已删除
+     */
+    DELETED("已删除");
+
+    /**
+     * 错误描述
+     */
+    private String desc;
+
+}
+

+ 85 - 0
fs-service/src/main/java/com/fs/live/param/MergedOrderQueryParam.java

@@ -0,0 +1,85 @@
+package com.fs.live.param;
+
+import com.fs.common.param.BaseQueryParam;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 合并订单查询参数
+ *
+ * @author fs
+ * @date 2025-01-XX
+ */
+@Data
+public class MergedOrderQueryParam extends BaseQueryParam implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 订单状态 */
+    private String status;
+
+    /** 用户ID */
+    private Long userId;
+
+    /** 公司ID */
+    private Long companyId;
+
+    /** 部门ID */
+    private Long deptId;
+
+    /** 订单号 */
+    private String orderCode;
+
+    /** 订单号列表(多个订单号用逗号分隔) */
+    private String orderCodeList;
+
+    /** 运单号 */
+    private String deliveryId;
+
+    /** 银行交易流水号 */
+    private String bankTransactionId;
+
+    /** 手机号 */
+    private String userPhone;
+
+    /** 收件人 */
+    private String realName;
+
+    /** 产品名称 */
+    private String productName;
+
+    /** 物流状态 */
+    private Integer deliveryStatus;
+
+    /** 物流结算状态 */
+    private Integer deliveryPayStatus;
+
+    /** 支付方式 */
+    private String payType;
+
+    /** 下单时间范围 */
+    private String createTimeRange;
+
+    /** 支付时间范围 */
+    private String payTimeRange;
+
+    /** 发货时间范围 */
+    private String deliverySendTimeRange;
+
+    /** 回单时间范围 */
+    private String deliveryImportTimeRange;
+
+    /** 小程序AppId */
+    private String appId;
+
+    /** 订单类型筛选:1-销售订单,2-商城订单,3-直播订单,null-全部 */
+    private Integer orderTypeFilter;
+
+    /** 销售名称(company_user表的user_name) */
+    private String salesName;
+
+    /** 员工姓名(company_user表的nick_name) */
+    private String companyUserNickName;
+}
+

+ 96 - 2
fs-service/src/main/java/com/fs/live/service/impl/LiveGoodsServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.live.service.impl;
 
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.entity.SysUser;
+import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.DateUtils;
 import com.fs.company.domain.CompanyUser;
 import com.fs.his.domain.FsStoreProduct;
@@ -10,6 +11,7 @@ import com.fs.his.mapper.FsStoreProductMapper;
 import com.fs.hisStore.domain.FsStoreProductScrm;
 import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
 import com.fs.live.domain.LiveGoods;
+import com.fs.live.enums.LiveGoodsAddErrorEnum;
 import com.fs.live.mapper.LiveGoodsMapper;
 import com.fs.live.service.ILiveAutoTaskService;
 import com.fs.live.service.ILiveGoodsService;
@@ -91,8 +93,8 @@ public class LiveGoodsServiceImpl  implements ILiveGoodsService {
         liveGoods.setUpdateTime(DateUtils.getNowDate());
         LiveGoods existGoods = baseMapper.selectLiveGoodsByGoodsId(liveGoods.getGoodsId());
         if (liveGoods.getStock() != null) {
-            if(liveGoods.getProductId() == null) return R.error("店铺已停止售卖商品!");
-            FsStoreProductScrm fsStoreProduct = fsStoreProductMapper.selectFsStoreProductById(liveGoods.getProductId());
+            if(existGoods.getProductId() == null) return R.error("店铺已停止售卖商品!");
+            FsStoreProductScrm fsStoreProduct = fsStoreProductMapper.selectFsStoreProductById(existGoods.getProductId());
             if(fsStoreProduct == null) return R.error("商品不存在");
             if(fsStoreProduct.getIsShow() == 0 || existGoods.getStatus() == 0) return R.error("商品已下架");
             if(fsStoreProduct.getStock() < liveGoods.getStock()) return R.error("商品库存不足");
@@ -223,6 +225,52 @@ public class LiveGoodsServiceImpl  implements ILiveGoodsService {
         //  查询商品信息列表(假设返回 List<StoreProduct>)
         List<FsStoreProductScrm> productInfoList = fsStoreProductMapper.selectFsStoreProductByProductIds(productIdsLong);
 
+        // 检查商品状态:未上架、未审核、已删除
+        StringBuilder errorMsg = new StringBuilder();
+        List<String> notShelvedProducts = new ArrayList<>();
+        List<String> notAuditedProducts = new ArrayList<>();
+        List<String> deletedProducts = new ArrayList<>();
+
+        for (FsStoreProductScrm product : productInfoList) {
+            // 检查是否未上架
+            if (product.getIsShow() == null || product.getIsShow() == 0) {
+                notShelvedProducts.add(product.getProductId() + "(" + product.getProductName() + ")");
+            }
+            // 检查是否未审核
+            if (product.getIsAudit() == null || !"1".equals(product.getIsAudit())) {
+                notAuditedProducts.add(product.getProductId() + "(" + product.getProductName() + ")");
+            }
+            // 检查是否已删除
+            if (product.getIsDel() != null && product.getIsDel() == 1) {
+                deletedProducts.add(product.getProductId() + "(" + product.getProductName() + ")");
+            }
+        }
+
+        // 构建错误信息
+        if (!notShelvedProducts.isEmpty()) {
+            errorMsg.append(LiveGoodsAddErrorEnum.NOT_SHELVED.getDesc()).append(":");
+            errorMsg.append(String.join("、", notShelvedProducts));
+        }
+        if (!notAuditedProducts.isEmpty()) {
+            if (errorMsg.length() > 0) {
+                errorMsg.append(";");
+            }
+            errorMsg.append(LiveGoodsAddErrorEnum.NOT_AUDITED.getDesc()).append(":");
+            errorMsg.append(String.join("、", notAuditedProducts));
+        }
+        if (!deletedProducts.isEmpty()) {
+            if (errorMsg.length() > 0) {
+                errorMsg.append(";");
+            }
+            errorMsg.append(LiveGoodsAddErrorEnum.DELETED.getDesc()).append(":");
+            errorMsg.append(String.join("、", deletedProducts));
+        }
+
+        // 如果有错误,返回错误信息
+        if (errorMsg.length() > 0) {
+            return R.error("添加失败原因:" + errorMsg.toString());
+        }
+
         //  转换为 LiveGoods 并批量插入
         List<LiveGoods> liveGoodsList = productInfoList.stream()
                 .map(product -> {
@@ -265,6 +313,52 @@ public class LiveGoodsServiceImpl  implements ILiveGoodsService {
         //  查询商品信息列表(假设返回 List<StoreProduct>)
         List<FsStoreProductScrm> productInfoList = fsStoreProductMapper.selectFsStoreProductByProductIds(productIdsLong);
 
+        // 检查商品状态:未上架、未审核、已删除
+        StringBuilder errorMsg = new StringBuilder();
+        List<String> notShelvedProducts = new ArrayList<>();
+        List<String> notAuditedProducts = new ArrayList<>();
+        List<String> deletedProducts = new ArrayList<>();
+
+        for (FsStoreProductScrm product : productInfoList) {
+            // 检查是否未上架
+            if (product.getIsShow() == null || product.getIsShow() == 0) {
+                notShelvedProducts.add(product.getProductId() + "(" + product.getProductName() + ")");
+            }
+            // 检查是否未审核
+            if (product.getIsAudit() == null || !"1".equals(product.getIsAudit())) {
+                notAuditedProducts.add(product.getProductId() + "(" + product.getProductName() + ")");
+            }
+            // 检查是否已删除
+            if (product.getIsDel() != null && product.getIsDel() == 1) {
+                deletedProducts.add(product.getProductId() + "(" + product.getProductName() + ")");
+            }
+        }
+
+        // 构建错误信息
+        if (!notShelvedProducts.isEmpty()) {
+            errorMsg.append(LiveGoodsAddErrorEnum.NOT_SHELVED.getDesc()).append(":");
+            errorMsg.append(String.join("、", notShelvedProducts));
+        }
+        if (!notAuditedProducts.isEmpty()) {
+            if (errorMsg.length() > 0) {
+                errorMsg.append(";");
+            }
+            errorMsg.append(LiveGoodsAddErrorEnum.NOT_AUDITED.getDesc()).append(":");
+            errorMsg.append(String.join("、", notAuditedProducts));
+        }
+        if (!deletedProducts.isEmpty()) {
+            if (errorMsg.length() > 0) {
+                errorMsg.append(";");
+            }
+            errorMsg.append(LiveGoodsAddErrorEnum.DELETED.getDesc()).append(":");
+            errorMsg.append(String.join("、", deletedProducts));
+        }
+
+        // 如果有错误,抛出异常(因为返回类型是int,不能返回R.error)
+        if (errorMsg.length() > 0) {
+            throw new ServiceException("添加失败原因:" + errorMsg.toString());
+        }
+
         //  转换为 LiveGoods 并批量插入
         List<LiveGoods> liveGoodsList = productInfoList.stream()
                 .map(product -> {

+ 27 - 1
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -1879,8 +1879,12 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         }
         BigDecimal payPrice = BigDecimal.ZERO;
         BigDecimal payDelivery = BigDecimal.ZERO;
+        BigDecimal badCode = BigDecimal.valueOf(-1);
         if (param.getCityId() != null) {
             payDelivery = handleDeliveryMoney(param.getCityId(), fsStoreProduct, param.getTotalNum());
+            if (payDelivery.compareTo(badCode) == 0) {
+                throw new ServiceException("偏远地区暂不可购买");
+            }
             totalPrice = totalPrice.add(payDelivery);
         }
         return LiveOrderComputeDTO.builder().payPrice(payPrice)
@@ -1948,6 +1952,9 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 //        payPrice = payPrice.add(serviceFee);
         // 生成
         BigDecimal deliveryMoney = handleDeliveryMoney(liveOrder);
+        if (deliveryMoney.compareTo(BigDecimal.valueOf(-1)) == 0) {
+            return R.error("偏远地区暂不可购买");
+        }
         totalPrice = totalPrice.add(deliveryMoney);
         liveOrder.setDiscountMoney(totalPrice);
 
@@ -2028,8 +2035,12 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         totalPrice = totalPrice.add(payPrice);
         BigDecimal payDelivery = BigDecimal.ZERO;
         BigDecimal deductionPrice = BigDecimal.ZERO;
+        BigDecimal badCode = BigDecimal.valueOf(-1);
         if (param.getCityId() != null) {
             payDelivery = handleDeliveryMoney(param.getCityId(), fsStoreProduct, param.getTotalNum());
+            if (payDelivery.compareTo(badCode) == 0) {
+                throw new ServiceException("偏远地区暂不可购买");
+            }
             payPrice = payPrice.add(payDelivery);
         }
 
@@ -2472,6 +2483,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
     private BigDecimal handleDeliveryMoney(Long cityId, FsStoreProductScrm fsStoreProduct, String totalNumSize) {
         BigDecimal storePostage = BigDecimal.ZERO;
+        BigDecimal badCode = BigDecimal.valueOf(-1);
         if (ObjectUtil.isNull(fsStoreProduct.getTempId())) {
             return storePostage;
         }
@@ -2487,6 +2499,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         String cityIds = String.join(",", citys.stream()
                 .map(String::valueOf).collect(Collectors.toList()));
         List<FsShippingTemplatesRegionScrm> shippingTemplatesRegionList = shippingTemplatesRegionService.selectFsShippingTemplatesRegionListByTempIdsAndCityIds(ids,cityIds);
+        // 有运费模板,但当前城市没有匹配的区域
+        if (shippingTemplatesList != null && !shippingTemplatesList.isEmpty()
+                && (shippingTemplatesRegionList == null || shippingTemplatesRegionList.isEmpty())) {
+            return badCode;
+        }
         Map<Long, Integer> shippingTemplatesMap = shippingTemplatesList
                 .stream()
                 .collect(Collectors.toMap(FsShippingTemplatesScrm::getId,
@@ -2521,7 +2538,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         FsShippingTemplatesRegionScrm shippingTemplatesRegion = shippingTemplatesRegionMap.get(tempId);
         if (shippingTemplatesRegion == null) {
             log.error("没有找到运费模板");
-            return storePostage;
+            return badCode;
         }
         BigDecimal price = NumberUtil.round(NumberUtil.mul(totalNum, fsStoreProduct.getPrice()), 2);
 
@@ -3542,6 +3559,9 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 //        payPrice = payPrice.add(serviceFee);
         // 生成
         BigDecimal deliveryMoney = handleDeliveryMoney(liveOrder);
+        if (deliveryMoney.compareTo(BigDecimal.valueOf(-1)) == 0) {
+            return R.error("偏远地区暂不可购买");
+        }
         payPrice = payPrice.add(deliveryMoney);
         liveOrder.setDiscountMoney(BigDecimal.ZERO);
 
@@ -3621,6 +3641,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
     private BigDecimal handleDeliveryMoney(LiveOrder liveOrder) {
         BigDecimal storePostage = BigDecimal.ZERO;
+        BigDecimal badCode = BigDecimal.valueOf(-1);
         if(liveOrder.getUserAddress() == null || liveOrder.getCityId() == null) return storePostage;
         List<Long> citys = new ArrayList<>();
         citys.add(liveOrder.getCityId());
@@ -3633,6 +3654,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
         //获取运费模板区域列表按照城市排序
         List<FsShippingTemplatesRegionScrm> shippingTemplatesRegionList = shippingTemplatesRegionService.selectFsShippingTemplatesRegionListByTempIdsAndCityIds(ids, StringUtils.join(citys, ","));
+        // 有运费模板但城市未匹配到区域,返回 badCode
+        if (shippingTemplatesList != null && !shippingTemplatesList.isEmpty()
+                && (shippingTemplatesRegionList == null || shippingTemplatesRegionList.isEmpty())) {
+            return badCode;
+        }
 
         //提取运费模板类型
         Map<Long, Integer> shippingTemplatesMap = shippingTemplatesList

+ 195 - 0
fs-service/src/main/java/com/fs/live/vo/MergedOrderVO.java

@@ -0,0 +1,195 @@
+package com.fs.live.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 合并订单VO(销售订单+商城订单+直播订单)
+ *
+ * @author fs
+ * @date 2025-01-XX
+ */
+@Data
+public class MergedOrderVO implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 订单ID */
+    private Long id;
+
+    /** 订单ID(直播订单使用) */
+    private Long orderId;
+
+    /** 直播ID(直播订单使用) */
+    private Long liveId;
+
+    /** 售后ID(直播订单使用) */
+    private Long afterSalesId;
+
+    /** 订单号 */
+    private String orderCode;
+
+    /** 实际支付金额 */
+    private BigDecimal payPrice;
+
+    /** 会员等级 */
+    private Integer userLevel;
+
+    /** 实付金额 */
+    private BigDecimal payMoney;
+
+    /** 优惠金额(直播订单使用) */
+    private Integer discountMoney;
+
+    /** 运费 */
+    private BigDecimal payDelivery;
+
+    /** 成本价 */
+    private BigDecimal cost;
+
+    /** 订单状态 */
+    @Excel(name = "订单状态",dictType="sys_live_order_status")
+    private Integer status;
+
+    /** 订单总价 */
+    private BigDecimal totalPrice;
+
+    /** 是否套餐 */
+    private Integer isPackage;
+
+    /** 套餐JSON */
+    private String packageJson;
+
+    /** 商品JSON */
+    private String itemJson;
+
+    /** 物流单号 */
+    private String deliveryId;
+
+    /** 是否可以申请售后 */
+    private Integer isAfterSales;
+
+    /** 完成时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date finishTime;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /** 支付时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date payTime;
+
+    /** 发货时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date deliverySendTime;
+
+    /** 总数量(直播订单使用) */
+    private Integer totalNum;
+
+
+
+    /** 订单类型:1-销售订单,2-商城订单,3-直播订单 */
+    private Integer orderType;
+
+    /** 订单类型名称 */
+    private String orderTypeName;
+
+    /** 公司名称 */
+    private String companyName;
+
+    /** 销售名称(company_user表的user_name) */
+    private String salesName;
+
+    /** 销售创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date salesCreateTime;
+
+    /** 销售手机 */
+    private String salesPhone;
+
+    /** 员工昵称(company_user表的nick_name) */
+    private String companyUserNickName;
+
+    /** 用户昵称 */
+    private String nickname;
+
+    /** 用户手机号 */
+    private String phone;
+
+    /** 用户ID */
+    private Long userId;
+
+    /** 用户累计成交避暑 */
+    private Integer userOrderCount;
+
+    /** 用户累计成交避暑 */
+    private BigDecimal userTotalAmount;
+
+    /** 收货人姓名 */
+    private String realName;
+
+    /** 收货人电话 */
+    private String userPhone;
+
+    /** 店铺ID */
+    private Long storeId;
+
+    /** 店铺名字 */
+    private String storeName;
+
+    /** 产品ID */
+    private Long productId;
+
+    /** 产品名字 */
+    private String productName;
+    /** 商品规格 */
+    private String productSpec;
+
+    /** 商品编码 */
+    private String barCode;
+
+    /** 商品分类 */
+    private String cateName;
+
+
+
+    /** 收货地址 */
+    private String userAddress;
+
+    /** 支付方式 */
+    private String payType;
+
+    /** 物流状态 */
+    private Integer deliveryStatus;
+
+    /** 物流结算状态 */
+    private Integer deliveryPayStatus;
+
+
+
+    /** 订单商品列表 */
+    private List<?> items;
+
+    /** 小程序名称 */
+    private String miniProgramName;
+
+    /** ERP账号 */
+    private String erpAccount;
+
+    /** ERP电话 */
+    private String erpPhone;
+
+    /** 银行交易流水号 */
+    private String bankTransactionId;
+
+
+}
+

+ 2 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java

@@ -48,6 +48,8 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
 
     public List<QwExternalContact> selectQwExternalContactByIds(@Param("ids") List<Long> ids);
 
+    public List<QwExternalContact> selectQwExternalContactByIdsStatus(@Param("ids") List<Long> ids);
+
     @Select("SELECT id,stage_status,name,fs_user_id from qw_external_contact where id=#{id}")
     public QwExternalContact selectQwExternalContactByIdForStageStatus(@Param("id") Long id);
 

+ 3 - 2
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -1258,10 +1258,11 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
             List<Future<?>> futures = new ArrayList<>();
 
 
-            // 1. 批量查询所有用户数据
+            // 1. 批量查询所有用户数据(流失客户不打了)
             List<QwExternalContact> contacts;
             try {
-                contacts = qwExternalContactMapper.selectQwExternalContactByIds(param.getUserIds());
+//                contacts = qwExternalContactMapper.selectQwExternalContactByIds(param.getUserIds());
+                contacts = qwExternalContactMapper.selectQwExternalContactByIdsStatus(param.getUserIds());
                 if (contacts == null || contacts.isEmpty()) {
                     return R.error("成功:0,失败:" + param.getUserIds().size());
                 }

+ 2 - 1
fs-service/src/main/java/com/fs/sop/domain/QwSopTemp.java

@@ -113,8 +113,9 @@ public class QwSopTemp implements Serializable
 
     @TableField(exist = false)
     private List<String> companyUserIds=new ArrayList<>();
-
+    @TableField(exist = false)
     private Integer pageNum;
+    @TableField(exist = false)
     private Integer pageSize;
 
     public List<String> getCompanyUserIds() {

+ 3 - 0
fs-service/src/main/java/com/fs/sop/domain/QwSopTempRules.java

@@ -68,6 +68,9 @@ public class QwSopTempRules{
     @Excel(name = "排序")
     private Integer sorts;
 
+    @TableField(exist = false)
+    private Long courseSort;
+
     @TableField(exist = false)
     private List<QwSopTempContent> settingList;
     @TableField(exist = false)

+ 19 - 0
fs-service/src/main/java/com/fs/sop/mapper/QwSopTempRulesMapper.java

@@ -70,6 +70,25 @@ public interface QwSopTempRulesMapper extends BaseMapper<QwSopTempRules> {
     @Select("select * from qw_sop_temp_rules where day_num is null ")
     List<QwSopTempRules> rulesNull();
 
+    @DataSource(DataSourceType.SOP)
+    @Select("<script>" +
+            "select tr.* from qw_sop_temp_rules tr " +
+            "left join qw_sop_temp st on tr.temp_id=st.id " +
+            " where tr.course_id = #{courseId}" +
+            " and st.send_type=11 and st.status = 1  " +
+            "</script>")
+    List<QwSopTempRules> listByCourseId(@Param("courseId") Long courseId);
+
+    @DataSource(DataSourceType.SOP)
+    @Select("<script>" +
+            "select tr.* from qw_sop_temp_rules tr " +
+            "left join qw_sop_temp st on tr.temp_id=st.id " +
+            " where tr.course_id = #{courseId}" +
+            " and tr.temp_id=#{tempId} " +
+            " and st.send_type=11 and st.status = 1  " +
+            "</script>")
+    List<QwSopTempRules> listByCourseIdAndTempId(@Param("courseId") Long courseId,@Param("tempId") String tempId);
+
 
 
     void deleteByTempId(@Param("id") String id);

+ 2 - 0
fs-service/src/main/java/com/fs/sop/service/IQwSopTempContentService.java

@@ -92,5 +92,7 @@ public interface IQwSopTempContentService extends IService<QwSopTempContent>{
 
     List<QwSopTempContent> listByTempIds(Collection<String> tempIds);
 
+    List<QwSopTempContent> listByTempId(String tempId);
+
     void removeByWrapper(LambdaQueryWrapper<QwSopTempContent> wrapper);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/sop/service/IQwSopTempDayService.java

@@ -44,6 +44,7 @@ public interface IQwSopTempDayService extends IService<QwSopTempDay> {
     void removeByWrapper(LambdaQueryWrapper<QwSopTempDay> wrapper);
 
     List<QwSopTempDay> listByTempIds(LambdaQueryWrapper<QwSopTempDay> wrapper);
+    List<QwSopTempDay> listByTempById(LambdaQueryWrapper<QwSopTempDay> wrapper);
 
     void updateByWrapper(UpdateWrapper<QwSopTempDay> wrapper);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/sop/service/IQwSopTempRulesService.java

@@ -94,6 +94,8 @@ public interface IQwSopTempRulesService extends IService<QwSopTempRules>{
 
     List<QwSopTempRules> listByCourseId(Long courseId);
 
+    List<QwSopTempRules> listByCourseIdAndTempId(Long courseId,String tempId);
+
     void removeByTempIds(Collection<String> tempIds);
 
     void removeByWrapper(LambdaQueryWrapper<QwSopTempRules> wrapper);

+ 6 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempContentServiceImpl.java

@@ -165,6 +165,12 @@ public class QwSopTempContentServiceImpl extends ServiceImpl<QwSopTempContentMap
         return baseMapper.selectList(new QueryWrapper<QwSopTempContent>().in("temp_id", tempIds));
     }
 
+    @Override
+    @DataSource(DataSourceType.SOP)
+    public List<QwSopTempContent> listByTempId(String tempId) {
+        return baseMapper.selectList(new QueryWrapper<QwSopTempContent>().eq("temp_id", tempId));
+    }
+
     @Override
     @DataSource(DataSourceType.SOP)
     public void removeByWrapper(LambdaQueryWrapper<QwSopTempContent> wrapper) {

+ 7 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempDayServiceImpl.java

@@ -109,6 +109,13 @@ public class QwSopTempDayServiceImpl extends ServiceImpl<QwSopTempDayMapper, QwS
         return this.list(wrapper);
     }
 
+    @Override
+    @DataSource(DataSourceType.SOP)
+    public List<QwSopTempDay> listByTempById(LambdaQueryWrapper<QwSopTempDay> wrapper) {
+        return this.list(wrapper);
+    }
+
+
     @Override
     @DataSource(DataSourceType.SOP)
     public void updateByWrapper(UpdateWrapper<QwSopTempDay> wrapper) {

+ 7 - 2
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempRulesServiceImpl.java

@@ -243,9 +243,14 @@ public class QwSopTempRulesServiceImpl extends ServiceImpl<QwSopTempRulesMapper,
     }
 
     @Override
-    @DataSource(DataSourceType.SOP)
     public List<QwSopTempRules> listByCourseId(Long courseId) {
-        return list(new QueryWrapper<QwSopTempRules>().eq("course_id", courseId));
+//        return list(new QueryWrapper<QwSopTempRules>().eq("course_id", courseId));
+        return qwSopTempRulesMapper.listByCourseId(courseId);
+    }
+
+    @Override
+    public List<QwSopTempRules> listByCourseIdAndTempId(Long courseId, String tempId) {
+        return qwSopTempRulesMapper.listByCourseIdAndTempId(courseId,tempId);
     }
 
     @Override

+ 111 - 35
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.common.BeanCopyUtils;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
 import com.fs.common.exception.base.BaseException;
@@ -321,6 +322,7 @@ public class QwSopTempServiceImpl implements IQwSopTempService {
         if (day == null) return;
         qwSopTempDayService.removeById(day.getId());
         qwSopTempContentService.removeByDayId(day.getId());
+        qwSopTempRulesService.removeByDayId(day.getId());
         reorder(day.getTempId());
     }
 
@@ -633,6 +635,7 @@ public class QwSopTempServiceImpl implements IQwSopTempService {
         if (CollectionUtils.isEmpty(rulesList)) {
             return;
         }
+
         // 获取这些规则关联的模板ID集合
         Set<String> tempIds = rulesList.stream()
                 .map(QwSopTempRules::getTempId)
@@ -641,11 +644,7 @@ public class QwSopTempServiceImpl implements IQwSopTempService {
 
         FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(courseId);
         List<FsUserCourseVideo> videoList = fsUserCourseVideoMapper.selectVideoByCourseId(fsUserCourse.getCourseId());
-        List<QwSopTemp> tempList = qwSopTempMapper.selectListByIds(tempIds);
-        List<QwSopTempContent> contentList = qwSopTempContentService.listByTempIds(tempIds);
-        List<QwSopTempDay> dayList = qwSopTempDayService.listByTempIds(new LambdaQueryWrapper<QwSopTempDay>().in(QwSopTempDay::getTempId, tempIds));
         List<Long> videoIdList = videoList.stream().map(FsUserCourseVideo::getVideoId).collect(Collectors.toList());
-        // videoList转Map key 为videoId value 为 courseSort
         Map<Long, Long> videoSortMap = videoList.stream().collect(Collectors.toMap(FsUserCourseVideo::getVideoId, FsUserCourseVideo::getCourseSort));
 
         // 将课程中已删除的视频在规则和日期中删除
@@ -656,54 +655,131 @@ public class QwSopTempServiceImpl implements IQwSopTempService {
             qwSopTempContentService.removeByWrapper(new LambdaQueryWrapper<QwSopTempContent>().in(QwSopTempContent::getDayId, dayIdList));
         }
 
-        // 需要添加的课程视频
-        List<FsUserCourseVideo> addVideoList = videoList.stream()
-                .filter(e -> rulesList.stream().noneMatch(f -> f.getVideoId().equals(e.getVideoId()))).collect(Collectors.toList());
 
-        if (CollectionUtils.isNotEmpty(addVideoList)) {
-            for (QwSopTemp temp : tempList) {
+        tempIds.forEach(teId->{
+            QwSopTemp sopTemp = qwSopTempMapper.selectQwSopTempById(teId);
+            List<QwSopTempContent> contentList = qwSopTempContentService.listByTempId(teId);
+            List<QwSopTempDay> dayList = qwSopTempDayService.listByTempById(new LambdaQueryWrapper<QwSopTempDay>().in(QwSopTempDay::getTempId, teId));
+            List<QwSopTempRules> tempRulesList = qwSopTempRulesService.listByCourseIdAndTempId(courseId, teId);
+
+            List<FsUserCourseVideo> addVideoList = videoList.stream()
+                    .filter(e -> tempRulesList.stream()
+                            .noneMatch(f -> f.getVideoId().equals(e.getVideoId())))
+                    .collect(Collectors.toList());
+
+            if (CollectionUtils.isNotEmpty(addVideoList)) {
+
                 // 通过历史中的第一课的数据来构建
-                Optional<QwSopTempDay> first = dayList.stream().filter(e -> e.getTempId().equals(temp.getId())).findFirst();
+                Optional<QwSopTempDay> first = dayList.stream().filter(e -> e.getTempId().equals(sopTemp.getId())).findFirst();
                 if (!first.isPresent()) {
-                    break;
+                    return;
                 }
                 QwSopTempDay qwSopTempDay = first.get();
+
                 // 构造timeList timeDesc time
-                temp.setTime(LocalTime.now());
+                sopTemp.setTime(LocalTime.now());
 
-                temp.setTimeList(rulesList.stream()
-                        .filter(e -> e.getTempId().equals(temp.getId()) && Objects.equals(e.getIsOfficial(), "0")
+                sopTemp.setTimeList(tempRulesList.stream()
+                        .filter(e -> e.getTempId().equals(sopTemp.getId()) && Objects.equals(e.getIsOfficial(), "0")
                                 && Objects.equals(e.getDayId(), qwSopTempDay.getId())
                         ).map(QwSopTempRules::getTime)
                         .collect(Collectors.toList()));
 
-                temp.setTimeDesc(contentList.stream().filter(e -> e.getTempId().equals(temp.getId())
+                sopTemp.setTimeDesc(contentList.stream().filter(e -> e.getTempId().equals(sopTemp.getId())
                                 && Objects.isNull(e.getIsBindUrl())
                                 && Objects.equals(qwSopTempDay.getId(), e.getDayId())
                         )
                         .map(m -> JSONObject.parseObject(m.getContent()).getString("value")).collect(Collectors.toList()));
-                temp.setProject(fsUserCourse.getProject());
-                temp.setCourseId(courseId);
-                temp.setOpenOfficial("1");
-                qwSopTempMapper.updateQwSopTemp(temp);
-                createSopTempRules(temp, addVideoList, fsUserCourse);
-            }
-        }
+                sopTemp.setProject(fsUserCourse.getProject());
+                sopTemp.setCourseId(courseId);
+                sopTemp.setOpenOfficial("1");
+
+                qwSopTempMapper.updateQwSopTemp(sopTemp);
+
+                createSopTempRules(sopTemp, addVideoList, fsUserCourse);
+
+                // 更新排序
+                List<QwSopTempRules> newTempRulesList = qwSopTempRulesService.listByCourseIdAndTempId(courseId, teId);
+                // 整理排序
+                Long[] dayIdArray = newTempRulesList.stream().filter(e -> e.getTempId().equals(sopTemp.getId())).sorted(Comparator.comparing(a -> videoSortMap.get(a.getVideoId())))
+                        .map(QwSopTempRules::getDayId).distinct().toArray(Long[]::new);
+                for (int i = 0; i < dayIdArray.length; i++) {
+                    qwSopTempDayService.updateByWrapper(new UpdateWrapper<QwSopTempDay>()
+                            .eq("id", dayIdArray[i])
+                            .set("sorts", i + 1)
+                            .set("name", "第" + (i + 1) + "天")
+                            .set("day_num", i + 1)
+                    );
+                }
 
-        // 整理排序
-        List<QwSopTempRules> afterRuleList = qwSopTempRulesService.listByCourseId(courseId);
-        for (QwSopTemp temp : tempList) {
-            Long[] dayIdArray = afterRuleList.stream().filter(e -> e.getTempId().equals(temp.getId())).sorted(Comparator.comparing(a -> videoSortMap.get(a.getVideoId())))
-                    .map(QwSopTempRules::getDayId).distinct().toArray(Long[]::new);
-            for (int i = 0; i < dayIdArray.length; i++) {
-                qwSopTempDayService.updateByWrapper(new UpdateWrapper<QwSopTempDay>()
-                        .eq("id", dayIdArray[i])
-                        .set("sorts", i + 1)
-                        .set("name", "第" + (i + 1) + "天")
-                        .set("day_num", i + 1)
-                );
             }
-        }
+        });
+
+//        FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(courseId);
+//        List<FsUserCourseVideo> videoList = fsUserCourseVideoMapper.selectVideoByCourseId(fsUserCourse.getCourseId());
+//        List<QwSopTemp> tempList = qwSopTempMapper.selectListByIds(tempIds);
+//        List<QwSopTempContent> contentList = qwSopTempContentService.listByTempIds(tempIds);
+//        List<QwSopTempDay> dayList = qwSopTempDayService.listByTempIds(new LambdaQueryWrapper<QwSopTempDay>().in(QwSopTempDay::getTempId, tempIds));
+//        List<Long> videoIdList = videoList.stream().map(FsUserCourseVideo::getVideoId).collect(Collectors.toList());
+//        // videoList转Map key 为videoId value 为 courseSort
+//        Map<Long, Long> videoSortMap = videoList.stream().collect(Collectors.toMap(FsUserCourseVideo::getVideoId, FsUserCourseVideo::getCourseSort));
+
+        // 将课程中已删除的视频在规则和日期中删除
+//        Set<Long> dayIdList = rulesList.stream().filter(e -> !videoIdList.contains(e.getVideoId())).map(QwSopTempRules::getDayId).collect(Collectors.toSet());
+//        if (CollectionUtils.isNotEmpty(dayIdList)) {
+//            qwSopTempDayService.removeByWrapper(new LambdaQueryWrapper<QwSopTempDay>().in(QwSopTempDay::getId, dayIdList));
+//            qwSopTempRulesService.removeByWrapper(new LambdaQueryWrapper<QwSopTempRules>().in(QwSopTempRules::getDayId, dayIdList));
+//            qwSopTempContentService.removeByWrapper(new LambdaQueryWrapper<QwSopTempContent>().in(QwSopTempContent::getDayId, dayIdList));
+//        }
+
+        // 需要添加的课程视频
+//        List<FsUserCourseVideo> addVideoList = videoList.stream()
+//                .filter(e -> rulesList.stream().noneMatch(f -> f.getVideoId().equals(e.getVideoId()))).collect(Collectors.toList());
+
+//        if (CollectionUtils.isNotEmpty(addVideoList)) {
+//            for (QwSopTemp temp : tempList) {
+//                // 通过历史中的第一课的数据来构建
+//                Optional<QwSopTempDay> first = dayList.stream().filter(e -> e.getTempId().equals(temp.getId())).findFirst();
+//                if (!first.isPresent()) {
+//                    break;
+//                }
+//                QwSopTempDay qwSopTempDay = first.get();
+//                // 构造timeList timeDesc time
+//                temp.setTime(LocalTime.now());
+//
+//                temp.setTimeList(rulesList.stream()
+//                        .filter(e -> e.getTempId().equals(temp.getId()) && Objects.equals(e.getIsOfficial(), "0")
+//                                && Objects.equals(e.getDayId(), qwSopTempDay.getId())
+//                        ).map(QwSopTempRules::getTime)
+//                        .collect(Collectors.toList()));
+//
+//                temp.setTimeDesc(contentList.stream().filter(e -> e.getTempId().equals(temp.getId())
+//                                && Objects.isNull(e.getIsBindUrl())
+//                                && Objects.equals(qwSopTempDay.getId(), e.getDayId())
+//                        )
+//                        .map(m -> JSONObject.parseObject(m.getContent()).getString("value")).collect(Collectors.toList()));
+//                temp.setProject(fsUserCourse.getProject());
+//                temp.setCourseId(courseId);
+//                temp.setOpenOfficial("1");
+//                qwSopTempMapper.updateQwSopTemp(temp);
+//                createSopTempRules(temp, addVideoList, fsUserCourse);
+//            }
+//        }
+
+//        // 整理排序
+//        List<QwSopTempRules> afterRuleList = qwSopTempRulesService.listByCourseId(courseId);
+//        for (QwSopTemp temp : tempList) {
+//            Long[] dayIdArray = afterRuleList.stream().filter(e -> e.getTempId().equals(temp.getId())).sorted(Comparator.comparing(a -> videoSortMap.get(a.getVideoId())))
+//                    .map(QwSopTempRules::getDayId).distinct().toArray(Long[]::new);
+//            for (int i = 0; i < dayIdArray.length; i++) {
+//                qwSopTempDayService.updateByWrapper(new UpdateWrapper<QwSopTempDay>()
+//                        .eq("id", dayIdArray[i])
+//                        .set("sorts", i + 1)
+//                        .set("name", "第" + (i + 1) + "天")
+//                        .set("day_num", i + 1)
+//                );
+//            }
+//        }
     }
 
 }

+ 3 - 1
fs-service/src/main/resources/application-druid-cfryt.yml

@@ -168,5 +168,7 @@ openIM:
 im:
     type: OPENIM
 #是否为新商户,新商户不走mpOpenId
-isNewWxMerchant: true
+isNewWxMerchant: false
+
+enableRedPackAccount: 0
 

+ 438 - 345
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -60,7 +60,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         l.log_type,SEC_TO_TIME(l.duration) as duration,c.company_name,l.camp_period_time,l.finish_time,
         cu.nick_name as company_user_name ,l.send_type,l.create_time,l.update_time,l.last_heartbeat_time,
         qu.qw_user_name,qec.name as external_user_name,c.company_id,u.avatar as fsAvatar,u.nick_name as fsNickName,qec.create_time as qec_create_time,
-        u.is_vip isVip,l.reward_type
+        u.is_vip isVip,l.reward_type,cu.dept_id
          from fs_course_watch_log l
          left join fs_user_course_video v on v.video_id = l.video_id
          left join fs_user_course uc on uc.course_id = l.course_id
@@ -172,358 +172,358 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     #{item}
                 </foreach>
             </if>
-           <if test="maps.userIds != null and !maps.userIds.isEmpty()">
-            AND l.company_user_id IN
-               <foreach collection='maps.userIds' item='item' open='(' separator=',' close=')'>
-                  #{item}
-               </foreach>
+            <if test="maps.userIds != null and !maps.userIds.isEmpty()">
+                AND cu.user_id IN
+                    <foreach collection='maps.userIds' item='item' open='(' separator=',' close=')'>
+                        #{item}
+                    </foreach>
             </if>
-        </where>
-         order by l.finish_time desc,l.update_time desc,l.create_time desc
-    </select>
+                </where>
+                 order by l.finish_time desc,l.update_time desc,l.create_time desc
+            </select>
 
-    <select id="selectFsCourseWatchLogListByParam" resultType="com.fs.course.vo.FsCourseWatchLogListVO">
-        select l.log_id,l.user_id,uc.course_name,v.title as video_name,u.nick_name as fsNickName, u.avatar as fsAvatar,
-        l.log_type,SEC_TO_TIME(l.duration) as duration,c.company_name,l.camp_period_time,l.finish_time,
-        cu.nick_name as company_user_name ,l.send_type,l.create_time, qu.qw_user_name,qec.name as external_user_name
-        from fs_course_watch_log l
-        left join fs_user_course_video v on v.video_id = l.video_id
-        left join fs_user_course uc on uc.course_id = l.course_id
-        left join fs_user u on u.user_id = l.user_id
-        left join company_user cu on cu.user_id = l.company_user_id
-        left join company c on c.company_id = l.company_id
-        LEFT JOIN qw_user qu on qu.id= l.qw_user_id
-        LEFT JOIN qw_external_contact qec on l.qw_external_contact_id = qec.id
-        <where>
-            <if test ='userId !=null'>
-                and l.user_id = #{userId}
-            </if>
-            <if test ='qwUserId !=null'>
-                and l.qw_user_id = #{qwUserId}
-            </if>
-            <if test ='courseId !=null'>
-                and l.course_id = #{courseId}
-            </if>
-            <if test ='videoId !=null'>
-                and l.video_id = #{videoId}
-            </if>
-            <if test ='logType !=null'>
-                and l.log_type = #{logType}
-            </if>
-            <if test ='companyId !=null'>
-                and l.company_id = #{companyId}
-            </if>
-            <if test ='companyUserId !=null'>
-                and l.company_user_id = #{companyUserId}
-            </if>
-            <if test ='companyUserName !=null and maps.companyUserName!=""'>
-                and cu.nick_name  like concat('%', #{companyUserName}, '%')
-            </if>
-            <if test ='nickName !=null and maps.nickName!=""'>
-                and u.nick_name  like concat('%', #{nickName}, '%')
-            </if>
-            <if test= 'sTime != null '>
-                and DATE(l.create_time) &gt;= DATE(#{sTime})
-            </if>
-            <if test='eTime != null '>
-                and DATE(l.create_time) &lt;= DATE(#{eTime})
-            </if>
-            <if test= 'maps.scheduleStartTime != null '>
-                and DATE(l.camp_period_time) &gt;= DATE(#{maps.scheduleStartTime})
-            </if>
-            <if test='maps.scheduleEndTime != null '>
-                and DATE(l.camp_period_time) &lt;= DATE(#{maps.scheduleEndTime})
-            </if>
-            <if test="sopIds != null and sopIds.size() > 0">
-                and l.sop_id in
-                <foreach item="sopId" index="index" collection="sopIds" open="(" separator="," close=")">
-                    #{sopId}
+            <select id="selectFsCourseWatchLogListByParam" resultType="com.fs.course.vo.FsCourseWatchLogListVO">
+                select l.log_id,l.user_id,uc.course_name,v.title as video_name,u.nick_name as fsNickName, u.avatar as fsAvatar,
+                l.log_type,SEC_TO_TIME(l.duration) as duration,c.company_name,l.camp_period_time,l.finish_time,
+                cu.nick_name as company_user_name ,l.send_type,l.create_time, qu.qw_user_name,qec.name as external_user_name
+                from fs_course_watch_log l
+                left join fs_user_course_video v on v.video_id = l.video_id
+                left join fs_user_course uc on uc.course_id = l.course_id
+                left join fs_user u on u.user_id = l.user_id
+                left join company_user cu on cu.user_id = l.company_user_id
+                left join company c on c.company_id = l.company_id
+                LEFT JOIN qw_user qu on qu.id= l.qw_user_id
+                LEFT JOIN qw_external_contact qec on l.qw_external_contact_id = qec.id
+                <where>
+                    <if test ='userId !=null'>
+                        and l.user_id = #{userId}
+                    </if>
+                    <if test ='qwUserId !=null'>
+                        and l.qw_user_id = #{qwUserId}
+                    </if>
+                    <if test ='courseId !=null'>
+                        and l.course_id = #{courseId}
+                    </if>
+                    <if test ='videoId !=null'>
+                        and l.video_id = #{videoId}
+                    </if>
+                    <if test ='logType !=null'>
+                        and l.log_type = #{logType}
+                    </if>
+                    <if test ='companyId !=null'>
+                        and l.company_id = #{companyId}
+                    </if>
+                    <if test ='companyUserId !=null'>
+                        and l.company_user_id = #{companyUserId}
+                    </if>
+                    <if test ='companyUserName !=null and maps.companyUserName!=""'>
+                        and cu.nick_name  like concat('%', #{companyUserName}, '%')
+                    </if>
+                    <if test ='nickName !=null and maps.nickName!=""'>
+                        and u.nick_name  like concat('%', #{nickName}, '%')
+                    </if>
+                    <if test= 'sTime != null '>
+                        and DATE(l.create_time) &gt;= DATE(#{sTime})
+                    </if>
+                    <if test='eTime != null '>
+                        and DATE(l.create_time) &lt;= DATE(#{eTime})
+                    </if>
+                    <if test= 'maps.scheduleStartTime != null '>
+                        and DATE(l.camp_period_time) &gt;= DATE(#{maps.scheduleStartTime})
+                    </if>
+                    <if test='maps.scheduleEndTime != null '>
+                        and DATE(l.camp_period_time) &lt;= DATE(#{maps.scheduleEndTime})
+                    </if>
+                    <if test="sopIds != null and sopIds.size() > 0">
+                        and l.sop_id in
+                        <foreach item="sopId" index="index" collection="sopIds" open="(" separator="," close=")">
+                            #{sopId}
+                        </foreach>
+                    </if>
+                </where>
+                order by l.log_id desc
+            </select>
+            <insert id="insertFsCourseWatchLog" parameterType="FsCourseWatchLog" useGeneratedKeys="true" keyProperty="logId">
+                insert into fs_course_watch_log
+                <trim prefix="(" suffix=")" suffixOverrides=",">
+                    <if test="userId != null">user_id,</if>
+                    <if test="videoId != null">video_id,</if>
+                    <if test="logType != null">log_type,</if>
+                    <if test="createTime != null">create_time,</if>
+                    <if test="updateTime != null">update_time,</if>
+                    <if test="qwExternalContactId != null">qw_external_contact_id,</if>
+                    <if test="duration != null">duration,</if>
+                    <if test="qwUserId != null">qw_user_id,</if>
+                    <if test="companyUserId != null">company_user_id,</if>
+                    <if test="companyId != null">company_id,</if>
+                    <if test="courseId != null">course_id,</if>
+                    <if test="sendType != null">send_type,</if>
+                    <if test="rewardType != null">reward_type,</if>
+                    <if test="sopId != null">sop_id,</if>
+                    <if test="finishTime != null">finish_time,</if>
+                    <if test="sendFinishMsg != null">send_finish_msg,</if>
+                    <if test="campPeriodTime != null">camp_period_time,</if>
+                    <if test="periodId != null">period_id,</if>
+                    <if test="project != null">project,</if>
+                </trim>
+                <trim prefix="values (" suffix=")" suffixOverrides=",">
+                    <if test="userId != null">#{userId},</if>
+                    <if test="videoId != null">#{videoId},</if>
+                    <if test="logType != null">#{logType},</if>
+                    <if test="createTime != null">#{createTime},</if>
+                    <if test="updateTime != null">#{updateTime},</if>
+                    <if test="qwExternalContactId != null">#{qwExternalContactId},</if>
+                    <if test="duration != null">#{duration},</if>
+                    <if test="qwUserId != null">#{qwUserId},</if>
+                    <if test="companyUserId != null">#{companyUserId},</if>
+                    <if test="companyId != null">#{companyId},</if>
+                    <if test="courseId != null">#{courseId},</if>
+                    <if test="sendType != null">#{sendType},</if>
+                    <if test="rewardType != null">#{rewardType},</if>
+                    <if test="sopId != null">#{sopId},</if>
+                    <if test="finishTime != null">#{finishTime},</if>
+                    <if test="sendFinishMsg != null">#{sendFinishMsg},</if>
+                    <if test="campPeriodTime != null">#{campPeriodTime},</if>
+                    <if test="periodId != null">#{periodId},</if>
+                    <if test="project != null">#{project},</if>
+                </trim>
+            </insert>
+
+            <insert id="insertOrUpdateFsCourseWatchLog" parameterType="FsCourseWatchLog">
+                insert into fs_course_watch_log
+                <trim prefix="(" suffix=")" suffixOverrides=",">
+                    <if test="userId != null">user_id,</if>
+                    <if test="videoId != null">video_id,</if>
+                    <if test="logType != null">log_type,</if>
+                    <if test="createTime != null">create_time,</if>
+                    <if test="updateTime != null">update_time,</if>
+                    <if test="qwExternalContactId != null">qw_external_contact_id,</if>
+                    <if test="duration != null">duration,</if>
+                    <if test="qwUserId != null">qw_user_id,</if>
+                    <if test="companyUserId != null">company_user_id,</if>
+                    <if test="companyId != null">company_id,</if>
+                    <if test="courseId != null">course_id,</if>
+                    <if test="sendType != null">send_type,</if>
+                    <if test="rewardType != null">reward_type,</if>
+                    <if test="sopId != null">sop_id,</if>
+                    <if test="finishTime != null">finish_time,</if>
+                    <if test="sendFinishMsg != null">send_finish_msg,</if>
+                    <if test="campPeriodTime != null">camp_period_time,</if>
+                    <if test="project != null">project,</if>
+                </trim>
+                <trim prefix="values (" suffix=")" suffixOverrides=",">
+                    <if test="userId != null">#{userId},</if>
+                    <if test="videoId != null">#{videoId},</if>
+                    <if test="logType != null">#{logType},</if>
+                    <if test="createTime != null">#{createTime},</if>
+                    <if test="updateTime != null">#{updateTime},</if>
+                    <if test="qwExternalContactId != null">#{qwExternalContactId},</if>
+                    <if test="duration != null">#{duration},</if>
+                    <if test="qwUserId != null">#{qwUserId},</if>
+                    <if test="companyUserId != null">#{companyUserId},</if>
+                    <if test="companyId != null">#{companyId},</if>
+                    <if test="courseId != null">#{courseId},</if>
+                    <if test="sendType != null">#{sendType},</if>
+                    <if test="rewardType != null">#{rewardType},</if>
+                    <if test="sopId != null">#{sopId},</if>
+                    <if test="finishTime != null">#{finishTime},</if>
+                    <if test="sendFinishMsg != null">#{sendFinishMsg},</if>
+                    <if test="campPeriodTime != null">#{campPeriodTime},</if>
+                    <if test="project != null">#{project},</if>
+                </trim>
+                on duplicate key update
+                <trim suffixOverrides=",">
+                    <if test="updateTime != null">update_time = #{updateTime},</if>
+                </trim>
+
+            </insert>
+
+
+            <insert id="insertFsCourseWatchLogBatch" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="logId">
+                INSERT INTO fs_course_watch_log (
+                user_id,
+                video_id,
+                log_type,
+                create_time,
+                update_time,
+                qw_external_contact_id,
+                duration,
+                qw_user_id,
+                company_user_id,
+                company_id,
+                course_id,
+                send_type,
+                reward_type,
+                sop_id,
+                camp_period_time,
+                project,
+                period_id,
+                im_msg_send_detail_id
+                )
+                VALUES
+                <foreach collection="watchLogs" item="log" separator=",">
+                    (
+                    #{log.userId},
+                    #{log.videoId},
+                    #{log.logType},
+                    #{log.createTime},
+                    #{log.updateTime},
+                    #{log.qwExternalContactId},
+                    #{log.duration},
+                    #{log.qwUserId},
+                    #{log.companyUserId},
+                    #{log.companyId},
+                    #{log.courseId},
+                    #{log.sendType},
+                    #{log.rewardType},
+                    #{log.sopId},
+                    #{log.campPeriodTime},
+                    #{log.project},
+                    #{log.periodId},
+                    #{log.imMsgSendDetailId}
+                    )
                 </foreach>
-            </if>
-        </where>
-        order by l.log_id desc
-    </select>
-    <insert id="insertFsCourseWatchLog" parameterType="FsCourseWatchLog" useGeneratedKeys="true" keyProperty="logId">
-        insert into fs_course_watch_log
-        <trim prefix="(" suffix=")" suffixOverrides=",">
-            <if test="userId != null">user_id,</if>
-            <if test="videoId != null">video_id,</if>
-            <if test="logType != null">log_type,</if>
-            <if test="createTime != null">create_time,</if>
-            <if test="updateTime != null">update_time,</if>
-            <if test="qwExternalContactId != null">qw_external_contact_id,</if>
-            <if test="duration != null">duration,</if>
-            <if test="qwUserId != null">qw_user_id,</if>
-            <if test="companyUserId != null">company_user_id,</if>
-            <if test="companyId != null">company_id,</if>
-            <if test="courseId != null">course_id,</if>
-            <if test="sendType != null">send_type,</if>
-            <if test="rewardType != null">reward_type,</if>
-            <if test="sopId != null">sop_id,</if>
-            <if test="finishTime != null">finish_time,</if>
-            <if test="sendFinishMsg != null">send_finish_msg,</if>
-            <if test="campPeriodTime != null">camp_period_time,</if>
-            <if test="periodId != null">period_id,</if>
-            <if test="project != null">project,</if>
-        </trim>
-        <trim prefix="values (" suffix=")" suffixOverrides=",">
-            <if test="userId != null">#{userId},</if>
-            <if test="videoId != null">#{videoId},</if>
-            <if test="logType != null">#{logType},</if>
-            <if test="createTime != null">#{createTime},</if>
-            <if test="updateTime != null">#{updateTime},</if>
-            <if test="qwExternalContactId != null">#{qwExternalContactId},</if>
-            <if test="duration != null">#{duration},</if>
-            <if test="qwUserId != null">#{qwUserId},</if>
-            <if test="companyUserId != null">#{companyUserId},</if>
-            <if test="companyId != null">#{companyId},</if>
-            <if test="courseId != null">#{courseId},</if>
-            <if test="sendType != null">#{sendType},</if>
-            <if test="rewardType != null">#{rewardType},</if>
-            <if test="sopId != null">#{sopId},</if>
-            <if test="finishTime != null">#{finishTime},</if>
-            <if test="sendFinishMsg != null">#{sendFinishMsg},</if>
-            <if test="campPeriodTime != null">#{campPeriodTime},</if>
-            <if test="periodId != null">#{periodId},</if>
-            <if test="project != null">#{project},</if>
-        </trim>
-    </insert>
-
-    <insert id="insertOrUpdateFsCourseWatchLog" parameterType="FsCourseWatchLog">
-        insert into fs_course_watch_log
-        <trim prefix="(" suffix=")" suffixOverrides=",">
-            <if test="userId != null">user_id,</if>
-            <if test="videoId != null">video_id,</if>
-            <if test="logType != null">log_type,</if>
-            <if test="createTime != null">create_time,</if>
-            <if test="updateTime != null">update_time,</if>
-            <if test="qwExternalContactId != null">qw_external_contact_id,</if>
-            <if test="duration != null">duration,</if>
-            <if test="qwUserId != null">qw_user_id,</if>
-            <if test="companyUserId != null">company_user_id,</if>
-            <if test="companyId != null">company_id,</if>
-            <if test="courseId != null">course_id,</if>
-            <if test="sendType != null">send_type,</if>
-            <if test="rewardType != null">reward_type,</if>
-            <if test="sopId != null">sop_id,</if>
-            <if test="finishTime != null">finish_time,</if>
-            <if test="sendFinishMsg != null">send_finish_msg,</if>
-            <if test="campPeriodTime != null">camp_period_time,</if>
-            <if test="project != null">project,</if>
-        </trim>
-        <trim prefix="values (" suffix=")" suffixOverrides=",">
-            <if test="userId != null">#{userId},</if>
-            <if test="videoId != null">#{videoId},</if>
-            <if test="logType != null">#{logType},</if>
-            <if test="createTime != null">#{createTime},</if>
-            <if test="updateTime != null">#{updateTime},</if>
-            <if test="qwExternalContactId != null">#{qwExternalContactId},</if>
-            <if test="duration != null">#{duration},</if>
-            <if test="qwUserId != null">#{qwUserId},</if>
-            <if test="companyUserId != null">#{companyUserId},</if>
-            <if test="companyId != null">#{companyId},</if>
-            <if test="courseId != null">#{courseId},</if>
-            <if test="sendType != null">#{sendType},</if>
-            <if test="rewardType != null">#{rewardType},</if>
-            <if test="sopId != null">#{sopId},</if>
-            <if test="finishTime != null">#{finishTime},</if>
-            <if test="sendFinishMsg != null">#{sendFinishMsg},</if>
-            <if test="campPeriodTime != null">#{campPeriodTime},</if>
-            <if test="project != null">#{project},</if>
-        </trim>
-        on duplicate key update
-        <trim suffixOverrides=",">
-            <if test="updateTime != null">update_time = #{updateTime},</if>
-        </trim>
-
-    </insert>
-
-
-    <insert id="insertFsCourseWatchLogBatch" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="logId">
-        INSERT INTO fs_course_watch_log (
-        user_id,
-        video_id,
-        log_type,
-        create_time,
-        update_time,
-        qw_external_contact_id,
-        duration,
-        qw_user_id,
-        company_user_id,
-        company_id,
-        course_id,
-        send_type,
-        reward_type,
-        sop_id,
-        camp_period_time,
-        project,
-        period_id,
-        im_msg_send_detail_id
-        )
-        VALUES
-        <foreach collection="watchLogs" item="log" separator=",">
-            (
-            #{log.userId},
-            #{log.videoId},
-            #{log.logType},
-            #{log.createTime},
-            #{log.updateTime},
-            #{log.qwExternalContactId},
-            #{log.duration},
-            #{log.qwUserId},
-            #{log.companyUserId},
-            #{log.companyId},
-            #{log.courseId},
-            #{log.sendType},
-            #{log.rewardType},
-            #{log.sopId},
-            #{log.campPeriodTime},
-            #{log.project},
-            #{log.periodId},
-            #{log.imMsgSendDetailId}
-            )
-        </foreach>
-        ON DUPLICATE KEY UPDATE
-        update_time = NOW(),
-        im_msg_send_detail_id = VALUES(im_msg_send_detail_id)
-    </insert>
-
-
-
-    <update id="updateFsCourseWatchLog" parameterType="FsCourseWatchLog">
-        update fs_course_watch_log
-        <trim prefix="SET" suffixOverrides=",">
-            <if test="userId != null">user_id = #{userId},</if>
-            <if test="videoId != null">video_id = #{videoId},</if>
-            <if test="logType != null">log_type = #{logType},</if>
-            <if test="createTime != null">create_time = #{createTime},</if>
-            <if test="updateTime != null">update_time = #{updateTime},</if>
-            <if test="qwExternalContactId != null">qw_external_contact_id = #{qwExternalContactId},</if>
-            <if test="duration != null">duration = #{duration},</if>
-            <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
-            <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
-            <if test="companyId != null">company_id = #{companyId},</if>
-            <if test="courseId != null">course_id = #{courseId},</if>
-            <if test="sendType != null">send_type = #{sendType},</if>
-            <if test="rewardType != null">reward_type = #{rewardType},</if>
-            <if test="sopId != null">sop_id = #{sopId},</if>
-            <if test="finishTime != null">finish_time = #{finishTime},</if>
-            <if test="sendFinishMsg != null">send_finish_msg = #{sendFinishMsg},</if>
-            <if test="lastHeartbeatTime != null">last_heartbeat_time = #{lastHeartbeatTime},</if>
-            <if test="periodId != null">period_id = #{periodId},</if>
-            <if test="project != null">project = #{project},</if>
-        </trim>
-        where log_id = #{logId}
-    </update>
+                ON DUPLICATE KEY UPDATE
+                update_time = NOW(),
+                im_msg_send_detail_id = VALUES(im_msg_send_detail_id)
+            </insert>
 
-    <delete id="deleteFsCourseWatchLogByLogId" parameterType="Long">
-        delete from fs_course_watch_log where log_id = #{logId}
-    </delete>
 
-    <delete id="deleteFsCourseWatchLogByLogIds" parameterType="String">
-        delete from fs_course_watch_log where log_id in
-        <foreach item="logId" collection="array" open="(" separator="," close=")">
-            #{logId}
-        </foreach>
-    </delete>
 
-    <select id="selectFsCourseWatchLogByFinishTime" resultType="com.fs.course.param.FsCourseWatchLogByFinishTimeParam">
-        <![CDATA[
-        SELECT
-            fcwl.log_id,
-            fcwl.create_time,
-            fcwl.qw_external_contact_id,
-            fcwl.qw_user_id,
-            fcwl.user_id,
-            fcwl.company_user_id,
-            fcwl.company_id,
-            fcwl.sop_id,
-            fcwl.finish_time,
-            fcwl.camp_period_time,
-            qec.corp_id,
-            qec.external_user_id,
-            qec.tag_ids,
-            qec.user_id AS qw_user,
-            qec.name AS external_contact_name
-        FROM
-            fs_course_watch_log fcwl
-                LEFT JOIN qw_external_contact qec ON fcwl.qw_external_contact_id = qec.id
-        WHERE
-            DATE(fcwl.finish_time)= '2025-02-09'
-          and fcwl.camp_period_time is not NULL
-        ]]>
-    </select>
-    <select id="getWatchLogByFsUser" resultType="com.fs.course.domain.FsCourseWatchLog">
-        SELECT
-            log_id,
-            user_id,
-            video_id,
-            log_type,
-            create_time,
-            update_time,
-            duration,
-            company_user_id,
-            company_id,
-            course_id,
-            send_type,
-            reward_type,
-            last_heartbeat_time,
-            sop_id,
-            finish_time,
-            send_finish_msg,
-            camp_period_time
-        FROM
-            fs_course_watch_log
-        WHERE
-            send_type = 1
-          AND video_id = #{videoId}
-          AND user_id = #{fsUserId}
-          AND company_user_id = #{companyUserId}  order by log_id desc limit 1
-    </select>
-    <select id="selectFsCourseWatchLogStatisticsListVONew"
-            resultType="com.fs.course.vo.FsCourseWatchLogStatisticsListVO">
-        SELECT
-        o.company_user_id,o.user_id,DATE(o.create_time) create_time,
-        SUM(CASE WHEN o.log_type = '1' THEN 1 ELSE 0 END) AS type1,
-        SUM(CASE WHEN o.log_type = '2' THEN 1 ELSE 0 END) AS type2,
-        SUM(CASE WHEN o.log_type = '3' THEN 1 ELSE 0 END) AS type3,
-        SUM(CASE WHEN o.log_type = '4' THEN 1 ELSE 0 END) AS type4,
-        o.project as project,
-        o.course_id as course_id,
-        o.video_id as video_id
-        FROM fs_course_watch_log o
-        <where>
-            send_type=1
-            <if test="companyId != null">
-                and o.company_id=#{companyId}
-            </if>
-            <if test= 'sTime != null '>
-                and DATE(o.create_time) &gt;= #{sTime}
-            </if>
-            <if test='eTime != null '>
-                and DATE(o.create_time) &lt;= #{eTime}
-            </if>
-            <if test ='courseId !=null'>
-                and o.course_id = #{courseId}
-            </if>
-            <if test ='videoId !=null'>
-                and o.video_id = #{videoId}
-            </if>
-            <if test="companyUserId != null">
-                and o.company_user_id = #{companyUserId}
-            </if>
-            <if test="project != null">
-                and o.project = #{project}
-            </if>
-            <if test="userId != null">
-                and o.user_id = #{userId}
-            </if>
-        </where>
+            <update id="updateFsCourseWatchLog" parameterType="FsCourseWatchLog">
+                update fs_course_watch_log
+                <trim prefix="SET" suffixOverrides=",">
+                    <if test="userId != null">user_id = #{userId},</if>
+                    <if test="videoId != null">video_id = #{videoId},</if>
+                    <if test="logType != null">log_type = #{logType},</if>
+                    <if test="createTime != null">create_time = #{createTime},</if>
+                    <if test="updateTime != null">update_time = #{updateTime},</if>
+                    <if test="qwExternalContactId != null">qw_external_contact_id = #{qwExternalContactId},</if>
+                    <if test="duration != null">duration = #{duration},</if>
+                    <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
+                    <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+                    <if test="companyId != null">company_id = #{companyId},</if>
+                    <if test="courseId != null">course_id = #{courseId},</if>
+                    <if test="sendType != null">send_type = #{sendType},</if>
+                    <if test="rewardType != null">reward_type = #{rewardType},</if>
+                    <if test="sopId != null">sop_id = #{sopId},</if>
+                    <if test="finishTime != null">finish_time = #{finishTime},</if>
+                    <if test="sendFinishMsg != null">send_finish_msg = #{sendFinishMsg},</if>
+                    <if test="lastHeartbeatTime != null">last_heartbeat_time = #{lastHeartbeatTime},</if>
+                    <if test="periodId != null">period_id = #{periodId},</if>
+                    <if test="project != null">project = #{project},</if>
+                </trim>
+                where log_id = #{logId}
+            </update>
 
-        GROUP BY o.video_id,o.user_id,DATE(o.create_time),o.project,o.course_id
-        ORDER BY o.video_id ,DATE(o.create_time)
+            <delete id="deleteFsCourseWatchLogByLogId" parameterType="Long">
+                delete from fs_course_watch_log where log_id = #{logId}
+            </delete>
+
+            <delete id="deleteFsCourseWatchLogByLogIds" parameterType="String">
+                delete from fs_course_watch_log where log_id in
+                <foreach item="logId" collection="array" open="(" separator="," close=")">
+                    #{logId}
+                </foreach>
+            </delete>
 
-<!--        limit ${(pageNum-1)*pageSize},${pageSize}-->
+            <select id="selectFsCourseWatchLogByFinishTime" resultType="com.fs.course.param.FsCourseWatchLogByFinishTimeParam">
+                <![CDATA[
+                SELECT
+                    fcwl.log_id,
+                    fcwl.create_time,
+                    fcwl.qw_external_contact_id,
+                    fcwl.qw_user_id,
+                    fcwl.user_id,
+                    fcwl.company_user_id,
+                    fcwl.company_id,
+                    fcwl.sop_id,
+                    fcwl.finish_time,
+                    fcwl.camp_period_time,
+                    qec.corp_id,
+                    qec.external_user_id,
+                    qec.tag_ids,
+                    qec.user_id AS qw_user,
+                    qec.name AS external_contact_name
+                FROM
+                    fs_course_watch_log fcwl
+                        LEFT JOIN qw_external_contact qec ON fcwl.qw_external_contact_id = qec.id
+                WHERE
+                    DATE(fcwl.finish_time)= '2025-02-09'
+                  and fcwl.camp_period_time is not NULL
+                ]]>
+            </select>
+            <select id="getWatchLogByFsUser" resultType="com.fs.course.domain.FsCourseWatchLog">
+                SELECT
+                    log_id,
+                    user_id,
+                    video_id,
+                    log_type,
+                    create_time,
+                    update_time,
+                    duration,
+                    company_user_id,
+                    company_id,
+                    course_id,
+                    send_type,
+                    reward_type,
+                    last_heartbeat_time,
+                    sop_id,
+                    finish_time,
+                    send_finish_msg,
+                    camp_period_time
+                FROM
+                    fs_course_watch_log
+                WHERE
+                    send_type = 1
+                  AND video_id = #{videoId}
+                  AND user_id = #{fsUserId}
+                  AND company_user_id = #{companyUserId}  order by log_id desc limit 1
+            </select>
+            <select id="selectFsCourseWatchLogStatisticsListVONew"
+                    resultType="com.fs.course.vo.FsCourseWatchLogStatisticsListVO">
+                SELECT
+                o.company_user_id,o.user_id,DATE(o.create_time) create_time,
+                SUM(CASE WHEN o.log_type = '1' THEN 1 ELSE 0 END) AS type1,
+                SUM(CASE WHEN o.log_type = '2' THEN 1 ELSE 0 END) AS type2,
+                SUM(CASE WHEN o.log_type = '3' THEN 1 ELSE 0 END) AS type3,
+                SUM(CASE WHEN o.log_type = '4' THEN 1 ELSE 0 END) AS type4,
+                o.project as project,
+                o.course_id as course_id,
+                o.video_id as video_id
+                FROM fs_course_watch_log o
+                <where>
+                    send_type=1
+                    <if test="companyId != null">
+                        and o.company_id=#{companyId}
+                    </if>
+                    <if test= 'sTime != null '>
+                        and DATE(o.create_time) &gt;= #{sTime}
+                    </if>
+                    <if test='eTime != null '>
+                        and DATE(o.create_time) &lt;= #{eTime}
+                    </if>
+                    <if test ='courseId !=null'>
+                        and o.course_id = #{courseId}
+                    </if>
+                    <if test ='videoId !=null'>
+                        and o.video_id = #{videoId}
+                    </if>
+                    <if test="companyUserId != null">
+                        and o.company_user_id = #{companyUserId}
+                    </if>
+                    <if test="project != null">
+                        and o.project = #{project}
+                    </if>
+                    <if test="userId != null">
+                        and o.user_id = #{userId}
+                    </if>
+                </where>
+
+                GROUP BY o.video_id,o.user_id,DATE(o.create_time),o.project,o.course_id
+                ORDER BY o.video_id ,DATE(o.create_time)
+
+        <!--        limit ${(pageNum-1)*pageSize},${pageSize}-->
     </select>
     <select id="selectFsCourseWatchLogStatisticsListVONewCount" resultType="java.lang.Long">
         SELECT COUNT(*)
@@ -1005,4 +1005,97 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             o.send_type
     </select>
 
+
+    <select id="selectFsCourseWatchLogStatisticsListVO_COUNT"
+            resultType="java.lang.Long">
+        SELECT COUNT(*) FROM (
+        SELECT
+        o.video_id,
+        <!-- 用choose保证sendType逻辑互斥,避免GROUP BY字段缺失 -->
+        <choose>
+            <when test="sendType != 1">
+                o.qw_user_id,
+            </when>
+            <when test="sendType == 1">
+                o.company_user_id,
+            </when>
+            <!-- sendType为null时兜底,避免空指针 -->
+            <otherwise>
+                o.qw_user_id,
+            </otherwise>
+        </choose>
+        DATE(o.create_time) create_time
+        FROM fs_course_watch_log o
+        <!-- 动态关联qw_user表 -->
+        <if test="sendType != 1">
+            LEFT JOIN qw_user qu ON qu.id = o.qw_user_id
+        </if>
+        LEFT JOIN fs_user_course_video v ON v.video_id = o.video_id
+        LEFT JOIN fs_user_course uc ON uc.course_id = v.course_id
+        <!-- 动态关联company_user表 -->
+        <if test="sendType == 1">
+            LEFT JOIN company_user cu ON cu.user_id = o.company_user_id
+        </if>
+        WHERE o.company_id = #{companyId}
+        <!-- 发送类型筛选 -->
+        <if test="sendType != null">
+            AND send_type = #{sendType}
+        </if>
+        <!-- 开始时间筛选:区分String/Date类型,避免类型比较异常 -->
+        <if test="sTime != null">
+            <choose>
+                <!-- sTime是String类型(yyyy-MM-dd) -->
+                <when test="sTime instanceof java.lang.String and sTime.trim() != ''">
+                    AND o.create_time &gt;= STR_TO_DATE(#{sTime}, '%Y-%m-%d')
+                </when>
+                <!-- sTime是Date类型 -->
+                <otherwise>
+                    AND o.create_time &gt;= #{sTime}
+                </otherwise>
+            </choose>
+        </if>
+        <!-- 结束时间筛选:区分String/Date类型 -->
+        <if test="eTime != null">
+            <choose>
+                <when test="eTime instanceof java.lang.String and eTime.trim() != ''">
+                    AND o.create_time &lt; DATE_ADD(STR_TO_DATE(#{eTime}, '%Y-%m-%d'), INTERVAL 1 DAY)
+                </when>
+                <otherwise>
+                    AND o.create_time &lt; DATE_ADD(#{eTime}, INTERVAL 1 DAY)
+                </otherwise>
+            </choose>
+        </if>
+        <!-- 昵称筛选:sendType!=1时关联qw_user -->
+        <if test="sendType != 1 and nickName != null and nickName.trim() != ''">
+            AND qu.qw_user_name LIKE CONCAT(#{nickName}, '%')
+        </if>
+        <!-- 昵称筛选:sendType==1时关联company_user -->
+        <if test="sendType == 1 and nickName != null and nickName.trim() != ''">
+            AND cu.nick_name LIKE CONCAT(#{nickName}, '%')
+        </if>
+        <!-- 课程ID筛选:加>0判断,避免null值拼接 -->
+        <if test="courseId != null and courseId > 0">
+            AND o.course_id = #{courseId}
+        </if>
+        <!-- 视频ID筛选:加>0判断 -->
+        <if test="videoId != null and videoId > 0">
+            AND o.video_id = #{videoId}
+        </if>
+        <!-- 分组条件:与子查询字段一致 -->
+        GROUP BY
+        o.video_id,
+        <choose>
+            <when test="sendType != 1">
+                o.qw_user_id,
+            </when>
+            <when test="sendType == 1">
+                o.company_user_id,
+            </when>
+            <otherwise>
+                o.qw_user_id,
+            </otherwise>
+        </choose>
+        DATE(o.create_time)
+        ) AS t
+    </select>
 </mapper>

+ 6 - 1
fs-service/src/main/resources/mapper/course/FsUserCoursePeriodDaysMapper.xml

@@ -194,7 +194,12 @@
                     when id=#{item.id} then #{item.lesson}
                 </if>
             </foreach>
-
+            `status` =
+            <foreach collection="list" item="item" open="case" close=" end,">
+                <if test="item.status != null">
+                    when id=#{item.id} then #{item.status}
+                </if>
+            </foreach>
         </trim>
         where id in
         <foreach collection="list" index="index" item="item" separator="," open="(" close=")">

+ 3 - 0
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -721,6 +721,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             user_id = #{userId}
         </foreach>
     </update>
+    <update id="updatePasswordByPhone">
+        update fs_user set password = #{password} where phone = #{encryptPhone}
+    </update>
 
     <select id="selectUserListByMap" resultType="com.fs.his.vo.OptionsVO">
         select

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

@@ -1795,7 +1795,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 <!--        </if>-->
 
         <where>
-            <if test="maps.appId != null and map.appId != ''">
+            <if test="maps.appId != null and maps.appId != ''">
                 and csc.appid = #{maps.appId}
             </if>
             <if test="maps.orderCodes != null  and maps.orderCodes.size > 0">

+ 1 - 0
fs-service/src/main/resources/mapper/hisStore/FsUserAddressScrmMapper.xml

@@ -6,6 +6,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <resultMap type="FsUserAddressScrm" id="FsUserAddressResult">
         <result property="id"    column="address_id"    />
+        <result property="addressId"    column="address_id"    />
         <result property="userId"    column="user_id"    />
         <result property="realName"    column="real_name"    />
         <result property="phone"    column="phone"    />

+ 403 - 0
fs-service/src/main/resources/mapper/hisStore/MergedOrderMapper.xml

@@ -0,0 +1,403 @@
+<?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.hisStore.mapper.MergedOrderMapper">
+
+    <select id="selectMergedOrderList" parameterType="com.fs.live.param.MergedOrderQueryParam" resultType="com.fs.live.vo.MergedOrderVO">
+        SELECT * FROM (
+      SELECT
+      o.id,
+      '销售订单' AS order_type_name,
+      NULL AS order_id,
+      NULL AS live_id,
+      NULL AS after_sales_id,
+      o.order_code,
+      o.pay_price,
+      o.pay_money,
+      o.STATUS,
+      o.is_package,
+      o.package_json,
+      o.item_json,
+      o.delivery_id,
+      o.finish_time,
+      o.create_time,
+      o.pay_time,
+      o.delivery_send_time,
+      NULL AS total_num,
+      NULL AS discount_money,
+      1 AS order_type,
+
+        cu.phonenumber as salesPhone,
+        cu.create_time as salesCreateTime,
+        u.user_id as userId,
+        u.order_count as userOrderCount,
+        u.total_amount as userTotalAmount,
+        u.level as userLevel,
+        fspc.product_id as productId,
+        fspc.product_name as productName,
+        fspc.cost as cost,
+        o.pay_postage as payDelivery,
+        o.coupon_price as discountMoney,
+        fspc.prescribe_spec as productSpec,
+        fss.store_id as storeId,
+        fss.store_name as storeName,
+        fspcs.cate_name as cateName,
+        GROUP_CONCAT(JSON_UNQUOTE(JSON_EXTRACT(o.item_json, '$.barCode')) SEPARATOR ',') AS barCode,
+
+      c.company_name,
+      cu.user_name AS sales_name,
+      cu.nick_name AS company_user_nick_name,
+      u.nickname,
+      u.phone,
+      o.real_name,
+      o.user_phone,
+      o.user_address,
+      o.pay_type,
+      o.delivery_status,
+      o.delivery_pay_status,
+      o.total_price,
+      csc.NAME AS mini_program_name,
+      sp_latest.bank_transaction_id
+      FROM
+      fs_store_order_scrm o
+      left join ( SELECT fsois.*, ROW_NUMBER() OVER ( PARTITION BY fsois.item_id  ) AS rn FROM fs_store_order_item_scrm fsois ) item_latest ON item_latest.order_id = o.id and item_latest.rn = 1
+      LEFT JOIN fs_user u ON o.user_id = u.user_id
+
+      LEFT JOIN fs_store_product_scrm  fspc ON fspc.product_id = item_latest.product_id
+      LEFT JOIN fs_store_scrm  fss ON fspc.store_id = fss.store_id
+      left join fs_store_product_category_scrm fspcs on fspc.cate_id = fspcs.cate_id
+
+      LEFT JOIN company c ON c.company_id = o.company_id
+      LEFT JOIN company_user cu ON cu.user_id = o.company_user_id
+      LEFT JOIN ( SELECT sp.*, ROW_NUMBER() OVER ( PARTITION BY sp.business_code ORDER BY sp.create_time DESC ) AS rn FROM fs_store_payment_scrm sp ) sp_latest ON sp_latest.business_code = o.order_code
+      AND sp_latest.rn = 1
+      LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
+          WHERE o.is_del = 0 AND o.is_sys_del = 0 AND o.company_user_id IS NOT NULL AND o.company_user_id != 0
+          <if test="maps.status != null and maps.status != ''">
+            AND o.status = #{maps.status}
+          </if>
+          <if test="maps.orderCode != null and maps.orderCode != ''">
+            AND o.order_code LIKE CONCAT('%', #{maps.orderCode}, '%')
+          </if>
+          <if test="maps.orderCodeList != null and maps.orderCodeList != ''">
+            AND FIND_IN_SET(o.order_code, #{maps.orderCodeList})
+          </if>
+          <if test="maps.deliveryId != null and maps.deliveryId != ''">
+            AND o.delivery_id LIKE CONCAT('%', #{maps.deliveryId}, '%')
+          </if>
+          <if test="maps.bankTransactionId != null and maps.bankTransactionId != ''">
+            AND o.bank_transaction_id LIKE CONCAT('%', #{maps.bankTransactionId}, '%')
+          </if>
+          <if test="maps.userPhone != null and maps.userPhone != ''">
+            AND o.user_phone LIKE CONCAT('%', #{maps.userPhone}, '%')
+          </if>
+          <if test="maps.realName != null and maps.realName != ''">
+            AND o.real_name LIKE CONCAT('%', #{maps.realName}, '%')
+          </if>
+          <if test="maps.productName != null and maps.productName != ''">
+            AND fspc.productName LIKE CONCAT('%', #{maps.productName}, '%')
+          </if>
+          <if test="maps.deliveryStatus != null">
+            AND o.delivery_status = #{maps.deliveryStatus}
+          </if>
+          <if test="maps.deliveryPayStatus != null">
+            AND o.delivery_pay_status = #{maps.deliveryPayStatus}
+          </if>
+          <if test="maps.payType != null and maps.payType != ''">
+            AND o.pay_type = #{maps.payType}
+          </if>
+          <if test="maps.companyId != null">
+            AND o.company_id = #{maps.companyId}
+          </if>
+          <if test="maps.deptId != null">
+            AND o.dept_id = #{maps.deptId}
+          </if>
+          <if test="maps.salesName != null and maps.salesName != ''">
+            AND cu.user_name LIKE CONCAT('%', #{maps.salesName}, '%')
+          </if>
+          <if test="maps.companyUserNickName != null and maps.companyUserNickName != ''">
+            AND cu.nick_name LIKE CONCAT('%', #{maps.companyUserNickName}, '%')
+          </if>
+          <if test="maps.createTimeRange != null and maps.createTimeRange != ''">
+            AND DATE(o.create_time) BETWEEN SUBSTRING_INDEX(#{maps.createTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.createTimeRange}, '--', -1)
+          </if>
+          <if test="maps.payTimeRange != null and maps.payTimeRange != ''">
+            AND DATE(o.pay_time) BETWEEN SUBSTRING_INDEX(#{maps.payTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.payTimeRange}, '--', -1)
+          </if>
+          <if test="maps.deliverySendTimeRange != null and maps.deliverySendTimeRange != ''">
+            AND DATE(o.delivery_send_time) BETWEEN SUBSTRING_INDEX(#{maps.deliverySendTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.deliverySendTimeRange}, '--', -1)
+          </if>
+          <if test="maps.deliveryImportTimeRange != null and maps.deliveryImportTimeRange != ''">
+            AND DATE(o.delivery_import_time) BETWEEN SUBSTRING_INDEX(#{maps.deliveryImportTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.deliveryImportTimeRange}, '--', -1)
+          </if>
+          <if test="maps.appId != null and maps.appId != ''">
+            AND csc.appid = #{maps.appId}
+          </if>
+          group by o.id
+          UNION ALL
+          -- 商城订单(没有company_user_id的商城订单)
+      SELECT
+      o.id,
+      '商城订单' AS order_type_name,
+      NULL AS order_id,
+      NULL AS live_id,
+      NULL AS after_sales_id,
+      o.order_code,
+      o.pay_price,
+      o.pay_money,
+      o.STATUS,
+      o.is_package,
+      o.package_json,
+      o.item_json,
+      o.delivery_id,
+      o.finish_time,
+      o.create_time,
+      o.pay_time,
+      o.delivery_send_time,
+      NULL AS total_num,
+      NULL AS discount_money,
+      2 AS order_type,
+
+    cu.phonenumber as salesPhone,
+    cu.create_time as salesCreateTime,
+    u.user_id as userId,
+    u.order_count as userOrderCount,
+    u.total_amount as userTotalAmount,
+    u.level as userLevel,
+    fspc.product_id as productId,
+    fspc.product_name as productName,
+    fspc.prescribe_spec as productSpec,
+        fspc.cost as cost,
+        o.pay_postage as payDelivery,
+        o.coupon_price as discountMoney,
+    fss.store_id as storeId,
+    fss.store_name as storeName,
+    fspcs.cate_name as cateName,
+    GROUP_CONCAT(JSON_UNQUOTE(JSON_EXTRACT(o.item_json, '$.barCode')) SEPARATOR ',') AS barCode,
+
+      c.company_name,
+      cu.user_name AS sales_name,
+      cu.nick_name AS company_user_nick_name,
+      u.nickname,
+      u.phone,
+      o.real_name,
+      o.user_phone,
+      o.user_address,
+      o.pay_type,
+      o.delivery_status,
+      o.delivery_pay_status,
+      o.total_price,
+      csc.NAME AS mini_program_name,
+      sp_latest.bank_transaction_id
+      FROM
+      fs_store_order_scrm o
+        left join ( SELECT fsois.*, ROW_NUMBER() OVER ( PARTITION BY fsois.item_id  ) AS rn FROM fs_store_order_item_scrm fsois ) item_latest ON item_latest.order_id = o.id
+      LEFT JOIN fs_user u ON o.user_id = u.user_id
+
+        LEFT JOIN fs_store_product_scrm  fspc ON fspc.product_id = item_latest.product_id
+        LEFT JOIN fs_store_scrm  fss ON fspc.store_id = fss.store_id
+        left join fs_store_product_category_scrm fspcs on fspc.cate_id = fspcs.cate_id
+
+      LEFT JOIN company c ON c.company_id = o.company_id
+      LEFT JOIN company_user cu ON cu.user_id = o.company_user_id
+      LEFT JOIN ( SELECT sp.*, ROW_NUMBER() OVER ( PARTITION BY sp.business_code ORDER BY sp.create_time DESC ) AS rn FROM fs_store_payment_scrm sp ) sp_latest ON sp_latest.business_code = o.order_code
+      AND sp_latest.rn = 1
+      LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
+          WHERE o.is_del = 0 AND o.is_sys_del = 0 AND (o.company_user_id IS NULL OR o.company_user_id = 0)
+          <if test="maps.status != null and maps.status != ''">
+            AND o.status = #{maps.status}
+          </if>
+          <if test="maps.orderCode != null and maps.orderCode != ''">
+            AND o.order_code LIKE CONCAT('%', #{maps.orderCode}, '%')
+          </if>
+          <if test="maps.orderCodeList != null and maps.orderCodeList != ''">
+            AND FIND_IN_SET(o.order_code, #{maps.orderCodeList})
+          </if>
+          <if test="maps.deliveryId != null and maps.deliveryId != ''">
+            AND o.delivery_id LIKE CONCAT('%', #{maps.deliveryId}, '%')
+          </if>
+          <if test="maps.bankTransactionId != null and maps.bankTransactionId != ''">
+            AND o.bank_transaction_id LIKE CONCAT('%', #{maps.bankTransactionId}, '%')
+          </if>
+          <if test="maps.userPhone != null and maps.userPhone != ''">
+            AND o.user_phone LIKE CONCAT('%', #{maps.userPhone}, '%')
+          </if>
+          <if test="maps.realName != null and maps.realName != ''">
+            AND o.real_name LIKE CONCAT('%', #{maps.realName}, '%')
+          </if>
+          <if test="maps.productName != null and maps.productName != ''">
+            AND o.item_json LIKE CONCAT('%', #{maps.productName}, '%')
+          </if>
+          <if test="maps.deliveryStatus != null">
+            AND o.delivery_status = #{maps.deliveryStatus}
+          </if>
+          <if test="maps.deliveryPayStatus != null">
+            AND o.delivery_pay_status = #{maps.deliveryPayStatus}
+          </if>
+          <if test="maps.payType != null and maps.payType != ''">
+            AND o.pay_type = #{maps.payType}
+          </if>
+          <if test="maps.companyId != null">
+            AND o.company_id = #{maps.companyId}
+          </if>
+          <if test="maps.deptId != null">
+            AND o.dept_id = #{maps.deptId}
+          </if>
+          <if test="maps.salesName != null and maps.salesName != ''">
+            AND cu.user_name LIKE CONCAT('%', #{maps.salesName}, '%')
+          </if>
+          <if test="maps.companyUserNickName != null and maps.companyUserNickName != ''">
+            AND cu.nick_name LIKE CONCAT('%', #{maps.companyUserNickName}, '%')
+          </if>
+          <if test="maps.createTimeRange != null and maps.createTimeRange != ''">
+            AND DATE(o.create_time) BETWEEN SUBSTRING_INDEX(#{maps.createTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.createTimeRange}, '--', -1)
+          </if>
+          <if test="maps.payTimeRange != null and maps.payTimeRange != ''">
+            AND DATE(o.pay_time) BETWEEN SUBSTRING_INDEX(#{maps.payTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.payTimeRange}, '--', -1)
+          </if>
+          <if test="maps.deliverySendTimeRange != null and maps.deliverySendTimeRange != ''">
+            AND DATE(o.delivery_send_time) BETWEEN SUBSTRING_INDEX(#{maps.deliverySendTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.deliverySendTimeRange}, '--', -1)
+          </if>
+          <if test="maps.deliveryImportTimeRange != null and maps.deliveryImportTimeRange != ''">
+            AND DATE(o.delivery_import_time) BETWEEN SUBSTRING_INDEX(#{maps.deliveryImportTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.deliveryImportTimeRange}, '--', -1)
+          </if>
+          <if test="maps.appId != null and maps.appId != ''">
+            AND csc.appid = #{maps.appId}
+          </if>
+        group by o.id
+          UNION ALL
+          -- 直播订单
+      SELECT NULL AS
+      id,
+      '直播订单' AS order_type_name,
+      o.order_id,
+      o.live_id,
+      a.id AS after_sales_id,
+      o.order_code,
+      o.pay_price,
+      o.pay_money,
+      o.STATUS,
+      NULL AS is_package,
+      NULL AS package_json,
+      o.item_json,
+      o.delivery_sn AS delivery_id,
+      o.finish_time,
+      o.create_time,
+      o.pay_time,
+      o.delivery_send_time,
+      o.total_num,
+      o.discount_money,
+      3 AS order_type,
+
+        cu.phonenumber as salesPhone,
+        cu.create_time as salesCreateTime,
+        u.user_id as userId,
+        u.order_count as userOrderCount,
+        u.total_amount as userTotalAmount,
+        u.level as userLevel,
+        fspc.product_id as productId,
+        fspc.product_name as productName,
+        fspc.prescribe_spec as productSpec,
+        fspc.cost as cost,
+        o.pay_delivery as payDelivery,
+        o.discount_money as discountMoney,
+        fss.store_id as storeId,
+        fss.store_name as storeName,
+        fspcs.cate_name as cateName,
+        GROUP_CONCAT(JSON_UNQUOTE(JSON_EXTRACT(loi.json_info, '$.barCode')) SEPARATOR ',') AS barCode,
+
+      c.company_name,
+      cu.user_name AS sales_name,
+      cu.nick_name AS company_user_nick_name,
+      u.nickname,
+      u.phone,
+      o.user_name AS real_name,
+      o.user_phone,
+      o.user_address,
+      o.pay_type,
+      o.delivery_status,
+      o.delivery_pay_status,
+      o.total_price,
+      csc.NAME AS mini_program_name,
+      sp_latest.bank_transaction_id
+      FROM
+      live_order o
+      left join live_order_item loi on loi.order_id = o.order_id
+      LEFT JOIN fs_user u ON o.user_id = u.user_id
+
+        LEFT JOIN fs_store_product_scrm  fspc ON fspc.product_id = o.product_id
+        LEFT JOIN fs_store_scrm  fss ON fspc.store_id = fss.store_id
+        left join fs_store_product_category_scrm fspcs on fspc.cate_id = fspcs.cate_id
+
+
+      LEFT JOIN company c ON c.company_id = o.company_id
+      LEFT JOIN company_user cu ON cu.user_id = o.company_user_id
+      LEFT JOIN ( SELECT t.*, ROW_NUMBER() OVER ( PARTITION BY t.order_id ORDER BY t.create_time DESC ) AS rn FROM live_after_sales t ) a ON o.order_id = a.order_id
+      AND a.rn = 1
+      LEFT JOIN ( SELECT sp.*, ROW_NUMBER() OVER ( PARTITION BY sp.business_code ORDER BY sp.create_time DESC ) AS rn FROM live_order_payment sp ) sp_latest ON sp_latest.business_code = o.order_code
+      AND sp_latest.rn = 1
+      LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
+          WHERE o.is_del = 0
+          <if test="maps.status != null and maps.status != ''">
+            AND o.status = #{maps.status}
+          </if>
+          <if test="maps.orderCode != null and maps.orderCode != ''">
+            AND o.order_code LIKE CONCAT('%', #{maps.orderCode}, '%')
+          </if>
+          <if test="maps.orderCodeList != null and maps.orderCodeList != ''">
+            AND FIND_IN_SET(o.order_code, #{maps.orderCodeList})
+          </if>
+          <if test="maps.deliveryId != null and maps.deliveryId != ''">
+            AND o.delivery_sn LIKE CONCAT('%', #{maps.deliveryId}, '%')
+          </if>
+          <if test="maps.userPhone != null and maps.userPhone != ''">
+            AND o.user_phone LIKE CONCAT('%', #{maps.userPhone}, '%')
+          </if>
+          <if test="maps.realName != null and maps.realName != ''">
+            AND o.user_name LIKE CONCAT('%', #{maps.realName}, '%')
+          </if>
+          <if test="maps.productName != null and maps.productName != ''">
+            AND o.item_json LIKE CONCAT('%', #{maps.productName}, '%')
+          </if>
+          <if test="maps.deliveryStatus != null">
+            AND o.delivery_status = #{maps.deliveryStatus}
+          </if>
+          <if test="maps.deliveryPayStatus != null">
+            AND o.delivery_pay_status = #{maps.deliveryPayStatus}
+          </if>
+          <if test="maps.payType != null and maps.payType != ''">
+            AND o.pay_type = #{maps.payType}
+          </if>
+          <if test="maps.companyId != null">
+            AND o.company_id = #{maps.companyId}
+          </if>
+          <if test="maps.deptId != null">
+            AND o.dept_id = #{maps.deptId}
+          </if>
+          <if test="maps.salesName != null and maps.salesName != ''">
+            AND cu.user_name LIKE CONCAT('%', #{maps.salesName}, '%')
+          </if>
+          <if test="maps.companyUserNickName != null and maps.companyUserNickName != ''">
+            AND cu.nick_name LIKE CONCAT('%', #{maps.companyUserNickName}, '%')
+          </if>
+          <if test="maps.createTimeRange != null and maps.createTimeRange != ''">
+            AND DATE(o.create_time) BETWEEN SUBSTRING_INDEX(#{maps.createTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.createTimeRange}, '--', -1)
+          </if>
+          <if test="maps.payTimeRange != null and maps.payTimeRange != ''">
+            AND DATE(o.pay_time) BETWEEN SUBSTRING_INDEX(#{maps.payTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.payTimeRange}, '--', -1)
+          </if>
+          <if test="maps.deliverySendTimeRange != null and maps.deliverySendTimeRange != ''">
+            AND DATE(o.delivery_send_time) BETWEEN SUBSTRING_INDEX(#{maps.deliverySendTimeRange}, '--', 1) AND SUBSTRING_INDEX(#{maps.deliverySendTimeRange}, '--', -1)
+          </if>
+        group by o.order_id
+        ) AS merged_orders
+        WHERE 1=1
+        <if test="maps.orderTypeFilter != null">
+          AND order_type = #{maps.orderTypeFilter}
+        </if>
+        ORDER BY create_time DESC
+    </select>
+
+</mapper>
+

+ 3 - 3
fs-service/src/main/resources/mapper/live/LiveDataMapper.xml

@@ -283,7 +283,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <!-- 查询直播间统计数据 -->
     <select id="selectLiveDataStatistics" resultType="com.fs.live.vo.LiveDataStatisticsVo">
         SELECT
-            COUNT( lwu.user_id) AS totalViewers,
+            COUNT( distinct lwu.user_id) AS totalViewers,
             COUNT( CASE WHEN lwu.live_flag = 1 and lwu.replay_flag = 0 THEN lwu.user_id END) AS liveViewers,
             COUNT( CASE WHEN lwu.live_flag = 0 and lwu.replay_flag = 1 THEN lwu.user_id END) AS playbackViewers,
             COALESCE(AVG(CASE WHEN lwu.live_flag = 1 and lwu.replay_flag = 0 THEN lwu.online_seconds END), 0) AS liveAvgDuration,
@@ -360,7 +360,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             l.status AS status,
             l.start_time AS startTime,
             l.finish_time AS finishTime,
-            COUNT(1) AS totalViewers,
+            COUNT(distinct lwu.user_id) AS totalViewers,
             COUNT(CASE WHEN lwu.live_flag = 1 and lwu.replay_flag = 0 THEN lwu.user_id END) AS liveViewers,
             COUNT(CASE WHEN lwu.live_flag = 0 and lwu.replay_flag = 1 THEN lwu.user_id END) AS playbackViewers,
             COALESCE(AVG(CASE WHEN lwu.live_flag = 1 and lwu.replay_flag = 0 THEN lwu.online_seconds END), 0) AS liveAvgDuration,
@@ -420,7 +420,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             CASE
                 WHEN COUNT(DISTINCT lwu.user_id) > 0 THEN
                     ROUND(COUNT(DISTINCT CASE
-                        WHEN COALESCE(user_duration.total_duration, 0) >= 1800
+                        WHEN COALESCE(user_duration.total_duration, 0) >= 1200
                         THEN lwu.user_id
                     END) * 100.0 / COUNT(DISTINCT lwu.user_id), 2)
                 ELSE 0

+ 2 - 2
fs-service/src/main/resources/mapper/qw/CustomerTransferApprovalMapper.xml

@@ -40,8 +40,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="approverUserId != null "> and approver_user_id = #{approverUserId}</if>
             <if test="approvalRemark != null  and approvalRemark != ''"> and approval_remark = #{approvalRemark}</if>
             <if test="processedAt != null "> and processed_at = #{processedAt}</if>
-            <if test="createdAt != null "> and created_at = #{createdAt}</if>
-            <if test="updatedAt != null "> and updated_at = #{updatedAt}</if>
+            <if test="createdAt != null "> and date_format(created_at,'%y%m%d') = date_format(#{createdAt},'%y%m%d')</if>
+            <if test="updatedAt != null "> and date_format(updated_at,'%y%m%d') = date_format(#{updatedAt},'%y%m%d')</if>
         </where>
         order by id desc
     </select>

+ 9 - 1
fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml

@@ -89,7 +89,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectQwExternalContactByIds" resultType="com.fs.qw.domain.QwExternalContact">
         select * from qw_external_contact
-        where id in
+        where  id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
+
+    <select id="selectQwExternalContactByIdsStatus" resultType="com.fs.qw.domain.QwExternalContact">
+        select * from qw_external_contact
+        where status !=3 and id in
         <foreach collection="ids" item="id" open="(" separator="," close=")">
             #{id}
         </foreach>

+ 92 - 0
fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java

@@ -10,6 +10,7 @@ import com.fs.common.VerifyCodeUtil;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.exception.ServiceException;
 import com.fs.common.service.ISmsService;
 import com.fs.common.utils.sign.Md5Utils;
 import com.fs.core.config.WxOpenProperties;
@@ -300,6 +301,61 @@ public class AppLoginController extends AppBaseController{
 
     }
 
+    @PostMapping("/loginByPhone")
+    public R loginByPhone(@RequestBody Map<String,String> map){
+        String phone = map.get("phone");
+        String code = map.get("code");
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> user = userService.selectFsUserListByPhone(encryptPhone);
+        if (CollectionUtil.isEmpty(user)){
+            user = userService.selectFsUserListByPhone(encryptPhoneOldKey(phone));
+        }
+        if (CollectionUtil.isEmpty(user)){
+            return R.error("此电话号码未绑定用户");
+        }
+        if (user.size()>1){
+            //如果出现了一个手机号多个用户的情况,找出登陆过app的那个用户
+            user.removeIf(fsUser -> StringUtils.isEmpty(fsUser.getHistoryApp()));
+        }
+        String redisCode = redisCache.getCacheObject("sms:code:" + phone);
+        if (StringUtils.isEmpty(redisCode)){
+            return R.error("验证码已过期,请重新发送");
+        }
+        if (!redisCode.equals(code)) {
+            return R.error("验证码错误");
+        }
+        updateExistingUserJpushId(user.get(0), map.get("jpushId"));
+        return generateTokenAndReturn(user.get(0));
+    }
+
+    @PostMapping("/resetPassword")
+    public R resetPassword(@RequestBody Map<String, String> body){
+        String phone = body.get("phone");
+        String code = body.get("code");
+        String newPassword = body.get("newPassword");
+        String confirmPassword = body.get("confirmPassword");
+        if (!newPassword.equals(confirmPassword)){
+            throw new ServiceException("两次输入密码不一致,请检查");
+        }
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> user = userService.selectFsUserListByPhone(encryptPhone);
+        if (CollectionUtil.isEmpty(user)){
+            user = userService.selectFsUserListByPhone(encryptPhoneOldKey(phone));
+        }
+        if (CollectionUtil.isEmpty(user)){
+            return R.error("此电话号码未绑定用户");
+        }
+        String redisCode = redisCache.getCacheObject("sms:code:" + phone);
+        if (StringUtils.isEmpty(redisCode)){
+            return R.error("验证码已过期,请重新发送");
+        }
+        if (!redisCode.equals(code)) {
+            return R.error("验证码错误");
+        }
+        String password = Md5Utils.hash(newPassword);
+        return userService.updatePasswordByPhone(password,encryptPhone);
+    }
+
     @ApiOperation("绑定手机号")
     @PostMapping("/setPhone")
     public R setPhone(@Validated @RequestBody FsUserEditPhoneParam param) {
@@ -456,6 +512,42 @@ public class AppLoginController extends AppBaseController{
 
     }
 
+    @PostMapping("/sendCode")
+    public R sendCode(@RequestBody Map<String, String> body){
+        String phone = body.get("phone");
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> user = userService.selectFsUserListByPhone(encryptPhone);
+        if(CollectionUtil.isEmpty(user)){
+            user = userService.selectFsUserListByPhone(encryptPhoneOldKey(phone));
+        }
+        if (CollectionUtil.isEmpty(user)){
+            return R.error("此电话号码未绑定用户");
+        }
+
+        // 验证码 key(3分钟有效)
+        String smsCodeKey = "sms:code:" + phone;
+        // 冷却 key(60秒内不能重复发送)
+        String smsCooldownKey = "sms:cooldown:" + phone;
+
+        // 判断是否在 60 秒冷却期
+        if (redisCache.getCacheObject(smsCooldownKey) != null) {
+            return R.error("验证码已发送,请稍后再试");
+        }
+
+        // 生成新验证码
+        String smsCode = VerifyCodeUtil.generateCode();
+
+        // 发送短信
+        smsService.sendCaptcha(phone, smsCode, "验证码");
+
+        // 缓存验证码(3分钟有效)
+        redisCache.setCacheObject(smsCodeKey, smsCode, 180, TimeUnit.SECONDS);
+        // 设置冷却时间(60秒内不能再发)
+        redisCache.setCacheObject(smsCooldownKey, "1", 60, TimeUnit.SECONDS);
+
+        return R.ok("验证码已发送");
+    }
+
     private List<FsUser> findUsersByPhone(String phone) {
         // 先根据加密手机号查询用户
         String jiami = (encryptPhone(phone));

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

@@ -66,6 +66,21 @@ public class IntegralController extends  AppBaseController {
     @Cacheable(value = "getIntegralGoodsById", key = "#goodsId")
     public R getIntegralGoodsById(@RequestParam("goodsId")Long goodsId, HttpServletRequest request){
         FsIntegralGoods goods=goodsService.selectFsIntegralGoodsByGoodsId(goodsId);
+        // 填充默认值
+        if (goods != null) {
+            if (goods.getImages() == null) {
+                goods.setImages("");
+            }
+            if (goods.getNum() == null) {
+                goods.setNum(0);
+            }
+            if (goods.getRemark() == null) {
+                goods.setRemark("");
+            }
+            if (goods.getSearchValue() == null) {
+                goods.setSearchValue("");
+            }
+        }
         return R.ok().put("data",goods);
     }
 

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/controller/store/AddressScrmController.java

@@ -113,7 +113,7 @@ public class AddressScrmController extends AppBaseController {
         FsUserAddressScrm userAddress=new FsUserAddressScrm();
         BeanUtil.copyProperties(address, userAddress);
         addressService.insertFsUserAddress(userAddress);
-        return R.ok("操作成功");
+        return R.ok("操作成功").put("addressId", userAddress.getId());
     }
 
     @Login