Long 3 недель назад
Родитель
Сommit
e344b43820
24 измененных файлов с 670 добавлено и 9 удалено
  1. 44 0
      fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactTransferCompanyAuditController.java
  2. 6 4
      fs-company/src/main/java/com/fs/company/controller/company/CompanyController.java
  3. 47 1
      fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java
  4. 9 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java
  5. 5 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java
  6. 5 0
      fs-service/src/main/java/com/fs/company/service/ICompanyService.java
  7. 8 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  8. 72 0
      fs-service/src/main/java/com/fs/qw/domain/QwExternalContactTransferCompanyAudit.java
  9. 60 0
      fs-service/src/main/java/com/fs/qw/domain/QwExternalContactTransferCompanyAuditUser.java
  10. 28 0
      fs-service/src/main/java/com/fs/qw/dto/CompanyTransferDTO.java
  11. 14 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactTransferCompanyAuditMapper.java
  12. 15 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactTransferCompanyAuditUserMapper.java
  13. 5 1
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  14. 21 0
      fs-service/src/main/java/com/fs/qw/service/IQwExternalContactTransferCompanyAuditService.java
  15. 19 0
      fs-service/src/main/java/com/fs/qw/service/IQwExternalContactTransferCompanyAuditUserService.java
  16. 5 2
      fs-service/src/main/java/com/fs/qw/service/IQwUserService.java
  17. 147 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactTransferCompanyAuditServiceImpl.java
  18. 39 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactTransferCompanyAuditUserServiceImpl.java
  19. 8 1
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java
  20. 46 0
      fs-service/src/main/resources/db/20250928-企微客户公司转接.sql
  21. 7 0
      fs-service/src/main/resources/mapper/company/CompanyMapper.xml
  22. 26 0
      fs-service/src/main/resources/mapper/qw/QwExternalContactTransferCompanyAuditMapper.xml
  23. 17 0
      fs-service/src/main/resources/mapper/qw/QwExternalContactTransferCompanyAuditUserMapper.xml
  24. 17 0
      fs-service/src/main/resources/mapper/qw/QwUserMapper.xml

+ 44 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactTransferCompanyAuditController.java

@@ -0,0 +1,44 @@
+package com.fs.qw.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditService;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/qw/externalContactTransferCompanyAudit")
+public class QwExternalContactTransferCompanyAuditController extends BaseController {
+
+    @Autowired
+    private IQwExternalContactTransferCompanyAuditService auditService;
+    @Autowired
+    private IQwExternalContactTransferCompanyAuditUserService auditUserService;
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwExternalContactTransferCompanyAudit param) {
+        startPage();
+        List<QwExternalContactTransferCompanyAudit> list = auditService.selectQwExternalContactTransferCompanyAuditList(param);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:detail')")
+    @GetMapping("/detail/{auditId}")
+    public AjaxResult detail(@PathVariable Long auditId) {
+        return AjaxResult.success(auditUserService.getListByAuditId(auditId));
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:audit')")
+    @PostMapping("/audit")
+    public AjaxResult audit() {
+        return AjaxResult.success();
+    }
+
+}

+ 6 - 4
fs-company/src/main/java/com/fs/company/controller/company/CompanyController.java

@@ -17,10 +17,7 @@ import com.fs.framework.service.TokenService;
 import com.fs.his.vo.OptionsVO;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
@@ -119,4 +116,9 @@ public class CompanyController extends BaseController
         return R.ok();
     }
 
+    @GetMapping("/getCompanyListByCorId/{corpId}")
+    public R getCompanyListByCorId(@PathVariable String corpId) {
+        List<OptionsVO> list = companyService.getCompanyListByCorpId(corpId);
+        return R.ok().put("data",list);
+    }
 }

+ 47 - 1
fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java

@@ -11,6 +11,7 @@ import com.fs.common.utils.PubFun;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.impl.CompanyDeptServiceImpl;
 import com.fs.course.param.FsUserCourseListUParam;
 import com.fs.course.service.IFsUserCourseStudyService;
@@ -23,6 +24,7 @@ import com.fs.framework.service.TokenService;
 import com.fs.his.service.IFsUserService;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwTag;
+import com.fs.qw.dto.CompanyTransferDTO;
 import com.fs.qw.param.*;
 import com.fs.qw.service.*;
 import com.fs.qw.vo.QwExternalContactVO;
@@ -38,6 +40,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
+import javax.validation.Valid;
 import java.io.IOException;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -78,6 +81,8 @@ public class QwExternalContactController extends BaseController
 
     @Autowired
     private CompanyDeptServiceImpl companyDeptService;
+    @Autowired
+    private IQwExternalContactTransferCompanyAuditService auditService;
 
     /**
      * 查询企业微信客户列表
@@ -224,7 +229,7 @@ public class QwExternalContactController extends BaseController
     /**
      * 导出企业微信客户列表
      */
-    @PreAuthorize("@ss.hasPermi('qw:externalContact:export')")
+    @PreAuthorize("@ss.hasAnyPermi('qw:externalContact:export,qw:externalContact:companyExport')")
     @Log(title = "企业微信客户", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
     public AjaxResult export(QwExternalContactParam qwExternalContact)
@@ -645,4 +650,45 @@ public class QwExternalContactController extends BaseController
         return util.exportExcel(qwUserDelLossLogVOS, "企微用户删除流失统计");
     }
 
+    /**
+     * 公司客户
+     */
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:companyExtList')")
+    @GetMapping("/companyExtList")
+    public TableDataInfo companyExtList(QwExternalContactParam qwExternalContact)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        qwExternalContact.setCompanyId(loginUser.getCompany().getCompanyId());
+
+        startPage();
+        List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVO(qwExternalContact);
+        list.forEach(item->{
+
+            if (!Objects.equals(item.getTagIds(), "[]") && item.getTagIds()!=null) {
+                QwTagSearchParam param = new QwTagSearchParam();
+                Gson gson = new Gson();
+                List<String> tagIds = gson.fromJson(
+                        item.getTagIds(),
+                        new TypeToken<List<String>>() {
+                        }.getType()
+                );
+
+                param.setTagIds(tagIds);
+
+                item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
+            }
+        });
+
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:companyTransfer')")
+    @PostMapping("/companyTransfer")
+    public R companyTransfer(@Valid @RequestBody CompanyTransferDTO param) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        CompanyUser user = loginUser.getUser();
+        auditService.addAudit(param, user.getCompanyId(), user.getUserName());
+        return R.ok();
+    }
+
 }

+ 9 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java

@@ -842,4 +842,13 @@ public class QwUserController extends BaseController
         return R.ok();
     }
 
+    @GetMapping("/companyQwUserlist")
+    public TableDataInfo companyQwUserlist(@RequestParam Long companyId,
+                                           @RequestParam String corpId,
+                                           @RequestParam(required = false) String nickName)
+    {
+        startPage();
+        List<QwUserVO> list = qwUserService.selectQwUserListByCompanyIdAndCorpIdAndNickName(companyId, corpId, nickName);
+        return getDataTable(list);
+    }
 }

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

@@ -198,4 +198,9 @@ public interface CompanyMapper
 
 
     List<CompanyUser> selectCompanyListByIds(@Param("userIds") String result);
+
+    /**
+     * 查询企微主体管理公司列表
+     */
+    List<OptionsVO> getCompanyListByCorpId(@Param("corpId") String corpId);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyService.java

@@ -159,4 +159,9 @@ public interface ICompanyService
      * @return
      */
     List<CompanyUser> selectCompanyListByIds(String result);
+
+    /**
+     * 查询企微主体管理公司列表
+     */
+    List<OptionsVO> getCompanyListByCorpId(String corpId);
 }

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

@@ -1333,4 +1333,12 @@ public class CompanyServiceImpl implements ICompanyService
     public List<CompanyUser> selectCompanyListByIds(String result) {
         return companyMapper.selectCompanyListByIds(result);
     }
+
+    /**
+     * 查询企微主体管理公司列表
+     */
+    @Override
+    public List<OptionsVO> getCompanyListByCorpId(String corpId) {
+        return companyMapper.getCompanyListByCorpId(corpId);
+    }
 }

+ 72 - 0
fs-service/src/main/java/com/fs/qw/domain/QwExternalContactTransferCompanyAudit.java

@@ -0,0 +1,72 @@
+package com.fs.qw.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("qw_external_contact_transfer_company_audit")
+public class QwExternalContactTransferCompanyAudit {
+
+    @ApiModelProperty("主键ID")
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("企微主体ID")
+    private Long qwCompanyId;
+
+    @ApiModelProperty("企微CorpID")
+    private String corpId;
+
+    @ApiModelProperty("企微主体名称")
+    private String corpName;
+
+    @ApiModelProperty("接替公司ID")
+    private Long companyId;
+
+    @ApiModelProperty("接替公司名称")
+    private String companyName;
+
+    @ApiModelProperty("接替公司销售ID")
+    private Long companyUserId;
+
+    @ApiModelProperty("接替公司销售名称")
+    private String companyUserName;
+
+    @ApiModelProperty("接替企微用户ID")
+    private Long qwUserId;
+
+    @ApiModelProperty("接替企微用户ID(企微)")
+    private String qwUserExtId;
+
+    @ApiModelProperty("接替企微用户名称")
+    private String qwUserName;
+
+    @ApiModelProperty("消息内容")
+    private String content;
+
+    @ApiModelProperty("状态 1待审核 2审核通过 3审核被拒")
+    private Integer status;
+
+    @ApiModelProperty("被拒原因")
+    private String reason;
+
+    @ApiModelProperty("备注")
+    private String remark;
+
+    @ApiModelProperty("审核时间")
+    private LocalDateTime auditTime;
+
+    @ApiModelProperty("审核人")
+    private String auditBy;
+
+    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("创建人")
+    private String createBy;
+}

+ 60 - 0
fs-service/src/main/java/com/fs/qw/domain/QwExternalContactTransferCompanyAuditUser.java

@@ -0,0 +1,60 @@
+package com.fs.qw.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("qw_external_contact_transfer_company_audit_user")
+public class QwExternalContactTransferCompanyAuditUser {
+
+    @ApiModelProperty("主键ID")
+    private Long id;
+
+    @ApiModelProperty("审核记录ID")
+    private Long auditId;
+
+    @ApiModelProperty("外部联系人ID")
+    private Long externalId;
+
+    @ApiModelProperty("客户ID(企微)")
+    private String externalUserId;
+
+    @ApiModelProperty("客户名称")
+    private String externalUserName;
+
+    @ApiModelProperty("原公司ID")
+    private Long companyId;
+
+    @ApiModelProperty("原公司名称")
+    private String companyName;
+
+    @ApiModelProperty("原公司销售ID")
+    private Long companyUserId;
+
+    @ApiModelProperty("原公司销售名称")
+    private String companyUserName;
+
+    @ApiModelProperty("原企微用户ID")
+    private Long qwUserId;
+
+    @ApiModelProperty("原企微用户ID(企微)")
+    private String qwUserExtId;
+
+    @ApiModelProperty("原企微用户名称")
+    private String qwUserName;
+
+    @ApiModelProperty("0-待处理 1-接替完毕 2-等待接替 3-客户拒绝 4-接替成员客户达到上限")
+    private Integer status;
+
+    @ApiModelProperty("备注")
+    private String remark;
+
+    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("接替时间")
+    private LocalDateTime replaceTime;
+}

+ 28 - 0
fs-service/src/main/java/com/fs/qw/dto/CompanyTransferDTO.java

@@ -0,0 +1,28 @@
+package com.fs.qw.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class CompanyTransferDTO {
+
+    @NotNull(message = "接替员工不能为空")
+    @ApiModelProperty("接替企微用户")
+    private Long qwUserId;
+
+    @ApiModelProperty("转移外部联系人")
+    private List<Long> ids;
+
+    @ApiModelProperty("消息内容")
+    private String content;
+
+    @ApiModelProperty("转移类型 0.转移ids外部联系人 1.转移qwUserName员工下外部联系人")
+    private Integer type = 0;
+
+    @ApiModelProperty("原员工企微ID")
+    private Long oldQwUserId;
+}

+ 14 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactTransferCompanyAuditMapper.java

@@ -0,0 +1,14 @@
+package com.fs.qw.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
+
+import java.util.List;
+
+public interface QwExternalContactTransferCompanyAuditMapper extends BaseMapper<QwExternalContactTransferCompanyAudit> {
+
+    /**
+     * 查询审核记录列表
+     */
+    List<QwExternalContactTransferCompanyAudit> selectQwExternalContactTransferCompanyAuditList(QwExternalContactTransferCompanyAudit param);
+}

+ 15 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactTransferCompanyAuditUserMapper.java

@@ -0,0 +1,15 @@
+package com.fs.qw.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface QwExternalContactTransferCompanyAuditUserMapper extends BaseMapper<QwExternalContactTransferCompanyAuditUser> {
+
+    /**
+     * 根据ID集合查询已提交的记录
+     */
+    List<QwExternalContactTransferCompanyAuditUser> getExistAuditByExtIds(@Param("ids") List<Long> ids);
+}

+ 5 - 1
fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java

@@ -12,7 +12,6 @@ import com.fs.qw.vo.*;
 import com.fs.qw.vo.sidebar.ExternalContactQwUserVO;
 import com.fs.sop.domain.QwSop;
 import com.fs.sop.dto.SopUserLogsParamDTO;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.ibatis.annotations.MapKey;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -433,4 +432,9 @@ public interface QwUserMapper extends BaseMapper<QwUser>
     void updateSendType(UpdateSendTypeVo vo);
 
     QwUser selectOfflineUser();
+
+    /**
+     * 根据销售公司和企微ID查询企微用户
+     */
+    List<QwUserVO> selectQwUserListVOByCompanyIdAndCorpIdAndNickName(@Param("companyId") Long companyId, @Param("corpId") String corpId, @Param("nickName") String nickName);
 }

+ 21 - 0
fs-service/src/main/java/com/fs/qw/service/IQwExternalContactTransferCompanyAuditService.java

@@ -0,0 +1,21 @@
+package com.fs.qw.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
+import com.fs.qw.dto.CompanyTransferDTO;
+
+import java.util.List;
+
+
+public interface IQwExternalContactTransferCompanyAuditService extends IService<QwExternalContactTransferCompanyAudit> {
+
+    /**
+     * 添加待审核记录
+     */
+    void addAudit(CompanyTransferDTO param, Long companyId, String userName);
+
+    /**
+     * 查询审核记录列表
+     */
+    List<QwExternalContactTransferCompanyAudit> selectQwExternalContactTransferCompanyAuditList(QwExternalContactTransferCompanyAudit param);
+}

+ 19 - 0
fs-service/src/main/java/com/fs/qw/service/IQwExternalContactTransferCompanyAuditUserService.java

@@ -0,0 +1,19 @@
+package com.fs.qw.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser;
+
+import java.util.List;
+
+public interface IQwExternalContactTransferCompanyAuditUserService extends IService<QwExternalContactTransferCompanyAuditUser> {
+
+    /**
+     * 根据ID集合查询已提交的记录
+     */
+    List<QwExternalContactTransferCompanyAuditUser> getExistAuditByExtIds(List<Long> ids);
+
+    /**
+     * 根据审核ID查询记录
+     */
+    List<QwExternalContactTransferCompanyAuditUser> getListByAuditId(Long auditId);
+}

+ 5 - 2
fs-service/src/main/java/com/fs/qw/service/IQwUserService.java

@@ -7,9 +7,7 @@ import com.fs.qw.dto.QwUserKeyDTO;
 import com.fs.qw.param.*;
 import com.fs.qw.vo.*;
 import com.fs.sop.domain.QwSop;
-import org.apache.commons.lang3.tuple.Pair;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -193,4 +191,9 @@ public interface IQwUserService
     void atMsg(QwUser qwUser, String s);
 
     void changeVideoStatus(Long id);
+
+    /**
+     * 根据销售公司和企微ID查询企微用户
+     */
+    List<QwUserVO> selectQwUserListByCompanyIdAndCorpIdAndNickName(Long companyId, String corpId, String nickName);
 }

+ 147 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactTransferCompanyAuditServiceImpl.java

@@ -0,0 +1,147 @@
+package com.fs.qw.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.exception.ServiceException;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyMapper;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.qw.domain.*;
+import com.fs.qw.dto.CompanyTransferDTO;
+import com.fs.qw.mapper.QwCompanyMapper;
+import com.fs.qw.mapper.QwExternalContactMapper;
+import com.fs.qw.mapper.QwExternalContactTransferCompanyAuditMapper;
+import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.param.QwExternalContactParam;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditService;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditUserService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@Service
+public class QwExternalContactTransferCompanyAuditServiceImpl extends ServiceImpl<QwExternalContactTransferCompanyAuditMapper, QwExternalContactTransferCompanyAudit>
+        implements IQwExternalContactTransferCompanyAuditService {
+
+    @Resource
+    private QwUserMapper qwUserMapper;
+    @Resource
+    private QwExternalContactMapper contactMapper;
+    @Resource
+    private QwCompanyMapper qwCompanyMapper;
+    @Resource
+    private CompanyMapper companyMapper;
+    @Resource
+    private CompanyUserMapper companyUserMapper;
+    @Resource
+    private IQwExternalContactTransferCompanyAuditUserService auditUserService;
+
+    /**
+     * 添加待审核记录
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void addAudit(CompanyTransferDTO param, Long companyId, String userName) {
+        QwUser qwUser = qwUserMapper.selectQwUserById(param.getQwUserId());
+
+        if (Objects.isNull(qwUser)) {
+            throw new ServiceException("接替员工不存在");
+        }
+
+//        if (qwUser.getCompanyId().equals(companyId)) {
+//            throw new ServiceException("接替员工不能为本公司员工");
+//        }
+
+        List<QwExternalContact> qwExternalContacts = new ArrayList<>();
+        // 为1转移员工下客户 其余转移转递的客户
+        if (param.getType() == 1) {
+            if (Objects.nonNull(param.getOldQwUserId())) {
+                QwExternalContact params = new QwExternalContact();
+                params.setCompanyId(companyId);
+                params.setQwUserId(param.getOldQwUserId());
+                qwExternalContacts = contactMapper.selectQwExternalContactList(params);
+            }
+        } else {
+            qwExternalContacts = contactMapper.selectQwExternalContactByIds(param.getIds());
+        }
+
+        boolean hasNotCurrentCompanyUser = qwExternalContacts.stream().anyMatch(c -> !c.getCompanyId().equals(companyId));
+        if (hasNotCurrentCompanyUser) {
+            throw new ServiceException("只能转移本公司下的客户");
+        }
+
+        if (qwExternalContacts.isEmpty()) {
+            throw new ServiceException("请选择需要分配的客户");
+        }
+
+        List<Long> extIds = qwExternalContacts.stream().map(QwExternalContact::getId).collect(Collectors.toList());
+        List<QwExternalContactTransferCompanyAuditUser> existAuditList = auditUserService.getExistAuditByExtIds(extIds);
+        if (!existAuditList.isEmpty()) {
+            String names = existAuditList.stream().map(QwExternalContactTransferCompanyAuditUser::getExternalUserName).collect(Collectors.joining());
+            throw new ServiceException("客户[" + names + "]已提交审核,请勿重复提交");
+        }
+
+        QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(qwUser.getCorpId());
+        Company company = companyMapper.selectCompanyById(qwUser.getCompanyId());
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(qwUser.getCompanyUserId());
+
+        QwExternalContactTransferCompanyAudit audit = new QwExternalContactTransferCompanyAudit();
+        audit.setQwCompanyId(qwCompany.getId());
+        audit.setCorpId(qwCompany.getCorpId());
+        audit.setCorpName(qwCompany.getCorpName());
+        audit.setCompanyId(company.getCompanyId());
+        audit.setCompanyName(company.getCompanyName());
+        audit.setCompanyUserId(companyUser.getUserId());
+        audit.setCompanyUserName(companyUser.getUserName());
+        audit.setQwUserId(qwUser.getId());
+        audit.setQwUserExtId(qwUser.getQwUserId());
+        audit.setQwUserName(qwUser.getQwUserName());
+        audit.setContent(param.getContent());
+        audit.setCreateTime(LocalDateTime.now());
+        audit.setCreateBy(userName);
+        baseMapper.insert(audit);
+
+        List<QwExternalContactTransferCompanyAuditUser> auditUserList = qwExternalContacts
+            .stream()
+            .map(c -> {
+
+                // 后面可优化为一起查询再取值
+                Company userCompany = companyMapper.selectCompanyById(c.getCompanyId());
+                CompanyUser userCompanyUser = companyUserMapper.selectCompanyUserById(c.getCompanyUserId());
+                QwUser userQwUser = qwUserMapper.selectQwUserById(c.getQwUserId());
+
+                QwExternalContactTransferCompanyAuditUser auditUser = new QwExternalContactTransferCompanyAuditUser();
+                auditUser.setAuditId(audit.getId());
+                auditUser.setExternalId(c.getId());
+                auditUser.setExternalUserId(c.getExternalUserId());
+                auditUser.setExternalUserName(c.getName());
+                auditUser.setCompanyId(userCompany.getCompanyId());
+                auditUser.setCompanyName(userCompany.getCompanyName());
+                auditUser.setCompanyUserId(userCompanyUser.getUserId());
+                auditUser.setCompanyUserName(userCompanyUser.getUserName());
+                auditUser.setQwUserId(userQwUser.getId());
+                auditUser.setQwUserExtId(userQwUser.getQwUserId());
+                auditUser.setQwUserName(userQwUser.getQwUserName());
+                auditUser.setCreateTime(LocalDateTime.now());
+
+                return auditUser;
+            }).collect(Collectors.toList());
+
+        auditUserService.saveBatch(auditUserList);
+    }
+
+    /**
+     * 查询审核记录列表
+     */
+    @Override
+    public List<QwExternalContactTransferCompanyAudit> selectQwExternalContactTransferCompanyAuditList(QwExternalContactTransferCompanyAudit param) {
+        return baseMapper.selectQwExternalContactTransferCompanyAuditList(param);
+    }
+}

+ 39 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactTransferCompanyAuditUserServiceImpl.java

@@ -0,0 +1,39 @@
+package com.fs.qw.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser;
+import com.fs.qw.mapper.QwExternalContactTransferCompanyAuditUserMapper;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditUserService;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Service
+public class QwExternalContactTransferCompanyAuditUserServiceImpl extends ServiceImpl<QwExternalContactTransferCompanyAuditUserMapper, QwExternalContactTransferCompanyAuditUser>
+        implements IQwExternalContactTransferCompanyAuditUserService {
+
+    /**
+     * 根据ID集合查询已提交的记录
+     */
+    @Override
+    public List<QwExternalContactTransferCompanyAuditUser> getExistAuditByExtIds(List<Long> ids) {
+        if (ids.isEmpty()) {
+            return new ArrayList<>();
+        }
+        return baseMapper.getExistAuditByExtIds(ids);
+    }
+
+    /**
+     * 根据审核ID查询记录
+     */
+    @Override
+    public List<QwExternalContactTransferCompanyAuditUser> getListByAuditId(Long auditId) {
+        Wrapper<QwExternalContactTransferCompanyAuditUser> queryWrapper = Wrappers.<QwExternalContactTransferCompanyAuditUser>lambdaQuery()
+                .eq(QwExternalContactTransferCompanyAuditUser::getAuditId, auditId);
+        return baseMapper.selectList(queryWrapper);
+    }
+}

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

@@ -51,7 +51,6 @@ import com.fs.wxwork.dto.*;
 import com.fs.wxwork.service.WxWorkService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -1538,6 +1537,14 @@ public class QwUserServiceImpl implements IQwUserService
         qwUserMapper.updateById(qwUser);
     }
 
+    /**
+     * 根据销售公司和企微ID查询企微用户
+     */
+    @Override
+    public List<QwUserVO> selectQwUserListByCompanyIdAndCorpIdAndNickName(Long companyId, String corpId, String nickName) {
+        return qwUserMapper.selectQwUserListVOByCompanyIdAndCorpIdAndNickName(companyId, corpId, nickName);
+    }
+
 
     /**
      * 构建查询条件

+ 46 - 0
fs-service/src/main/resources/db/20250928-企微客户公司转接.sql

@@ -0,0 +1,46 @@
+-- 企微客户转移审核记录表
+drop table if exists `qw_external_contact_transfer_company_audit`;
+create table `qw_external_contact_transfer_company_audit` (
+    `id`                    bigint not null auto_increment       comment '主键ID',
+    `qw_company_id`         bigint not null                      comment '企微主体ID',
+    `corp_id`               varchar(255) not null                comment '企微CorpID',
+    `corp_name`             varchar(255) not null                comment '企微主体名称',
+    `company_id`            bigint not null                      comment '接替公司ID',
+    `company_name`          varchar(255) not null                comment '接替公司名称',
+    `company_user_id`       bigint not null                      comment '接替公司销售ID',
+    `company_user_name`     varchar(255) not null                comment '接替公司销售名称',
+    `qw_user_id`            bigint not null                      comment '接替企微用户ID',
+    `qw_user_ext_id`        varchar(255) not null                comment '接替企微用户ID(企微)',
+    `qw_user_name`          varchar(255) not null                comment '接替企微用户名称',
+    `content`               varchar(255)                         comment '消息内容',
+    `status`                tinyint(1) default 1                 comment '状态 1待审核 2审核通过 3审核被拒',
+    `reason`                varchar(500)                         comment '被拒原因',
+    `remark`                varchar(500)                         comment '备注',
+    `audit_time`            datetime                             comment '审核时间',
+    `audit_by`              varchar(255)                         comment '审核人',
+    `create_time`           datetime                             comment '创建时间',
+    `create_by`             varchar(255)                         comment '创建人',
+    primary key (`id`) using btree
+) engine = Innodb comment '企微客户转移审核记录表';
+
+-- 企微客户转移审核用户表
+drop table if exists `qw_external_contact_transfer_company_audit_user`;
+create table `qw_external_contact_transfer_company_audit_user` (
+    `id`                    bigint not null auto_increment       comment '主键ID',
+    `audit_id`              bigint  not null                     comment '审核记录ID',
+    `external_id`           bigint  not null                     comment '外部联系人ID',
+    `external_user_id`      varchar(255) not null                comment '客户ID(企微)',
+    `external_user_name`    varchar(255) not null                comment '客户名称',
+    `company_id`            bigint not null                      comment '原公司ID',
+    `company_name`          varchar(255) not null                comment '原公司名称',
+    `company_user_id`       bigint not null                      comment '原公司销售ID',
+    `company_user_name`     varchar(255) not null                comment '原公司销售名称',
+    `qw_user_id`            bigint not null                      comment '原企微用户ID',
+    `qw_user_ext_id`        varchar(255) not null                comment '原企微用户ID(企微)',
+    `qw_user_name`          varchar(255) not null                comment '原企微用户名称',
+    `status`                tinyint(1) default 0                 comment '0-待处理 1-接替完毕 2-等待接替 3-客户拒绝 4-接替成员客户达到上限',
+    `remark`                varchar(500)                         comment '备注',
+    `create_time`           datetime                             comment '创建时间',
+    `replace_time`          datetime                             comment '接替时间',
+    primary key (`id`) using btree
+) engine = Innodb comment '企微客户转移审核用户表';

+ 7 - 0
fs-service/src/main/resources/mapper/company/CompanyMapper.xml

@@ -255,4 +255,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             and dept_id = #{deptId}
         </if>
     </select>
+
+    <select id="getCompanyListByCorpId" resultType="com.fs.his.vo.OptionsVO">
+        select c.company_id dictValue, c.company_name dictLabel
+        from company c
+        inner join qw_company qc on find_in_set(c.company_id, qc.company_ids)
+        where c.is_del= 0 and qc.corp_id = #{corpId}
+    </select>
 </mapper>

+ 26 - 0
fs-service/src/main/resources/mapper/qw/QwExternalContactTransferCompanyAuditMapper.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.qw.mapper.QwExternalContactTransferCompanyAuditMapper">
+
+    <select id="selectQwExternalContactTransferCompanyAuditList" resultType="com.fs.qw.domain.QwExternalContactTransferCompanyAudit">
+        select *
+        from qw_external_contact_transfer_company_audit
+        <where>
+            <if test="corpName != null and corpName != ''">
+                and corp_name like concat('%', #{corpName}, '%')
+            </if>
+            <if test="companyName != null and companyName != ''">
+                and company_name like concat('%', #{companyName}, '%')
+            </if>
+            <if test="companyUserName != null and companyUserName != ''">
+                and company_user_name like concat('%', #{companyUserName}, '%')
+            </if>
+            <if test="status != null">
+                and `status` = #{status}
+            </if>
+        </where>
+        order by create_time desc,id desc
+    </select>
+</mapper>

+ 17 - 0
fs-service/src/main/resources/mapper/qw/QwExternalContactTransferCompanyAuditUserMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.qw.mapper.QwExternalContactTransferCompanyAuditUserMapper">
+
+    <select id="getExistAuditByExtIds" resultType="com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser">
+        select
+            au.*
+        from qw_external_contact_transfer_company_audit_user au
+        inner join qw_external_contact_transfer_company_audit ca on au.audit_id = ca.id and ca.status = 1
+        where au.external_id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
+</mapper>

+ 17 - 0
fs-service/src/main/resources/mapper/qw/QwUserMapper.xml

@@ -269,4 +269,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </select>
 
+    <select id="selectQwUserListVOByCompanyIdAndCorpIdAndNickName" resultType="com.fs.qw.vo.QwUserVO">
+        select
+            qu.*,
+            cu.nick_name,
+            cu.user_name,
+            qd.dept_name as departmentName,
+            c.company_name
+        from qw_user qu
+        left join company_user cu on cu.user_id = qu.company_user_id
+        right join qw_dept qd on qu.department = qd.dept_id and qd.corp_id = qu.corp_id
+        left join company c on qu.company_id = c.company_id
+        where qu.company_id = #{companyId} and qu.corp_id = #{corpId}
+        <if test="nickName != null and nickName != ''">
+            and qu.qw_user_name like concat('%', #{nickName}, '%')
+        </if>
+    </select>
+
 </mapper>