Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master'

ct 5 giorni fa
parent
commit
a000484588
73 ha cambiato i file con 2558 aggiunte e 144 eliminazioni
  1. 20 0
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsTempController.java
  2. 16 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java
  3. 34 0
      fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java
  4. 23 0
      fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java
  5. 18 0
      fs-admin/src/main/java/com/fs/crm/controller/CrmCustomerController.java
  6. 133 0
      fs-admin/src/main/java/com/fs/fastGpt/FastGptChatMsgController.java
  7. 116 0
      fs-admin/src/main/java/com/fs/fastGpt/FastGptChatMsgLogsController.java
  8. 121 0
      fs-admin/src/main/java/com/fs/fastGpt/FastGptChatSessionController.java
  9. 23 35
      fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderController.java
  10. 136 0
      fs-admin/src/main/java/com/fs/qw/controller/QwAutoTagsController.java
  11. 132 0
      fs-admin/src/main/java/com/fs/qw/controller/QwAutoTagsLogsController.java
  12. 160 0
      fs-admin/src/main/java/com/fs/qw/controller/QwGroupMsgController.java
  13. 118 0
      fs-admin/src/main/java/com/fs/qw/controller/QwGroupMsgUserController.java
  14. 83 0
      fs-admin/src/main/java/com/fs/qw/controller/QwTagGroupController.java
  15. 328 0
      fs-admin/src/main/java/com/fs/qw/controller/QwUserVoiceLogController.java
  16. 1 8
      fs-common/src/main/java/com/fs/common/core/redis/service/StockDeductService.java
  17. 7 1
      fs-company/src/main/java/com/fs/company/controller/qw/QwSopController.java
  18. 108 0
      fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderItemScrmController.java
  19. 17 5
      fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  20. 151 0
      fs-company/src/main/java/com/fs/hisStore/controller/FsStoreScrmController.java
  21. 59 0
      fs-live-app/src/main/java/com/fs/live/utils/WebSocketRateLimiter.java
  22. 63 0
      fs-live-app/src/main/java/com/fs/live/websocket/config/WebSocketSessionManager.java
  23. 5 0
      fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisFsUserCourseVideoController.java
  24. 10 10
      fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwSopController.java
  25. 5 0
      fs-qwhook-sop/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  26. 44 1
      fs-qwhook-sop/src/main/java/com/fs/app/controller/QwSopController.java
  27. 5 0
      fs-qwhook/src/main/java/com/fs/app/controller/ApisFsUserCourseVideoController.java
  28. 5 0
      fs-qwhook/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  29. 3 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java
  30. 21 8
      fs-service/src/main/java/com/fs/company/mapper/CompanySmsTempMapper.java
  31. 10 8
      fs-service/src/main/java/com/fs/company/service/ICompanySmsTempService.java
  32. 3 0
      fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java
  33. 13 8
      fs-service/src/main/java/com/fs/company/service/impl/CompanySmsTempServiceImpl.java
  34. 8 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  35. 4 1
      fs-service/src/main/java/com/fs/course/mapper/FsCourseRedPacketLogMapper.java
  36. 6 3
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  37. 8 2
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  38. 3 0
      fs-service/src/main/java/com/fs/course/param/FsCourseListBySidebarParam.java
  39. 5 0
      fs-service/src/main/java/com/fs/course/param/FsCourseRedPacketLogParam.java
  40. 5 0
      fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java
  41. 2 0
      fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogStatisticsListParam.java
  42. 2 0
      fs-service/src/main/java/com/fs/course/service/IFsCourseRedPacketLogService.java
  43. 6 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java
  44. 1 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  45. 1 0
      fs-service/src/main/java/com/fs/course/vo/FsCourseRedPacketLogListPVO.java
  46. 49 0
      fs-service/src/main/java/com/fs/course/vo/FsCourseRedPacketLogListVO.java
  47. 1 1
      fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java
  48. 1 0
      fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogStatisticsListVO.java
  49. 5 3
      fs-service/src/main/java/com/fs/his/vo/FsIntegralOrderListVO.java
  50. 3 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderExportVO.java
  51. 4 1
      fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java
  52. 2 1
      fs-service/src/main/java/com/fs/qw/mapper/QwWatchLogMapper.java
  53. 2 0
      fs-service/src/main/java/com/fs/qw/param/QwSidebarStatsParam.java
  54. 18 18
      fs-service/src/main/java/com/fs/qw/service/impl/AsyncSopTestService.java
  55. 0 1
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
  56. 8 1
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserVoiceLogServiceImpl.java
  57. 2 0
      fs-service/src/main/java/com/fs/qw/vo/QwWatchLogStatisticsListVO.java
  58. 3 0
      fs-service/src/main/java/com/fs/sop/mapper/QwSopMapper.java
  59. 2 0
      fs-service/src/main/java/com/fs/sop/service/IQwSopService.java
  60. 9 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopServiceImpl.java
  61. 0 2
      fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java
  62. 2 2
      fs-service/src/main/java/com/fs/wx/order/service/impl/ShopExpressToWxService.java
  63. 2 2
      fs-service/src/main/resources/application-config-druid-bjzm-test.yml
  64. 2 2
      fs-service/src/main/resources/application-config-druid-bjzm.yml
  65. 142 0
      fs-service/src/main/resources/application-config-zlwh.yml
  66. 1 1
      fs-service/src/main/resources/application-druid-bjzm.yml
  67. 165 0
      fs-service/src/main/resources/application-druid-zlwh.yml
  68. 62 0
      fs-service/src/main/resources/mapper/course/FsCourseRedPacketLogMapper.xml
  69. 17 11
      fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml
  70. 2 2
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  71. 3 3
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  72. 7 0
      fs-service/src/main/resources/mapper/sop/QwSopMapper.xml
  73. 2 2
      fs-user-app/src/main/java/com/fs/app/controller/CompanyUserController.java

+ 20 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanySmsTempController.java

@@ -8,7 +8,9 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.CompanySmsTemp;
+import com.fs.company.param.CompanySmsTempListQueryParam;
 import com.fs.company.service.ICompanySmsTempService;
+import com.fs.company.vo.CompanySmsTempListQueryVO;
 import com.fs.company.vo.CompanySmsTempListVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -112,4 +114,22 @@ public class CompanySmsTempController extends BaseController
             return R.error("操作失败");
         }
     }
+
+    /**
+     * 总后台取不到companyId,全部展示
+     * @return
+     */
+    @GetMapping("/getSmsTempList")
+    public R getSmsTempList()
+    {
+        CompanySmsTempListQueryParam maps=new CompanySmsTempListQueryParam();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        maps.setCompanyId(loginUser.getCompany().getCompanyId());
+        maps.setStatus(1);
+        maps.setIsAudit(1);
+//        List<CompanySmsTempListQueryVO> list = companySmsTempService.selectCompanySmsTempListQuery(maps);
+        List<CompanySmsTempListQueryVO> list = companySmsTempService.selectCompanySmsTempListQueryForAdmin(maps);
+
+        return R.ok().put("data",list);
+    }
 }

+ 16 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java

@@ -9,10 +9,12 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.dto.UserProjectDTO;
+import com.fs.qw.vo.QwUserVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -198,4 +200,18 @@ public class CompanyUserController extends BaseController
         List<OptionsVO> companyUserList = companyUserService.selectCompanyUserListByMap(params);
         return R.ok().put("data", new PageInfo<>(companyUserList));
     }
+    @GetMapping("/getQwAllUserList/{id}/{companyId}")
+    public R getQwAllUserList(@PathVariable("id") String corpId,@PathVariable("companyId") Long companyId)
+    {
+
+        List<QwUserVO> list = companyUserService.selectCompanyQwUserList(corpId,companyId);
+        return  R.ok().put("data",list);
+    }
+    @GetMapping("/getCompanyList/{id}")
+    public R getCompanyList(@PathVariable("id") String corpId)
+    {
+
+        List<Company> list = companyUserService.getCompanyList(corpId);
+        return  R.ok().put("data",list);
+    }
 }

+ 34 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java

@@ -13,6 +13,7 @@ import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.param.FsCourseRedPacketLogParam;
 import com.fs.course.service.IFsUserCoursePeriodService;
 import com.fs.course.vo.FsCourseRedPacketLogListPVO;
+import com.fs.course.vo.FsCourseRedPacketLogListVO;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.OptionsVO;
@@ -209,4 +210,37 @@ public class FsCourseRedPacketLogController extends BaseController
         List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id);
         return R.ok().put("list", optionsVOS);
     }
+
+
+    /**
+    * 红包消耗统计
+    */
+    @PreAuthorize("@ss.hasPermi('course:courseRedPacketLog:countList')")
+    @PostMapping("/getRedPacketLogCount")
+    public R getRedPacketLogCount(@RequestBody FsCourseRedPacketLogParam fsCourseRedPacketLog){
+
+        PageHelper.startPage(fsCourseRedPacketLog.getPageNum(), fsCourseRedPacketLog.getPageSize());
+
+        List<FsCourseRedPacketLogListVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListCountVO(fsCourseRedPacketLog);
+
+
+        return R.ok().put("data", new PageInfo<>(list));
+    }
+
+
+    /**
+     * 导出短链课程看课记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:courseRedPacketLog:countExport')")
+    @Log(title = "红包消耗统计导出", businessType = BusinessType.EXPORT)
+    @PostMapping("/countExport")
+    public AjaxResult countExport(@RequestBody FsCourseRedPacketLogParam fsCourseRedPacketLog)
+    {
+
+        List<FsCourseRedPacketLogListVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListCountVO(fsCourseRedPacketLog);
+
+        ExcelUtil<FsCourseRedPacketLogListVO> util = new ExcelUtil<FsCourseRedPacketLogListVO>(FsCourseRedPacketLogListVO.class);
+        return util.exportExcel(list, "红包消耗统计导出");
+    }
+
 }

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

@@ -22,13 +22,18 @@ import com.fs.course.vo.FsCourseWatchLogStatisticsListVO;
 import com.fs.qw.param.QwWatchLogStatisticsListParam;
 import com.fs.qw.service.IQwWatchLogService;
 import com.fs.qw.vo.QwWatchLogAllStatisticsListVO;
+import com.fs.sop.domain.QwSop;
+import com.fs.sop.service.IQwSopService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 短链课程看课记录Controller
@@ -48,6 +53,9 @@ public class QwFsCourseWatchLogController extends BaseController
 
     @Autowired
     private IQwWatchLogService qwWatchLogService;
+
+    @Autowired
+    private IQwSopService qwSopService;
     /**
      * 查询短链课程看课记录列表
      */
@@ -217,4 +225,19 @@ public class QwFsCourseWatchLogController extends BaseController
         List<FsCourseOverVO> list = fsCourseWatchLogService.selectFsCourseWatchLogOverStatisticsListVO(param);
         return getDataTable(list);
     }
+
+    /**
+     * 查询档期列表
+     */
+    @GetMapping("/fetchScheduleList")
+    public R fetchScheduleList(String sopName) {
+        List<QwSop> list = qwSopService.fetchScheduleList(sopName);
+        List<Map<String, Object>> result = list.stream().map(sop -> {
+            Map<String, Object> map = new HashMap<>();
+            map.put("qwSopId", sop.getId()); // 重命名id为qwSopId
+            map.put("qwSopName", sop.getName());
+            return map;
+        }).collect(Collectors.toList());
+        return R.ok().put("rows", result);
+    }
 }

+ 18 - 0
fs-admin/src/main/java/com/fs/crm/controller/CrmCustomerController.java

@@ -23,6 +23,8 @@ import com.fs.crm.vo.CrmCustomerListVO;
 import com.fs.framework.web.service.TokenService;
 import com.fs.system.service.ISysRoleService;
 import com.github.pagehelper.PageHelper;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -30,6 +32,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -324,5 +327,20 @@ public class CrmCustomerController extends BaseController
         return R.ok().put("data",customerList);
     }
 
+    @ApiOperation("获取客户详情")
+    @GetMapping("/getCustomerDetails")
+    @PreAuthorize("@ss.hasPermi('crm:customer:query')")
+    public R getCustomerDetails(
+            HttpServletRequest request,
+            @ApiParam(required = true, name = "customerId", value = "客户ID") @RequestParam(value = "customerId", required = false) Long customerId
+    ){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        CrmCustomer customer=crmCustomerService.selectCrmCustomerById(customerId);
+        Boolean isReceive=false;
+        if(customer.getIsReceive()!=null&&customer.getIsReceive()==1&&customer.getReceiveUserId()!=null&&loginUser.getUser().getUserId().equals(customer.getReceiveUserId())){
+            isReceive=true;
+        }
+        return R.ok().put("customer",customer).put("isReceive",isReceive);
 
+    }
 }

+ 133 - 0
fs-admin/src/main/java/com/fs/fastGpt/FastGptChatMsgController.java

@@ -0,0 +1,133 @@
+package com.fs.fastGpt;
+
+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.poi.ExcelUtil;
+import com.fs.fastGpt.domain.FastGptChatMsg;
+import com.fs.fastGpt.param.FastGptChatMsgListCParam;
+import com.fs.fastGpt.service.IFastGptChatMsgLogsService;
+import com.fs.fastGpt.service.IFastGptChatMsgService;
+import com.fs.fastGpt.vo.FastGptChatMsgListCVO;
+//import com.fs.framework.security.LoginUser;
+//import com.fs.framework.service.TokenService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 聊天记录Controller
+ *
+ * @author fs
+ * @date 2024-10-10
+ */
+@RestController
+@RequestMapping("/fastGpt/fastGptChatMsg")
+public class FastGptChatMsgController extends BaseController
+{
+    @Autowired
+    private IFastGptChatMsgService fastGptChatMsgService;
+
+//    @Autowired
+//    private TokenService tokenService;
+
+    @Autowired
+    private IFastGptChatMsgLogsService iFastGptChatMsgLogsService;
+
+    /**
+     * 查询聊天记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsg:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FastGptChatMsgListCParam param)
+    {
+        startPage();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        param.setCompanyId(loginUser.getCompany().getCompanyId());
+
+        List<FastGptChatMsgListCVO> list = fastGptChatMsgService.selectFastGptChatMsgListCVO(param);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出聊天记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsg:export')")
+    @Log(title = "聊天记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FastGptChatMsg fastGptChatMsg)
+    {
+        List<FastGptChatMsg> list = fastGptChatMsgService.selectFastGptChatMsgList(fastGptChatMsg);
+        ExcelUtil<FastGptChatMsg> util = new ExcelUtil<FastGptChatMsg>(FastGptChatMsg.class);
+        return util.exportExcel(list, "聊天记录数据");
+    }
+
+    /**
+     * 获取聊天记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsg:query')")
+    @GetMapping(value = "/{msgId}")
+    public AjaxResult getInfo(@PathVariable("msgId") Long msgId)
+    {
+        return AjaxResult.success(fastGptChatMsgService.selectFastGptChatMsgVOByMsgId(msgId));
+    }
+
+//    /**
+//     * 新增聊天记录
+//     */
+//    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsg:add')")
+//    @Log(title = "聊天记录", businessType = BusinessType.INSERT)
+//    @PostMapping
+//    public AjaxResult add(@RequestBody FastGptChatMsg fastGptChatMsg)
+//    {
+//        return toAjax(fastGptChatMsgService.insertFastGptChatMsg(fastGptChatMsg));
+//    }
+
+//    /**
+//     * 修改聊天记录
+//     */
+//    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsg:edit')")
+//    @Log(title = "聊天记录", businessType = BusinessType.UPDATE)
+//    @PutMapping
+//    public AjaxResult edit(@RequestBody FastGptChatMsg param)
+//    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        FastGptChatMsg fastGptChatMsg = fastGptChatMsgService.selectFastGptChatMsgByMsgId(param.getMsgId());
+//
+//        FastGptChatMsgLogs logs = new FastGptChatMsgLogs();
+//
+//        logs.setMsgId(param.getMsgId());
+//        logs.setLogsType(2);
+//        if (param.getContent()!=null&&!param.getContent().equals("")){
+//            logs.setContent(param.getContent());
+//        }
+//        if (param.getStatus()!=null){
+//            logs.setLogsType(1);
+//        }
+//        String userContent = fastGptChatMsgService.selectUserContent(fastGptChatMsg.getMsgId(), fastGptChatMsg.getUserId(),fastGptChatMsg.getRoleId());
+//        logs.setSContent(fastGptChatMsg.getContent());
+//        logs.setUserContent(userContent);
+//        logs.setCompanyUserId(loginUser.getUser().getUserId());
+//        logs.setCreateBy(loginUser.getUser().getNickName());
+//        logs.setCompanyId(loginUser.getCompany().getCompanyId());
+//
+//        iFastGptChatMsgLogsService.insertFastGptChatMsgLogs(logs);
+//
+//        return toAjax(fastGptChatMsgService.updateFastGptChatMsg(param));
+//    }
+
+//    /**
+//     * 删除聊天记录
+//     */
+//    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsg:remove')")
+//    @Log(title = "聊天记录", businessType = BusinessType.DELETE)
+//	@DeleteMapping("/{msgIds}")
+//    public AjaxResult remove(@PathVariable Long[] msgIds)
+//    {
+//        return toAjax(fastGptChatMsgService.deleteFastGptChatMsgByMsgIds(msgIds));
+//    }
+}

+ 116 - 0
fs-admin/src/main/java/com/fs/fastGpt/FastGptChatMsgLogsController.java

@@ -0,0 +1,116 @@
+package com.fs.fastGpt;
+
+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.poi.ExcelUtil;
+import com.fs.fastGpt.domain.FastGptChatMsgLogs;
+import com.fs.fastGpt.param.FastGptChatMsgLogsListParam;
+import com.fs.fastGpt.service.IFastGptChatMsgLogsService;
+import com.fs.fastGpt.vo.FastGptChatMsgLogsListCVO;
+import com.fs.fastGpt.vo.FastGptChatMsgLogsVO;
+//import com.fs.framework.security.LoginUser;
+//import com.fs.framework.service.TokenService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 聊天记录日志Controller
+ *
+ * @author fs
+ * @date 2024-10-10
+ */
+@RestController
+@RequestMapping("/fastGpt/fastGptChatMsgLogs")
+public class FastGptChatMsgLogsController extends BaseController
+{
+    @Autowired
+    private IFastGptChatMsgLogsService fastGptChatMsgLogsService;
+
+//    @Autowired
+//    private TokenService tokenService;
+
+    /**
+     * 查询聊天记录日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsgLogs:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FastGptChatMsgLogs fastGptChatMsgLogs)
+    {
+        startPage();
+        List<FastGptChatMsgLogsVO> list = fastGptChatMsgLogsService.selectFastGptChatMsgLogsListVO(fastGptChatMsgLogs);
+        return getDataTable(list);
+    }
+
+//    @GetMapping("/logsList")
+//    public R list(FastGptChatMsgLogsListParam param)
+//    {
+//        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        param.setCompanyId(loginUser.getCompany().getCompanyId());
+//
+//        List<FastGptChatMsgLogsListCVO> list= fastGptChatMsgLogsService.selectFastGptChatMsgLogsListCVO(param);
+//        PageInfo<FastGptChatMsgLogsListCVO> listPageInfo=new PageInfo<>(list);
+//        return R.ok().put("data",listPageInfo);
+//    }
+    /**
+     * 导出聊天记录日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsgLogs:export')")
+    @Log(title = "聊天记录日志", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FastGptChatMsgLogsListParam param)
+    {
+        List<FastGptChatMsgLogsListCVO> list = fastGptChatMsgLogsService.selectFastGptChatMsgLogsListCVO(param);
+        ExcelUtil<FastGptChatMsgLogsListCVO> util = new ExcelUtil<FastGptChatMsgLogsListCVO>(FastGptChatMsgLogsListCVO.class);
+        return util.exportExcel(list, "聊天记录日志数据");
+    }
+
+    /**
+     * 获取聊天记录日志详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsgLogs:query')")
+    @GetMapping(value = "/{logsId}")
+    public AjaxResult getInfo(@PathVariable("logsId") Long logsId)
+    {
+        return AjaxResult.success(fastGptChatMsgLogsService.selectFastGptChatMsgLogsByLogsId(logsId));
+    }
+
+    /**
+     * 新增聊天记录日志
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsgLogs:add')")
+    @Log(title = "聊天记录日志", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FastGptChatMsgLogs fastGptChatMsgLogs)
+    {
+        return toAjax(fastGptChatMsgLogsService.insertFastGptChatMsgLogs(fastGptChatMsgLogs));
+    }
+
+    /**
+     * 修改聊天记录日志
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsgLogs:edit')")
+    @Log(title = "聊天记录日志", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FastGptChatMsgLogs fastGptChatMsgLogs)
+    {
+        return toAjax(fastGptChatMsgLogsService.updateFastGptChatMsgLogs(fastGptChatMsgLogs));
+    }
+
+    /**
+     * 删除聊天记录日志
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatMsgLogs:remove')")
+    @Log(title = "聊天记录日志", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{logsIds}")
+    public AjaxResult remove(@PathVariable Long[] logsIds)
+    {
+        return toAjax(fastGptChatMsgLogsService.deleteFastGptChatMsgLogsByLogsIds(logsIds));
+    }
+}

+ 121 - 0
fs-admin/src/main/java/com/fs/fastGpt/FastGptChatSessionController.java

@@ -0,0 +1,121 @@
+package com.fs.fastGpt;
+
+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.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.fastGpt.domain.FastGptChatSession;
+import com.fs.fastGpt.param.FastGptChatSessionParam;
+import com.fs.fastGpt.service.IFastGptChatMsgService;
+import com.fs.fastGpt.service.IFastGptChatSessionService;
+import com.fs.fastGpt.vo.FastGptChatMsgCVO;
+import com.fs.fastGpt.vo.FastGptChatSessionCVO;
+import com.fs.fastGpt.vo.FastGptChatSessionListCVO;
+//import com.fs.framework.security.LoginUser;
+//import com.fs.framework.service.TokenService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 对话关系Controller
+ *
+ * @author fs
+ * @date 2024-10-10
+ */
+@RestController
+@RequestMapping("/fastGpt/fastGptChatSession")
+public class FastGptChatSessionController extends BaseController
+{
+    @Autowired
+    private IFastGptChatSessionService fastGptChatSessionService;
+
+//    @Autowired
+//    private TokenService tokenService;
+
+    @Autowired
+    private IFastGptChatMsgService fastGptChatMsgService;
+
+
+    /**
+     * 查询对话关系列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatSession:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FastGptChatSessionParam param)
+    {
+        startPage();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<FastGptChatSessionListCVO> list = fastGptChatSessionService.selectFastGptChatSessionListCVO(param);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出对话关系列表
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatSession:export')")
+    @Log(title = "对话关系", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FastGptChatSession fastGptChatSession)
+    {
+        List<FastGptChatSession> list = fastGptChatSessionService.selectFastGptChatSessionList(fastGptChatSession);
+        ExcelUtil<FastGptChatSession> util = new ExcelUtil<FastGptChatSession>(FastGptChatSession.class);
+        return util.exportExcel(list, "对话关系数据");
+    }
+
+    /**
+     * 获取对话关系详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatSession:query')")
+    @GetMapping(value = "/{sessionId}")
+    public R getInfo(@PathVariable("sessionId") Long sessionId)
+    {
+        FastGptChatSessionCVO sessionCVO = fastGptChatSessionService.selectFastGptChatSessionCVOBySessionId(sessionId);
+
+        List<FastGptChatMsgCVO> list = fastGptChatMsgService.selectFastGptChatMsgCVOBySessionId(sessionId,sessionCVO.getUserId());
+
+        return R.ok().put("data",sessionCVO).put("list",list);
+    }
+
+    /**
+     * 新增对话关系
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatSession:add')")
+    @Log(title = "对话关系", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FastGptChatSession fastGptChatSession)
+    {
+        return toAjax(fastGptChatSessionService.insertFastGptChatSession(fastGptChatSession));
+    }
+
+    /**
+     * 修改对话关系
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatSession:edit')")
+    @Log(title = "对话关系", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FastGptChatSession fastGptChatSession)
+    {
+        FastGptChatSession session = new FastGptChatSession();
+        session.setSessionId(fastGptChatSession.getSessionId());
+        session.setIsArtificial(fastGptChatSession.getIsArtificial());
+        return toAjax(fastGptChatSessionService.updateFastGptChatSession(session));
+    }
+
+    /**
+     * 删除对话关系
+     */
+    @PreAuthorize("@ss.hasPermi('fastGpt:fastGptChatSession:remove')")
+    @Log(title = "对话关系", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{sessionIds}")
+    public AjaxResult remove(@PathVariable Long[] sessionIds)
+    {
+        return toAjax(fastGptChatSessionService.deleteFastGptChatSessionBySessionIds(sessionIds));
+    }
+}

+ 23 - 35
fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderController.java

@@ -3,6 +3,7 @@ package com.fs.his.controller;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.common.BeanCopyUtils;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -143,12 +144,11 @@ public class FsIntegralOrderController extends BaseController
     }
 
     /**
-     * 导出积分商品订单列表
+     * 导出积分商品订单列表 卓美个性化导出
      */
     @PreAuthorize("@ss.hasPermi('his:integralOrder:export')")
     @Log(title = "积分商品订单", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
-
     public AjaxResult export(FsIntegralOrderParam fsIntegralOrder) {
         List<FsIntegralOrderListVO> fsIntegralOrderListVOS = new ArrayList<>();
         if (CloudHostUtils.hasCloudHostName("金牛明医")){
@@ -163,7 +163,12 @@ public class FsIntegralOrderController extends BaseController
         }
         SysRole sysRole = isCheckPermission();
         // 处理商品名称:解析item_json并设置goodsName
+        List<FsIntegralOrderListVO> newFsIntegralOrderListVOS=new ArrayList<>();
         for (FsIntegralOrderListVO vo : fsIntegralOrderListVOS) {
+            if (!(sysRole.getIsCheckPhone()==1)){
+                // 加密手机号
+                vo.setUserPhone(decryptAutoPhoneMk(vo.getUserPhone()));
+            }
             if (StringUtils.isNotEmpty(vo.getItemJson())) {
                 try {
                     // 尝试解析JSON格式的商品信息
@@ -171,44 +176,30 @@ public class FsIntegralOrderController extends BaseController
                         // 数组格式,遍历所有商品,用换行符分隔
                         com.alibaba.fastjson.JSONArray jsonArray = com.alibaba.fastjson.JSONArray.parseArray(vo.getItemJson());
                         if (jsonArray != null && !jsonArray.isEmpty()) {
-                            StringBuilder goodsNameBuilder = new StringBuilder();
-                            StringBuilder barCodeBuilder = new StringBuilder();
-
                             for (int i = 0; i < jsonArray.size(); i++) {
+                                FsIntegralOrderListVO newVo = BeanCopyUtils.copy(vo,FsIntegralOrderListVO.class);
+                                if (newVo==null){
+                                    continue;
+                                }
                                 com.alibaba.fastjson.JSONObject goods = jsonArray.getJSONObject(i);
 
                                 // 处理商品名称和数量
                                 if (goods != null && goods.getString("goodsName") != null) {
                                     String name = goods.getString("goodsName");
                                     String num = goods.getString("num");
-                                    if (StringUtils.isEmpty(num)) {
-                                        num = "1"; // 默认数量为1
-                                    }
-                                    if (goodsNameBuilder.length() > 0) {
-                                        goodsNameBuilder.append("\r\n");
-                                    }
-                                    goodsNameBuilder.append(name).append(",数量:").append(num).append("个");
+                                    newVo.setNum(num);
+                                    newVo.setGoodsName(name);
                                 }
 
                                 // 处理商品编码
                                 if (goods != null && goods.getString("barCode") != null) {
                                     String barCode = goods.getString("barCode");
-                                    if (barCodeBuilder.length() > 0) {
-                                        barCodeBuilder.append("\r\n");
-                                    }
-                                    barCodeBuilder.append(barCode);
+                                    newVo.setBarCode(barCode);
                                 }
+                                newFsIntegralOrderListVOS.add(newVo);
                             }
-
-                            // 设置商品名称
-                            if (goodsNameBuilder.length() > 0) {
-                                vo.setGoodsName(goodsNameBuilder.toString());
-                            }
-
-                            // 设置商品编码
-                            if (barCodeBuilder.length() > 0) {
-                                vo.setBarCode(barCodeBuilder.toString());
-                            }
+                        }else{
+                            newFsIntegralOrderListVOS.add(vo);
                         }
                     } else if (vo.getItemJson().startsWith("{")) {
                         // 对象格式
@@ -218,30 +209,27 @@ public class FsIntegralOrderController extends BaseController
                         if (goods != null && goods.getString("goodsName") != null) {
                             String name = goods.getString("goodsName");
                             String num = goods.getString("num");
-                            if (StringUtils.isEmpty(num)) {
-                                num = "1"; // 默认数量为1
-                            }
-                            vo.setGoodsName(name + ",数量:" + num + "个");
+                            vo.setNum(num);
+                            vo.setGoodsName(name);
                         }
 
                         // 处理商品编码
                         if (goods != null && goods.getString("barCode") != null) {
                             vo.setBarCode(goods.getString("barCode"));
                         }
+                        newFsIntegralOrderListVOS.add(vo);
                     }
                 } catch (Exception e) {
                     // 解析失败时保持goodsName为空,避免导出出错
                     log.warn("解析商品信息失败,订单编号:{}, 商品信息:{}", vo.getOrderCode(), vo.getItemJson());
                 }
-            }
-            if (!(sysRole.getIsCheckPhone()==1)){
-                // 加密手机号
-                vo.setUserPhone(decryptAutoPhoneMk(vo.getUserPhone()));
+            }else {
+                newFsIntegralOrderListVOS.add(vo);
             }
 
         }
         ExcelUtil<FsIntegralOrderListVO> util = new ExcelUtil<>(FsIntegralOrderListVO.class);
-        return util.exportExcel(new ArrayList<>(fsIntegralOrderListVOS), "积分商品订单数据");
+        return util.exportExcel(new ArrayList<>(newFsIntegralOrderListVOS), "积分商品订单数据");
     }
 
     /*public AjaxResult export(FsIntegralOrderParam fsIntegralOrder) {

+ 136 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwAutoTagsController.java

@@ -0,0 +1,136 @@
+package com.fs.qw.controller;
+
+
+import ch.qos.logback.core.util.ContextUtil;
+import com.alibaba.fastjson.JSON;
+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.domain.R;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+//import com.fs.framework.security.LoginUser;
+//import com.fs.framework.service.TokenService;
+import com.fs.qw.domain.QwAutoTags;
+import com.fs.qw.param.QwAutoTagsParam;
+import com.fs.qw.param.QwAutoTagsRulesTags;
+import com.fs.qw.param.QwTagSearchParam;
+import com.fs.qw.service.IQwAutoTagsService;
+import com.fs.qw.service.IQwTagService;
+import com.fs.qw.vo.QwAutoTagsVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+/**
+ * 自动打标签主Controller
+ *
+ * @author fs
+ * @date 2024-07-20
+ */
+@RestController
+@RequestMapping("/qw/autoTags")
+public class QwAutoTagsController extends BaseController
+{
+    @Autowired
+    private IQwAutoTagsService qwAutoTagsService;
+
+//    @Autowired
+//    private TokenService tokenService;
+
+    @Autowired
+    private IQwTagService iQwTagService;
+    /**
+     * 查询自动打标签主列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwAutoTagsParam qwAutoTags)
+    {
+        startPage();
+        List<QwAutoTagsVO> list = qwAutoTagsService.selectQwAutoTagsListVO(qwAutoTags);
+        list.forEach(item->{
+
+            QwTagSearchParam param = new QwTagSearchParam();
+
+            Set<String> combinedTagsSet = new HashSet<>();
+            List<QwAutoTagsRulesTags> qwAutoTagsRulesTagsList = JSON.parseArray(item.getRulesTags(), QwAutoTagsRulesTags.class);
+            for (QwAutoTagsRulesTags rulesTags : qwAutoTagsRulesTagsList) {
+                List<String> tagsItem = rulesTags.getTags();
+
+                combinedTagsSet.addAll(tagsItem);
+            }
+
+            param.setTagIds(new ArrayList<>(combinedTagsSet));
+            item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
+
+        });
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出自动打标签主列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:export')")
+    @Log(title = "自动打标签主", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwAutoTagsParam qwAutoTags)
+    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwAutoTags.setCompanyId( loginUser.getCompany().getCompanyId());
+        List<QwAutoTagsVO> list = qwAutoTagsService.selectQwAutoTagsListVO(qwAutoTags);
+        ExcelUtil<QwAutoTagsVO> util = new ExcelUtil<QwAutoTagsVO>(QwAutoTagsVO.class);
+        return util.exportExcel(list, "自动打标签主数据");
+    }
+
+    /**
+     * 获取自动打标签主详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:query')")
+    @GetMapping(value = "/{id}")
+    public R getInfo(@PathVariable("id") Long id)
+    {
+        return qwAutoTagsService.selectQwAutoTagsByIdVO(id);
+    }
+
+    /**
+     * 新增自动打标签主
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:add')")
+    @Log(title = "自动打标签主", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody QwAutoTags qwAutoTags)
+    {
+        LoginUser loginUser = getLoginUser();
+        qwAutoTags.setCreateName(loginUser.getUser().getNickName());
+        qwAutoTags.setCreateTime(new Date());
+        return toAjax(qwAutoTagsService.insertQwAutoTags(qwAutoTags));
+    }
+
+    /**
+     * 修改自动打标签主
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:edit')")
+    @Log(title = "自动打标签主", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody QwAutoTags qwAutoTags)
+    {
+        return toAjax(qwAutoTagsService.updateQwAutoTags(qwAutoTags));
+    }
+
+    /**
+     * 删除自动打标签主
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:remove')")
+    @Log(title = "自动打标签主", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(qwAutoTagsService.deleteQwAutoTagsByIds(ids));
+    }
+}

+ 132 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwAutoTagsLogsController.java

@@ -0,0 +1,132 @@
+package com.fs.qw.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.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+//import com.fs.framework.security.LoginUser;
+//import com.fs.framework.service.TokenService;
+import com.fs.qw.domain.QwAutoTagsLogs;
+import com.fs.qw.param.QwAutoTagsLogsParams;
+import com.fs.qw.param.QwTagSearchParam;
+import com.fs.qw.service.IQwAutoTagsLogsService;
+import com.fs.qw.service.IQwTagService;
+import com.fs.qw.vo.QwAutoTagsLogsVO;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * 自动打标签的日志Controller
+ *
+ * @author fs
+ * @date 2024-07-20
+ */
+@RestController
+@RequestMapping("/qw/autoTagsLogs")
+public class QwAutoTagsLogsController extends BaseController
+{
+    @Autowired
+    private IQwAutoTagsLogsService qwAutoTagsLogsService;
+
+
+//    @Autowired
+//    private TokenService tokenService;
+
+    @Autowired
+    private IQwTagService iQwTagService;
+
+    /**
+     * 查询自动打标签的日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:query')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwAutoTagsLogsParams params)
+    {
+        startPage();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        params.setCompanyId( loginUser.getCompany().getCompanyId());
+        List<QwAutoTagsLogsVO> list = qwAutoTagsLogsService.selectQwAutoTagsLogsListVO(params);
+        list.forEach(item->{
+
+            if (!Objects.equals(item.getEffectiveRules(), "[]") && item.getEffectiveRules()!=null) {
+                QwTagSearchParam param = new QwTagSearchParam();
+                Gson gson = new Gson();
+                List<String> tagIds = gson.fromJson(
+                        item.getEffectiveRules(),
+                        new TypeToken<List<String>>() {
+                        }.getType()
+                );
+
+                param.setTagIds(tagIds);
+
+                item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
+            }
+        });
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出自动打标签的日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:export')")
+    @Log(title = "自动打标签的日志", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwAutoTagsLogs qwAutoTagsLogs)
+    {
+        List<QwAutoTagsLogs> list = qwAutoTagsLogsService.selectQwAutoTagsLogsList(qwAutoTagsLogs);
+        ExcelUtil<QwAutoTagsLogs> util = new ExcelUtil<QwAutoTagsLogs>(QwAutoTagsLogs.class);
+        return util.exportExcel(list, "自动打标签的日志数据");
+    }
+
+    /**
+     * 获取自动打标签的日志详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(qwAutoTagsLogsService.selectQwAutoTagsLogsById(id));
+    }
+
+    /**
+     * 新增自动打标签的日志
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:add')")
+    @Log(title = "自动打标签的日志", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody QwAutoTagsLogs qwAutoTagsLogs)
+    {
+        return toAjax(qwAutoTagsLogsService.insertQwAutoTagsLogs(qwAutoTagsLogs));
+    }
+
+    /**
+     * 修改自动打标签的日志
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:edit')")
+    @Log(title = "自动打标签的日志", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody QwAutoTagsLogs qwAutoTagsLogs)
+    {
+        return toAjax(qwAutoTagsLogsService.updateQwAutoTagsLogs(qwAutoTagsLogs));
+    }
+
+    /**
+     * 删除自动打标签的日志
+     */
+    @PreAuthorize("@ss.hasPermi('qw:autoTags:remove')")
+    @Log(title = "自动打标签的日志", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(qwAutoTagsLogsService.deleteQwAutoTagsLogsByIds(ids));
+    }
+}

+ 160 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwGroupMsgController.java

@@ -0,0 +1,160 @@
+package com.fs.qw.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.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+//import com.fs.framework.security.LoginUser;
+//import com.fs.framework.service.TokenService;
+import com.fs.qw.domain.QwGroupMsg;
+import com.fs.qw.param.QwGroupMsgDetailsParam;
+import com.fs.qw.service.IQwGroupMsgService;
+import com.fs.qw.vo.QwGroupMsgDetailsVO;
+import com.fs.qw.vo.QwGroupMsgVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 客户群发记录主Controller
+ *
+ * @author fs
+ * @date 2024-06-20
+ */
+@RestController
+@RequestMapping("/qw/groupMsg")
+public class QwGroupMsgController extends BaseController
+{
+    @Autowired
+    private IQwGroupMsgService qwGroupMsgService;
+
+//    @Autowired
+//    private TokenService tokenService;
+    /**
+     * 查询客户群发记录主列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsg:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwGroupMsg qwGroupMsg)
+    {
+        startPage();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwGroupMsg.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<QwGroupMsgVO> list = qwGroupMsgService.selectQwGroupMsgListVO(qwGroupMsg);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询客户群发记录主列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsg:myList')")
+    @GetMapping("/myList")
+    public TableDataInfo myList(QwGroupMsg qwGroupMsg)
+    {
+        startPage();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwGroupMsg.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<QwGroupMsgVO> list = qwGroupMsgService.selectQwGroupMsgListMyVO(qwGroupMsg);
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 导出客户群发记录主列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsg:export')")
+    @Log(title = "客户群发记录主", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwGroupMsg qwGroupMsg)
+    {
+        List<QwGroupMsgVO> list = qwGroupMsgService.selectQwGroupMsgListVO(qwGroupMsg);
+        ExcelUtil<QwGroupMsgVO> util = new ExcelUtil<QwGroupMsgVO>(QwGroupMsgVO.class);
+        return util.exportExcel(list, "客户群发记录主数据");
+    }
+
+    /**
+     * 获取客户群发记录主详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsg:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(qwGroupMsgService.selectQwGroupMsgByIdVO(id));
+    }
+
+//    /**
+//     * 新增客户群发/客户群群发记录
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:groupMsg:add')")
+//    @Log(title = "客户群发记录", businessType = BusinessType.INSERT)
+//    @PostMapping
+//    public R add(@RequestBody QwGroupMsgParam qwGroupMsgParam) throws Exception {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+////        Long companyId = loginUser.getCompany().getCompanyId();
+//        qwGroupMsgParam.setCreateName(loginUser.getUser().getNickName());
+//        return qwGroupMsgService.insertQwGroupMsg(qwGroupMsgParam);
+//    }
+
+    /** 统计数据详情,已发送,未发送,已接收,未接收等
+     *  groupMsgId 消息主表的主键
+     * */
+    @GetMapping("/getCountGroupMsgUser/{groupMsgId}")
+    public R getCountGroupMsgUser(@PathVariable("groupMsgId") Long groupMsgId){
+
+        return qwGroupMsgService.getCountGroupMsgUser(groupMsgId);
+    }
+
+    /** 统计数据详情,已发送群主,送达群聊,未发送群主,未送达群聊等 */
+    @GetMapping("/getCountGroupMsgBaseUser/{groupMsgId}")
+    public R getCountGroupMsgBaseUser(@PathVariable("groupMsgId") Long groupMsgId){
+
+        return qwGroupMsgService.getCountGroupMsgBaseUser(groupMsgId);
+    }
+
+    /**
+     * 客户群发 发送/接收的数据详情
+     */
+    @GetMapping("/getCountGroupMsgUserDetails")
+    public TableDataInfo getCountGroupMsgUserDetails(QwGroupMsgDetailsParam qwGroupMsgDetailsParam){
+
+        startPage();
+        List<QwGroupMsgDetailsVO> list = qwGroupMsgService.getCountGroupMsgUserDetails(qwGroupMsgDetailsParam);
+        return getDataTable(list);
+    }
+
+    /** 提醒成员群发 */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsg:remindGroupMsg')")
+    @GetMapping("/remindGroupMsg")
+    public R remindGroupMsg(QwGroupMsgDetailsParam qwGroupMsgDetailsParam){
+
+
+        return  qwGroupMsgService.remindGroupMsg(qwGroupMsgDetailsParam);
+    }
+
+//    /**
+//     * 修改客户群发记录主
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:groupMsg:edit')")
+//    @Log(title = "客户群发记录主", businessType = BusinessType.UPDATE)
+//    @PutMapping
+//    public AjaxResult edit(@RequestBody QwGroupMsg qwGroupMsg)
+//    {
+//        return toAjax(qwGroupMsgService.updateQwGroupMsg(qwGroupMsg));
+//    }
+
+    /**
+     * 删除客户群发记录主
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsg:remove')")
+    @Log(title = "客户群发记录主", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(qwGroupMsgService.deleteQwGroupMsgByIds(ids));
+    }
+}

+ 118 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwGroupMsgUserController.java

@@ -0,0 +1,118 @@
+package com.fs.qw.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.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+//import com.fs.framework.service.TokenService;
+import com.fs.qw.domain.QwGroupMsgUser;
+import com.fs.qw.service.IQwGroupMsgUserService;
+import com.fs.qw.vo.QwGroupMsgDetailsVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 群发成员发送任务及执行结果反馈记录Controller
+ *
+ * @author fs
+ * @date 2024-06-20
+ */
+@RestController
+@RequestMapping("/qw/groupMsgUser")
+public class QwGroupMsgUserController extends BaseController
+{
+    @Autowired
+    private IQwGroupMsgUserService qwGroupMsgUserService;
+
+//    @Autowired
+//    private TokenService tokenService;
+
+    /**
+     * 查询群发成员发送任务及执行结果反馈记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsgUser:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwGroupMsgUser qwGroupMsgUser)
+    {
+        startPage();
+        List<QwGroupMsgUser> list = qwGroupMsgUserService.selectQwGroupMsgUserList(qwGroupMsgUser);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出群发成员发送任务及执行结果反馈记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsgUser:export')")
+    @Log(title = "群发成员发送任务及执行结果反馈记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwGroupMsgUser qwGroupMsgUser)
+    {
+        List<QwGroupMsgUser> list = qwGroupMsgUserService.selectQwGroupMsgUserList(qwGroupMsgUser);
+        ExcelUtil<QwGroupMsgUser> util = new ExcelUtil<QwGroupMsgUser>(QwGroupMsgUser.class);
+        return util.exportExcel(list, "群发成员发送任务及执行结果反馈记录数据");
+    }
+
+    /**
+     * 获取群发成员发送任务及执行结果反馈记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsgUser:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(qwGroupMsgUserService.selectQwGroupMsgUserById(id));
+    }
+
+    /**
+     * 新增群发成员发送任务及执行结果反馈记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsgUser:add')")
+    @Log(title = "群发成员发送任务及执行结果反馈记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody QwGroupMsgUser qwGroupMsgUser)
+    {
+        return toAjax(qwGroupMsgUserService.insertQwGroupMsgUser(qwGroupMsgUser));
+    }
+
+    /**
+     * 修改群发成员发送任务及执行结果反馈记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsgUser:edit')")
+    @Log(title = "群发成员发送任务及执行结果反馈记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody QwGroupMsgUser qwGroupMsgUser)
+    {
+        return toAjax(qwGroupMsgUserService.updateQwGroupMsgUser(qwGroupMsgUser));
+    }
+
+    /**
+     * 删除群发成员发送任务及执行结果反馈记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupMsgUser:remove')")
+    @Log(title = "群发成员发送任务及执行结果反馈记录", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(qwGroupMsgUserService.deleteQwGroupMsgUserByIds(ids));
+    }
+
+    /** 刷新/同步 客户群群发 结果 */
+    @PostMapping("/refreshResultsGroupMsgUser")
+    public R refreshResultsGroupMsgUser(@RequestBody List<QwGroupMsgDetailsVO> list){
+
+
+        return  qwGroupMsgUserService.refreshResultsGroupMsgUser(list);
+    }
+
+    /** 刷新/同步 客户群发 结果 */
+    @PostMapping("/refreshResultsMsgUser")
+    public R refreshResultsMsgUser(@RequestBody List<QwGroupMsgDetailsVO> list,String corpId){
+        QwGroupMsgDetailsVO qwGroupMsgDetailsVO = list.get(0);
+        return  qwGroupMsgUserService.refreshResultsMsgUser(list,qwGroupMsgDetailsVO.getCorpId() );
+    }
+}

+ 83 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwTagGroupController.java

@@ -1,12 +1,19 @@
 package com.fs.qw.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.domain.R;
 import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.qw.domain.QwTagGroup;
 import com.fs.qw.service.IQwTagGroupService;
+import com.fs.qw.vo.QwTagGroupAddParam;
 import com.fs.qw.vo.QwTagGroupListVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -50,4 +57,80 @@ public class QwTagGroupController extends BaseController
         List<QwTagGroupListVO> list = qwTagGroupService.selectQwTagGroupListVO(qwTagGroup);
         return getDataTable(list);
     }
+
+    @PreAuthorize("@ss.hasPermi('qw:tagGroup:sync')")
+    @Log(title = "同步标签", businessType = BusinessType.INSERT)
+    @PostMapping("/syncTag/{corpId}")
+    public R syncTag(@PathVariable("corpId") String corpId)
+    {
+
+        return qwTagGroupService.syncQwTagGroup(corpId);
+    }
+    /**
+     * 查询企微客户标签组列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:tagGroup:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwTagGroup qwTagGroup)
+    {
+        startPage();
+
+        List<QwTagGroupListVO> list = qwTagGroupService.selectQwTagGroupListVO(qwTagGroup);
+        return getDataTable(list);
+    }
+    /**
+     * 获取企微客户标签组详细信息
+     */
+//    @PreAuthorize("@ss.hasPermi('qw:tagGroup:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(qwTagGroupService.selectQwTagGroupByIdVO(id));
+    }
+    /**
+     * 删除企微客户标签组
+     */
+    @PreAuthorize("@ss.hasPermi('qw:tagGroup:remove')")
+    @Log(title = "企微客户标签组", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R remove(@PathVariable Long[] ids)
+    {
+
+        return qwTagGroupService.deleteQwTagGroupByIds(ids);
+    }
+    /**
+     * 新增企微客户标签组
+     */
+    @PreAuthorize("@ss.hasPermi('qw:tagGroup:add')")
+    @Log(title = "企微客户标签组", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody QwTagGroupAddParam qwTagGroup)
+    {
+
+        return toAjax(qwTagGroupService.insertQwTagGroupParam(qwTagGroup));
+    }
+    /**
+     * 修改企微客户标签组
+     */
+    @PreAuthorize("@ss.hasPermi('qw:tagGroup:edit')")
+    @Log(title = "企微客户标签组", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody QwTagGroupAddParam qwTagGroup)
+    {
+
+        return toAjax(qwTagGroupService.updateQwTagGroupParam(qwTagGroup));
+    }
+    /**
+     * 导出企微客户标签组列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:tagGroup:export')")
+    @Log(title = "企微客户标签组", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwTagGroup qwTagGroup)
+    {
+
+        List<QwTagGroup> list = qwTagGroupService.selectQwTagGroupList(qwTagGroup);
+        ExcelUtil<QwTagGroup> util = new ExcelUtil<QwTagGroup>(QwTagGroup.class);
+        return util.exportExcel(list, "企微客户标签组数据");
+    }
 }

+ 328 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwUserVoiceLogController.java

@@ -0,0 +1,328 @@
+package com.fs.qw.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.constant.HttpStatus;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.PageDomain;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.core.page.TableSupport;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.service.ICompanyUserService;
+//import com.fs.framework.security.LoginUser;
+//import com.fs.framework.service.TokenService;
+import com.fs.qw.domain.QwUserVoiceLog;
+import com.fs.qw.param.QwTagSearchParam;
+import com.fs.qw.service.IQwTagService;
+import com.fs.qw.service.IQwUserVoiceLogService;
+import com.fs.qw.vo.QwUserVoiceLogTotalVo;
+import com.fs.qw.vo.QwUserVoiceLogVo;
+import com.github.pagehelper.PageHelper;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * 企微用户通话记录Controller
+ *
+ * @author fs
+ * @date 2025-05-08
+ */
+@RestController
+@RequestMapping("/qw/qwUserVoiceLog")
+public class QwUserVoiceLogController extends BaseController
+{
+    @Autowired
+    private IQwUserVoiceLogService qwUserVoiceLogService;
+
+//    @Autowired
+//    private TokenService tokenService;
+
+    @Autowired
+    private IQwTagService iQwTagService;
+
+    @Autowired
+    private ICompanyUserService userService;
+
+//    /**
+//     * 查询企微用户通话记录列表
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:list')")
+//    @GetMapping("/list")
+//    public TableDataInfo list(QwUserVoiceLogVo qwUserVoiceLog)
+//    {
+//        startPage();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
+//        List<QwUserVoiceLogVo> list = qwUserVoiceLogService.selectQwUserVoiceLogList(qwUserVoiceLog);
+//        return getDataTable(list);
+//    }
+
+
+//    /**
+//     * 查询企微用户通话记录列表
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:list')")
+//    @PostMapping("/newList")
+//    public TableDataInfo newList(@RequestBody QwUserVoiceLogVo qwUserVoiceLog)
+//    {
+//        PageHelper.startPage(qwUserVoiceLog.getPageNum(), qwUserVoiceLog.getPageSize());
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
+//        List<QwUserVoiceLogVo> list = qwUserVoiceLogService.selectQwUserVoiceLogList(qwUserVoiceLog);
+//        list.forEach(item->{
+//
+//            if (!Objects.equals(item.getQwExternalContact().getTagIds(), "[]") && item.getQwExternalContact().getTagIds()!=null) {
+//                QwTagSearchParam param = new QwTagSearchParam();
+//                Gson gson = new Gson();
+//                List<String> tagIds = gson.fromJson(
+//                        item.getQwExternalContact().getTagIds(),
+//                        new TypeToken<List<String>>() {
+//                        }.getType()
+//                );
+//                param.setTagIds(tagIds);
+//                item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
+//            }
+//        });
+//        return getDataTable(list);
+//    }
+
+//    /**
+//     * 查询我的通话记录列表
+//     * @param qwUserVoiceLog
+//     * @return
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:myList')")
+//    @GetMapping("/myList")
+//    public TableDataInfo myList(QwUserVoiceLogVo qwUserVoiceLog)
+//    {
+//        startPage();
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUserVoiceLog.setCompanyUserId(loginUser.getUser().getUserId());
+//        qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
+//        List<QwUserVoiceLogVo> list = qwUserVoiceLogService.selectQwUserVoiceLogList(qwUserVoiceLog);
+//        return getDataTable(list);
+//    }
+
+//    /**
+//     * 导出我的通话记录
+//     */
+//
+//    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:myExport')")
+//    @Log(title = "我的通话记录", businessType = BusinessType.EXPORT)
+//    @GetMapping("/myExport")
+//    public AjaxResult myExport(QwUserVoiceLogVo qwUserVoiceLog)
+//    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUserVoiceLog.setCompanyUserId(loginUser.getUser().getUserId());
+//        qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
+//        List<QwUserVoiceLogVo> list = qwUserVoiceLogService.selectQwUserVoiceLogList(qwUserVoiceLog);
+//        list.forEach(m-> {
+//            m.setCompanyUserName(m.getCompanyUser().getUserName());
+//            m.setCompanyName(m.getCompany().getCompanyName());
+//            m.setExtName(m.getQwExternalContact().getName());
+//            m.setQwUserName(m.getQwUser().getQwUserName());
+//        });
+//        ExcelUtil<QwUserVoiceLogVo> util = new ExcelUtil<QwUserVoiceLogVo>(QwUserVoiceLogVo.class);
+//        return util.exportExcel(list, "企微用户通话记录数据");
+//    }
+
+
+    /**
+     * 统计查询企微用户通话记录
+     * @param qwUserVoiceLog
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:totalList')")
+    @GetMapping("/totalList")
+    public TableDataInfo totalList(QwUserVoiceLogTotalVo qwUserVoiceLog)
+    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
+        qwUserVoiceLog.setQwUserId(1L);
+        List<QwUserVoiceLogTotalVo> list = qwUserVoiceLogService.selectQwUserVoiceLogTotalList(qwUserVoiceLog);
+        list.forEach(item->{
+            if(item.getQwExternalContact() != null){
+                if (item.getQwExternalContact().getTagIds() != null && !Objects.equals(item.getQwExternalContact().getTagIds(), "[]")) {
+                    QwTagSearchParam param = new QwTagSearchParam();
+                    Gson gson = new Gson();
+                    List<String> tagIds = gson.fromJson(
+                            item.getQwExternalContact().getTagIds(),
+                            new TypeToken<List<String>>() {
+                            }.getType()
+                    );
+                    param.setTagIds(tagIds);
+                    item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
+                }
+            }
+        });
+
+        // 获取分页参数
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+
+        int total = list.size();
+        // 在内存中进行分页处理
+        if (pageNum != null && pageSize != null) {
+            int fromIndex = (pageNum - 1) * pageSize;
+            int toIndex = Math.min(fromIndex + pageSize, total);
+
+            // 确保索引不越界
+            if (fromIndex < total) {
+                list = list.subList(fromIndex, toIndex);
+            } else {
+                list = new ArrayList<>(); // 返回空列表
+            }
+        }
+
+        // 构造返回结果
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(list);
+        rspData.setTotal(total);
+        return rspData;
+    }
+
+
+    @GetMapping("/sellTotalList")
+    public TableDataInfo sellTotalList(QwUserVoiceLogTotalVo qwUserVoiceLog)
+    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<QwUserVoiceLogTotalVo> list = qwUserVoiceLogService.selectQwUserVoiceLogTotalList(qwUserVoiceLog);
+
+        // 获取分页参数
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+
+        int total = list.size();
+        // 在内存中进行分页处理
+        if (pageNum != null && pageSize != null) {
+            int fromIndex = (pageNum - 1) * pageSize;
+            int toIndex = Math.min(fromIndex + pageSize, total);
+
+            // 确保索引不越界
+            if (fromIndex < total) {
+                list = list.subList(fromIndex, toIndex);
+            } else {
+                list = new ArrayList<>(); // 返回空列表
+            }
+        }
+
+        // 构造返回结果
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(list);
+        rspData.setTotal(total);
+        return rspData;
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:sellTotalExport')")
+    @Log(title = "企微用户通话记录统计", businessType = BusinessType.EXPORT)
+    @GetMapping("/sellTotalExport")
+    public AjaxResult sellTotalExport(QwUserVoiceLogTotalVo qwUserVoiceLog)
+    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<QwUserVoiceLogTotalVo> list = qwUserVoiceLogService.selectQwUserVoiceLogTotalList(qwUserVoiceLog);
+        list.forEach(m-> {
+            m.setQwUserName(m.getQwUser().getQwUserName());
+        });
+        ExcelUtil<QwUserVoiceLogTotalVo> util = new ExcelUtil<QwUserVoiceLogTotalVo>(QwUserVoiceLogTotalVo.class);
+        return util.exportExcel(list, "企微用户通话记录数据");
+    }
+
+//    /**
+//     * 导出统计企微用户通话记录
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:totalExport')")
+//    @Log(title = "企微用户通话记录统计", businessType = BusinessType.EXPORT)
+//    @GetMapping("/totalExport")
+//    public AjaxResult totalExport(QwUserVoiceLogTotalVo qwUserVoiceLog)
+//    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
+//        qwUserVoiceLog.setQwUserId(1L);
+//        List<QwUserVoiceLogTotalVo> list = qwUserVoiceLogService.selectQwUserVoiceLogTotalList(qwUserVoiceLog);
+//        list.forEach(m-> {
+//            m.setQwUserName(m.getQwUser().getQwUserName());
+//        });
+//        ExcelUtil<QwUserVoiceLogTotalVo> util = new ExcelUtil<QwUserVoiceLogTotalVo>(QwUserVoiceLogTotalVo.class);
+//        return util.exportExcel(list, "企微用户通话记录数据");
+//    }
+
+
+    /**
+     * 导出企微用户通话记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:export')")
+    @Log(title = "企微用户通话记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwUserVoiceLogVo qwUserVoiceLog)
+    {
+        List<QwUserVoiceLogVo> list = qwUserVoiceLogService.selectQwUserVoiceLogList(qwUserVoiceLog);
+        list.forEach(m-> {
+            m.setCompanyUserName(m.getCompanyUser().getUserName());
+            m.setCompanyName(m.getCompany().getCompanyName());
+            m.setExtName(m.getQwExternalContact().getName());
+            m.setQwUserName(m.getQwUser().getQwUserName());
+        });
+        ExcelUtil<QwUserVoiceLogVo> util = new ExcelUtil<QwUserVoiceLogVo>(QwUserVoiceLogVo.class);
+        return util.exportExcel(list, "企微用户通话记录数据");
+    }
+
+    /**
+     * 获取企微用户通话记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(qwUserVoiceLogService.selectQwUserVoiceLogById(id));
+    }
+
+    /**
+     * 新增企微用户通话记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:add')")
+    @Log(title = "企微用户通话记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody QwUserVoiceLog qwUserVoiceLog)
+    {
+        return toAjax(qwUserVoiceLogService.insertQwUserVoiceLog(qwUserVoiceLog));
+    }
+
+    /**
+     * 修改企微用户通话记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:edit')")
+    @Log(title = "企微用户通话记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody QwUserVoiceLog qwUserVoiceLog)
+    {
+        return toAjax(qwUserVoiceLogService.updateQwUserVoiceLog(qwUserVoiceLog));
+    }
+
+    /**
+     * 删除企微用户通话记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:remove')")
+    @Log(title = "企微用户通话记录", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(qwUserVoiceLogService.deleteQwUserVoiceLogByIds(ids));
+    }
+}

+ 1 - 8
fs-common/src/main/java/com/fs/common/core/redis/service/StockDeductService.java

@@ -31,8 +31,6 @@ public class StockDeductService {
 
     // 库存扣减Lua脚本(预编译,提升高并发性能)
     private static final DefaultRedisScript<Long> STOCK_DEDUCT_SCRIPT;
-    // 锁释放Lua脚本(预编译)
-    private static final DefaultRedisScript<Long> LOCK_RELEASE_SCRIPT;
 
     // 库存扣减Lua脚本(优化后,增强健壮性)
     static {
@@ -40,11 +38,6 @@ public class StockDeductService {
         STOCK_DEDUCT_SCRIPT = new DefaultRedisScript<>();
         STOCK_DEDUCT_SCRIPT.setScriptText("if redis.call('exists', KEYS[1]) ~= 1 then " + "return -2; " + "end " + "local stock_str = redis.call('get', KEYS[1]); " + "local stock = tonumber(stock_str); " + "if stock == nil then " + "return -3; " + "end " + "local deductNum_str = ARGV[1]; " + "local deductNum = tonumber(deductNum_str); " + "if deductNum == nil or deductNum <= 0 then " + "return -4; " + "end " + "if stock >= deductNum then " + "return redis.call('decrby', KEYS[1], deductNum); " + "else " + "return -1; " + "end");
         STOCK_DEDUCT_SCRIPT.setResultType(Long.class);
-
-        // 锁释放脚本保持不变
-        LOCK_RELEASE_SCRIPT = new DefaultRedisScript<>();
-        LOCK_RELEASE_SCRIPT.setScriptText("if redis.call('get', KEYS[1]) == ARGV[1] then " + "return redis.call('del', KEYS[1]) " + "else return 0 end");
-        LOCK_RELEASE_SCRIPT.setResultType(Long.class);
     }
 
     /**
@@ -55,7 +48,7 @@ public class StockDeductService {
      */
     public void initStock(Long productId, Long liveId, Integer initStock) {
         String stockKey = RedisConstant.STOCK_KEY_PREFIX + liveId + ":" + productId;
-        redisTemplate.opsForValue().set(stockKey, initStock, 24 * 60 * 60, TimeUnit.SECONDS);
+        redisTemplate.opsForValue().set(stockKey, initStock);
         log.info("商品" + productId + "库存初始化完成,初始库存:" + initStock);
     }
 

+ 7 - 1
fs-company/src/main/java/com/fs/company/controller/qw/QwSopController.java

@@ -8,6 +8,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.service.impl.CompanyDeptServiceImpl;
@@ -180,7 +181,12 @@ public class QwSopController extends BaseController
     @GetMapping(value = "/videoList/{id}")
     public R videoList(@PathVariable("id") Long id)
     {
-        List<OptionsVO> optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id);
+        List<OptionsVO> optionsVOS;
+        if (CloudHostUtils.hasCloudHostName("木易华康")) {
+            optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVideoAllListV2(id);
+        } else {
+            optionsVOS = fsUserCourseVideoMapper.selectFsUserCourseVodeAllList(id);
+        }
         return R.ok().put("list", optionsVOS);
     }
 

+ 108 - 0
fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderItemScrmController.java

@@ -0,0 +1,108 @@
+package com.fs.hisStore.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.poi.ExcelUtil;
+import com.fs.hisStore.domain.FsStoreOrderItemScrm;
+import com.fs.hisStore.service.IFsStoreOrderItemScrmService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 订单详情Controller
+ *
+ * @author fs
+ * @date 2022-03-21
+ */
+@RestController
+@RequestMapping("/store/store/storeOrderItem")
+public class FsStoreOrderItemScrmController extends BaseController
+{
+    @Autowired
+    private IFsStoreOrderItemScrmService fsStoreOrderItemService;
+
+    /**
+     * 查询订单详情列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrderItem:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsStoreOrderItemScrm fsStoreOrderItem)
+    {
+        startPage();
+        List<FsStoreOrderItemScrm> list = fsStoreOrderItemService.selectFsStoreOrderItemList(fsStoreOrderItem);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出订单详情列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrderItem:export')")
+    @Log(title = "订单详情", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsStoreOrderItemScrm fsStoreOrderItem)
+    {
+        List<FsStoreOrderItemScrm> list = fsStoreOrderItemService.selectFsStoreOrderItemList(fsStoreOrderItem);
+        ExcelUtil<FsStoreOrderItemScrm> util = new ExcelUtil<FsStoreOrderItemScrm>(FsStoreOrderItemScrm.class);
+        return util.exportExcel(list, "storeOrderItem");
+    }
+
+    /**
+     * 获取订单详情详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrderItem:query')")
+    @GetMapping(value = "/{itemId}")
+    public AjaxResult getInfo(@PathVariable("itemId") Long itemId)
+    {
+        return AjaxResult.success(fsStoreOrderItemService.selectFsStoreOrderItemById(itemId));
+    }
+
+    /**
+     * 新增订单详情
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrderItem:add')")
+    @Log(title = "订单详情", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsStoreOrderItemScrm fsStoreOrderItem)
+    {
+        return toAjax(fsStoreOrderItemService.insertFsStoreOrderItem(fsStoreOrderItem));
+    }
+
+    /**
+     * 修改订单详情
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrderItem:edit')")
+    @Log(title = "订单详情", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsStoreOrderItemScrm fsStoreOrderItem)
+    {
+        return toAjax(fsStoreOrderItemService.updateFsStoreOrderItem(fsStoreOrderItem));
+    }
+
+    /**
+     * 删除订单详情
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrderItem:remove')")
+    @Log(title = "订单详情", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{itemIds}")
+    public AjaxResult remove(@PathVariable Long[] itemIds)
+    {
+        return toAjax(fsStoreOrderItemService.deleteFsStoreOrderItemByIds(itemIds));
+    }
+
+    /**
+     * 修改订单数量及总价
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrderItem:updateNum')")
+    @Log(title = "订单详情修改订单数量", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateNum")
+    public AjaxResult updateNum(@RequestBody FsStoreOrderItemScrm fsStoreOrderItem)
+    {
+        return toAjax(fsStoreOrderItemService.updateFsStoreOrderItemNum(fsStoreOrderItem));
+    }
+}

+ 17 - 5
fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java

@@ -272,12 +272,17 @@ public class FsStoreOrderScrmController extends BaseController
     public R getPhone(@PathVariable("id") Long id)
     {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        if (loginUser.getUser().getUserType().equals("00")){
+        if("广州郑多燕".equals(cloudHostProper.getCompanyName())){
             FsStoreOrderScrm order = fsStoreOrderService.selectFsStoreOrderById(id);
-            String userPhone = order.getUserPhone();
-            return R.ok().put("userPhone",userPhone);
+            return R.ok().put("userPhone",order.getUserPhone());
+        } else {
+            if (loginUser.getUser().getUserType().equals("00")){
+                FsStoreOrderScrm order = fsStoreOrderService.selectFsStoreOrderById(id);
+                String userPhone = order.getUserPhone();
+                return R.ok().put("userPhone",userPhone);
+            }
+            return R.error("无权查看");
         }
-        return R.error("无权查看");
     }
 
     @PreAuthorize("@ss.hasPermi('store:storeOrder:express')")
@@ -507,5 +512,12 @@ public class FsStoreOrderScrmController extends BaseController
         int count = fsStoreOrderService.batchAuditOrder(param);
         return R.ok("成功审核 " + count + " 条订单");
     }
-
+    /**
+     * 修改订单itemJson
+     */
+    @Log(title = "修改订单itemJson", businessType = BusinessType.UPDATE)
+    @GetMapping("/updateStoreOrderItemJson/{orderId}/{backendEditProductType}")
+    public AjaxResult updateStoreOrderItemJson(@PathVariable("orderId") Long orderId,@PathVariable("backendEditProductType") Integer backendEditProductType) {
+        return toAjax(fsStoreOrderService.updateStoreOrderItemJson(orderId,backendEditProductType));
+    }
 }

+ 151 - 0
fs-company/src/main/java/com/fs/hisStore/controller/FsStoreScrmController.java

@@ -0,0 +1,151 @@
+package com.fs.hisStore.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.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ParseUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.his.param.FsStoreAuditParam;
+import com.fs.hisStore.domain.FsStoreScrm;
+import com.fs.hisStore.service.IFsStoreScrmService;
+import com.fs.hisStore.utils.StoreAuditLogUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 店铺管理Controller
+ *
+ * @author fs
+ * @date 2023-06-15
+ */
+@RestController
+@RequestMapping("/store/his/store")
+public class FsStoreScrmController extends BaseController
+{
+    @Autowired
+    private IFsStoreScrmService fsStoreService;
+
+    @Autowired
+    private StoreAuditLogUtil storeAuditLogUtil;
+
+    /**
+     * 查询店铺管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:his:store:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsStoreScrm fsStore)
+    {
+        startPage();
+        List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
+        for (FsStoreScrm store : list) {
+            store.setPhone(ParseUtils.parsePhone(store.getPhone()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出店铺管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:his:store:export')")
+    @Log(title = "店铺管理", businessType = BusinessType.EXPORT,logParam = {"店铺","导出店铺信息"},isStoreLog = true)
+    @GetMapping("/export")
+    public AjaxResult export(FsStoreScrm fsStore)
+    {
+        storeAuditLogUtil.generateOperId();
+        List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
+        for (FsStoreScrm store : list) {
+            store.setPhone(ParseUtils.parsePhone(store.getPhone()));
+        }
+        ExcelUtil<FsStoreScrm> util = new ExcelUtil<FsStoreScrm>(FsStoreScrm.class);
+        return util.exportExcel(list, "店铺管理数据");
+    }
+
+    /**
+     * 获取店铺管理详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('store:his:store:query')")
+    @GetMapping(value = "/{storeId}")
+    public AjaxResult getInfo(@PathVariable("storeId") Long storeId)
+    {
+        FsStoreScrm fsStore = fsStoreService.selectFsStoreByStoreId(storeId);
+        fsStore.setPhone(ParseUtils.parsePhone(fsStore.getPhone()));
+        return AjaxResult.success(fsStore);
+    }
+
+    /**
+     * 新增店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('store:his:store:add')")
+    @Log(title = "店铺管理", businessType = BusinessType.INSERT,logParam = {"店铺","新增店铺信息"},isStoreLog = true)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsStoreScrm fsStore)
+    {
+        storeAuditLogUtil.addOperLog(fsStoreService.insertFsStore(fsStore));
+        return AjaxResult.success();
+    }
+
+    /**
+     * 修改店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('store:his:store:edit')")
+    @Log(title = "店铺管理", businessType = BusinessType.UPDATE,logParam = {"店铺","修改店铺信息"},isStoreLog = true)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsStoreScrm fsStore)
+    {
+
+        if (fsStore.getPhone()!=null&&fsStore.getPhone().contains("*")){
+            fsStore.setPhone(null);
+        }
+        return toAjax(fsStoreService.updateFsStore(fsStore));
+    }
+
+    /**
+     * 删除店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('store:his:store:remove')")
+    @Log(title = "店铺管理", businessType = BusinessType.DELETE,logParam = {"店铺","删除店铺信息"},isStoreLog = true)
+	@DeleteMapping("/{storeIds}")
+    public AjaxResult remove(@PathVariable Long[] storeIds)
+    {
+        return toAjax(fsStoreService.deleteFsStoreByStoreIds(storeIds));
+    }
+
+    /**
+     * 店铺审核
+     */
+    @PreAuthorize("@ss.hasPermi('store:his:store:audit')")
+    @Log(title = "店铺审核", businessType = BusinessType.AUDIT,logParam = {"店铺","店铺审核"},isStoreLog = true
+    ,logParamExpression = "#p0.getIsAudit()==1?new String[]{'店铺','店铺审核通过'}: new String[]{'店铺','店铺审核退回'}")
+    @PutMapping("/audit")
+    public AjaxResult audit(@RequestBody FsStoreAuditParam fsStore)
+    {
+        return toAjax(fsStoreService.updateFsStoreAudit(fsStore));
+    }
+
+    /**
+     * 重置店铺密码
+     * */
+    @PreAuthorize("@ss.hasPermi('store:his:store:refresh')")
+    @Log(title = "店铺管理", businessType = BusinessType.UPDATE,logParam = {"店铺","重置店铺密码"},isStoreLog = true)
+    @PutMapping("/refresh/{storeId}")
+    public AjaxResult refresh(@PathVariable Long storeId)
+    {
+        return toAjax(fsStoreService.refreshFsStore(storeId));
+    }
+
+
+    /**
+     * 店铺审核日志
+     * */
+    @PreAuthorize("@ss.hasPermi('store:his:store:auditLog')")
+    @GetMapping("/auditLog/{storeId}")
+    public R auditLog(@PathVariable Long storeId){
+        return R.ok().put("auditLog",storeAuditLogUtil.selectOperLogByMainId(storeId));
+    }
+}

+ 59 - 0
fs-live-app/src/main/java/com/fs/live/utils/WebSocketRateLimiter.java

@@ -0,0 +1,59 @@
+package com.fs.live.utils;
+
+import com.google.common.util.concurrent.RateLimiter;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * WebSocket限流工具类
+ */
+public class WebSocketRateLimiter {
+
+    // 用户级别限流:每个用户每秒最多发送5条消息
+    private static final double USER_RATE_LIMIT = 5.0;
+    private static final ConcurrentHashMap<String, RateLimiter> userLimiters = new ConcurrentHashMap<>();
+
+    // 直播间级别限流:每个直播间每秒最多处理100条消息
+    private static final double ROOM_RATE_LIMIT = 100.0;
+    private static final ConcurrentHashMap<Long, RateLimiter> roomLimiters = new ConcurrentHashMap<>();
+
+    /**
+     * 检查用户是否被限流
+     * @param userId 用户ID
+     * @param liveId 直播间ID
+     * @return true-允许通过,false-被限流
+     */
+    public static boolean tryAcquire(Long userId, Long liveId) {
+        // 检查用户级别限流
+        String userKey = userId + "_" + liveId;
+        RateLimiter userLimiter = userLimiters.computeIfAbsent(
+                userKey,
+                k -> RateLimiter.create(USER_RATE_LIMIT)
+        );
+
+        if (!userLimiter.tryAcquire()) {
+            return false;
+        }
+
+        // 检查直播间级别限流
+        RateLimiter roomLimiter = roomLimiters.computeIfAbsent(
+                liveId,
+                k -> RateLimiter.create(ROOM_RATE_LIMIT)
+        );
+
+        return roomLimiter.tryAcquire();
+    }
+
+    /**
+     * 清理用户限流器
+     */
+    public static void removeUserLimiter(Long userId, Long liveId) {
+        userLimiters.remove(userId + "_" + liveId);
+    }
+
+    /**
+     * 清理直播间限流器
+     */
+    public static void removeRoomLimiter(Long liveId) {
+        roomLimiters.remove(liveId);
+    }
+}

+ 63 - 0
fs-live-app/src/main/java/com/fs/live/websocket/config/WebSocketSessionManager.java

@@ -0,0 +1,63 @@
+package com.fs.live.websocket.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.Session;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * 直播间WebSocket连接管理器
+ * 核心:按直播间ID分组存储Session,线程安全,低锁竞争
+ */
+@Slf4j
+@Component
+public class WebSocketSessionManager {
+
+    /**
+     * 存储结构:直播间ID -> 该直播间的所有连接Session
+     * CopyOnWriteArraySet:读多写少场景,线程安全且遍历无锁
+     */
+    private static final Map<String, Set<Session>> ROOM_SESSIONS = new ConcurrentHashMap<>();
+
+    /**
+     * 添加连接(绑定直播间)
+     */
+    public void addSession(String roomId, Session session) {
+        // 不存在则创建空集合(ConcurrentHashMap的原子操作)
+        ROOM_SESSIONS.computeIfAbsent(roomId, k -> new CopyOnWriteArraySet<>()).add(session);
+        log.info("直播间[{}]新增连接,当前连接数:{}", roomId, ROOM_SESSIONS.get(roomId).size());
+    }
+
+    /**
+     * 移除连接(清理无效连接)
+     */
+    public void removeSession(String roomId, Session session) {
+        if (ROOM_SESSIONS.containsKey(roomId)) {
+            Set<Session> sessions = ROOM_SESSIONS.get(roomId);
+            sessions.remove(session);
+            // 直播间无连接时清空,释放内存
+            if (sessions.isEmpty()) {
+                ROOM_SESSIONS.remove(roomId);
+            }
+            log.info("直播间[{}]移除连接,当前连接数:{}", roomId, sessions.size());
+        }
+    }
+
+    /**
+     * 获取直播间所有连接
+     */
+    public Set<Session> getRoomSessions(String roomId) {
+        return ROOM_SESSIONS.getOrDefault(roomId, new CopyOnWriteArraySet<>());
+    }
+
+    /**
+     * 获取所有直播间ID
+     */
+    public Set<String> getAllRoomIds() {
+        return ROOM_SESSIONS.keySet();
+    }
+}

+ 5 - 0
fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisFsUserCourseVideoController.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.R;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.param.FsCourseLinkCreateParam;
@@ -107,6 +108,10 @@ public class ApisFsUserCourseVideoController extends BaseController {
             return R.error("课程id不能为空");
         }
 
+        if (CloudHostUtils.hasCloudHostName("木易华康")) {
+            param.setIsOnPut(0);
+        }
+
         String json = configService.selectConfigByKey("course.config");
         if(null == json || StringUtils.isBlank(json)){
             return R.error("未配置课程信息");

+ 10 - 10
fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwSopController.java

@@ -173,29 +173,29 @@ public class ApisQwSopController  extends BaseController {
         return R.error();
     }
 
-    //员工看板 课程/答题/红包统计--侧边栏
-    @GetMapping("/boardCourseQuizRedEnvelopeStats")
+    //员工看板 课程/答题/红包统计--侧边栏(查得很慢,设计点进去了才查)
+    @PostMapping("/boardCourseQuizRedEnvelopeStats")
     @ApiOperation("员工看板 课程/答题/红包统计")
-    public ResponseResult<FsUserStatisticsVO> boardCourseQuizRedEnvelopeStats(CourseQuizRedEnvelopeStatsParam qwParam) {
+    public ResponseResult<FsUserStatisticsVO> boardCourseQuizRedEnvelopeStats(@RequestBody CourseQuizRedEnvelopeStatsParam qwParam) {
         if (StringUtils.isBlank(qwParam.getStartTime()) || StringUtils.isBlank(qwParam.getEndTime())) {
-            return ResponseResult.ok(new FsUserStatisticsVO());
+            return ResponseResult.fail(500,"时间不能为空");
         }
         FsUserStatisticsVO resultVo = qwSopService.boardCourseQuizRedEnvelopeStats(qwParam);
         return ResponseResult.ok(resultVo);
     }
 
-    //外部联系人答题/红包/看课统计--侧边栏
-    @GetMapping("/externalStatsList")
+    //外部联系人答题/红包/看课统计--侧边栏(查得很慢,设计点进去了才查)
+    @PostMapping("/externalStatsList")
     @ApiOperation("外部联系人答题/红包/看课统计")
-    public ResponseResult<ExternalUserStatsVO> externalStatsList(QwSidebarStatsParam qwParam) {
+    public ResponseResult<ExternalUserStatsVO> externalStatsList(@RequestBody QwSidebarStatsParam qwParam) {
         ExternalUserStatsVO vo = qwSopService.externalStatsList(qwParam);
         return ResponseResult.ok(vo);
     }
 
-    //外部联系人看课轨迹--侧边栏
-    @GetMapping("/externalWatchRecordStatsList")
+    //外部联系人看课轨迹--侧边栏(查得很慢,设计点进去了才查)
+    @PostMapping("/externalWatchRecordStatsList")
     @ApiOperation("用户看课轨迹")
-    public TableDataInfo externalWatchRecordStatsList(QwSidebarStatsParam qwParam) {
+    public TableDataInfo externalWatchRecordStatsList(@RequestBody QwSidebarStatsParam qwParam) {
         if (qwParam.getStartTime() == null || qwParam.getEndTime() == null) {
             return getDataTable(Collections.emptyList());
         }

+ 5 - 0
fs-qwhook-sop/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.param.FsCourseLinkMiniParam;
@@ -85,6 +86,10 @@ public class FsUserCourseVideoController {
             return R.error("课程id不能为空");
         }
 
+        if (CloudHostUtils.hasCloudHostName("木易华康")) {
+            param.setIsOnPut(0);
+        }
+
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
         List<FsCourseVideoListBySidebarVO> videoListBySidebar = fsUserCourseVideoService.getFsCourseVideoListBySidebar(param);
         PageInfo<FsCourseVideoListBySidebarVO> result = new PageInfo<>(videoListBySidebar);

+ 44 - 1
fs-qwhook-sop/src/main/java/com/fs/app/controller/QwSopController.java

@@ -2,10 +2,17 @@ package com.fs.app.controller;
 
 import com.fs.app.params.SopLogsEditParam;
 import com.fs.common.BeanCopyUtils;
+import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.StringUtils;
+import com.fs.course.vo.FsCourseWatchLogStatisticsListVO;
 import com.fs.fastGpt.service.IFastGptChatSessionService;
 import com.fs.qw.domain.QwTagGroup;
+import com.fs.qw.param.CourseQuizRedEnvelopeStatsParam;
+import com.fs.qw.param.QwSidebarStatsParam;
 import com.fs.qw.param.SopMsgParam;
 import com.fs.qw.param.sidebar.ExternalContactInfoParam;
 import com.fs.qw.param.sidebar.TagGroupListParam;
@@ -20,6 +27,9 @@ import com.fs.sop.domain.QwSopLogs;
 import com.fs.sop.params.GetQwSopLogsByJsApiParam;
 import com.fs.sop.params.SendSopParamDetailsC;
 import com.fs.sop.service.IQwSopLogsService;
+import com.fs.sop.service.IQwSopService;
+import com.fs.store.vo.h5.ExternalUserStatsVO;
+import com.fs.store.vo.h5.FsUserStatisticsVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.ApiOperation;
@@ -28,13 +38,14 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
 import java.text.SimpleDateFormat;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
 
 @RestController
 @RequestMapping("/app/qwSop")
-public class QwSopController {
+public class QwSopController extends BaseController {
 
     @Autowired
     RedisCache redisCache;
@@ -49,6 +60,9 @@ public class QwSopController {
     @Autowired
     private IQwTagGroupService qwTagGroupService;
 
+    @Autowired
+    private IQwSopService qwSopService;
+
     /**
      * 更新AI发送状态
      */
@@ -108,4 +122,33 @@ public class QwSopController {
         return R.ok().put("data",listPageInfo);
     }
 
+    //员工看板 课程/答题/红包统计--侧边栏(查得很慢,设计点进去了才查)
+    @PostMapping("/boardCourseQuizRedEnvelopeStats")
+    @ApiOperation("员工看板 课程/答题/红包统计")
+    public ResponseResult<FsUserStatisticsVO> boardCourseQuizRedEnvelopeStats(@RequestBody CourseQuizRedEnvelopeStatsParam qwParam) {
+        if (StringUtils.isBlank(qwParam.getStartTime()) || StringUtils.isBlank(qwParam.getEndTime())) {
+            return ResponseResult.fail(500,"时间不能为空");
+        }
+        FsUserStatisticsVO resultVo = qwSopService.boardCourseQuizRedEnvelopeStats(qwParam);
+        return ResponseResult.ok(resultVo);
+    }
+
+    //外部联系人答题/红包/看课统计--侧边栏
+    @PostMapping("/externalStatsList")
+    @ApiOperation("外部联系人答题/红包/看课统计")
+    public ResponseResult<ExternalUserStatsVO> externalStatsList(@RequestBody QwSidebarStatsParam qwParam) {
+        ExternalUserStatsVO vo = qwSopService.externalStatsList(qwParam);
+        return ResponseResult.ok(vo);
+    }
+
+    //外部联系人看课轨迹--侧边栏
+    @PostMapping("/externalWatchRecordStatsList")
+    @ApiOperation("用户看课轨迹")
+    public TableDataInfo externalWatchRecordStatsList(@RequestBody QwSidebarStatsParam qwParam) {
+        if (qwParam.getStartTime() == null || qwParam.getEndTime() == null) {
+            return getDataTable(Collections.emptyList());
+        }
+        List<FsCourseWatchLogStatisticsListVO> list = qwSopService.externalWatchRecordStatsList(qwParam);
+        return getDataTable(list);
+    }
 }

+ 5 - 0
fs-qwhook/src/main/java/com/fs/app/controller/ApisFsUserCourseVideoController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.R;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.param.FsCourseLinkMiniParam;
@@ -85,6 +86,10 @@ public class ApisFsUserCourseVideoController extends BaseController {
             return R.error("课程id不能为空");
         }
 
+        if (CloudHostUtils.hasCloudHostName("木易华康")) {
+            param.setIsOnPut(0);
+        }
+
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
         List<FsCourseVideoListBySidebarVO> videoListBySidebar = fsUserCourseVideoService.getFsCourseVideoListBySidebar(param);
         PageInfo<FsCourseVideoListBySidebarVO> result = new PageInfo<>(videoListBySidebar);

+ 5 - 0
fs-qwhook/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.param.FsCourseLinkMiniParam;
@@ -86,6 +87,10 @@ public class FsUserCourseVideoController {
             return R.error("课程id不能为空");
         }
 
+        if (CloudHostUtils.hasCloudHostName("木易华康")) {
+            param.setIsOnPut(0);
+        }
+
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
         List<FsCourseVideoListBySidebarVO> videoListBySidebar = fsUserCourseVideoService.getFsCourseVideoListBySidebar(param);
         PageInfo<FsCourseVideoListBySidebarVO> result = new PageInfo<>(videoListBySidebar);

+ 3 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java

@@ -250,4 +250,7 @@ public interface CompanyMapper
             " `status` != 0   " +
             " and is_del != 1 ")
     List<CompanyVO> getCompanyDropList();
+
+    @Select("select company_id,company_name from company where FIND_IN_SET( company_id , (select company_ids from qw_company where corp_id = #{corpId})) ")
+    List<Company> getCompanyList(@Param("corpId") String corpId);
 }

+ 21 - 8
fs-service/src/main/java/com/fs/company/mapper/CompanySmsTempMapper.java

@@ -10,15 +10,15 @@ import org.apache.ibatis.annotations.Select;
 
 /**
  * 短信模板Mapper接口
- * 
+ *
  * @author fs
  * @date 2023-01-09
  */
-public interface CompanySmsTempMapper 
+public interface CompanySmsTempMapper
 {
     /**
      * 查询短信模板
-     * 
+     *
      * @param tempId 短信模板ID
      * @return 短信模板
      */
@@ -26,7 +26,7 @@ public interface CompanySmsTempMapper
 
     /**
      * 查询短信模板列表
-     * 
+     *
      * @param companySmsTemp 短信模板
      * @return 短信模板集合
      */
@@ -34,7 +34,7 @@ public interface CompanySmsTempMapper
 
     /**
      * 新增短信模板
-     * 
+     *
      * @param companySmsTemp 短信模板
      * @return 结果
      */
@@ -42,7 +42,7 @@ public interface CompanySmsTempMapper
 
     /**
      * 修改短信模板
-     * 
+     *
      * @param companySmsTemp 短信模板
      * @return 结果
      */
@@ -50,7 +50,7 @@ public interface CompanySmsTempMapper
 
     /**
      * 删除短信模板
-     * 
+     *
      * @param tempId 短信模板ID
      * @return 结果
      */
@@ -58,7 +58,7 @@ public interface CompanySmsTempMapper
 
     /**
      * 批量删除短信模板
-     * 
+     *
      * @param tempIds 需要删除的数据ID
      * @return 结果
      */
@@ -93,4 +93,17 @@ public interface CompanySmsTempMapper
             "order by t.temp_id desc " +
             "</script>"})
     List<CompanySmsTempListQueryVO> selectCompanySmsTempListQuery(@Param("maps")CompanySmsTempListQueryParam companySmsTemp);
+
+    @Select({"<script> " +
+            "select t.*,c.company_name from company_sms_temp t left join company c on c.company_id=t.company_id " +
+            "where 1=1  " +
+            "<if test = 'maps.status != null  '> " +
+            "and t.status = #{maps.status}" +
+            "</if>" +
+            "<if test = 'maps.isAudit != null  '> " +
+            "and t.is_audit = #{maps.isAudit}" +
+            "</if>" +
+            "order by t.temp_id desc " +
+            "</script>"})
+    List<CompanySmsTempListQueryVO> selectCompanySmsTempListQueryForAdmin(@Param("maps") CompanySmsTempListQueryParam maps);
 }

+ 10 - 8
fs-service/src/main/java/com/fs/company/service/ICompanySmsTempService.java

@@ -8,15 +8,15 @@ import com.fs.company.vo.CompanySmsTempListVO;
 
 /**
  * 短信模板Service接口
- * 
+ *
  * @author fs
  * @date 2023-01-09
  */
-public interface ICompanySmsTempService 
+public interface ICompanySmsTempService
 {
     /**
      * 查询短信模板
-     * 
+     *
      * @param tempId 短信模板ID
      * @return 短信模板
      */
@@ -24,7 +24,7 @@ public interface ICompanySmsTempService
 
     /**
      * 查询短信模板列表
-     * 
+     *
      * @param companySmsTemp 短信模板
      * @return 短信模板集合
      */
@@ -32,7 +32,7 @@ public interface ICompanySmsTempService
 
     /**
      * 新增短信模板
-     * 
+     *
      * @param companySmsTemp 短信模板
      * @return 结果
      */
@@ -40,7 +40,7 @@ public interface ICompanySmsTempService
 
     /**
      * 修改短信模板
-     * 
+     *
      * @param companySmsTemp 短信模板
      * @return 结果
      */
@@ -48,7 +48,7 @@ public interface ICompanySmsTempService
 
     /**
      * 批量删除短信模板
-     * 
+     *
      * @param tempIds 需要删除的短信模板ID
      * @return 结果
      */
@@ -56,7 +56,7 @@ public interface ICompanySmsTempService
 
     /**
      * 删除短信模板信息
-     * 
+     *
      * @param tempId 短信模板ID
      * @return 结果
      */
@@ -67,4 +67,6 @@ public interface ICompanySmsTempService
     List<CompanySmsTempListVO> selectCompanySmsTempListVO(CompanySmsTemp companySmsTemp);
 
     List<CompanySmsTempListQueryVO> selectCompanySmsTempListQuery(CompanySmsTempListQueryParam companySmsTemp);
+
+    List<CompanySmsTempListQueryVO> selectCompanySmsTempListQueryForAdmin(CompanySmsTempListQueryParam maps);
 }

+ 3 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java

@@ -1,6 +1,7 @@
 package com.fs.company.service;
 
 import com.fs.common.core.domain.R;
+import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.param.CompanyUserAreaParam;
 import com.fs.company.param.CompanyUserCodeParam;
@@ -273,4 +274,6 @@ public interface ICompanyUserService {
      * @return
      */
     List<CompanyUser> getDataScopeCompanyUser(Long companyUserId);
+
+    List<Company> getCompanyList(String corpId);
 }

+ 13 - 8
fs-service/src/main/java/com/fs/company/service/impl/CompanySmsTempServiceImpl.java

@@ -13,19 +13,19 @@ import com.fs.company.service.ICompanySmsTempService;
 
 /**
  * 短信模板Service业务层处理
- * 
+ *
  * @author fs
  * @date 2023-01-09
  */
 @Service
-public class CompanySmsTempServiceImpl implements ICompanySmsTempService 
+public class CompanySmsTempServiceImpl implements ICompanySmsTempService
 {
     @Autowired
     private CompanySmsTempMapper companySmsTempMapper;
 
     /**
      * 查询短信模板
-     * 
+     *
      * @param tempId 短信模板ID
      * @return 短信模板
      */
@@ -37,7 +37,7 @@ public class CompanySmsTempServiceImpl implements ICompanySmsTempService
 
     /**
      * 查询短信模板列表
-     * 
+     *
      * @param companySmsTemp 短信模板
      * @return 短信模板
      */
@@ -49,7 +49,7 @@ public class CompanySmsTempServiceImpl implements ICompanySmsTempService
 
     /**
      * 新增短信模板
-     * 
+     *
      * @param companySmsTemp 短信模板
      * @return 结果
      */
@@ -62,7 +62,7 @@ public class CompanySmsTempServiceImpl implements ICompanySmsTempService
 
     /**
      * 修改短信模板
-     * 
+     *
      * @param companySmsTemp 短信模板
      * @return 结果
      */
@@ -75,7 +75,7 @@ public class CompanySmsTempServiceImpl implements ICompanySmsTempService
 
     /**
      * 批量删除短信模板
-     * 
+     *
      * @param tempIds 需要删除的短信模板ID
      * @return 结果
      */
@@ -87,7 +87,7 @@ public class CompanySmsTempServiceImpl implements ICompanySmsTempService
 
     /**
      * 删除短信模板信息
-     * 
+     *
      * @param tempId 短信模板ID
      * @return 结果
      */
@@ -111,4 +111,9 @@ public class CompanySmsTempServiceImpl implements ICompanySmsTempService
     public List<CompanySmsTempListQueryVO> selectCompanySmsTempListQuery(CompanySmsTempListQueryParam companySmsTemp) {
         return companySmsTempMapper.selectCompanySmsTempListQuery(companySmsTemp);
     }
+
+    @Override
+    public List<CompanySmsTempListQueryVO> selectCompanySmsTempListQueryForAdmin(CompanySmsTempListQueryParam maps) {
+        return companySmsTempMapper.selectCompanySmsTempListQueryForAdmin(maps);
+    }
 }

+ 8 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java

@@ -127,6 +127,8 @@ public class CompanyUserServiceImpl implements ICompanyUserService
 
     @Autowired
     private CompanyRoleMapper companyRoleMapper;
+    @Autowired
+    private CompanyMapper companyMapper;
 
 
     /**
@@ -1120,4 +1122,10 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         }
         return companyUsers;
     }
+
+    @Override
+    public List<Company> getCompanyList(String corpId) {
+        return companyMapper.getCompanyList(corpId);
+
+    }
 }

+ 4 - 1
fs-service/src/main/java/com/fs/course/mapper/FsCourseRedPacketLogMapper.java

@@ -12,6 +12,7 @@ import com.fs.course.param.CourseRedPacketStatisticsParam;
 import com.fs.course.param.FsCourseRedPacketLogParam;
 import com.fs.course.param.FsUserCourseOrderParam;
 import com.fs.course.vo.FsCourseRedPacketLogListPVO;
+import com.fs.course.vo.FsCourseRedPacketLogListVO;
 import com.fs.course.vo.FsUserCourseOrderListPVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -138,7 +139,7 @@ public interface FsCourseRedPacketLogMapper
             "                <foreach collection=\"maps.userIds\" open=\"(\" close=\")\" separator=\",\" item=\"item\">\n" +
             "                    ${item}\n" +
             "                </foreach>\n" +
-            "            </if>" +
+            "</if>" +
             " order by l.log_id desc  "+
             "</script>"})
     List<FsCourseRedPacketLogListPVO> selectFsCourseRedPacketLogListVO(@Param("maps")FsCourseRedPacketLogParam fsCourseRedPacketLog);
@@ -148,6 +149,8 @@ public interface FsCourseRedPacketLogMapper
 
     List<FsCourseRedPacketLogListPVO> selectFsCourseRedPacketLogListVONew(FsCourseRedPacketLogParam fsCourseRedPacketLog);
 
+    List<FsCourseRedPacketLogListVO> selectFsCourseRedPacketLogListCountVO(@Param("maps") FsCourseRedPacketLogParam fsCourseRedPacketLog);
+
     @Select("select * from fs_course_red_packet_log where video_id = #{videoId} and user_id = #{userId} order by log_id desc limit 1")
     FsCourseRedPacketLog selectFsCourseRedPacketLogByTemporary(@Param("videoId") Long videoId, @Param("userId")Long userId);
 

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

@@ -247,8 +247,8 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
             " ,sum(if((o.user_id is not null or o.user_id>0) and o.log_type=3,1,0)) is_user_wait_number" +
             " ,sum(if((o.user_id is null or o.user_id=0) and o.log_type=3,1,0)) no_user_wait_number" +
 //            " ,sum(ifnull(fcr.amount,0)) red_amount" +
-            ",(SELECT SUM(amount) FROM fs_course_red_packet_log \n" +
-            "     WHERE user_id = o.user_id AND video_id = o.video_id) as red_amount " +
+            ",COALESCE((SELECT SUM(amount) FROM fs_course_red_packet_log \n" +
+            "     WHERE user_id = o.user_id AND video_id = o.video_id), 0) as red_amount " +
             "</if> " +
             "FROM fs_course_watch_log o " +
             "<if test= 'sendType != 1 '> " +
@@ -288,6 +288,9 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
             "<if test ='courseId !=null'> " +
             "     and o.course_id = #{courseId} " +
             "</if>" +
+            "<if test ='qwSopId !=null and qwSopId!=\"\"'> " +
+            "     and o.sop_id = #{qwSopId} " +
+            "</if>" +
             "<if test ='videoId !=null'> " +
             "     and o.video_id = #{videoId} " +
             "</if>" +
@@ -716,7 +719,7 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     /**
      * 看课统计
      * */
-    List<FsCourseWatchLogStatisticsListVO> selectQwFsCourseWatchLogStatisticsListVO(QwSidebarStatsParam param);
+    List<FsCourseWatchLogStatisticsListVO> selectQwFsCourseWatchLogStatisticsListVO(@Param("data") QwSidebarStatsParam param);
 
     // 统计当天各公司的观看人数和完播人数, 存到redis中,定时任务每 ? 分钟执行一次
     List<WatchCourseStatisticsResultDTO> watchCourseStatisticsGroupByCompany(@Param("params") Map<String, Object> params);

+ 8 - 2
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java

@@ -152,6 +152,9 @@ public interface FsUserCourseVideoMapper extends BaseMapper<FsUserCourseVideo> {
     @Select("select video_id dict_value, title dict_label  from fs_user_course_video where course_id=#{id} and is_del = 0 order by course_sort")
     List<OptionsVO> selectFsUserCourseVodeAllList(Long id);
 
+    @Select("select video_id dict_value, title dict_label  from fs_user_course_video where course_id=#{id} and is_del = 0 and is_on_put = 0 order by course_sort, video_id")
+    List<OptionsVO> selectFsUserCourseVideoAllListV2(@Param("id") Long id);
+
     @Select({"<script> " +
             "select v.*,p.red_packet_money company_red_packet_money from fs_user_course_video v " +
             "LEFT JOIN fs_user_course_video_red_package p on p.video_id= v.video_id and p.company_id =#{maps.companyId} and p.data_type = 1 " +
@@ -205,18 +208,21 @@ public interface FsUserCourseVideoMapper extends BaseMapper<FsUserCourseVideo> {
     List<OptionsVO> selectVideoListByMap(@Param("params") Map<String, Object> params);
 
     @Select("<script> " +
-            "select v.video_id,v.course_id,v.title,v.video_url,v.thumbnail,v.duration,v.create_time from fs_user_course_video v " +
+            "select v.video_id,v.course_id,v.title,v.line_one as video_url,v.thumbnail,v.duration,v.create_time from fs_user_course_video v " +
             "left join fs_user_course c on c.course_id = v.course_id " +
             "where c.is_private = 1 and v.is_del = 0 and v.course_id=#{data.courseId} " +
             "        <if test=\"data.keyword != null and data.keyword !='' \">\n" +
             "            AND v.title LIKE concat('%',#{data.keyword},'%')\n" +
             "        </if>" +
+            "        <if test=\"data.isOnPut != null\">\n" +
+            "            AND v.is_on_put = #{data.isOnPut}\n" +
+            "        </if>" +
             "order by v.course_sort asc, v.video_id asc " +
             "</script>")
     List<FsCourseVideoListBySidebarVO> getFsCourseVideoListBySidebar(@Param("data") FsCourseListBySidebarParam param);
 
     @Select("<script> " +
-            "select v.video_id,v.course_id,v.title,v.video_url,v.thumbnail,v.duration,v.create_time from fs_user_course_video v " +
+            "select v.video_id,v.course_id,v.title,v.line_one as video_url,v.thumbnail,v.duration,v.create_time from fs_user_course_video v " +
             "left join fs_user_course c on c.course_id = v.course_id " +
             "where c.is_private = 1 and v.is_del = 0 and v.course_id=#{data.courseId} " +
             "  <if test=\"data.videoIds != null  \">\n" +

+ 3 - 0
fs-service/src/main/java/com/fs/course/param/FsCourseListBySidebarParam.java

@@ -41,4 +41,7 @@ public class FsCourseListBySidebarParam implements Serializable {
      * 用于过滤用户当日应该看课的视频id
      */
     private List<Long> videoIds;
+
+    // 是否上架 0:上架,1:下架
+    private Integer isOnPut;
 }

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

@@ -15,6 +15,7 @@ public class FsCourseRedPacketLogParam implements Serializable {
     private Long userId;
 
     private Long companyId;
+    private List<Long> companyIds;
     private Long companyUserId;
     private String companyUserName;
 
@@ -30,6 +31,10 @@ public class FsCourseRedPacketLogParam implements Serializable {
     private Long periodId;
 
     private Long status;
+    /**
+    * 1 销售公司 2 员工
+    */
+    private Long changeType;
 
     private String phone;
 

+ 5 - 0
fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java

@@ -93,6 +93,11 @@ public class FsCourseWatchLogListParam implements Serializable {
      */
     private Integer isVip;
 
+    /**
+     * 会员状态 正常、删除、接替、拉黑等等
+     * */
+    private Integer externalStatus;
+
     /**
      * 所属项目
      */

+ 2 - 0
fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogStatisticsListParam.java

@@ -44,6 +44,8 @@ public class FsCourseWatchLogStatisticsListParam {
 
     private String endTime;
 
+    private String qwSopId;
+
     private Long project;
 
     private Long pageNum;

+ 2 - 0
fs-service/src/main/java/com/fs/course/service/IFsCourseRedPacketLogService.java

@@ -7,6 +7,7 @@ import com.fs.common.core.domain.R;
 import com.fs.course.domain.FsCourseRedPacketLog;
 import com.fs.course.param.FsCourseRedPacketLogParam;
 import com.fs.course.vo.FsCourseRedPacketLogListPVO;
+import com.fs.course.vo.FsCourseRedPacketLogListVO;
 
 /**
  * 短链课程看课记录Service接口
@@ -70,6 +71,7 @@ public interface IFsCourseRedPacketLogService
 
     List<FsCourseRedPacketLogListPVO> selectFsCourseRedPacketLogListVO(FsCourseRedPacketLogParam fsCourseRedPacketLog);
     List<FsCourseRedPacketLogListPVO> selectFsCourseRedPacketLogListVONew(FsCourseRedPacketLogParam fsCourseRedPacketLog);
+    List<FsCourseRedPacketLogListVO> selectFsCourseRedPacketLogListCountVO(FsCourseRedPacketLogParam fsCourseRedPacketLog);
 
     /**
      * 查询红包金额数

+ 6 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java

@@ -26,6 +26,7 @@ import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
 import com.fs.course.param.FsCourseRedPacketLogParam;
 import com.fs.course.vo.FsCourseRedPacketLogListPVO;
+import com.fs.course.vo.FsCourseRedPacketLogListVO;
 import com.fs.his.domain.FsUser;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.param.WxSendRedPacketParam;
@@ -198,6 +199,11 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
         return fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogListVONew(fsCourseRedPacketLog);
     }
 
+    @Override
+    public List<FsCourseRedPacketLogListVO> selectFsCourseRedPacketLogListCountVO(FsCourseRedPacketLogParam fsCourseRedPacketLog) {
+        return fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogListCountVO(fsCourseRedPacketLog);
+    }
+
     /**
      * 查询红包金额数
      * @param companyUserId 销售ID

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

@@ -138,7 +138,7 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
     private static final String SHORT_LINK_PREFIX = "/courseH5/pages/course/learning?s=";
     // 排除看课数量限制的公司集合
     private static final Set<String> EXCLUDE_PROJECTS = new HashSet<>(Arrays.asList(
-            "福本源", "宽益堂", "叮当国医", "易行健"
+            "福本源", "宽益堂", "叮当国医", "易行健","河山医院"
     ));
     @Autowired
     ICompanyService companyService;

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

@@ -23,6 +23,7 @@ public class FsCourseRedPacketLogListPVO extends BaseEntity
 
     @Excel(name = "会员id")
     private Long userId;
+
     @Excel(name = "会员名称")
     private String fsNickName;
 

+ 49 - 0
fs-service/src/main/java/com/fs/course/vo/FsCourseRedPacketLogListVO.java

@@ -0,0 +1,49 @@
+package com.fs.course.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class FsCourseRedPacketLogListVO {
+
+    private static final long serialVersionUID = 1L;
+
+    private Long logId;
+
+    @Excel(name = "销售公司")
+    private String companyName;
+
+    @Excel(name = "销售编号")
+    private Long companyUserId;
+
+
+    @Excel(name = "销售昵称")
+    private String nickName;
+
+    @Excel(name = "课程id")
+    private Long courseId;
+
+    @Excel(name = "小节id")
+    private Long videoId;
+
+    /** 转帐金额 */
+    @Excel(name = "转帐金额")
+    private BigDecimal amount;
+
+
+    @Excel(name = "部门id")
+    private Long deptId;
+
+    @Excel(name = "部门昵称")
+    private String deptName;
+
+    /** 创建时间 */
+    @Excel(name = "创建时间",dateFormat = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+}

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

@@ -134,7 +134,7 @@ public class FsCourseWatchLogListVO extends BaseEntity
     private Long courseId;
     private Long videoId;
     private Integer isVip;
-
+    private Integer externalStatus;
     /**
      * im发送消息详情id
      */

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

@@ -76,5 +76,6 @@ public class FsCourseWatchLogStatisticsListVO {
     private String  finishedRate;
 
     /** 消耗红包金额 */
+    @Excel(name = "消耗红包金额")
     private String  redAmount;
 }

+ 5 - 3
fs-service/src/main/java/com/fs/his/vo/FsIntegralOrderListVO.java

@@ -36,14 +36,16 @@ public class FsIntegralOrderListVO {
     /** 商品信息 */
     //@Excel(name = "商品信息")
     private String itemJson;
-    //@Excel(name = "商品名称")
-    @Excel(name = "商品信息")//卓美 导出时候把商品名称 数据拼接在一起
+    @Excel(name = "商品名称")
+    //@Excel(name = "商品信息")//卓美 导出时候把商品名称 数据拼接在一起
     private String goodsName;
 
     /** 商品条码 */
     @Excel(name = "商品编码")
     private String barCode;
-
+    /** 商品数量 */
+    @Excel(name = "商品数量")
+    private String num;
     /** 支付积分 */
     @Excel(name = "支付积分")
     private String integral;

+ 3 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderExportVO.java

@@ -273,4 +273,7 @@ public class FsStoreOrderExportVO implements Serializable
 
     @Excel(name = "是否审核")
     private String isAudit;
+
+    @Excel(name = "订单备注")
+    private String orderRemark;
 }

+ 4 - 1
fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java

@@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.core.page.PageRequest;
+import com.fs.common.core.redis.service.StockDeductService;
 import com.fs.common.exception.base.BaseException;
 import com.fs.company.mapper.CompanyMapper;
 import com.fs.company.vo.CompanyVO;
@@ -109,6 +110,8 @@ public class LiveServiceImpl implements ILiveService
     @Autowired
     private LiveLotteryProductConfMapper liveLotteryProductConfMapper;
     @Autowired
+    private StockDeductService stockDeductService;
+    @Autowired
     private FsStoreProductScrmMapper fsStoreProductScrmMapper;
     @Autowired
     private RedisCache redisCache;
@@ -1292,7 +1295,7 @@ public class LiveServiceImpl implements ILiveService
                 newGoods.setStock(goodsMap.containsKey(liveGoods.getProductId())
                         ? goodsMap.get(liveGoods.getProductId()).getStock() : 0);
                 liveGoodsService.insertLiveGoods(newGoods);
-
+                stockDeductService.initStock(newGoods.getProductId(), newLiveId, newGoods.getStock().intValue());
                 goodsIdMapping.put(liveGoods.getGoodsId(), newGoods.getGoodsId());
 
                 // 复制商品推送任务(taskType=1)

+ 2 - 1
fs-service/src/main/java/com/fs/qw/mapper/QwWatchLogMapper.java

@@ -82,7 +82,8 @@ public interface QwWatchLogMapper extends BaseMapper<QwWatchLog>{
             "    COUNT(CASE WHEN qec.fs_user_id IS NOT NULL THEN 1 END) AS sign,\n" +
             "    COUNT(CASE WHEN qec.`status` =3 THEN 1 END) AS los,\n" +
             "    COUNT(CASE WHEN qec.`status` IN (4, 5,6) THEN 1 END) AS del,\n" +
-            "    COUNT(CASE WHEN qec.fs_user_id IS NOT NULL and qec.fs_user_id != 0 THEN 1 END) AS reg_num\n"+
+            "    COUNT(CASE WHEN qec.fs_user_id IS NOT NULL and qec.fs_user_id != 0 THEN 1 END) AS reg_num,\n"+
+            "    COUNT(CASE WHEN qec.is_repeat = 1 THEN 1 END) AS repeat_count\n" +
             "FROM\n" +
             "    qw_external_contact qec\n" +
             "JOIN\n" +

+ 2 - 0
fs-service/src/main/java/com/fs/qw/param/QwSidebarStatsParam.java

@@ -29,6 +29,8 @@ public class QwSidebarStatsParam implements Serializable {
 
     private String startTime;
 
+    private Long sendType;
+
     private String endTime;
 
     //外部联系人主键Id

+ 18 - 18
fs-service/src/main/java/com/fs/qw/service/impl/AsyncSopTestService.java

@@ -478,24 +478,24 @@ public class AsyncSopTestService {
                                             Integer courseId,String linkTile,String linkImageUrl,Integer videoId,
                                             String linkDescribe,String appMsgLink,Long externalId){
 
-//        FsCourseSopAppLink sopAppLink=new FsCourseSopAppLink();
-//        sopAppLink.setLink(link);
-//        sopAppLink.setCreateTime(sendTime);
-//        sopAppLink.setUpdateTime(updateTime);
-//        sopAppLink.setCompanyId(Long.parseLong(companyId));
-//        sopAppLink.setCompanyUserId(Long.parseLong(companyUserId));
-//        sopAppLink.setQwUserId(Long.parseLong(qwUserId));
-//        sopAppLink.setQwUserName(qwUserName);
-//        sopAppLink.setCorpId(corpId);
-//        sopAppLink.setCourseId(Long.valueOf(courseId));
-//        sopAppLink.setCourseTitle(linkTile);
-//        sopAppLink.setCourseUrl(linkImageUrl);
-//        sopAppLink.setVideoId(Long.valueOf(videoId));
-//        sopAppLink.setVideoTitle(linkDescribe);
-//        sopAppLink.setAppRealLink(appMsgLink);
-//        sopAppLink.setQwExternalId(externalId);
-//
-//        fsCourseSopAppLinkMapper.insertFsCourseSopAppLink(sopAppLink);
+        FsCourseSopAppLink sopAppLink=new FsCourseSopAppLink();
+        sopAppLink.setLink(link);
+        sopAppLink.setCreateTime(sendTime);
+        sopAppLink.setUpdateTime(updateTime);
+        sopAppLink.setCompanyId(Long.parseLong(companyId));
+        sopAppLink.setCompanyUserId(Long.parseLong(companyUserId));
+        sopAppLink.setQwUserId(Long.parseLong(qwUserId));
+        sopAppLink.setQwUserName(qwUserName);
+        sopAppLink.setCorpId(corpId);
+        sopAppLink.setCourseId(Long.valueOf(courseId));
+        sopAppLink.setCourseTitle(linkTile);
+        sopAppLink.setCourseUrl(linkImageUrl);
+        sopAppLink.setVideoId(Long.valueOf(videoId));
+        sopAppLink.setVideoTitle(linkDescribe);
+        sopAppLink.setAppRealLink(appMsgLink);
+        sopAppLink.setQwExternalId(externalId);
+
+        fsCourseSopAppLinkMapper.insertFsCourseSopAppLink(sopAppLink);
 
     }
 

+ 0 - 1
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -2407,7 +2407,6 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
                             }
                         });
                     }
-
                     QwResult qwResult = qwApiService.sendWelcomeMsg(sendWelcomeMsgParam, corpId);
                     logger.info("发送好友欢迎语的参数:" + sendWelcomeMsgParam+"发送好友欢迎语结果:" + qwResult);
 //                    if (qwResult.getErrcode()==41050||qwResult.getErrcode()==41051){

+ 8 - 1
fs-service/src/main/java/com/fs/qw/service/impl/QwUserVoiceLogServiceImpl.java

@@ -2,7 +2,9 @@ package com.fs.qw.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.utils.DateUtils;
+import com.fs.company.domain.CompanyDept;
 import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyDeptMapper;
 import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.qw.domain.*;
 import com.fs.qw.mapper.QwExternalContactMapper;
@@ -50,6 +52,9 @@ public class QwUserVoiceLogServiceImpl extends ServiceImpl<QwUserVoiceLogMapper,
 
     @Autowired
     private CompanyUserMapper companyUserMapper;
+    @Autowired
+    private CompanyDeptMapper companyDeptMapper;
+
     /**
      * 查询企微用户通话记录
      *
@@ -136,9 +141,11 @@ public class QwUserVoiceLogServiceImpl extends ServiceImpl<QwUserVoiceLogMapper,
 
             // 如果有部门过滤条件,则预先过滤用户列表
             if (qwUserVoiceLog.getDeptId() != null) {
+                Set<Long> deptIds = companyDeptMapper.selectChildrenDeptById(qwUserVoiceLog.getDeptId()).stream().map(CompanyDept::getDeptId).collect(Collectors.toSet());
                 companyUserMap.entrySet().removeIf(entry ->
                         entry.getValue().getDeptId() == null ||
-                                !entry.getValue().getDeptId().equals(qwUserVoiceLog.getDeptId()));
+                                !deptIds.contains(entry.getValue().getDeptId()));//需要deptId及其下级的部门
+//                                !entry.getValue().getDeptId().equals(qwUserVoiceLog.getDeptId()));
             }
 
             // 设置用户姓名和部门ID

+ 2 - 0
fs-service/src/main/java/com/fs/qw/vo/QwWatchLogStatisticsListVO.java

@@ -67,4 +67,6 @@ public class QwWatchLogStatisticsListVO {
     private Long los;//流失数
     @Excel(name = "删除数")
     private Long del;//删除数
+    @Excel(name = "重粉数")
+    private Long repeatCount;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/sop/mapper/QwSopMapper.java

@@ -432,6 +432,9 @@ public interface QwSopMapper extends BaseMapper<QwSop> {
     @DataSource(DataSourceType.SOP)
     List<QwSop> selectGroup(@Param("now")LocalDate now);
 
+    @DataSource(DataSourceType.SOP)
+    List<QwSop> fetchScheduleList(@Param("name")String name);
+
     @DataSource(DataSourceType.SOP)
     void updateSopGroupIds(@Param("id") String id, @Param("chatId") String chatId);
 }

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

@@ -104,6 +104,8 @@ public interface IQwSopService
 
     List<QwSop> selectAllQwSopInfo(QwSop qwSop);
 
+    List<QwSop> fetchScheduleList(String name);
+
     int deleteQwSopLogsBySopIds(String[] ids);
 
     //员工看板 课程/答题/红包统计--侧边栏

+ 9 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopServiceImpl.java

@@ -1115,6 +1115,15 @@ public class QwSopServiceImpl implements IQwSopService
         return qwSopMapper.selectAllQwSopInfo(qwSop);
     }
 
+    @Override
+    public List<QwSop> fetchScheduleList(String name) {
+        List<QwSop> qwSops = qwSopMapper.fetchScheduleList(name);
+        if (CollectionUtils.isEmpty(qwSops)){
+            return Collections.emptyList();
+        }
+        return qwSops;
+    }
+
     @Override
     @DataSource(DataSourceType.SOP)
     public int deleteQwSopLogsBySopIds(String[] ids) {

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

@@ -2214,8 +2214,6 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
         //异步给app用户发送消息
         asyncSopTestService.asyncSendMsgBySopAppLink(externalId,setting.getLinkTitle(),setting.getLinkDescribe(),appMsgLink);
 
-
-
         //存短链-
         fsCourseLinkMapper.insertFsCourseLink(link);
 

+ 2 - 2
fs-service/src/main/java/com/fs/wx/order/service/impl/ShopExpressToWxService.java

@@ -65,13 +65,13 @@ public class ShopExpressToWxService extends ExpressToWxService {
     @Override
     public String getExpressCompany() {
 
-        return fsStoreOrder.getDeliveryCode();
+        return fsStoreOrder.getDeliverySn();
     }
 
     @Override
     public String getExpressNo() {
 
-        return fsStoreOrder.getDeliverySn();
+        return fsStoreOrder.getDeliveryId();
     }
 
     @Override

+ 2 - 2
fs-service/src/main/resources/application-config-druid-bjzm-test.yml

@@ -15,8 +15,8 @@ logging:
 wx:
   miniapp:
     configs:
-      - appid: wxcc2de555e32acb08   #百域佳选
-        secret: 76eaf5e27ad79abb237c7a83ed8b80a3 #北京卓美
+      - appid: wx9bb2cd1e3afe714e   #百域佳选
+        secret: 56a2a3314d4b73eea2eac7e8b861b321 #北京卓美
         token: cbnd7lJvkripVOpyTFAna6NAWCxCrvC
         aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
         msgDataFormat: JSON

+ 2 - 2
fs-service/src/main/resources/application-config-druid-bjzm.yml

@@ -10,8 +10,8 @@ logging:
 wx:
   miniapp:
     configs:
-      - appid: wxcc2de555e32acb08   #百域佳选
-        secret: 76eaf5e27ad79abb237c7a83ed8b80a3 #北京卓美
+      - appid: wx9bb2cd1e3afe714e   #百域佳选
+        secret: 56a2a3314d4b73eea2eac7e8b861b321 #北京卓美
         token: cbnd7lJvkripVOpyTFAna6NAWCxCrvC
         aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
         msgDataFormat: JSON

+ 142 - 0
fs-service/src/main/resources/application-config-zlwh.yml

@@ -0,0 +1,142 @@
+#配置
+fsConfig:
+  #快递鸟
+  kdnId: 1886082
+  kdnKeyId: 5a66df03-3d88-469a-ab42-23cb082b57ac
+  kdnUrl: http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx
+  kdnSubscribeUrl: https://api.kdniao.com/api/dist
+  kdnAddressUrl: https://api.kdniao.com/api/dist
+  #ERP配置
+  erpOpen: 1
+  erpAppKey: 108123
+  erpSessionKey: 9caae15474cb443ea22235e7bb86016b
+  erpSecret: 96f774dbd60847b59a16f92fd963a0c8
+  erpUrl: http://v2.api.guanyierp.com/rest/erp_open
+  erpShopCode: test
+  #ERP-hc
+  erpWdAppKey: beiliyou2-gw
+  erpWdAppsecret: 37c7cebf6e5af56c783d865b63553993
+  erpWdSid: beiliyou2
+  erpWdShopCode: ziyou123456
+  erpWdBaseUrl: https://api.wangdian.cn/openapi2/
+  erpWarehouseCode: "02"
+  #第三方支付配置
+  payOpen: 1
+  payPartnerId: 22051909542647100020
+  payKey: f256bd35aa36115d729537e1a1e01b92
+  payGateWayUrl: https://openapi.t2bank.cn/gateway.html
+  payNotifyUrl: https://api.yjf.runtzh.com/app/pay/payNotify
+  refundNotifyUrl: https://api.yjf.runtzh.com/app/pay/refundNotify
+  # 腾讯云IM
+  sdkAppId: 1400693126
+  sdkAppKey: 9afa6e63db943293680e37b3ba032e52cdb238112750806e82e58e9240604b70
+  # 处方接口Test
+  #  prescribeUrl: https://yixian-new-test.yixianmedical.com/platform-shenfang/nethosp/webservice/jsonapi
+  #  actId:  uporder
+  #  appId: 1646204278
+  #  manuId:  3981112bfcc64bf68f7744ffec7e3ca7
+  #  callbackUrl:  https://api.hospital.ifeiyu100.com/app/prescribe/presribeNotify
+  # 处方接口g
+  prescribeUrl: https://app3.nxk520.com/platform-shenfang/nethosp/webservice/jsonapi
+  actId: uporder
+  appId: 1661496555
+  manuId: 0212af1e742b41b09089afeec98f8276
+  callbackUrl: https://api.yjf.runtzh.com/app/prescribe/presribeNotify
+  commonApi: http://192.168.0.224:7011
+logging:
+  level:
+    org.springframework.web: INFO
+    com.github.binarywang.demo.wx.cp: DEBUG
+    me.chanjar.weixin: DEBUG
+wx:
+  cp:
+    corpId: wwb2a1055fb6c9a7c2
+    appConfigs:
+      - agentId: 1000002
+        secret: bhj3402rPCT0YGcosffyTO3eUMs1G2MFHMspXVBNf-c
+        token: PPKOdAlCoMO
+        aesKey: PKvaxtpSv8NGpfTDm7VUHIK8Wok2ESyYX24qpXJAdMP
+  miniapp:
+    configs:
+      - appid: wx11a2ce7c2bbc4521   #倍力优会员商城
+        secret: d680dc8ff20258b158c9355f8b7769ae
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+      - appid: wx301ab2fad04c658a   #倍力优看课小程序
+        secret: 35018f10929b84c8c4a225de253bbcc6
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+
+  pay:
+    appId: wx11a2ce7c2bbc4521 #微信公众号或者小程序等的appid
+    mchId: 1703311381 #微信支付商户号
+    mchKey: FotTIbIzn4AisMW7de712LJQIazSqqAl #微信支付商户密钥
+    v3Key: y5Eo99q93qzdQRAs6E2BDKIF7f3EnS3G
+    subAppId:  #服务商模式下的子商户公众账号ID
+    subMchId:  #服务商模式下的子商户号
+    keyPath: c:\\Tools\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
+    notifyUrl:  https://userapp.bly.ylrztop.com/app/wxpay/wxPayNotify
+  mp:
+    useRedis: false
+    redisConfig:
+      host: 127.0.0.1
+      port: 6379
+      timeout: 2000
+    configs:
+      - appId: wx568ea6b70350c585 # 第一个公众号的appid  倍力优
+        secret: b14343e22871b1c207df5d3321e826b4 # 公众号的appsecret
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+jpush:
+  appKey: cc9a0120a3e4270c9cba340d
+  masterSecret: cfc2575d3cd7470d584c990c
+  liveTime: 1000
+  apnsProduction: true
+aifabu:  #爱链接
+  appKey: 7b471be905ab17e00f3b858c6710dd117601d008
+
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: beliyo-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: beliyo
+cloud_host:
+  company_name: 泽林文化
+  projectCode: ZLWH
+  spaceName: zlwh-2114522511
+  volcengineUrl: https://zlwhvolcengine.ylrztop.com
+headerImg:
+  imgUrl: https://beiliyo-2025.obs.cn-north-4.myhuaweicloud.com/fs/20250115/1736944490230.png
+
+baidu:
+  token: 1231321232
+  back-domain: admin.muyi88.com
+watch:
+  watchUrl: watch.ylrzcloud.com/prod-api
+  #  account: tcloud
+  #  password: mdf-m2h_6yw2$hq
+  account1: ccif #866655060138751
+  password1: cp-t5or_6xw7$mt
+  account2: tcloud #rt500台
+  password2: mdf-m2h_6yw2$hq
+  account3: whr
+  password3: v9xsKuqn_$d2y
+
+fs:
+  commonApi: http://172.21.76.167:8010
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+ipad:
+  ipadUrl:
+  aiApi:
+  voiceApi:
+  commonApi:
+wx_miniapp_temp:
+  pay_order_temp_id: VXEvKaGNPFuJmhWK9O_QPrTZxe9umDCukq-maI8Vdek
+  inquiry_temp_id: 9POPYeqhI48LOPvq-Rfoklze7H-9SlunJKh10Qt4_2I
+

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

@@ -124,7 +124,7 @@ spring:
                 slave:
                     # 从数据源开关/默认关闭
                     enabled: true
-                    url: jdbc:mysql://172.16.0.24:3306/fs_his?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    url: jdbc:mysql://172.16.16.135:3306/fs_his?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                     username: root
                     password: Ylrz_1q2w3e4r5t6y
                     # 初始连接数

+ 165 - 0
fs-service/src/main/resources/application-druid-zlwh.yml

@@ -0,0 +1,165 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-zlwh,common
+    # redis 配置
+    redis:
+        host: 192.168.0.59
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password: Ylrztek250218!3@.
+        # 连接超时时间
+        timeout: 30s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 100
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+    datasource:
+#        clickhouse:
+#            type: com.alibaba.druid.pool.DruidDataSource
+#            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
+#            url: jdbc:clickhouse://1.14.104.71:8123/sop_test?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
+#            username: rt_2024
+#            password: Yzx_19860213
+#            initialSize: 10
+#            maxActive: 100
+#            minIdle: 10
+#            maxWait: 6000
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                  url: jdbc:mysql://192.168.0.7:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
+                  username: root
+                  password: Ylrztek250218!3@.
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://192.168.0.7:3306/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
+                    username: root
+                    password: Ylrztek250218!3@.
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: rmq-33namm2jeq.rocketmq.nj.qcloud.tencenttdmq.com:8080
+    producer:
+        group: my-producer-group
+        access-key: ak33namm2jeq90148878a325 # 替换为实际的 accessKey
+        secret-key: sk0256ccecd9f96742 # 替换为实际的 secretKey
+    consumer:
+        group: common-group
+        access-key: ak33namm2jeq90148878a325 # 替换为实际的 accessKey
+        secret-key: sk0256ccecd9f96742 # 替换为实际的 secretKey
+openIM:
+    secret: openIM123
+    userID: imAdmin
+    url: https://web.im.fbylive.com/api
+#是否使用新im
+im:
+    type: NONE
+#是否为新商户,新商户不走mpOpenId
+isNewWxMerchant: false
+qw:
+    enableAutoTag: 1
+tag:
+    thread:
+        num: 10
+    rate:
+        limit: 50
+

+ 62 - 0
fs-service/src/main/resources/mapper/course/FsCourseRedPacketLogMapper.xml

@@ -216,4 +216,66 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectFsCourseRedPacketLogVo"/> where status != 1 and create_time &gt;= #{maps.startTime} and create_time &lt;= #{maps.endTime}
 
     </select>
+
+
+    <select id="selectFsCourseRedPacketLogListCountVO"
+            resultType="com.fs.course.vo.FsCourseRedPacketLogListVO">
+
+        SELECT
+        <if test="maps.changeType == 2">
+            l.company_user_id,
+            cu.nick_name,
+            cu.dept_id,
+            cd.dept_name,
+        </if>
+                c.company_name,
+                l.company_id,
+                sum(l.amount) AS amount,
+                l.create_time AS createTime
+        FROM
+                fs_course_red_packet_log l
+                INNER JOIN company c ON c.company_id = l.company_id
+                LEFT JOIN company_user cu on l.company_user_id=cu.user_id
+                LEFT JOIN company_dept cd on cu.dept_id=cd.dept_id
+        WHERE 1=1
+                  and l.create_time &gt;= #{maps.sTime}
+                  AND l.create_time &lt;#{maps.eTime}
+                  AND l.STATUS = 1
+        <if test="maps.companyIds != null and maps.companyIds.size() > 0  and maps.changeType == 1 ">
+            AND l.company_id IN
+            <foreach collection="maps.companyIds" open="(" close=")" separator="," item="item">
+                ${item}
+            </foreach>
+        </if>
+        <if test="maps.courseId != null ">
+            AND l.course_id = #{maps.courseId}
+        </if>
+        <if test="maps.courseId != null ">
+            AND l.videoId = #{maps.videoId}
+        </if>
+        <if test="maps.status != null">
+            and l.status = #{maps.status}
+        </if>
+        <if test="maps.userIds != null and maps.userIds.size() > 0 and maps.changeType == 2 ">
+          AND l.company_user_id IN
+            <foreach collection="maps.userIds" open="(" close=")" separator="," item="item">
+                ${item}
+            </foreach>
+        </if>
+        GROUP BY
+        <choose>
+            <when test="maps.companyIds != null and maps.changeType == 1 ">
+                l.company_id
+            </when>
+            <when test="maps.userIds != null and maps.userIds.size() > 0 and maps.changeType == 2 ">
+                l.company_id, l.company_user_id
+            </when>
+            <otherwise>
+                l.company_id, l.company_user_id  <!-- 默认分组方式 -->
+            </otherwise>
+        </choose>
+
+    </select>
+
+
 </mapper>

+ 17 - 11
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -60,7 +60,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </select>
 
     <select id="selectFsCourseWatchLogListVO" resultType="com.fs.course.vo.FsCourseWatchLogListVO">
-        select l.log_id,l.project,l.period_id,l.user_id,uc.course_name,v.title as video_name,qec.avatar as external_user_avatar,
+        select l.log_id,l.project,l.period_id,l.user_id,uc.course_name,v.title as video_name,qec.avatar as external_user_avatar,qec.status as externalStatus,
         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,
@@ -161,6 +161,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.sopId != null  and maps.sopId != '' ">
                 and l.sop_id = #{maps.sopId}
             </if>
+            <if test="maps.externalStatus != null  and maps.externalStatus != '' ">
+                and qec.status = #{maps.externalStatus}
+            </if>
             <if test="maps.periodId != null">
                 and l.period_id = #{maps.periodId}
             </if>
@@ -758,7 +761,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </update>
 
 
-    <select id="selectListBytrainingCampId" resultType="com.fs.course.vo.FsCourseWatchLogVO">
+    <select id="selectListBytrainingCampId" resultType="com.fs.course.vo.FsCourseWatchLogListVO">
         select
         uc.course_name,v.title as video_name,
         watch.log_id,
@@ -777,7 +780,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         watch.company_user_id,
         watch.company_id,
         watch.course_id,
-        watch.camp_period_time
+        watch.camp_period_time,
+        company_user.nick_name as companyUserName
         from
         fs_user_course_training_camp camp
         left join fs_user_course_period period on
@@ -786,6 +790,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         period.period_id = watch.period_id
         left join fs_user_course uc on uc.course_id = watch.course_id
         left join fs_user_course_video v on v.video_id = watch.video_id
+        left join company_user on company_user.user_id = watch.company_user_id
         <where>
             `period`.del_flag = '0' and watch.log_type &lt;&gt; 3
             <if test="trainingCampId != null">and camp.training_camp_id = #{trainingCampId}</if>
@@ -992,18 +997,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         fs_course_watch_log o
         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
-        WHERE o.qw_external_contact_id=#{qwExternalContactId}
-        <if test="sendType != null">
-            AND send_type = #{sendType}
+        WHERE
+            o.qw_external_contact_id=#{data.qwExternalContactId}
+        <if test="data.sendType != null">
+            AND send_type = #{data.sendType}
         </if>
-        <if test="startTime != null">
-            AND DATE(o.create_time) &gt;= DATE(#{startTime})
+        <if test="data.startTime != null">
+            AND DATE(o.create_time) &gt;= DATE(#{data.startTime})
         </if>
 
-        <if test="endTime != null">
-            AND DATE(o.create_time) &lt;= DATE(#{endTime})
+        <if test="data.endTime != null">
+            AND DATE(o.create_time) &lt;= DATE(#{data.endTime})
         </if>
-        o.create_time DESC
+        order by o.create_time DESC
     </select>
 
     <!-- 统计当天各公司的观看人数和完播人数, 存到redis中,定时任务每 ? 分钟执行一次    -->

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

@@ -2390,8 +2390,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="countExternalRedPacketStats" resultType="com.fs.store.vo.h5.ExternalRedPacketStatsVO">
         SELECT
-            COUNT(red.log_id) AS redPacketNum,
-            COALESCE(SUM(red.amount), 0) AS redPacketAmount
+            COUNT(log.log_id) AS redPacketNum,
+            COALESCE(SUM(log.amount), 0) AS redPacketAmount
         FROM fs_course_red_packet_log log
         WHERE log.status = 1
           AND log.user_id = #{userId} AND log.company_user_id = #{companyUserId}

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

@@ -857,9 +857,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         company_user cu
         INNER JOIN company c ON cu.company_id = c.company_id
         LEFT JOIN fs_store_order_scrm fso ON cu.user_id = fso.company_user_id
-        INNER JOIN fs_store_order_item_scrm fsoi ON fso.id = fsoi.order_id
-        INNER JOIN fs_store_product_scrm fsp ON fsoi.product_id = fsp.product_id
-        INNER JOIN fs_store_product_category_scrm fspc ON fspc.cate_id = fsp.cate_id
+--         INNER JOIN fs_store_order_item_scrm fsoi ON fso.id = fsoi.order_id
+--         INNER JOIN fs_store_product_scrm fsp ON fsoi.product_id = fsp.product_id
+--         INNER JOIN fs_store_product_category_scrm fspc ON fspc.cate_id = fsp.cate_id
         WHERE
         fso.is_del = '0'
         AND fso.`status` != 0

+ 7 - 0
fs-service/src/main/resources/mapper/sop/QwSopMapper.xml

@@ -610,6 +610,13 @@
         select * from qw_sop where auto_group = 1
     </select>
 
+    <select id="fetchScheduleList" parameterType="String" resultMap="QwSopResult">
+        <include refid="selectQwSopVo"/>
+        <where>
+            <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
+        </where>
+    </select>
+
     <update id="updateSopGroupIds">
         update qw_sop set chat_id = #{chatId},pull_time = now() where id = #{id}
     </update>

+ 2 - 2
fs-user-app/src/main/java/com/fs/app/controller/CompanyUserController.java

@@ -198,7 +198,7 @@ public class CompanyUserController extends AppBaseController {
         companyUser.setVoicePrintUrl(param.getVoicePrintUrl());
 
         //转换音频格式 mp3-wav
-        String s = AudioUtils.audioWAVFromUrl(param.getVoicePrintUrl());
+        String s = AudioUtils.audioWAVFromUrl(param.getVoicePrintUrl());//需要本地c盘根目录有ffmpeg.exe,silk_v3_decoder.exe,silk_v3_encoder.exe
         //保存文件并且上传存储桶
         System.out.println(s);
         File file = new File(s);
@@ -567,7 +567,7 @@ public class CompanyUserController extends AppBaseController {
         MultipartFile convert = FileToMultipartConverterUtil.convert(file);
         R r = voiceCloneController.uploadVoice(vcCompanyUser.getSpeakerId(), convert, 1, 0);
         if (r.get("code") != "200")
-        return AjaxResult.error("上传声纹失败", r.get("msg"));
+            return AjaxResult.error("上传声纹失败", r.get("msg"));
         vcCompanyUser.incrementTimes();
         vcCompanyUser.setUploadTime(duration);
         companyUserMapper.updateVcCompanyUser(vcCompanyUser);