Parcourir la source

AI工作流
-绑定销售功能
-绑定销售后新增节点优化
-销售后台相关接口
今正
-企微客户管理增加(精确搜索)
-企微标签增加(精确搜索)
-今正总后台新增客户群菜单
-今正总后台新增离职继承
-今正总后台新增在职转接
-今正总后台新增通话记录

lk il y a 1 semaine
Parent
commit
3019f960a8
28 fichiers modifiés avec 736 ajouts et 27 suppressions
  1. 42 0
      fs-admin/src/main/java/com/fs/his/controller/FsAiWorkflowController.java
  2. 53 0
      fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactController.java
  3. 155 0
      fs-admin/src/main/java/com/fs/qw/controller/QwGroupChatController.java
  4. 71 0
      fs-admin/src/main/java/com/fs/qw/controller/QwGroupChatUserController.java
  5. 39 18
      fs-company/src/main/java/com/fs/company/controller/company/CompanyAiWorkflowController.java
  6. 1 1
      fs-service/src/main/java/com/fs/aiSoundReplication/param/TtsRequest.java
  7. 1 0
      fs-service/src/main/java/com/fs/aiSoundReplication/service/impl/TtsServiceImpl.java
  8. 3 4
      fs-service/src/main/java/com/fs/aiSoundReplication/service/impl/VoiceCloneServiceImpl.java
  9. 11 0
      fs-service/src/main/java/com/fs/company/param/CompanyUserAiWorkflowTtsVoiceParam.java
  10. 25 0
      fs-service/src/main/java/com/fs/his/mapper/FsAiWorkflowMapper.java
  11. 15 0
      fs-service/src/main/java/com/fs/his/param/FsAiWorkflowUpdateBindWCParam.java
  12. 17 0
      fs-service/src/main/java/com/fs/his/service/IFsAiWorkflowService.java
  13. 67 0
      fs-service/src/main/java/com/fs/his/service/impl/FsAiWorkflowServiceImpl.java
  14. 5 0
      fs-service/src/main/java/com/fs/his/vo/FsAiWorkflowExportVO.java
  15. 34 0
      fs-service/src/main/java/com/fs/his/vo/FsAiWorkflowNodeVoiceVo.java
  16. 4 0
      fs-service/src/main/java/com/fs/qw/domain/QwTag.java
  17. 2 0
      fs-service/src/main/java/com/fs/qw/mapper/QwGroupChatMapper.java
  18. 1 0
      fs-service/src/main/java/com/fs/qw/mapper/QwTagMapper.java
  19. 3 0
      fs-service/src/main/java/com/fs/qw/param/QwExternalContactParam.java
  20. 5 0
      fs-service/src/main/java/com/fs/qw/param/QwGroupChatParam.java
  21. 5 0
      fs-service/src/main/java/com/fs/qw/param/QwTagParam.java
  22. 2 0
      fs-service/src/main/java/com/fs/qw/service/IQwGroupChatService.java
  23. 11 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwGroupChatServiceImpl.java
  24. 1 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwTagServiceImpl.java
  25. 87 0
      fs-service/src/main/resources/mapper/his/FsAiWorkflowMapper.xml
  26. 3 0
      fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml
  27. 67 0
      fs-service/src/main/resources/mapper/qw/QwGroupChatMapper.xml
  28. 6 4
      fs-user-app/src/main/java/com/fs/app/controller/CompanyUserController.java

+ 42 - 0
fs-admin/src/main/java/com/fs/his/controller/FsAiWorkflowController.java

@@ -9,6 +9,7 @@ import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.his.domain.FsAiWorkflow;
 import com.fs.his.domain.FsAiWorkflowNodeType;
 import com.fs.his.param.FsAiWorkflowSaveParam;
+import com.fs.his.param.FsAiWorkflowUpdateBindWCParam;
 import com.fs.his.service.IFsAiWorkflowService;
 import com.fs.his.vo.FsAiWorkflowVO;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -16,6 +17,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * AI工作流Controller
@@ -118,4 +120,44 @@ public class FsAiWorkflowController extends BaseController {
     public AjaxResult exportJson(@PathVariable("workflowId") Long workflowId) {
         return AjaxResult.success(fsAiWorkflowService.exportWorkflowJson(workflowId));
     }
+    /**
+     * 分页销售
+     */
+    @GetMapping("/listCompanyUser")
+    public AjaxResult listCompanyUser() {
+        return AjaxResult.success(fsAiWorkflowService.listCompanyUser());
+    }
+
+    /**
+     * 查销售
+     */
+    @GetMapping("/getCompanyUserById/{companyUserId}")
+    public AjaxResult getCompanyUserById(@PathVariable("companyUserId") Long companyUserId) {
+        return AjaxResult.success(fsAiWorkflowService.getCompanyUserById(companyUserId));
+    }
+
+//    /**
+//     * 查销售是否已经被绑定
+//     */
+//    @GetMapping("/checkCompanyUserBeUsed/{companyUserId}")
+//    public AjaxResult checkCompanyUserBeUsed(@PathVariable("companyUserId") Long companyUserId) {
+//        return AjaxResult.success(fsAiWorkflowService.checkCompanyUserBeUsed(companyUserId));
+//    }
+
+    /**
+     * 查工作流已绑定的销售
+     */
+    @GetMapping("/getBindCompanyUserByWorkflowId/{workflowId}")
+    public AjaxResult getBindCompanyUserByWorkflowId(@PathVariable("workflowId") Long workflowId) {
+        return AjaxResult.success(fsAiWorkflowService.getBindCompanyUserByWorkflowId(workflowId));
+    }
+
+    /**
+     * 修改工作流绑定的销售
+     */
+    @PostMapping("/updateWorkflowBindCompanyUser")
+    public AjaxResult updateWorkflowBindCompanyUser(@RequestBody FsAiWorkflowUpdateBindWCParam param) {
+        return fsAiWorkflowService.updateWorkflowBindCompanyUser(param);
+    }
+
 }

+ 53 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactController.java

@@ -2,19 +2,24 @@ package com.fs.qw.controller;
 
 import java.util.List;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.ServiceException;
+import com.fs.common.utils.ServletUtils;
 import com.fs.qw.param.QwExternalContactParam;
 import com.fs.qw.param.QwTagSearchParam;
+import com.fs.qw.param.ResignedTransferParam;
+import com.fs.qw.param.TransferParam;
 import com.fs.qw.service.IQwExternalContactInfoService;
 import com.fs.qw.service.IQwTagService;
 import com.fs.qw.vo.QwExternalContactUnionIdExportVO;
 import com.fs.qw.vo.QwExternalContactVO;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -177,4 +182,52 @@ public class QwExternalContactController extends BaseController
         return R.ok().put("data",qwExternalContactInfoService.selectQwExternalContactInfoByExternalContactId(id));
     }
 
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:addUnassigned')")
+    @Log(title = "同步待转接", businessType = BusinessType.INSERT)
+    @PostMapping("/addUnassigned")
+    public R addUnassigned(@RequestBody QwExternalContact qwExternalContact)
+    {
+        return qwExternalContactService.syncQwExternalContactUnassigned(qwExternalContact.getCorpId());
+    }
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:transfer')")
+    @Log(title = "企业微信客户", businessType = BusinessType.UPDATE)
+    @PutMapping("/resignedTransfer")
+    public R resignedTransfer(@RequestBody ResignedTransferParam param)
+    {
+        if (ObjectUtil.isNotEmpty(param.getQwUserName())&&ObjectUtil.isNotEmpty(param.getType())&&param.getType().equals("1")){
+            QwExternalContactParam qwExternalContact =new QwExternalContactParam();
+            qwExternalContact.setQwUserName(param.getQwUserName());
+
+//            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//            qwExternalContact.setCompanyId(loginUser.getCompany().getCompanyId());
+            List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVO(qwExternalContact);
+            if (!CollectionUtils.isEmpty(list)){
+                List<Long> ids = list.stream().map(QwExternalContactVO::getId).collect(Collectors.toList());
+                param.setIds(ids);
+            }
+        }
+
+        return qwExternalContactService.resignedTransfer(param);
+    }
+    /**
+     * 在职转接 分配客户
+     */
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:transfer')")
+    @Log(title = "企业微信客户", businessType = BusinessType.UPDATE)
+    @PutMapping("/transfer")
+    public R transfer(@RequestBody TransferParam param)
+    {
+        if (ObjectUtil.isNotEmpty(param.getQwUserName())&&ObjectUtil.isNotEmpty(param.getType())&&param.getType().equals("1")){
+            QwExternalContactParam qwExternalContact =new QwExternalContactParam();
+            qwExternalContact.setQwUserName(param.getQwUserName());
+//            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//            qwExternalContact.setCompanyId(loginUser.getCompany().getCompanyId());
+            List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVO(qwExternalContact);
+            if (!CollectionUtils.isEmpty(list)){
+                List<Long> ids = list.stream().map(QwExternalContactVO::getId).collect(Collectors.toList());
+                param.setIds(ids);
+            }
+        }
+        return qwExternalContactService.transfer(param);
+    }
 }

+ 155 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwGroupChatController.java

@@ -0,0 +1,155 @@
+package com.fs.qw.controller;
+
+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.utils.ServletUtils;
+//import com.fs.company.service.impl.CompanyDeptServiceImpl;
+//import com.fs.framework.security.LoginUser;
+//import com.fs.framework.service.TokenService;
+import com.fs.qw.param.QwGroupChatParam;
+import com.fs.qw.service.IQwGroupChatService;
+//import com.fs.qw.service.IQwUserService;
+//import com.fs.qw.vo.QwGroupChatOptionsVO;
+import com.fs.qw.vo.QwGroupChatVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 客户群详情Controller
+ *
+ * @author fs
+ * @date 2024-06-20
+ */
+@RestController
+@RequestMapping("/qw/groupChat")
+public class QwGroupChatController extends BaseController
+{
+    @Autowired
+    private IQwGroupChatService qwGroupChatService;
+
+//    @Autowired
+//    private TokenService tokenService;
+
+//    @Autowired
+//    private CompanyDeptServiceImpl companyDeptService;
+//
+//
+//    @Autowired
+//    private IQwUserService iQwUserService;
+
+    /**
+     * 查询客户群详情列表总后台查看
+     */
+    @PreAuthorize("@ss.hasPermi('qw:groupChat:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwGroupChatParam qwGroupChat)
+    {
+        startPage();
+        List<QwGroupChatVO> list = qwGroupChatService.selectQwGroupChatListAdmin(qwGroupChat);
+        return getDataTable(list);
+    }
+
+//    /**
+//     * 查询我的部门客户群详情列表
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:groupChat:deptList')")
+//    @GetMapping("/deptList")
+//    public TableDataInfo deptList(QwGroupChatParam qwGroupChat)
+//    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//
+//        List<Long> combinedList = new ArrayList<>();
+//        //本部门
+//        Long deptId = loginUser.getUser().getDeptId();
+//        if (deptId!=null){
+//            combinedList.add(deptId);
+//        }
+//        //本部门的下级部门
+//        List<Long> deptList = companyDeptService.selectCompanyDeptByParentId(deptId);
+//        if (!deptList.isEmpty()){
+//            combinedList.addAll(deptList);
+//        }
+//        qwGroupChat.setCuDeptIdList(combinedList);
+//        qwGroupChat.setUserType(loginUser.getUser().getUserType());
+//
+//
+//        startPage();
+//        List<QwGroupChatVO> list = qwGroupChatService.selectQwGroupChatList(qwGroupChat);
+//        return getDataTable(list);
+//    }
+
+
+//    /**
+//     * 我的-查询客户群详情列表
+//     */
+//    @PreAuthorize("@ss.hasPermi('qw:groupChat:myList')")
+//    @GetMapping("/myList")
+//    public TableDataInfo myList(QwGroupChatParam qwGroupChat)
+//    {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        qwGroupChat.setCompanyId(loginUser.getCompany().getCompanyId());
+//        qwGroupChat.setCompanyUserId(loginUser.getUser().getUserId());
+//        startPage();
+//        List<QwGroupChatVO> list = qwGroupChatService.selectQwGroupChatList(qwGroupChat);
+//        return getDataTable(list);
+//    }
+
+
+//    /**
+//     * 获取客户群详情详细信息
+//     */
+////    @PreAuthorize("@ss.hasPermi('qw:groupChat:query')")
+//    @GetMapping(value = "/{chatId}")
+//    public AjaxResult getInfo(@PathVariable("chatId") String chatId)
+//    {
+//        return AjaxResult.success(qwGroupChatService.selectQwGroupChatByChatId(chatId));
+//    }
+
+    /**
+     *  同步 插入客户群信息
+     */
+    @GetMapping("/cogradientGroupChat/{corpId}")
+    public R cogradientGroupChat(@PathVariable("corpId") String corpId) throws Exception {
+
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        Long companyId = loginUser.getCompany().getCompanyId();
+        List<String> qwUserIdList=new ArrayList<>();
+        return qwGroupChatService.cogradientGroupChat(corpId,qwUserIdList);
+    }
+
+//    /**
+//     *  同步 我的客户群信息
+//     */
+//    @GetMapping("/cogradientMyGroupChat/{corpId}")
+//    public R cogradientMyGroupChat(@PathVariable("corpId") String corpId) throws Exception {
+//
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//
+//        List<String> qwUserIdList = iQwUserService.selectQwUserListByCompanyUserId(loginUser.getUser().getUserId(), corpId);
+//
+//        return qwGroupChatService.cogradientGroupChat(corpId,qwUserIdList);
+//    }
+
+//    @GetMapping("/allList/{corpId}")
+//    public AjaxResult allList(@PathVariable("corpId") String corpId)
+//    {
+////        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+////        Long companyId = loginUser.getCompany().getCompanyId();
+//        List<QwGroupChatOptionsVO> list = qwGroupChatService.selectGroupChatOptionsVOList(corpId);
+//        return AjaxResult.success(list);
+//    }
+//    @GetMapping("/listAll")
+//    public AjaxResult listAll(String qwUserIds, String corpId, String sopId){
+//        List<QwGroupChatOptionsVO> list = qwGroupChatService.listAllByQwUserList(qwUserIds, corpId, sopId);
+//        return AjaxResult.success(list);
+//    }
+}

+ 71 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwGroupChatUserController.java

@@ -0,0 +1,71 @@
+package com.fs.qw.controller;
+
+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.framework.service.TokenService;
+import com.fs.qw.domain.QwGroupChatUser;
+import com.fs.qw.param.QwGroupChatUserDataType;
+import com.fs.qw.param.QwInsertGroupChatUserParam;
+import com.fs.qw.service.IQwGroupChatUserService;
+import com.fs.qw.vo.QwGroupChatUserVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 客户群成员列Controller
+ *
+ * @author fs
+ * @date 2024-06-20
+ */
+@RestController
+@RequestMapping("/qw/group_chat_user")
+public class QwGroupChatUserController extends BaseController
+{
+    @Autowired
+    private IQwGroupChatUserService qwGroupChatUserService;
+
+//    @Autowired
+//    private TokenService tokenService;
+
+    /**
+     * 查询客户群成员列列表
+     */
+    @GetMapping("/list")
+    public TableDataInfo list(QwGroupChatUser qwGroupChatUser)
+    {
+        startPage();
+        List<QwGroupChatUserVO> list = qwGroupChatUserService.selectQwGroupChatUserList(qwGroupChatUser);
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 获取客户群成员列详细信息
+     */
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(qwGroupChatUserService.selectQwGroupChatUserById(id));
+    }
+
+
+    /** 获取日星月的入群退群统计 */
+    @GetMapping("/getDataWeekMonthCount")
+    public R getDataWeekMonthCount(QwGroupChatUserDataType qwGroupChatUserDataType){
+
+        return qwGroupChatUserService.getDataWeekMonthCount(qwGroupChatUserDataType);
+    }
+
+    /**
+     *  同步 插入某个客户群信息
+     */
+    @PutMapping("/cogradientGroupChatUser")
+    public R cogradientGroupChatUser(@RequestBody QwInsertGroupChatUserParam param) {
+
+        return qwGroupChatUserService.cogradientGroupChatUser(param.getCorpId(), param.getChatId());
+    }
+}

+ 39 - 18
fs-company/src/main/java/com/fs/company/controller/company/CompanyAiWorkflowController.java

@@ -4,6 +4,7 @@ import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.utils.ServletUtils;
+import com.fs.company.param.CompanyUserAiWorkflowTtsVoiceParam;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 import com.fs.his.domain.FsAiWorkflow;
@@ -57,8 +58,8 @@ public class CompanyAiWorkflowController extends BaseController {
      * 获取当前登录企业用户的工作流关键节点
      * 节点类型: start(开始), end(结束), ai_chat(AI对话)
      */
-    @GetMapping("/myNodes")
-    public R getMyWorkflowNodes() {
+//    @GetMapping("/myNodes")
+    public R getMyWorkflowNode() {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         if (loginUser == null || loginUser.getUser() == null) {
             return R.error("用户信息错误");
@@ -70,27 +71,47 @@ public class CompanyAiWorkflowController extends BaseController {
     }
 
     /**
-     * 更新节点的语音URL
-     * @param nodeId 节点ID
-     * @param voiceUrl 语音URL
+     * 获取当前登录企业用户的工作流及需要录音的节点
      */
-    @PutMapping("/node/voiceUrl")
-    public R updateNodeVoiceUrl(@RequestParam("nodeId") Long nodeId,
-                                @RequestParam("voiceUrl") String voiceUrl) {
+    @GetMapping("/myNodes")
+    public R getMyWorkflowNodes() {
+        startPage();
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         if (loginUser == null || loginUser.getUser() == null) {
             return R.error("用户信息错误");
         }
         Long companyUserId = loginUser.getUser().getUserId();
-
-        int result = fsAiWorkflowService.updateNodeVoiceUrl(nodeId, voiceUrl, companyUserId);
-        if (result == -1) {
-            return R.error("节点不存在");
-        } else if (result == -2) {
-            return R.error("无权限修改该节点");
-        } else if (result > 0) {
-            return R.ok("更新成功");
-        }
-        return R.error("更新失败");
+        return R.ok().put("data", fsAiWorkflowService.getMyWorkflowNodes(companyUserId));
     }
+
+//    @PostMapping("/ttsVoice")
+//    public R ttsVoice(@RequestBody CompanyUserAiWorkflowTtsVoiceParam param) {
+//        return R.ok().put("data", fsAiWorkflowService.ttsVoice(param));
+//    }
+
+//    /**
+//     * 更新节点的语音URL
+//     * @param nodeKey 节点ID
+//     * @param voiceUrl 语音URL
+//     */
+//    @PutMapping("/node/voiceUrl")
+//    public R updateNodeVoiceUrl(@RequestParam("nodeKey") String nodeKey,
+//                                @RequestParam("voiceUrl") String voiceUrl,
+//                                @RequestParam("workflowId") Long workflowId) {
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+//        if (loginUser == null || loginUser.getUser() == null) {
+//            return R.error("用户信息错误");
+//        }
+//        Long companyUserId = loginUser.getUser().getUserId();
+//
+//        int result = fsAiWorkflowService.updateNodeVoiceUrl(nodeKey, voiceUrl, companyUserId,workflowId);
+//        if (result == -1) {
+//            return R.error("节点不存在");
+//        } else if (result == -2) {
+//            return R.error("无权限修改该节点");
+//        } else if (result > 0) {
+//            return R.ok("更新成功");
+//        }
+//        return R.error("更新失败");
+//    }
 }

+ 1 - 1
fs-service/src/main/java/com/fs/aiSoundReplication/param/TtsRequest.java

@@ -16,7 +16,7 @@ public class TtsRequest {
     private String token;
 
     @JsonProperty("cluster")
-    private String cluster = "volcano_icl"; // 声音复刻必须使用此cluster
+    private String cluster = "volcano_icl"; // 声音复刻必须使用此cluster 2.0 volc_voice_clone_v2
 
     @JsonProperty("voice_type")
     private String voiceType; // 训练好的speaker_id

+ 1 - 0
fs-service/src/main/java/com/fs/aiSoundReplication/service/impl/TtsServiceImpl.java

@@ -316,6 +316,7 @@ public class TtsServiceImpl implements TtsService {
             put("reqid", request.getReqId());
             put("text", request.getText());
             put("operation","query");
+            put("split_sentence", 1);//处理声音复刻语速过快
         }};
 
         requestBody.put("app",app);

+ 3 - 4
fs-service/src/main/java/com/fs/aiSoundReplication/service/impl/VoiceCloneServiceImpl.java

@@ -41,7 +41,7 @@ public class VoiceCloneServiceImpl implements VoiceCloneService {
         try {
             // 1. 参数校验
             if (!validateUploadParams(speakerId, audioFile, modelType))
-                return R.error("参数错误");
+                throw new VoiceCloneException(ErrorCodeEnum.BAD_REQUEST_ERROR.getCode(),ErrorCodeEnum.BAD_REQUEST_ERROR.getMessage());
 
             // 2. 构建请求
             VoiceCloneRequest request = buildUploadRequest(speakerId, audioFile, modelType, language);
@@ -62,12 +62,11 @@ public class VoiceCloneServiceImpl implements VoiceCloneService {
 
         } catch (JsonProcessingException e) {
             log.error("JSON序列化失败,声音复刻发送豆包失败", e);
-            R.error("JSON序列化失败");
+            return R.error("JSON序列化失败");
         } catch (IOException e) {
             log.error("文件处理失败,声音复刻发送豆包失败", e);
-            R.error("文件处理失败");
+            return R.error("文件处理失败");
         }
-        return R.ok();
     }
 
     @Override

+ 11 - 0
fs-service/src/main/java/com/fs/company/param/CompanyUserAiWorkflowTtsVoiceParam.java

@@ -0,0 +1,11 @@
+package com.fs.company.param;
+
+import lombok.Data;
+
+/**
+ * ai工作流销售tts参数
+ */
+@Data
+public class CompanyUserAiWorkflowTtsVoiceParam {
+
+}

+ 25 - 0
fs-service/src/main/java/com/fs/his/mapper/FsAiWorkflowMapper.java

@@ -1,6 +1,11 @@
 package com.fs.his.mapper;
 
+import com.fs.company.domain.CompanyUser;
 import com.fs.his.domain.FsAiWorkflow;
+import com.fs.his.domain.FsAiWorkflowNode;
+import com.fs.his.vo.FsAiWorkflowNodeVoiceVo;
+import org.apache.ibatis.annotations.Param;
+
 import java.util.List;
 
 /**
@@ -27,4 +32,24 @@ public interface FsAiWorkflowMapper {
     int deleteFsAiWorkflowById(Long workflowId);
 
     int deleteFsAiWorkflowByIds(Long[] workflowIds);
+
+    int selectFsAiWorkflowCountByCompanyUserId(Long companyUserId);
+
+    int updateWorkflowBindCompanyUser(@Param("workflowId") Long workflowId, @Param("companyUserId") Long companyUserId);
+
+    List<CompanyUser> getBindCompanyUserByWorkflowId(Long workflowId);
+
+    int insertFsAiWorkflowCompanyUser(@Param("workflowId")Long workflowId,@Param("companyUserIds") List<Long> companyUserIds);
+
+    int insertAiWorkflowCompanyUserVoice(@Param("workflowId") Long workflowId, @Param("companyUserIds") List<Long> companyUserIds, @Param("fsAiWorkflowNodes") List<FsAiWorkflowNode> fsAiWorkflowNodes);
+
+    List<String> selectFsAiWorkflowNodeByWorkflowId(@Param("workflowId") Long workflowId);
+
+    List<Long> selectWorkflowCompanyUserByWfId(@Param("workflowId") Long workflowId);
+
+    void deleteAiWorkflowCompanyUserVoice(@Param("workflowId") Long workflowId,@Param("nodeKeyDel") List<String> nodeKeyDel);
+
+    void addAiWorkflowCompanyUserVoice(@Param("workflowId") Long workflowId, @Param("companyUserIds") List<Long> companyUserIds, @Param("nodeKeyAdd") List<String> nodeKeyAdd);
+
+    List<FsAiWorkflowNodeVoiceVo> getMyWorkflowNodes(@Param("companyUserId") Long companyUserId);
 }

+ 15 - 0
fs-service/src/main/java/com/fs/his/param/FsAiWorkflowUpdateBindWCParam.java

@@ -0,0 +1,15 @@
+package com.fs.his.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * AI工作流-工作流与销售id绑定关系
+ */
+@Data
+public class FsAiWorkflowUpdateBindWCParam {
+    private static final long serialVersionUID = 1L;
+    private Long workflowId;
+    private List<Long> companyUserIds;
+}

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

@@ -1,13 +1,18 @@
 package com.fs.his.service;
 
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.company.domain.CompanyUser;
 import com.fs.his.domain.FsAiWorkflow;
 import com.fs.his.domain.FsAiWorkflowNode;
 import com.fs.his.domain.FsAiWorkflowNodeType;
 import com.fs.his.param.FsAiWorkflowSaveParam;
+import com.fs.his.param.FsAiWorkflowUpdateBindWCParam;
 import com.fs.his.vo.FsAiWorkflowExportVO;
+import com.fs.his.vo.FsAiWorkflowNodeVoiceVo;
 import com.fs.his.vo.FsAiWorkflowVO;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * AI工作流Service接口
@@ -56,6 +61,8 @@ public interface IFsAiWorkflowService {
      */
     FsAiWorkflowExportVO exportWorkflowJson(Long workflowId);
 
+    List<CompanyUser> listCompanyUser();
+
     /**
      * 根据企业用户ID查询工作流的指定类型节点
      * @param companyUserId 企业用户ID
@@ -72,4 +79,14 @@ public interface IFsAiWorkflowService {
      * @return 1成功 0失败 -1节点不存在 -2无权限
      */
     int updateNodeVoiceUrl(Long nodeId, String voiceUrl, Long companyUserId);
+
+    CompanyUser getCompanyUserById(Long id);
+
+    Boolean checkCompanyUserBeUsed(Long companyUserId);
+
+    AjaxResult updateWorkflowBindCompanyUser(FsAiWorkflowUpdateBindWCParam param);
+
+    AjaxResult getBindCompanyUserByWorkflowId(Long workflowId);
+
+    List<FsAiWorkflowNodeVoiceVo> getMyWorkflowNodes(Long companyUserId);
 }

+ 67 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsAiWorkflowServiceImpl.java

@@ -1,6 +1,10 @@
 package com.fs.his.service.impl;
 
+import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.spring.SpringUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.his.domain.FsAiWorkflow;
 import com.fs.his.domain.FsAiWorkflowEdge;
 import com.fs.his.domain.FsAiWorkflowNode;
@@ -10,8 +14,10 @@ import com.fs.his.mapper.FsAiWorkflowMapper;
 import com.fs.his.mapper.FsAiWorkflowNodeMapper;
 import com.fs.his.mapper.FsAiWorkflowNodeTypeMapper;
 import com.fs.his.param.FsAiWorkflowSaveParam;
+import com.fs.his.param.FsAiWorkflowUpdateBindWCParam;
 import com.fs.his.service.IFsAiWorkflowService;
 import com.fs.his.vo.FsAiWorkflowExportVO;
+import com.fs.his.vo.FsAiWorkflowNodeVoiceVo;
 import com.fs.his.vo.FsAiWorkflowVO;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -39,6 +45,7 @@ public class FsAiWorkflowServiceImpl implements IFsAiWorkflowService {
     @Autowired
     private FsAiWorkflowNodeTypeMapper fsAiWorkflowNodeTypeMapper;
 
+    private static List<String> aiCallNodeTypes = Arrays.asList("param", "ai_chat","end");
     @Override
     public FsAiWorkflowVO selectFsAiWorkflowById(Long workflowId) {
         FsAiWorkflow workflow = fsAiWorkflowMapper.selectFsAiWorkflowById(workflowId);
@@ -110,6 +117,28 @@ public class FsAiWorkflowServiceImpl implements IFsAiWorkflowService {
             fsAiWorkflowEdgeMapper.batchInsertFsAiWorkflowEdge(edges);
         }
 
+        //更新工作流后,需要删除或新增录音节点对应的id
+
+        List<String> nodeKeyOlds = fsAiWorkflowMapper.selectFsAiWorkflowNodeByWorkflowId(workflowId);
+        List<Long> companyUserIds = fsAiWorkflowMapper.selectWorkflowCompanyUserByWfId(workflowId);
+
+        // 提取新节点的nodeKey
+        List<String> newNodeKeys = nodes.stream()
+                .filter(node -> aiCallNodeTypes.contains(node.getNodeType()))
+                .map(FsAiWorkflowNode::getNodeKey)
+                .collect(Collectors.toList());
+
+        // 找出新增的nodeKey(新节点中有,旧节点中没有)
+        List<String> nodeKeyAdd = newNodeKeys.stream()
+                .filter(key -> !nodeKeyOlds.contains(key))
+                .collect(Collectors.toList());
+
+        // 找出需要删除的nodeKey(旧节点中有,新节点中没有)
+        List<String> nodeKeyDel = nodeKeyOlds.stream()
+                .filter(key -> !newNodeKeys.contains(key))
+                .collect(Collectors.toList());
+        if (!nodeKeyDel.isEmpty())fsAiWorkflowMapper.deleteAiWorkflowCompanyUserVoice(workflowId, nodeKeyDel);
+        if (!nodeKeyAdd.isEmpty())fsAiWorkflowMapper.addAiWorkflowCompanyUserVoice(workflowId,companyUserIds, nodeKeyAdd);
         return workflowId;
     }
 
@@ -244,6 +273,11 @@ public class FsAiWorkflowServiceImpl implements IFsAiWorkflowService {
         return exportVO;
     }
 
+    @Override
+    public List<CompanyUser> listCompanyUser() {
+        return SpringUtils.getBean(CompanyUserMapper.class).selectAllCompanyUserList();
+    }
+
     private String getWorkflowTypeName(Integer workflowType) {
         if (workflowType == null) return "";
         switch (workflowType) {
@@ -299,4 +333,37 @@ public class FsAiWorkflowServiceImpl implements IFsAiWorkflowService {
         updateNode.setVoiceUrl(voiceUrl);
         return fsAiWorkflowNodeMapper.updateFsAiWorkflowNode(updateNode);
     }
+
+    @Override
+    public CompanyUser getCompanyUserById(Long id) {
+        return SpringUtils.getBean(CompanyUserMapper.class).selectCompanyUserById( id);
+    }
+
+    @Override
+    public Boolean checkCompanyUserBeUsed(Long companyUserId) {
+        return fsAiWorkflowMapper.selectFsAiWorkflowCountByCompanyUserId(companyUserId) > 0;
+    }
+
+    @Override
+    public AjaxResult updateWorkflowBindCompanyUser(FsAiWorkflowUpdateBindWCParam param) {
+        if (param == null ||param.getWorkflowId() == null || param.getCompanyUserIds() == null || param.getCompanyUserIds().size() == 0) return AjaxResult.error("传参异常");
+        FsAiWorkflow fsAiWorkflowResult = fsAiWorkflowMapper.selectFsAiWorkflowById(Long.valueOf(param.getWorkflowId().toString()));
+        if (fsAiWorkflowResult == null)return AjaxResult.error("未查询到对应工作流,请刷新后重试");
+        int i = fsAiWorkflowMapper.insertFsAiWorkflowCompanyUser(param.getWorkflowId(),param.getCompanyUserIds());
+        List<FsAiWorkflowNode> fsAiWorkflowNodes = fsAiWorkflowNodeMapper.selectNodesByWorkflowIdAndTypes(param.getWorkflowId(), aiCallNodeTypes);
+        fsAiWorkflowMapper.insertAiWorkflowCompanyUserVoice(param.getWorkflowId(), param.getCompanyUserIds(), fsAiWorkflowNodes);
+        return AjaxResult.success("绑定成功");
+    }
+
+    @Override
+    public AjaxResult getBindCompanyUserByWorkflowId(Long workflowId) {
+        FsAiWorkflow fsAiWorkflow = fsAiWorkflowMapper.selectFsAiWorkflowById(workflowId);
+        if (fsAiWorkflow == null) return AjaxResult.error("工作流不存在");
+        return AjaxResult.success(fsAiWorkflowMapper.getBindCompanyUserByWorkflowId(workflowId));
+    }
+
+    @Override
+    public List<FsAiWorkflowNodeVoiceVo> getMyWorkflowNodes(Long companyUserId) {
+        return fsAiWorkflowMapper.getMyWorkflowNodes(companyUserId);
+    }
 }

+ 5 - 0
fs-service/src/main/java/com/fs/his/vo/FsAiWorkflowExportVO.java

@@ -67,6 +67,11 @@ public class FsAiWorkflowExportVO implements Serializable {
 
         /** 排序 */
         private Integer sortOrder;
+
+        /**
+         * 语音URL
+         */
+        private String voiceUrl;
     }
 
     /** 连接信息 */

+ 34 - 0
fs-service/src/main/java/com/fs/his/vo/FsAiWorkflowNodeVoiceVo.java

@@ -0,0 +1,34 @@
+package com.fs.his.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+/**
+ *
+ */
+@Data
+public class FsAiWorkflowNodeVoiceVo {
+    /** 节点ID */
+    private Long nodeId;
+    /** 销售用户ID */
+    private Long companyUserId;
+
+    /** 工作流ID */
+    private Long workflowId;
+    /** 工作流名称 */
+    private String workflowName;
+
+    /** 节点唯一标识 */
+    private String nodeKey;
+
+    /** 节点名称 */
+    private String nodeName;
+
+    /** 节点类型 start/end/condition/action/ai/delay/http */
+    private String nodeType;
+
+    /**
+     * 语音URL
+     */
+    private String voiceUrl;
+}

+ 4 - 0
fs-service/src/main/java/com/fs/qw/domain/QwTag.java

@@ -25,6 +25,10 @@ public class QwTag extends BaseEntity
     /** 名称 */
     @Excel(name = "名称")
     private String name;
+    /**
+     * 精确查询名称
+     */
+    private String preciseName;
 
     /** 标签组id */
     @Excel(name = "标签组id")

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

@@ -130,4 +130,6 @@ public interface QwGroupChatMapper
     List<QwGroupChatTransferVO> selectQwGroupChatTransferList(QwGroupChatParam qwGroupChat);
 
     List<QwGroupChat> selectSopAndQwUser(@Param("qwUserId") String qwUserId, @Param("sopId") String sopId);
+
+    List<QwGroupChatVO> selectQwGroupChatListVOAdmin(@Param("map") QwGroupChatParam qwGroupChat, @Param("qwUserIds") List<String> qwUserIds);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwTagMapper.java

@@ -75,6 +75,7 @@ public interface QwTagMapper
             "<where>\n" +
             "            <if test=\"tagId != null  and tagId != ''\"> and t1.tag_id = #{tagId}</if>\n" +
             "            <if test=\"name != null  and name != ''\"> and t1.name like concat('%', #{name}, '%')</if>\n" +
+            "            <if test=\"preciseName != null  and preciseName != ''\"> and t1.name = #{preciseName}</if>\n" +
             "            <if test=\"groupId != null  and groupId != ''\"> and t1.group_id = #{groupId}</if>\n" +
             "            <if test=\"order != null  and order != ''\"> and t1.`order` = #{order}</if>\n" +
             "            <if test=\"corpId != null  and corpId != ''\"> and t1.corp_id = #{corpId}</if>\n" +

+ 3 - 0
fs-service/src/main/java/com/fs/qw/param/QwExternalContactParam.java

@@ -57,6 +57,9 @@ public class QwExternalContactParam {
     @Excel(name = "名称")
     private String name;
 
+    /** 精确查询名称 */
+    private String preciseName;
+
     /** 头像 */
     @Excel(name = "头像")
     private String avatar;

+ 5 - 0
fs-service/src/main/java/com/fs/qw/param/QwGroupChatParam.java

@@ -55,6 +55,11 @@ public class QwGroupChatParam {
      */
     private List<Long> cuDeptIdList;
 
+    /**
+     * 部门id
+     */
+    private Long deptId;
+
     /**
      * 部门类型 00 管理员 01 员工
      */

+ 5 - 0
fs-service/src/main/java/com/fs/qw/param/QwTagParam.java

@@ -10,6 +10,11 @@ public class QwTagParam  {
     @Excel(name = "名称")
     private String name;
 
+    /**
+     * 精确查询名称
+     */
+    private String preciseName;
+
     /** 企业id */
     @Excel(name = "企业id")
     private String corpId;

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

@@ -88,4 +88,6 @@ public interface IQwGroupChatService
     ResultMessage processTransfer(TransferChatParam param, CompanyUser user, boolean isResigned);
 
     List<QwGroupChat> selectSopAndQwUser(String qwUserId, String id);
+
+    List<QwGroupChatVO> selectQwGroupChatListAdmin(QwGroupChatParam qwGroupChat);
 }

+ 11 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwGroupChatServiceImpl.java

@@ -569,4 +569,15 @@ public class QwGroupChatServiceImpl implements IQwGroupChatService
         return qwGroupChatMapper.selectSopAndQwUser(qwUserId, sopId);
     }
 
+    @Override
+    public List<QwGroupChatVO> selectQwGroupChatListAdmin(QwGroupChatParam qwGroupChat) {
+        List<String> qwUserIds=null;
+        if (!StringUtil.strIsNullOrEmpty(qwGroupChat.getQwUserList())){
+            String[] split = qwGroupChat.getQwUserList().split(",");
+            // 使用 Arrays.asList() 将数组转换为 List
+            qwUserIds = Arrays.asList(split);
+        }
+        return qwGroupChatMapper.selectQwGroupChatListVOAdmin(qwGroupChat,qwUserIds);
+    }
+
 }

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

@@ -75,6 +75,7 @@ public class QwTagServiceImpl implements IQwTagService
         qwTag.setName(tagParam.getName());
         qwTag.setCorpId(tagParam.getCorpId());
         qwTag.setCompanyId(tagParam.getCompanyId());
+        qwTag.setPreciseName(tagParam.getPreciseName());
         List<QwTagVO> qwTags = qwTagMapper.selectQwTagListVO(qwTag);
 
         // Step 2: 提取 GroupId 列表(去重)

+ 87 - 0
fs-service/src/main/resources/mapper/his/FsAiWorkflowMapper.xml

@@ -24,6 +24,19 @@
                canvas_data, create_by, create_time, update_by, update_time, remark, del_flag, company_user_id
         from fs_ai_workflow
     </sql>
+    <update id="deleteAiWorkflowCompanyUserVoice" >
+        update
+            fs_ai_workflow_company_voice
+        set statu = 1
+        where
+            workflow_id = #{workflowId}
+            and node_key in
+            <foreach item="item" index="index" collection="nodeKeyDel" separator="," open="(" close=")">
+                #{item}
+            </foreach>
+
+    </update>
+
 
     <select id="selectFsAiWorkflowList" parameterType="FsAiWorkflow" resultMap="FsAiWorkflowResult">
         <include refid="selectFsAiWorkflowVo"/>
@@ -49,6 +62,52 @@
         where company_user_id = #{companyUserId} and del_flag = 0 and status = 1
         order by create_time desc
     </select>
+    <select id="selectFsAiWorkflowCountByCompanyUserId" resultType="java.lang.Integer">
+        select count(1) from fs_ai_workflow where company_user_id = #{companyUserId} and del_flag = 0 and status = 1
+    </select>
+    <select id="getBindCompanyUserByWorkflowId" resultType="com.fs.company.domain.CompanyUser">
+        select
+           aw.company_user_id userId,cu.user_name,cu.nick_name
+        from fs_ai_workflow_company_user aw
+        left join company_user cu
+            on aw.company_user_id = cu.user_id
+        where
+        cu.status = 0
+        and aw.del_flag = 0
+        and aw.workflow_id = #{workflowId}
+    </select>
+    <select id="selectFsAiWorkflowNodeByWorkflowId" resultType="java.lang.String">
+        select distinct
+            node_key
+        from
+            fs_ai_workflow_company_voice
+        where
+            workflow_id = #{workflowId}
+    </select>
+    <select id="selectWorkflowCompanyUserByWfId" resultType="java.lang.Long">
+        select distinct
+            company_user_id
+        from
+            fs_ai_workflow_company_voice
+        where
+            workflow_id = #{workflowId}
+    </select>
+    <select id="getMyWorkflowNodes" resultType="com.fs.his.vo.FsAiWorkflowNodeVoiceVo">
+        select
+            wcv.company_user_id,wcv.workflow_id,wcv.node_key,wcv.voice_url,aw.workflow_name,
+            awn.node_name,awn.node_type,awn.node_id
+        from
+            fs_ai_workflow_company_voice wcv
+        left join
+            fs_ai_workflow aw on aw.workflow_id = wcv.workflow_id
+        left join
+            fs_ai_workflow_node awn on awn.node_key = wcv.node_key
+        where
+            wcv.company_user_id = #{companyUserId}
+          and wcv.statu = 0
+          and aw.del_flag = 0
+    </select>
+
 
     <insert id="insertFsAiWorkflow" parameterType="FsAiWorkflow" useGeneratedKeys="true" keyProperty="workflowId">
         insert into fs_ai_workflow
@@ -77,6 +136,31 @@
             <if test="companyUserId != null">#{companyUserId},</if>
         </trim>
     </insert>
+    <insert id="insertFsAiWorkflowCompanyUser">
+        insert into fs_ai_workflow_company_user (workflow_id, company_user_id)
+        values
+        <foreach collection="companyUserIds" item="userId" separator=",">
+            (#{workflowId}, #{userId})
+        </foreach>
+    </insert>
+    <insert id="insertAiWorkflowCompanyUserVoice">
+        insert into fs_ai_workflow_company_voice (workflow_id, company_user_id, node_key)
+        values
+        <foreach collection="fsAiWorkflowNodes" item="node" separator=",">
+            <foreach collection="companyUserIds" item="userId" separator=",">
+                (#{workflowId}, #{userId}, #{node.nodeKey})
+            </foreach>
+        </foreach>
+    </insert>
+    <insert id="addAiWorkflowCompanyUserVoice">
+        insert into fs_ai_workflow_company_voice (workflow_id, company_user_id, node_key)
+            values
+        <foreach collection="companyUserIds" item="userId" separator=",">
+                <foreach collection="nodeKeyAdd" item="nodeKey" separator=",">
+                    (#{workflowId}, #{userId}, #{nodeKey})
+                </foreach>
+        </foreach>
+    </insert>
 
     <update id="updateFsAiWorkflow" parameterType="FsAiWorkflow">
         update fs_ai_workflow
@@ -104,4 +188,7 @@
             #{workflowId}
         </foreach>
     </update>
+    <update id="updateWorkflowBindCompanyUser">
+        update fs_ai_workflow set company_user_id = #{companyUserId} where workflow_id = #{workflowId}
+    </update>
 </mapper>

+ 3 - 0
fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml

@@ -684,6 +684,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 <if test="name != null and name != ''">
                     and ec.name like concat(#{name}, '%')
                 </if>
+                <if test="preciseName != null and preciseName != ''">
+                    and ec.name = #{preciseName}
+                </if>
                 <if test="type != null">
                     and ec.type = #{type}
                 </if>

+ 67 - 0
fs-service/src/main/resources/mapper/qw/QwGroupChatMapper.xml

@@ -226,4 +226,71 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        select * from qw_group_chat where owner = #{qwUserId} and sop_id = #{sopId}
             order by create_time desc limit 1
     </select>
+    <select id="selectQwGroupChatListVOAdmin" resultType="com.fs.qw.vo.QwGroupChatVO">
+        SELECT
+        ANY_VALUE(cu.nick_name) as ownerName,
+        ANY_VALUE(qu.qw_user_name) as qwName,
+        COUNT(CASE WHEN gcu.is_out = 1 AND DATE(gcu.join_time) = CURDATE() THEN 1 END) AS todayJoinByChartUser,
+        COUNT(CASE WHEN gcu.is_out = 2 AND DATE(gcu.out_time) = CURDATE() THEN 1 END) AS todayOutByChartUser,
+        COUNT(CASE WHEN gcu.is_out = 1 THEN gcu.chat_id END) AS groupSizeByChartUser,
+        gc.*
+        FROM
+        qw_group_chat gc
+        LEFT JOIN qw_group_chat_user gcu ON gc.chat_id = gcu.chat_id
+        AND gc.corp_id = gcu.corp_id
+        LEFT JOIN qw_user qu ON gc.owner = qu.qw_user_id
+        AND qu.is_del = 0
+        AND qu.corp_id = gc.corp_id
+        LEFT JOIN company_user cu ON cu.qw_user_id = qu.id
+        <where>
+            <if test="map.chatId != null and map.chatId != ''">
+                AND gc.chat_id LIKE CONCAT(#{map.chatId}, '%')
+            </if>
+            <if test="map.name != null and map.name != ''">
+                AND gc.name LIKE CONCAT(#{map.name}, '%')
+            </if>
+            <if test="map.ownerName != null and map.ownerName != ''">
+                AND cu.nick_name LIKE CONCAT(#{map.ownerName}, '%')
+            </if>
+            <if test="map.qwName != null and map.qwName != ''">
+                AND qu.qw_user_name LIKE CONCAT('%', #{map.qwName}, '%')
+            </if>
+            <if test="map.notice != null and map.notice != ''">
+                AND gc.notice LIKE CONCAT('%', #{map.notice}, '%')
+            </if>
+            <if test="map.status != null and map.status != ''">
+                AND gc.status = #{map.status}
+            </if>
+            <if test="map.companyId != null">
+                AND gc.company_id = #{map.companyId}
+            </if>
+            <if test="map.companyUserId != null">
+                AND qu.company_user_id = #{map.companyUserId}
+            </if>
+            <if test="map.corpId != null and map.corpId != ''">
+                AND gc.corp_id = #{map.corpId}
+            </if>
+            <if test="map.corpId != null and map.corpId != ''">
+                AND qu.corp_id = #{map.corpId}
+            </if>
+            <if test="map.qwUserList != null and map.qwUserList != ''">
+                AND gc.owner IN
+                <foreach item="item" index="index" collection="qwUserIds" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            <if test="map.cuDeptIdList != null and !map.cuDeptIdList.isEmpty() and map.userType != '00'">
+                AND cu.dept_id IN
+                <foreach collection="map.cuDeptIdList" item="item" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            <if test="map.deptId != null and map.deptId != 0">
+                AND (cu.dept_id = #{map.deptId} OR cu.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{map.deptId}, ancestors) ))
+            </if>
+        </where>
+        GROUP BY
+        gc.chat_id, cu.nick_name, qu.qw_user_name
+        ORDER BY gc.create_time DESC
+    </select>
 </mapper>

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

@@ -215,12 +215,12 @@ public class CompanyUserController extends AppBaseController {
                 "2".equals(vcConfig.getString("type"))) {
             /*走豆包直接不走原逻辑*/
             AjaxResult ajaxResult = uploadVoice(userId, wavUrl);
-            if (!ajaxResult.get("code").equals(200)){
+            if (!ajaxResult.get("code").equals(200)) {
                 return R.error((String) ajaxResult.get("msg"));
             }
             voiceService.insertQwSopTempVoiceModel(userId);
             return R.ok();
-        }else {
+        } else {
             try {
                 CloseableHttpClient httpClient = HttpClients.createDefault();
                 HttpPost httpPost = new HttpPost(aiHostProper.getCommonApi() + "/app/common/addCompanyAudio");
@@ -565,11 +565,13 @@ public class CompanyUserController extends AppBaseController {
         Double duration = (double) frames / format.getFrameRate();
         audioInputStream.close();
         MultipartFile convert = FileToMultipartConverterUtil.convert(file);
-        voiceCloneController.uploadVoice(vcCompanyUser.getSpeakerId(), convert, 1, 0);
+        R r = voiceCloneController.uploadVoice(vcCompanyUser.getSpeakerId(), convert, 1, 0);
+        if (r.get("code") != "200")
+        return AjaxResult.error("上传声纹失败", r.get("msg"));
         vcCompanyUser.incrementTimes();
         vcCompanyUser.setUploadTime(duration);
         companyUserMapper.updateVcCompanyUser(vcCompanyUser);
-        return AjaxResult.success();
+        return AjaxResult.success(String.format("您已上传%d次声纹,总共有5次录入次数", vcCompanyUser.getTimes()));
     }
 //    private static MultipartFile downloadAsMultipartFile(String fileUrl) throws Exception {
 //        URL url = new URL(fileUrl);