Bladeren bron

商机模块

三七 1 week geleden
bovenliggende
commit
83c33bf72e
40 gewijzigde bestanden met toevoegingen van 3687 en 12 verwijderingen
  1. 1 1
      fs-admin/src/main/java/com/fs/crm/controller/CrmEventController.java
  2. 0 4
      fs-admin/src/main/java/com/fs/crm/controller/CrmExtLogController.java
  3. 128 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyUserShowController.java
  4. 24 0
      fs-company/src/main/java/com/fs/company/controller/crm/CrmCustomerVisitController.java
  5. 198 0
      fs-company/src/main/java/com/fs/crm/CrmBusinessController.java
  6. 100 0
      fs-company/src/main/java/com/fs/crm/CrmExtDetailController.java
  7. 68 0
      fs-company/src/main/java/com/fs/crm/CrmExtLogController.java
  8. 83 0
      fs-company/src/main/java/com/fs/crm/CrmFollowUpController.java
  9. 591 0
      fs-company/src/main/java/com/fs/crm/CrmSjCustomerController.java
  10. 110 0
      fs-service/src/main/java/com/fs/company/domain/CompanyUserShow.java
  11. 69 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyUserShowMapper.java
  12. 25 0
      fs-service/src/main/java/com/fs/company/param/CompanyUserShowEditParam.java
  13. 66 0
      fs-service/src/main/java/com/fs/company/service/ICompanyUserShowService.java
  14. 113 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserShowServiceImpl.java
  15. 3 0
      fs-service/src/main/java/com/fs/crm/domain/CrmCustomer.java
  16. 23 0
      fs-service/src/main/java/com/fs/crm/mapper/CrmCustomerMapper.java
  17. 2 0
      fs-service/src/main/java/com/fs/crm/param/CrmCompanyLineCustomerImportParam.java
  18. 16 0
      fs-service/src/main/java/com/fs/crm/param/CrmCustomerBatchReceiveParam.java
  19. 14 0
      fs-service/src/main/java/com/fs/crm/param/CrmCustomerBatchRecoverParam.java
  20. 4 1
      fs-service/src/main/java/com/fs/crm/param/CrmCustomerListQueryParam.java
  21. 19 0
      fs-service/src/main/java/com/fs/crm/param/CrmCustomerRecoverParam.java
  22. 18 0
      fs-service/src/main/java/com/fs/crm/param/CrmLineCustomerListQueryParam.java
  23. 12 0
      fs-service/src/main/java/com/fs/crm/param/CrmMyCustomerListQueryParam.java
  24. 94 0
      fs-service/src/main/java/com/fs/crm/param/CrmUnPoolListQueryParam.java
  25. 16 0
      fs-service/src/main/java/com/fs/crm/service/ICrmCustomerService.java
  26. 0 5
      fs-service/src/main/java/com/fs/crm/service/impl/CrmBusinessServiceImpl.java
  27. 495 0
      fs-service/src/main/java/com/fs/crm/service/impl/CrmCustomerServiceImpl.java
  28. 143 0
      fs-service/src/main/java/com/fs/crm/vo/CrmCustomerUnPoolListQueryVO.java
  29. 7 0
      fs-service/src/main/java/com/fs/crm/vo/CrmLineCustomerListQueryVO.java
  30. 7 0
      fs-service/src/main/java/com/fs/crm/vo/CrmMyCustomerListQueryVO.java
  31. 96 0
      fs-service/src/main/java/com/fs/system/domain/SysUserShow.java
  32. 79 0
      fs-service/src/main/java/com/fs/system/mapper/SysUserShowMapper.java
  33. 106 0
      fs-service/src/main/java/com/fs/system/param/SysUserExcelParam.java
  34. 22 0
      fs-service/src/main/java/com/fs/system/param/SysUserShowEditParam.java
  35. 72 0
      fs-service/src/main/java/com/fs/system/service/ISysUserShowService.java
  36. 119 0
      fs-service/src/main/java/com/fs/system/service/impl/SysUserShowServiceImpl.java
  37. 105 0
      fs-service/src/main/resources/mapper/company/CompanyUserShowMapper.xml
  38. 538 0
      fs-service/src/main/resources/mapper/crm/CrmCustomerMapper.xml
  39. 1 1
      fs-service/src/main/resources/mapper/crm/CrmCustomerVisitMapper.xml
  40. 100 0
      fs-service/src/main/resources/mapper/system/SysUserShowMapper.xml

+ 1 - 1
fs-admin/src/main/java/com/fs/crm/controller/CrmEventController.java

@@ -22,7 +22,7 @@ import com.fs.common.core.page.TableDataInfo;
 
 /**
  * 代办事项Controller
- * 
+ *
  * @author fs
  * @date 2022-12-21
  */

+ 0 - 4
fs-admin/src/main/java/com/fs/crm/controller/CrmExtLogController.java

@@ -7,11 +7,7 @@ import com.fs.crm.service.ICrmExtLogService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import com.fs.common.annotation.Log;

+ 128 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyUserShowController.java

@@ -0,0 +1,128 @@
+package com.fs.company.controller.company;
+
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.domain.CompanyUserShow;
+import com.fs.company.param.CompanyUserShowEditParam;
+import com.fs.company.service.ICompanyUserShowService;
+import com.fs.framework.security.LoginUser;
+import com.hc.openapi.tool.util.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import com.fs.framework.service.TokenService;
+/**
+ * 用户展示字段Controller
+ *
+ * @author fs
+ * @date 2025-02-11
+ */
+@RestController
+@RequestMapping("/company/show")
+public class CompanyUserShowController extends BaseController
+{
+    @Autowired
+    private ICompanyUserShowService companyUserShowService;
+    @Autowired
+    private TokenService tokenService;
+
+//    /**
+//     * 查询用户展示字段列表
+//     */
+//    @PreAuthorize("@ss.hasPermi('company:show:list')")
+//    @GetMapping("/list")
+//    public TableDataInfo list(CompanyUserShow companyUserShow)
+//    {
+//        startPage();
+//        List<CompanyUserShow> list = companyUserShowService.selectCompanyUserShowList(companyUserShow);
+//        return getDataTable(list);
+//    }
+//
+//    /**
+//     * 导出用户展示字段列表
+//     */
+//    @PreAuthorize("@ss.hasPermi('company:show:export')")
+//    @Log(title = "用户展示字段", businessType = BusinessType.EXPORT)
+//    @GetMapping("/export")
+//    public AjaxResult export(CompanyUserShow companyUserShow)
+//    {
+//        List<CompanyUserShow> list = companyUserShowService.selectCompanyUserShowList(companyUserShow);
+//        ExcelUtil<CompanyUserShow> util = new ExcelUtil<CompanyUserShow>(CompanyUserShow.class);
+//        return util.exportExcel(list, "show");
+//    }
+
+//    /**
+//     * 获取用户展示字段详细信息
+//     */
+//    @PreAuthorize("@ss.hasPermi('company:show:query')")
+//    @GetMapping(value = "/{id}")
+//    public AjaxResult getInfo(@PathVariable("id") Long id)
+//    {
+//        return AjaxResult.success(companyUserShowService.selectCompanyUserShowById(id));
+//    }
+
+    /**
+     * 获取用户展示字段详细信息
+     */
+//    @PreAuthorize("@ss.hasPermi('company:show:query')")
+    @GetMapping(value = "/{type}")
+    public AjaxResult getInfo(@PathVariable("type") String type)
+    {
+        if (StringUtils.isBlank(type)) {
+            return AjaxResult.error("缺少必要参数");
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        return AjaxResult.success(companyUserShowService.selectShowByCompanyIdUserId(
+                loginUser.getCompany().getCompanyId(),
+                loginUser.getUser().getUserId(),
+                type));
+    }
+    /**
+     * 新增用户展示字段
+     */
+//    @PreAuthorize("@ss.hasPermi('company:show:add')")
+    @Log(title = "用户展示字段", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyUserShow companyUserShow)
+    {
+        return toAjax(companyUserShowService.insertCompanyUserShow(companyUserShow));
+    }
+
+    /**
+     * 修改用户展示字段
+     */
+//    @PreAuthorize("@ss.hasPermi('company:show:edit')")
+    @Log(title = "用户展示字段", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyUserShowEditParam param)
+    {
+        if (StringUtils.isBlank(param.getType()) || param.getColumns().size()<1) {
+            return AjaxResult.error("缺少必要参数");
+        }
+        CompanyUser user = tokenService.getLoginUser(ServletUtils.getRequest()).getUser();
+        CompanyUserShow show = new CompanyUserShow();
+        show.setCompanyId(user.getCompanyId());
+        show.setUserId(user.getUserId());
+        show.setType(param.getType());
+        show.setColumns(param.getColumns().toString().replace("[", "").replace("]", "").replace(" ", ""));
+        show.setUpdateBy(user.getNickName());
+        return toAjax(companyUserShowService.updateByCompanyIdAndUserIdAndType(show));
+    }
+
+
+    /**
+     * 删除用户展示字段
+     */
+    @PreAuthorize("@ss.hasPermi('company:show:remove')")
+    @Log(title = "用户展示字段", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(companyUserShowService.deleteCompanyUserShowByIds(ids));
+    }
+}

+ 24 - 0
fs-company/src/main/java/com/fs/company/controller/crm/CrmCustomerVisitController.java

@@ -9,6 +9,7 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.crm.domain.CrmCustomerVisit;
 import com.fs.crm.param.CrmCustomerVisitAddParam;
 import com.fs.crm.param.CrmCustomerVisitListParam;
 import com.fs.crm.service.ICrmCustomerVisitService;
@@ -80,5 +81,28 @@ public class CrmCustomerVisitController extends BaseController
     }
 
 
+    /**
+     * 修改跟进
+     */
+    @PreAuthorize("@ss.hasPermi('crm:customerVisit:edit')")
+    @Log(title = "跟进", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CrmCustomerVisit crmCustomerVisit)
+    {
+        return toAjax(crmCustomerVisitService.updateCrmCustomerVisit(crmCustomerVisit));
+    }
+
+    /**
+     * 删除跟进
+     */
+    @PreAuthorize("@ss.hasPermi('crm:customerVisit:remove')")
+    @Log(title = "跟进", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{visitIds}")
+    public AjaxResult remove(@PathVariable Long[] visitIds)
+    {
+        return toAjax(crmCustomerVisitService.deleteCrmCustomerVisitByIds(visitIds));
+    }
+
+
 
 }

+ 198 - 0
fs-company/src/main/java/com/fs/crm/CrmBusinessController.java

@@ -0,0 +1,198 @@
+package com.fs.crm;
+
+
+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.crm.param.CrmBusinessAddAndUpdateParam;
+import com.fs.crm.param.CrmBusinessImportParam;
+import com.fs.crm.param.CrmBusinessQueryParam;
+import com.fs.crm.service.ICrmBusinessService;
+import com.fs.crm.vo.CrmBusinessListVO;
+import com.fs.framework.security.LoginUser;
+import com.hc.openapi.tool.util.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import com.fs.framework.service.TokenService;
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 商机Controller
+ *
+ * @author fs
+ * @date 2025-01-16
+ */
+@RestController
+@RequestMapping("/crm/business")
+public class CrmBusinessController extends BaseController
+{
+    @Autowired
+    private ICrmBusinessService crmBusinessService;
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 查询商机列表
+     */
+    @GetMapping("/list")
+    public TableDataInfo list(CrmBusinessQueryParam param, HttpServletRequest request)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getUser().getCompanyId());
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeArr(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getNextTimeRange())){
+            param.setNextTimeArr(param.getNextTimeRange().split("--"));
+        }
+        List<CrmBusinessListVO> list = crmBusinessService.selectCrmBusinessList(param);
+
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询我的商机列表
+     */
+    @GetMapping("/myList")
+    public TableDataInfo myList(CrmBusinessQueryParam param, HttpServletRequest request)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getUser().getCompanyId());
+        param.setCreateId(loginUser.getUser().getUserId());
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeArr(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getNextTimeRange())){
+            param.setNextTimeArr(param.getNextTimeRange().split("--"));
+        }
+        List<CrmBusinessListVO> list = crmBusinessService.selectCrmBusinessList(param);
+
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 导出商机列表
+     */
+    @PreAuthorize("@ss.hasPermi('crm:business:export')")
+    @Log(title = "商机", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CrmBusinessQueryParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getUser().getCompanyId());
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeArr(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getNextTimeRange())){
+            param.setNextTimeArr(param.getNextTimeRange().split("--"));
+        }
+        List<CrmBusinessListVO> list = crmBusinessService.selectCrmBusinessList(param);
+        ExcelUtil<CrmBusinessListVO> util = new ExcelUtil<CrmBusinessListVO>(CrmBusinessListVO.class);
+        return util.exportExcel(list, "商机");
+    }
+
+    /**
+     * 导出我的商机列表
+     */
+    @PreAuthorize("@ss.hasPermi('crm:business:export')")
+    @Log(title = "商机", businessType = BusinessType.EXPORT)
+    @GetMapping("/exportMy")
+    public AjaxResult exportMy(CrmBusinessQueryParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getUser().getCompanyId());
+        param.setCreateId(loginUser.getUser().getUserId());
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeArr(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getNextTimeRange())){
+            param.setNextTimeArr(param.getNextTimeRange().split("--"));
+        }
+        List<CrmBusinessListVO> list = crmBusinessService.selectCrmBusinessList(param);
+        ExcelUtil<CrmBusinessListVO> util = new ExcelUtil<CrmBusinessListVO>(CrmBusinessListVO.class);
+        return util.exportExcel(list, "商机");
+    }
+
+    /**
+     * 获取商机详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('crm:business:query')")
+    @GetMapping(value = "/{businessId}")
+    public AjaxResult getInfo(@PathVariable("businessId") Long businessId)
+    {
+        return AjaxResult.success(crmBusinessService.selectCrmBusinessById(businessId));
+    }
+
+    /**
+     * 新增商机
+     */
+    @PreAuthorize("@ss.hasPermi('crm:business:add')")
+    @Log(title = "商机", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CrmBusinessAddAndUpdateParam param)
+    {
+        //创建人
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCreateBy(loginUser.getUsername());
+        param.setCreateId(loginUser.getUser().getUserId());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setOpeName(loginUser.getUser().getUserName());
+        return toAjax(crmBusinessService.insertCrmBusiness(param));
+    }
+
+    /**
+     * 修改商机
+     */
+    @PreAuthorize("@ss.hasPermi('crm:business:edit')")
+    @Log(title = "商机", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CrmBusinessAddAndUpdateParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setUpdateId(loginUser.getUser().getUserId());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        return toAjax(crmBusinessService.updateCrmBusiness(param));
+    }
+
+    /**
+     * 删除商机
+     */
+    @PreAuthorize("@ss.hasPermi('crm:business:remove')")
+    @Log(title = "商机", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{businessIds}")
+    public AjaxResult remove(@PathVariable Long[] businessIds)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        return toAjax(crmBusinessService.deleteCrmBusinessByIds(businessIds,loginUser.getUser().getNickName()));
+    }
+
+    //下载模板
+    @GetMapping("/importTemplate")
+    public AjaxResult importTemplate()
+    {
+        ExcelUtil<CrmBusinessImportParam> util = new ExcelUtil<CrmBusinessImportParam>(CrmBusinessImportParam.class);
+        return util.importTemplateExcel("商机数据");
+    }
+
+    @Log(title = "导入商机", businessType = BusinessType.IMPORT)
+    @PreAuthorize("@ss.hasPermi('crm:business:import')")
+    @PostMapping("/importBusinessData")
+    public AjaxResult importBusinessData(MultipartFile file) throws Exception
+    {
+        ExcelUtil<CrmBusinessImportParam> util = new ExcelUtil<CrmBusinessImportParam>(CrmBusinessImportParam.class);
+        List<CrmBusinessImportParam> list = util.importExcel(file.getInputStream());
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String message = crmBusinessService.importBusinessData(list, loginUser.getUser());
+        return AjaxResult.success(message);
+    }
+}

+ 100 - 0
fs-company/src/main/java/com/fs/crm/CrmExtDetailController.java

@@ -0,0 +1,100 @@
+package com.fs.crm;
+
+
+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.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.crm.param.CrmExtDetailAddOrUpdateParam;
+import com.fs.crm.service.ICrmExtDetailService;
+import com.fs.crm.vo.CrmExtDetailVo;
+import com.fs.watch.param.BaseQueryParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import com.fs.framework.service.TokenService;
+
+import java.util.List;
+
+/**
+ * 字段扩展详情Controller
+ *
+ * @author fs
+ * @date 2025-02-17
+ */
+@RestController
+@RequestMapping("/crm/detail")
+public class CrmExtDetailController extends BaseController
+{
+    @Autowired
+    private ICrmExtDetailService crmExtDetailService;
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 查询字段扩展列
+     */
+//    @PreAuthorize("@ss.hasPermi('crm:detail:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BaseQueryParam param)
+    {
+        startPage();
+        List<CrmExtDetailVo> list = crmExtDetailService.getTableColumnsMetadata(param);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出字段扩展详情列表
+     */
+//    @PreAuthorize("@ss.hasPermi('crm:detail:export')")
+    @Log(title = "字段扩展详情", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(BaseQueryParam param)
+    {
+        List<CrmExtDetailVo> list = crmExtDetailService.getTableColumnsMetadata(param);
+        ExcelUtil<CrmExtDetailVo> util = new ExcelUtil<CrmExtDetailVo>(CrmExtDetailVo.class);
+        return util.exportExcel(list, "detail");
+    }
+
+
+
+    /**
+     * 新增字段扩展详情
+     */
+    @PreAuthorize("@ss.hasPermi('crm:detail:add')")
+    @Log(title = "字段扩展详情", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R add(@RequestBody CrmExtDetailAddOrUpdateParam param)
+    {
+        String nickName = tokenService.getLoginUser(ServletUtils.getRequest()).getUser().getNickName();
+        return crmExtDetailService.insertColumn(param,nickName);
+    }
+
+    /**
+     * 修改字段扩展详情
+     */
+    @PreAuthorize("@ss.hasPermi('crm:detail:edit')")
+    @Log(title = "字段扩展详情", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R edit(@RequestBody CrmExtDetailAddOrUpdateParam param)
+    {
+        String nickName = tokenService.getLoginUser(ServletUtils.getRequest()).getUser().getNickName();
+        return crmExtDetailService.updateColumn(param,nickName);
+    }
+
+    /**
+     * 删除字段扩展详情
+     */
+    @PreAuthorize("@ss.hasPermi('crm:detail:remove')")
+    @Log(title = "字段扩展详情", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{columnNames}")
+    public R remove(@PathVariable String[] columnNames)
+    {
+        String nickName = tokenService.getLoginUser(ServletUtils.getRequest()).getUser().getNickName();
+        return crmExtDetailService.deleteColumns(columnNames,nickName);
+    }
+}

+ 68 - 0
fs-company/src/main/java/com/fs/crm/CrmExtLogController.java

@@ -0,0 +1,68 @@
+package com.fs.crm;
+
+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.crm.domain.CrmExtLog;
+import com.fs.crm.service.ICrmExtLogService;
+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.List;
+
+/**
+ * 修改字段扩展日志Controller
+ *
+ * @author fs
+ * @date 2025-02-17
+ */
+@RestController
+@RequestMapping("/crm/log")
+public class CrmExtLogController extends BaseController
+{
+    @Autowired
+    private ICrmExtLogService crmExtLogService;
+
+    /**
+     * 查询修改字段扩展日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('crm:log:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CrmExtLog crmExtLog)
+    {
+        startPage();
+        List<CrmExtLog> list = crmExtLogService.selectCrmExtLogList(crmExtLog);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出修改字段扩展日志列表
+     */
+    @PreAuthorize("@ss.hasPermi('crm:log:export')")
+    @Log(title = "修改字段扩展日志", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CrmExtLog crmExtLog)
+    {
+        List<CrmExtLog> list = crmExtLogService.selectCrmExtLogList(crmExtLog);
+        ExcelUtil<CrmExtLog> util = new ExcelUtil<CrmExtLog>(CrmExtLog.class);
+        return util.exportExcel(list, "log");
+    }
+
+    /**
+     * 获取修改字段扩展日志详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('crm:log:query')")
+    @GetMapping(value = "/{logId}")
+    public AjaxResult getInfo(@PathVariable("logId") Long logId)
+    {
+        return AjaxResult.success(crmExtLogService.selectCrmExtLogById(logId));
+    }
+
+}

+ 83 - 0
fs-company/src/main/java/com/fs/crm/CrmFollowUpController.java

@@ -0,0 +1,83 @@
+package com.fs.crm;
+
+
+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.crm.domain.CrmFollowUp;
+import com.fs.crm.service.ICrmFollowUpService;
+import com.fs.crm.vo.CrmFollowUpVo;
+import com.fs.framework.security.LoginUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import com.fs.framework.service.TokenService;
+
+import java.util.List;
+
+/**
+ * 跟进提醒Controller
+ *
+ * @author fs
+ * @date 2025-04-15
+ */
+@RestController
+@RequestMapping("/crm/followUp")
+public class CrmFollowUpController extends BaseController
+{
+    @Autowired
+    private ICrmFollowUpService crmFollowUpService;
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 查询跟进提醒列表
+     */
+    @GetMapping("/list")
+    public TableDataInfo list(CrmFollowUp crmFollowUp)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if (loginUser == null) {
+            return null;
+        }
+        crmFollowUp.setCompanyUserId(loginUser.getUser().getUserId());
+        startPage();
+        List<CrmFollowUpVo> list = crmFollowUpService.selectCrmFollowUpAndCustomerList(crmFollowUp);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取跟进提醒详细信息
+     */
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(crmFollowUpService.selectCrmFollowUpById(id));
+    }
+
+
+    /**
+     * 修改跟进提醒
+     */
+    @Log(title = "跟进提醒", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CrmFollowUp crmFollowUp)
+    {
+        return toAjax(crmFollowUpService.updateCrmFollowUp(crmFollowUp));
+    }
+
+
+    /**
+     * 删除跟进提醒
+     */
+    @PreAuthorize("@ss.hasPermi('crm:followUp:remove')")
+    @Log(title = "跟进提醒", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(crmFollowUpService.deleteCrmFollowUpByIds(ids));
+    }
+}

+ 591 - 0
fs-company/src/main/java/com/fs/crm/CrmSjCustomerController.java

@@ -0,0 +1,591 @@
+package com.fs.crm;
+
+import com.baidu.dev2.thirdparty.swagger.annotations.ApiOperation;
+import com.fs.common.OrderUtils;
+import com.fs.common.annotation.DataScope;
+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.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.crm.domain.CrmCustomer;
+import com.fs.crm.param.*;
+import com.fs.crm.service.ICrmCustomerService;
+import com.fs.crm.service.ICrmCustomerUserService;
+import com.fs.crm.service.ICrmExtDetailService;
+import com.fs.crm.vo.CrmCustomerExportVO;
+import com.fs.crm.vo.CrmCustomerListQueryVO;
+import com.fs.crm.vo.CrmFullCustomerListQueryVO;
+import com.fs.framework.security.LoginUser;
+import com.github.pagehelper.PageHelper;
+import com.hc.openapi.tool.util.StringUtils;
+import io.swagger.annotations.ApiParam;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+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.HashMap;
+import java.util.List;
+import java.util.Map;
+import com.fs.framework.service.TokenService;
+import com.fs.common.annotation.Log;
+/**
+ * 客户Controller
+ *
+ * @author fs
+ * @date 2022-12-21
+ */
+@RestController
+@RequestMapping("/crm/sj/customer")
+public class CrmSjCustomerController extends BaseController
+{
+    @Autowired
+    private ICrmCustomerService crmCustomerService;
+    @Autowired
+    ICompanyUserService companyUserService;
+    @Autowired
+    private TokenService tokenService;
+    @Autowired
+    ICrmCustomerUserService crmCustomerUserService;
+
+    @Autowired
+    private ICrmExtDetailService crmExtDetailService;
+
+    @ApiOperation("获取线索客户")
+    @PreAuthorize("@ss.hasPermi('crm:customer:lineList')")
+    @GetMapping("/getLineCustomerList")
+    public TableDataInfo getLineCustomerList(CrmLineCustomerListQueryParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setIsLine(1);
+        param.setIsPool(0);
+        return crmCustomerService.selectCrmLineCustomerListQueryInfo(param);
+    }
+
+    @ApiOperation("获取可离职继承的线索客户")
+    @PreAuthorize("@ss.hasPermi('crm:customer:transferList')")
+    @GetMapping("/getTransferCustomerList")
+    public TableDataInfo getTransferCustomerList(CrmLineCustomerListQueryParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setIsPool(0);
+        return crmCustomerService.selectTransferCustomerList(param);
+    }
+
+    @ApiOperation("获取我的线索客户")
+    @PreAuthorize("@ss.hasPermi('crm:customer:clueList')")
+    @GetMapping("/getMyLineCustomerList")
+    public TableDataInfo getMyLineCustomerList(CrmLineCustomerListQueryParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setIsReceive(1L);
+        param.setReceiveUserId(loginUser.getUser().getUserId());
+        param.setIsLine(1);
+        param.setIsPool(0);
+//        List<Map<String,Object>> list =
+//        if (list != null) {
+//            for (Map<String,Object> vo : list) {
+//                if(vo.get("mobile")!=null){
+//                    vo.put("mobile",vo.get("mobile").toString().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+//                }
+//            }
+//        }
+        return crmCustomerService.selectCrmLineCustomerListQueryInfo(param);
+    }
+
+    @ApiOperation("获取公海客户")
+    @PreAuthorize("@ss.hasPermi('crm:customer:fullList')")
+    @GetMapping("/getFullCustomerList")
+    @DataScope(deptAlias = "c",userAlias = "c")
+    public TableDataInfo getFullCustomerList(CrmFullCustomerListQueryParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+//        if(loginUser.getCompany().getCompanyId()==116){   // 河北湘银信息咨询服务有限公司(JZ-1)客户假删除不显示
+//            param.setCompanyId(0L);
+//        }
+        List<CrmFullCustomerListQueryVO> list = crmCustomerService.selectCrmFullCustomerListQuery(param);
+//        if (list != null) {
+//            for (CrmFullCustomerListQueryVO vo : list) {
+//                if(vo.getMobile()!=null){
+//                    vo.setMobile(vo.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+//                }
+//
+//            }
+//        }
+        return getDataTable(list);
+    }
+
+    @ApiOperation("获取我的客户列表")
+    @PreAuthorize("@ss.hasPermi('crm:customer:myList')")
+    @GetMapping("/getMyCustomerList")
+    public TableDataInfo getMyCustomerList(CrmMyCustomerListQueryParam param){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCustomerCreateTime(param.getCreateTimeRange().split("--"));
+        }
+        param.setIsLine(0);
+
+        return crmCustomerService.selectCrmMyCustomerListQueryInfo(param);
+
+    }
+
+    @ApiOperation("获取客户列表")
+    @GetMapping("/getCustomerList")
+    public TableDataInfo getCustomerList(CrmCustomerListQueryParam param){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setIsLine(0);
+        param.setIsPool(0);
+        if (param.getIsReceive() != null && param.getIsReceive() == 0){
+            CrmLineCustomerListQueryParam param1 = new CrmLineCustomerListQueryParam();
+            BeanUtils.copyProperties(param,param1);
+            return crmCustomerService.selectCrmLineCustomerListQueryInfo(param1);
+
+        }else {
+            List<CrmCustomerListQueryVO> list = crmCustomerService.selectCrmCustomerListQuery(param);
+            return getDataTable(list);
+        }
+    }
+
+
+    @ApiOperation("获取未入公海列表")
+    @PostMapping("/getMyUnPoolList")
+    public TableDataInfo getMyUnPoolList(@RequestBody CrmUnPoolListQueryParam param){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setReceiveUserId(loginUser.getUser().getUserId());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        return crmCustomerService.selectUnPoolCrmCustomerList(param);
+    }
+
+    @ApiOperation("获取所有未入公海列表")
+    @PostMapping("/getAllUnPoolList")
+    public TableDataInfo getAllUnPoolList(@RequestBody CrmUnPoolListQueryParam param){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        return crmCustomerService.selectUnPoolCrmCustomerList(param);
+    }
+
+
+
+    @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;
+        }
+        //查询扩展字段
+        HashMap<String, Object> map = new HashMap<>();
+        map.put("correlate_id",customerId);
+        map.put("correlate_type","customer_id");
+        Map<String,Object> ext=crmExtDetailService.selectCrmExtDetailByCondition(map);
+        return R.ok().put("customer",customer).put("isReceive",isReceive).put("ext",ext);
+
+    }
+
+    @ApiOperation("获取客户详情")
+    @GetMapping("/getCustomerDetails1")
+    @PreAuthorize("@ss.hasPermi('crm:customer:query1')")
+    public R getCustomerDetails1(
+            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);
+
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customer:query2')")
+    @GetMapping(value = "/query1/{customerId}")
+    public R getInfo1(@PathVariable("customerId") Long customerId)
+    {
+        CrmCustomer customer=crmCustomerService.selectCrmCustomerById(customerId);
+        String mobile = customer.getMobile();
+        return R.ok().put("mobile",mobile);
+    }
+
+    //分配
+    @PreAuthorize("@ss.hasPermi('crm:customer:assignToUser')")
+    @PostMapping("/assignToUser")
+    public R assignToUser(@RequestBody CrmCustomeAssignParam param)
+    {
+        if(param.getCustomerIds().size()>1000){
+            return R.error("分配数据超出范围,最大1000条");
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        return crmCustomerService.assignToUser(loginUser.getUsername(),loginUser.getUser().getUserId(),param);
+    }
+
+
+    @PreAuthorize("@ss.hasPermi('crm:customer:add')")
+    @Log(title = "创建客户", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    public AjaxResult add(@Validated @RequestBody CrmCustomerUpdateOrAddParam crmCustomer)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        crmCustomer.setCustomerCode(OrderUtils.getOrderNo());
+        crmCustomer.setIsDel(0);
+        crmCustomer.setIsLine(1);
+        crmCustomer.setCompanyId(loginUser.getCompany().getCompanyId());
+        crmCustomer.setCreateUserId(loginUser.getUser().getUserId());
+        crmCustomer.setDeptId(loginUser.getUser().getDeptId());
+        //是否是公司负责人新建待分配线索
+//        Integer status = crmCustomer.getStatus();
+//        if (status == 1) {
+//            crmCustomer.set
+//        }
+        crmCustomer.setOpeName(loginUser.getUser().getNickName());
+        return crmCustomerService.insertCrmCustomer(crmCustomer)>0?AjaxResult.success():AjaxResult.error("电话/客户名称已存在");
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customer:addMyCustomer')")
+    @ApiOperation("添加我的线索")
+    @PostMapping("/addMyClue")
+    public R addMyClue(@RequestBody CrmCustomerUpdateOrAddParam crmCustomer)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        crmCustomer.setCustomerCode(OrderUtils.getOrderNo());
+//        crmCustomer.setIsLine(1);
+//        crmCustomer.setIsPool(0);
+//        crmCustomer.setStatus(1);
+//        crmCustomer.setIsReceive(1);
+        crmCustomer.setDeptId(loginUser.getUser().getDeptId());
+        crmCustomer.setCreateUserId(loginUser.getUser().getUserId());
+        crmCustomer.setCompanyId(loginUser.getCompany().getCompanyId());
+        crmCustomer.setOpeName(loginUser.getUser().getNickName());
+        if(crmCustomerService.insertCrmCustomer(crmCustomer)>0){
+            CompanyUser companyUser=loginUser.getUser();
+            CrmCustomeReceiveParam param=new CrmCustomeReceiveParam();
+            String operName = companyUser.getNickName();
+            param.setCompanyId(companyUser.getCompanyId());
+            param.setCompanyUserId(companyUser.getUserId());
+            param.setCustomerId(crmCustomer.getCustomerId());
+            crmCustomerService.receive(param,operName);
+            return R.ok();
+        } else{
+            return R.error("该公司客户已存在,请勿重复添加");
+        }
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customer:addMyCustomer')")
+    @ApiOperation("添加我的客户")
+    @PostMapping("/addMyCustomer")
+    public R addMyCustomer(@RequestBody CrmCustomerUpdateOrAddParam crmCustomer)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        crmCustomer.setCustomerCode(OrderUtils.getOrderNo());
+        crmCustomer.setIsLine(0);
+        crmCustomer.setIsDel(0);
+        crmCustomer.setIsReceive(0);
+        crmCustomer.setStatus(1);
+        crmCustomer.setDeptId(loginUser.getUser().getDeptId());
+        crmCustomer.setCreateUserId(loginUser.getUser().getUserId());
+        crmCustomer.setCompanyId(loginUser.getCompany().getCompanyId());
+        crmCustomer.setOpeName(loginUser.getUser().getNickName());
+        if(crmCustomerService.insertCrmCustomer(crmCustomer)>0){
+            CompanyUser companyUser=loginUser.getUser();
+            CrmCustomeReceiveParam param=new CrmCustomeReceiveParam();
+            String operName = companyUser.getNickName();
+            param.setCompanyId(companyUser.getCompanyId());
+            param.setCompanyUserId(companyUser.getUserId());
+            param.setCustomerId(crmCustomer.getCustomerId());
+            crmCustomerService.receive(param,operName);
+            return R.ok();
+        }
+        else{
+            return R.error();
+        }
+    }
+
+    /**
+     * 修改客户
+     */
+//    @PreAuthorize("@ss.hasPermi('crm:customer:edit')")
+    @Log(title = "客户", businessType = BusinessType.UPDATE)
+    @PutMapping("/edit")
+    public AjaxResult edit(@RequestBody CrmCustomerUpdateOrAddParam crmCustomer) {
+        return crmCustomerService.updateCrmCustomer(crmCustomer)>0?AjaxResult.success():AjaxResult.error("修改电话或用户名已存在");
+    }
+
+
+    //认领
+    @PreAuthorize("@ss.hasPermi('crm:customer:receive')")
+    @PostMapping("/receive")
+    public R receive(@RequestBody CrmCustomeReceiveParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String operName = loginUser.getUsername();
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
+        param.setDeptId(loginUser.getUser().getDeptId());
+        return crmCustomerService.receive(param,operName);
+    }
+
+    /**
+     * 批量认领
+     * @param param
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('crm:customer:receive')")
+    @PostMapping("/batchReceive")
+    public R receive(@RequestBody CrmCustomerBatchReceiveParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String operName = loginUser.getUsername();
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
+        param.setDeptId(loginUser.getUser().getDeptId());
+        return crmCustomerService.batchReceive(param,operName);
+    }
+
+    //回收
+    @PreAuthorize("@ss.hasPermi('crm:customer:recover')")
+    @PostMapping("/recover")
+    public R recover(@RequestBody CrmCustomerRecoverParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String operName = loginUser.getUsername();
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
+        return crmCustomerService.recoverR(param,operName);
+    }
+
+    /**
+     * 未分配线索投入公海池
+     * @param param
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('crm:customer:recover')")
+    @PostMapping("/recoverBatch")
+    public R recoverBatch(@RequestBody CrmLineCustomerListQueryParam param)
+    {
+
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setIsLine(1);
+        param.setIsPool(0);
+        return crmCustomerService.recoverClueBatch(param);
+    }
+
+    /**
+     * 未分配线索投入公海池
+     * @param customerIds
+     * @return  dd
+     */
+    @PreAuthorize("@ss.hasPermi('crm:customer:recover')")
+    @PostMapping("/recoverBatchByIds")
+    public R recoverBatchByIds(@RequestBody Long[] customerIds)
+    {
+        if (customerIds == null || customerIds.length<1) {
+            return R.error("请选择需要投入公海的待分配线索");
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if (loginUser == null) {
+            return R.error("请先登录再进行操作");
+        }
+        return crmCustomerService.recoverBatchByIds(customerIds,loginUser.getCompany().getCompanyId(),loginUser.getUser().getNickName(),loginUser.getUser().getUserId());
+    }
+
+
+    /**
+     * 客户投入公海池
+     * @param param
+     * @return  dd
+     */
+    @PreAuthorize("@ss.hasPermi('crm:customer:recover')")
+    @PostMapping("/recoverCustomerBatchByIds")
+    public R recoverCustomerBatchByIds(@RequestBody CrmCustomerBatchRecoverParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
+        return crmCustomerService.recoverCustomerBatchByIds(param,loginUser.getUsername());
+    }
+
+
+
+
+    //分配
+    @PreAuthorize("@ss.hasPermi('crm:customer:assignUser')")
+    @PostMapping("/assignUser")
+    public R assignUser(@RequestBody CrmCustomeAssignUserParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String operName = loginUser.getUsername();
+        param.setDeptId(loginUser.getUser().getDeptId());
+        return crmCustomerService.assignUser(param,operName);
+    }
+
+    /**
+     *
+     * @param file
+     * @param type 导入类型 0:待分配员工 1:我的
+     * @return
+     * @throws Exception
+     */
+    @PreAuthorize("@ss.hasPermi('crm:customer:importLine')")
+    @PostMapping("/importLineData")
+    public AjaxResult importLineData(MultipartFile file, Integer type) throws Exception
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        ExcelUtil<CrmCompanyLineCustomerImportParam> util = new ExcelUtil<CrmCompanyLineCustomerImportParam>(CrmCompanyLineCustomerImportParam.class);
+        List<CrmCompanyLineCustomerImportParam> list = util.importExcel(file.getInputStream());
+        if(list.size()>12000){
+            return new AjaxResult(500,"导入数据超出范围,最大12000条");
+        }
+        String operName = loginUser.getUsername();
+        String message = crmCustomerService.importCompanyLineCustomerType(list, operName,loginUser.getCompany().getCompanyId(),loginUser.getUser().getUserId(),type);
+        return AjaxResult.success(message);
+    }
+
+    //下载模板
+    @GetMapping("/importLineTemplate")
+    public AjaxResult importLineTemplate()
+    {
+        ExcelUtil<CrmCompanyLineCustomerImportParam> util = new ExcelUtil<CrmCompanyLineCustomerImportParam>(CrmCompanyLineCustomerImportParam.class);
+        return util.importTemplateExcel("线索客户数据");
+    }
+
+    @Log(title = "导入", businessType = BusinessType.IMPORT)
+    @PreAuthorize("@ss.hasPermi('crm:customer:importVisit')")
+    @PostMapping("/importVisitData")
+    public AjaxResult importVisitData(MultipartFile file) throws Exception
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        ExcelUtil<CrmCustomerVisitImportParam> util = new ExcelUtil<CrmCustomerVisitImportParam>(CrmCustomerVisitImportParam.class);
+        List<CrmCustomerVisitImportParam> list = util.importExcel(file.getInputStream());
+        String message = crmCustomerService.importVisitCustomer(list,loginUser.getCompany().getCompanyId());
+        return AjaxResult.success(message);
+    }
+    //下载模板
+    @GetMapping("/importVisitTemplate")
+    public AjaxResult importVisitTemplate()
+    {
+        ExcelUtil<CrmCustomerVisitImportParam> util = new ExcelUtil<CrmCustomerVisitImportParam>(CrmCustomerVisitImportParam.class);
+        return util.importTemplateExcel("客户跟进");
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customer:export')")
+    @Log(title = "客户", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CrmCustomerListQueryParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        if (param.getImportType() != null && param.getImportType() == 1){
+            param.setCompanyUserId(loginUser.getCompany().getUserId());
+        }
+        List<CrmCustomerExportVO> list = crmCustomerService.selectCrmCustomerExportListQuery(param);
+        for(CrmCustomerExportVO customer:list){
+            if(StringUtils.isNotEmpty(customer.getMobile())){
+                if(loginUser.getUser().getUserType().equals("00")){
+                }
+                else{
+                    customer.setMobile(customer.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                }
+
+            }
+        }
+        ExcelUtil<CrmCustomerExportVO> util = new ExcelUtil<CrmCustomerExportVO>(CrmCustomerExportVO.class);
+        return util.exportExcel(list, "客户");
+    }
+
+
+
+    @PreAuthorize("@ss.hasPermi('crm:customer:export')")
+    @Log(title = "导出公海", businessType = BusinessType.EXPORT)
+    @GetMapping("/exportFull")
+    public AjaxResult export(CrmFullCustomerListQueryParam param)
+    {
+        List<CrmFullCustomerListQueryVO> list = crmCustomerService.selectCrmFullCustomerListQuery(param);
+        ExcelUtil<CrmFullCustomerListQueryVO> util = new ExcelUtil<CrmFullCustomerListQueryVO>(CrmFullCustomerListQueryVO.class);
+        return util.exportExcel(list, "公海客户");
+    }
+
+    @Log(title = "客户", businessType = BusinessType.EXPORT)
+    @PostMapping("/{customerIds}")
+    public AjaxResult exportByIds(@PathVariable Long[] customerIds)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        List<CrmCustomerExportVO> list = crmCustomerService.selectCrmCustomerExportListByIds(customerIds);
+        for(CrmCustomerExportVO customer:list){
+            if(StringUtils.isNotEmpty(customer.getMobile())){
+                if(loginUser.getUser().getUserType().equals("00")){
+                }
+                else{
+                    customer.setMobile(customer.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                }
+
+            }
+        }
+        ExcelUtil<CrmCustomerExportVO> util = new ExcelUtil<CrmCustomerExportVO>(CrmCustomerExportVO.class);
+        return util.exportExcel(list, "客户");
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customer:editSource')")
+    @PostMapping("/updateCustomerSource")
+    public AjaxResult updateCustomerSource(@RequestBody CrmCustomerEditSourceParam param)
+    {
+
+        return toAjax(crmCustomerService.updateCrmCustomerSource(param));
+    }
+
+
+    @GetMapping("/getCustomerListByIds")
+    public R getCustomerListByIds(@RequestParam("customerIds")String customerIds)
+    {
+        List<CrmCustomer> customerList=crmCustomerService.selectCrmCustomerListByIds(customerIds);
+        return R.ok().put("data",customerList);
+    }
+
+
+    @ApiOperation("查询客户")
+    @GetMapping("/getCustomerListBySearch")
+    public R getCustomerListBySearch(CrmCustomerSearchParam param){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<CrmCustomer> list = crmCustomerService.selectCrmCustomerListBySearch(param);
+        return R.ok().put("data",list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('crm:customer:removeLine')")
+    @Log(title = "客户", businessType = BusinessType.DELETE)
+    @PostMapping("/removeLine")
+    public AjaxResult removeLine(@RequestBody Long[] customerIds)
+    {
+        return toAjax(crmCustomerService.deleteCrmCustomerByIds(customerIds));
+    }
+
+
+}

+ 110 - 0
fs-service/src/main/java/com/fs/company/domain/CompanyUserShow.java

@@ -0,0 +1,110 @@
+package com.fs.company.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 用户展示字段对象 company_user_show
+ *
+ * @author fs
+ * @date 2025-02-11
+ */
+public class CompanyUserShow extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** Id */
+    private Long id;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 列表类型 */
+    @Excel(name = "列表类型")
+    private String type;
+
+    /** 列表字段 */
+    @Excel(name = "列表字段")
+    private String columns;
+
+    /** 是否删除 0:否 1:是 */
+    @Excel(name = "是否删除 0:否 1:是")
+    private Long isDel;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setCompanyId(Long companyId)
+    {
+        this.companyId = companyId;
+    }
+
+    public Long getCompanyId()
+    {
+        return companyId;
+    }
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+    public void setType(String type)
+    {
+        this.type = type;
+    }
+
+    public String getType()
+    {
+        return type;
+    }
+    public void setColumns(String columns)
+    {
+        this.columns = columns;
+    }
+
+    public String getColumns()
+    {
+        return columns;
+    }
+    public void setIsDel(Long isDel)
+    {
+        this.isDel = isDel;
+    }
+
+    public Long getIsDel()
+    {
+        return isDel;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("companyId", getCompanyId())
+            .append("userId", getUserId())
+            .append("type", getType())
+            .append("columns", getColumns())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("isDel", getIsDel())
+            .toString();
+    }
+}

+ 69 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyUserShowMapper.java

@@ -0,0 +1,69 @@
+package com.fs.company.mapper;
+
+import com.fs.company.domain.CompanyUserShow;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 用户展示字段Mapper接口
+ *
+ * @author fs
+ * @date 2025-02-11
+ */
+public interface CompanyUserShowMapper
+{
+    /**
+     * 查询用户展示字段
+     *
+     * @param id 用户展示字段ID
+     * @return 用户展示字段
+     */
+    public CompanyUserShow selectCompanyUserShowById(Long id);
+
+    /**
+     * 查询用户展示字段列表
+     *
+     * @param companyUserShow 用户展示字段
+     * @return 用户展示字段集合
+     */
+    public List<CompanyUserShow> selectCompanyUserShowList(CompanyUserShow companyUserShow);
+
+    /**
+     * 新增用户展示字段
+     *
+     * @param companyUserShow 用户展示字段
+     * @return 结果
+     */
+    public int insertCompanyUserShow(CompanyUserShow companyUserShow);
+
+    /**
+     * 修改用户展示字段
+     *
+     * @param companyUserShow 用户展示字段
+     * @return 结果
+     */
+    public int updateCompanyUserShow(CompanyUserShow companyUserShow);
+
+    /**
+     * 删除用户展示字段
+     *
+     * @param id 用户展示字段ID
+     * @return 结果
+     */
+    public int deleteCompanyUserShowById(Long id);
+
+    /**
+     * 批量删除用户展示字段
+     *
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteCompanyUserShowByIds(Long[] ids);
+
+    CompanyUserShow selectShowByCompanyIdUserId(@Param("companyId") Long companyId,
+                                                @Param("userId") Long userId,
+                                                @Param("type") String type);
+
+    int updateByCompanyIdAndUserIdAndType(CompanyUserShow show);
+}

+ 25 - 0
fs-service/src/main/java/com/fs/company/param/CompanyUserShowEditParam.java

@@ -0,0 +1,25 @@
+package com.fs.company.param;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class CompanyUserShowEditParam {
+    /** Id */
+    private Long id;
+
+    /** companyId */
+    private Long companyId;
+
+    /** 用户id */
+    private Long userId;
+
+    /** 列表类型 */
+    private String type;
+
+    /** 列表字段 */
+    @Excel(name = "列表字段")
+    private List<String> columns;
+}

+ 66 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyUserShowService.java

@@ -0,0 +1,66 @@
+package com.fs.company.service;
+
+import com.fs.company.domain.CompanyUserShow;
+
+import java.util.List;
+
+/**
+ * 用户展示字段Service接口
+ *
+ * @author fs
+ * @date 2025-02-11
+ */
+public interface ICompanyUserShowService
+{
+    /**
+     * 查询用户展示字段
+     *
+     * @param id 用户展示字段ID
+     * @return 用户展示字段
+     */
+    public CompanyUserShow selectCompanyUserShowById(Long id);
+
+    /**
+     * 查询用户展示字段列表
+     *
+     * @param companyUserShow 用户展示字段
+     * @return 用户展示字段集合
+     */
+    public List<CompanyUserShow> selectCompanyUserShowList(CompanyUserShow companyUserShow);
+
+    /**
+     * 新增用户展示字段
+     *
+     * @param companyUserShow 用户展示字段
+     * @return 结果
+     */
+    public int insertCompanyUserShow(CompanyUserShow companyUserShow);
+
+    /**
+     * 修改用户展示字段
+     *
+     * @param companyUserShow 用户展示字段
+     * @return 结果
+     */
+    public int updateCompanyUserShow(CompanyUserShow companyUserShow);
+
+    /**
+     * 批量删除用户展示字段
+     *
+     * @param ids 需要删除的用户展示字段ID
+     * @return 结果
+     */
+    public int deleteCompanyUserShowByIds(Long[] ids);
+
+    /**
+     * 删除用户展示字段信息
+     *
+     * @param id 用户展示字段ID
+     * @return 结果
+     */
+    public int deleteCompanyUserShowById(Long id);
+
+    CompanyUserShow selectShowByCompanyIdUserId(Long companyId, Long userId, String type);
+
+    int updateByCompanyIdAndUserIdAndType(CompanyUserShow show);
+}

+ 113 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserShowServiceImpl.java

@@ -0,0 +1,113 @@
+package com.fs.company.service.impl;
+
+import com.fs.common.utils.DateUtils;
+import com.fs.company.domain.CompanyUserShow;
+import com.fs.company.mapper.CompanyUserShowMapper;
+import com.fs.company.service.ICompanyUserShowService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 用户展示字段Service业务层处理
+ *
+ * @author fs
+ * @date 2025-02-11
+ */
+@Service
+public class CompanyUserShowServiceImpl implements ICompanyUserShowService
+{
+    @Autowired
+    private CompanyUserShowMapper companyUserShowMapper;
+
+    /**
+     * 查询用户展示字段
+     *
+     * @param id 用户展示字段ID
+     * @return 用户展示字段
+     */
+    @Override
+    public CompanyUserShow selectCompanyUserShowById(Long id)
+    {
+        return companyUserShowMapper.selectCompanyUserShowById(id);
+    }
+
+    /**
+     * 查询用户展示字段列表
+     *
+     * @param companyUserShow 用户展示字段
+     * @return 用户展示字段
+     */
+    @Override
+    public List<CompanyUserShow> selectCompanyUserShowList(CompanyUserShow companyUserShow)
+    {
+        return companyUserShowMapper.selectCompanyUserShowList(companyUserShow);
+    }
+
+    /**
+     * 新增用户展示字段
+     *
+     * @param companyUserShow 用户展示字段
+     * @return 结果
+     */
+    @Override
+    public int insertCompanyUserShow(CompanyUserShow companyUserShow)
+    {
+        companyUserShow.setCreateTime(DateUtils.getNowDate());
+        return companyUserShowMapper.insertCompanyUserShow(companyUserShow);
+    }
+
+    /**
+     * 修改用户展示字段
+     *
+     * @param companyUserShow 用户展示字段
+     * @return 结果
+     */
+    @Override
+    public int updateCompanyUserShow(CompanyUserShow companyUserShow)
+    {
+        companyUserShow.setUpdateTime(DateUtils.getNowDate());
+        return companyUserShowMapper.updateCompanyUserShow(companyUserShow);
+    }
+
+    /**
+     * 批量删除用户展示字段
+     *
+     * @param ids 需要删除的用户展示字段ID
+     * @return 结果
+     */
+    @Override
+    public int deleteCompanyUserShowByIds(Long[] ids)
+    {
+        return companyUserShowMapper.deleteCompanyUserShowByIds(ids);
+    }
+
+    /**
+     * 删除用户展示字段信息
+     *
+     * @param id 用户展示字段ID
+     * @return 结果
+     */
+    @Override
+    public int deleteCompanyUserShowById(Long id)
+    {
+        return companyUserShowMapper.deleteCompanyUserShowById(id);
+    }
+
+    @Override
+    public CompanyUserShow selectShowByCompanyIdUserId(Long companyId, Long userId, String type) {
+        return companyUserShowMapper.selectShowByCompanyIdUserId(companyId,userId,type);
+    }
+
+    @Override
+    public int updateByCompanyIdAndUserIdAndType(CompanyUserShow show) {
+        show.setUpdateTime(DateUtils.getNowDate());
+        int i = companyUserShowMapper.updateByCompanyIdAndUserIdAndType(show);
+        if (i<1){
+            //如果不存在则新增
+            i = insertCompanyUserShow(show);
+        }
+        return i;
+    }
+}

+ 3 - 0
fs-service/src/main/java/com/fs/crm/domain/CrmCustomer.java

@@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 import javax.validation.constraints.NotBlank;
 import java.math.BigDecimal;
@@ -17,6 +18,7 @@ import java.util.Date;
  * @author fs
  * @date 2022-12-21
  */
+@EqualsAndHashCode(callSuper = true)
 @Data
 public class CrmCustomer extends BaseEntity
 {
@@ -202,6 +204,7 @@ public class CrmCustomer extends BaseEntity
     private String businessScenario;
 
     private String product;
+    private String content;
 
     private String moneyRemark;
     @JsonFormat(pattern = "yyyy-MM-dd")

+ 23 - 0
fs-service/src/main/java/com/fs/crm/mapper/CrmCustomerMapper.java

@@ -12,6 +12,7 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 
@@ -344,6 +345,7 @@ public interface CrmCustomerMapper extends BaseMapper<CrmCustomer> {
             " order by cu.customer_user_id desc "+
             "</script>"})
     List<CrmMyCustomerListQueryVO> selectCrmMyCustomerListQuery(@Param("maps") CrmMyCustomerListQueryParam param);
+    List<CrmMyCustomerListQueryVO> selectCrmMyCustomerListQueryInfo(@Param("maps") CrmMyCustomerListQueryParam param);
     @Select({"<script> " +
             "select c.*,u.nick_name as company_user_nick_name,ccu.start_time as startTime,ca.attrition_level,ca.intention_degree,ca.customer_focus_json  from  crm_customer c " +
             "left join company_user u on u.user_id=c.receive_user_id " +
@@ -506,6 +508,9 @@ public interface CrmCustomerMapper extends BaseMapper<CrmCustomer> {
             " order by c.customer_id desc "+
             "</script>"})
     List<CrmLineCustomerListQueryVO> selectCrmLineCustomerListQuery(@Param("maps") CrmLineCustomerListQueryParam param);
+
+    List<CrmLineCustomerListQueryVO> selectCrmLineCustomerListQueryInfo(@Param("maps") CrmLineCustomerListQueryParam param);
+
     @Select({"<script> " +
             "select ifnull(count(1),0) from crm_customer c  " +
             "where c.status=1 and c.is_del=0 " +
@@ -1003,4 +1008,22 @@ public interface CrmCustomerMapper extends BaseMapper<CrmCustomer> {
     List<CrmCustomer> selectRecoveryClue(@Param("companyId") Long companyId,@Param("limitDay") Integer limitDay,@Param("businessLimit") Integer businessLimit);
 
     List<CrmCustomer> selectRecoveryBusiness(@Param("companyId") Long companyId,@Param("limitDay")Integer limitDay);
+
+    List<CrmLineCustomerListQueryVO> selectTransferCustomerList(@Param("maps")CrmLineCustomerListQueryParam param);
+
+    LinkedHashSet<CrmCustomerUnPoolListQueryVO> selectCrmCustomerListByUnPool(@Param("param1")CrmUnPoolListQueryParam param1,
+                                                                              @Param("param2")CrmUnPoolListQueryParam param2,
+                                                                              @Param("param3")CrmUnPoolListQueryParam param3,
+                                                                              @Param("param")CrmUnPoolListQueryParam param
+    );
+
+    Long countCrmCustomerListByUnPool(@Param("param1")CrmUnPoolListQueryParam param1,
+                                      @Param("param2")CrmUnPoolListQueryParam param2,
+                                      @Param("param3")CrmUnPoolListQueryParam param3,
+                                      @Param("param")CrmUnPoolListQueryParam param
+    );
+
+    int recoverCrmLineCustomerList(@Param("maps") CrmLineCustomerListQueryParam param);
+
+    List<CrmCustomer> selectCrmCustomerByCondition(CrmCustomer crmCustomer);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/crm/param/CrmCompanyLineCustomerImportParam.java

@@ -130,6 +130,8 @@ public class CrmCompanyLineCustomerImportParam implements Serializable {
     @TableField(exist = false)
     private String msg;
 
+    @Excel(name = "是否是商机" )
+    private String isBusiness;
 
 
 }

+ 16 - 0
fs-service/src/main/java/com/fs/crm/param/CrmCustomerBatchReceiveParam.java

@@ -0,0 +1,16 @@
+package com.fs.crm.param;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class CrmCustomerBatchReceiveParam {
+    private List<Long> customerIds;
+
+    private Long companyUserId;
+
+    private Long companyId;
+
+    private Long deptId;
+}

+ 14 - 0
fs-service/src/main/java/com/fs/crm/param/CrmCustomerBatchRecoverParam.java

@@ -0,0 +1,14 @@
+package com.fs.crm.param;
+
+import lombok.Data;
+
+@Data
+public class CrmCustomerBatchRecoverParam {
+    private Long[] customerUserIds;
+
+    private Long companyUserId;
+
+    private Long companyId;
+
+    private Long customerId;
+}

+ 4 - 1
fs-service/src/main/java/com/fs/crm/param/CrmCustomerListQueryParam.java

@@ -1,7 +1,6 @@
 package com.fs.crm.param;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fs.common.annotation.Excel;
 import lombok.Data;
 
@@ -108,4 +107,8 @@ public class CrmCustomerListQueryParam extends BaseQueryParam
     /** 意向度 */
     private String intentionDegree;
 
+    private Integer isPool;
+
+    private Integer importType; // 0:所有 //1:我的
+
 }

+ 19 - 0
fs-service/src/main/java/com/fs/crm/param/CrmCustomerRecoverParam.java

@@ -0,0 +1,19 @@
+package com.fs.crm.param;
+
+import com.fs.common.param.BaseQueryParam;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CrmCustomerRecoverParam extends BaseQueryParam
+{
+    private Long customerUserId;
+
+    private Long companyUserId;
+
+    private Long companyId;
+
+    private Long customerId;
+
+}

+ 18 - 0
fs-service/src/main/java/com/fs/crm/param/CrmLineCustomerListQueryParam.java

@@ -3,9 +3,11 @@ package com.fs.crm.param;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 import java.util.Date;
 
+@EqualsAndHashCode(callSuper = true)
 @Data
 public class CrmLineCustomerListQueryParam extends BaseQueryParam
 {
@@ -88,6 +90,22 @@ public class CrmLineCustomerListQueryParam extends BaseQueryParam
     /** 流失风险等级 0:无风险;1:低风险;2:中风险;3:高风险 */
     private Long attritionLevel;
 
+
+
     /** 意向度 */
     private String intentionDegree;
+
+    private Integer isLine;
+
+    private Integer isPool;
+
+    private Long receiveUserId;
+
+    public Integer getIsLine() {
+        return isLine;
+    }
+
+    public void setIsLine(Integer isLine) {
+        this.isLine = isLine;
+    }
 }

+ 12 - 0
fs-service/src/main/java/com/fs/crm/param/CrmMyCustomerListQueryParam.java

@@ -3,9 +3,11 @@ package com.fs.crm.param;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 import java.util.Date;
 
+@EqualsAndHashCode(callSuper = true)
 @Data
 public class CrmMyCustomerListQueryParam extends BaseQueryParam
 {
@@ -95,4 +97,14 @@ public class CrmMyCustomerListQueryParam extends BaseQueryParam
     private String corpId;
     /** 客户级别 */
     private Long customerLevel;
+
+    private Integer isLine;
+
+    public Integer getIsLine() {
+        return isLine;
+    }
+
+    public void setIsLine(Integer isLine) {
+        this.isLine = isLine;
+    }
 }

+ 94 - 0
fs-service/src/main/java/com/fs/crm/param/CrmUnPoolListQueryParam.java

@@ -0,0 +1,94 @@
+package com.fs.crm.param;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.watch.param.BaseQueryParam;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class CrmUnPoolListQueryParam extends BaseQueryParam {
+
+    Long companyId;
+
+    Long companyUserId;
+
+    private Long customerId;
+
+    @Excel(name = "客户编号")
+    private String customerCode;
+
+    /** 客户名称 */
+    @Excel(name = "客户名称")
+    private String customerName;
+
+    //公司
+    private String customerCompanyName;
+
+    /** 手机 */
+    @Excel(name = "手机")
+    private String mobile;
+
+    /** 性别 */
+    private Integer sex;
+
+    private String weixin;
+
+    private Long createUserId;
+
+    private Long receiveUserId;
+
+
+
+    /** 认领ID */
+    private Long customerUserId;
+
+    /** 客户状态  0锁定 1 正常 */
+    private String status;
+
+    /** 所属部门ID */
+    private Long deptId;
+
+
+    /** 客户类型 */
+    private String customerType;
+
+    private Integer isLine;
+
+    /** 最后一次跟进时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "创建时间",dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    private String createTimeRange;
+    private String[] customerCreateTime;
+
+
+    @Excel(name = "客户来源",dictType = "crm_customer_source")
+    private String source;
+
+    @Excel(name = "标签" )
+    private String tags;
+
+    private Integer isPool;
+
+    //配置放入公海天数
+    private Integer limitDay;
+
+    private Integer start;
+    private String orderBy;//nextTime排序规则
+//    @ApiModelProperty(value = "页大小,默认为10")
+//    private Integer pageSize;
+//    @ApiModelProperty(value = "页码,默认为1")
+//    private Integer pageNum;
+
+    /** 开始时间 */
+    private String beginReceiveTime;
+
+    /** 结束时间 */
+    private String endReceiveTime;
+
+    private String companyUserNickName;
+
+}

+ 16 - 0
fs-service/src/main/java/com/fs/crm/service/ICrmCustomerService.java

@@ -2,6 +2,7 @@ package com.fs.crm.service;
 
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.crm.domain.CrmCustomer;
 import com.fs.crm.param.*;
 import com.fs.crm.vo.*;
@@ -91,15 +92,18 @@ public interface ICrmCustomerService
     List<CrmCustomerListVO> selectCrmCustomerListQueryParam(CrmCustomerListQueryParam crmCustomer);
 
     List<CrmMyCustomerListQueryVO> selectCrmMyCustomerListQuery(CrmMyCustomerListQueryParam param);
+    TableDataInfo selectCrmMyCustomerListQueryInfo(CrmMyCustomerListQueryParam param);
 
     List<CrmCustomerListQueryVO> selectCrmCustomerListQuery(CrmCustomerListQueryParam param);
 
     List<CrmLineCustomerListQueryVO> selectCrmLineCustomerListQuery(CrmLineCustomerListQueryParam param);
+    TableDataInfo selectCrmLineCustomerListQueryInfo(CrmLineCustomerListQueryParam param);
 
 
     R receive(CrmCustomeReceiveParam param, String operName);
 
     R recover(CrmCustomeRecoverParam param, String operName);
+    R recoverR(CrmCustomerRecoverParam param, String operName);
 
     R assignUser(CrmCustomeAssignUserParam param, String operName);
 
@@ -114,6 +118,7 @@ public interface ICrmCustomerService
     List<CrmCustomerStatisticsVO> selectCrmCustomerStatisticsList(CrmCustomerStatisticsParam param);
 
     String importCompanyLineCustomer(List<CrmCompanyLineCustomerImportParam> list, String operName, Long companyId, Long companyUserId);
+    String importCompanyLineCustomerType(List<CrmCompanyLineCustomerImportParam> list, String operName, Long companyId, Long companyUserId,Integer type);
 
     R assignToUser(String operUserName, Long operUserId, CrmCustomeAssignParam param);
 
@@ -171,4 +176,15 @@ public interface ICrmCustomerService
      */
     void recoveryClue();
 
+    TableDataInfo selectTransferCustomerList(CrmLineCustomerListQueryParam param);
+
+    TableDataInfo selectUnPoolCrmCustomerList(CrmUnPoolListQueryParam param);
+
+    R batchReceive(CrmCustomerBatchReceiveParam param, String operName);
+
+    R recoverClueBatch(CrmLineCustomerListQueryParam param);
+
+    R recoverBatchByIds(Long[] customerIds,Long companyId,String opeName,Long opeUserId);
+
+    R recoverCustomerBatchByIds(CrmCustomerBatchRecoverParam param,String operName);
 }

+ 0 - 5
fs-service/src/main/java/com/fs/crm/service/impl/CrmBusinessServiceImpl.java

@@ -1,19 +1,14 @@
 package com.fs.crm.service.impl;
 
-import cn.jiguang.common.resp.APIConnectionException;
-import cn.jiguang.common.resp.APIRequestException;
-import com.alibaba.fastjson.JSON;
 import com.fs.aiSipCall.utils.DateUtils;
 import com.fs.common.OrderUtils;
 import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.entity.SysDictData;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.*;
 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.company.service.impl.CompanyServiceImpl;
 import com.fs.crm.domain.*;
 import com.fs.crm.enums.CustomerLogEnum;
 import com.fs.crm.mapper.*;

+ 495 - 0
fs-service/src/main/java/com/fs/crm/service/impl/CrmCustomerServiceImpl.java

@@ -7,8 +7,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.CluesUtils;
 import com.fs.common.OrderUtils;
 import com.fs.common.annotation.DataScope;
+import com.fs.common.constant.HttpStatus;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.entity.SysDictData;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
@@ -27,6 +29,7 @@ import com.fs.crm.mapper.*;
 import com.fs.crm.param.*;
 import com.fs.crm.service.ICrmBusinessService;
 import com.fs.crm.service.ICrmCustomerService;
+import com.fs.crm.service.ICrmExtDetailService;
 import com.fs.crm.service.ICrmMsgService;
 import com.fs.crm.utils.CidUserOrderExtractor;
 import com.fs.crm.vo.*;
@@ -38,6 +41,7 @@ import com.fs.system.config.SystemConfig;
 import com.fs.system.service.ISysDictDataService;
 import com.fs.system.service.ISysDictTypeService;
 import com.fs.wx.sop.service.IWxSopExecuteService;
+import com.github.pagehelper.PageInfo;
 import lombok.Synchronized;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
@@ -46,9 +50,12 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import com.alibaba.fastjson.JSON;
+
+import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
 /**
@@ -101,6 +108,14 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
 
     @Autowired
     private ICrmBusinessService crmBusinessService;
+
+
+    @Autowired
+    private ICrmExtDetailService crmExtDetailService;
+
+    @Autowired
+    private CrmCustomerLogsMapper crmCustomerLogsMapper;
+
     /**
      * 查询客户
      *
@@ -320,6 +335,48 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
         return crmCustomerMapper.selectCrmMyCustomerListQuery(param);
     }
 
+    @Override
+    public TableDataInfo selectCrmMyCustomerListQueryInfo(CrmMyCustomerListQueryParam param) {
+        List<CrmMyCustomerListQueryVO> list = crmCustomerMapper.selectCrmMyCustomerListQueryInfo(param);
+        TableDataInfo tableDataInfo = getDataTable(list);
+        ArrayList<Map<String, Object>> res = new ArrayList<>();
+        for (CrmMyCustomerListQueryVO vo : list) {
+            HashMap<String, Object> map = new HashMap<>();
+            map.put("correlate_id", vo.getCustomerId());
+            map.put("correlate_type", "customer_id");
+            Map<String, Object> ext = crmExtDetailService.selectCrmExtDetailByCondition(map);
+            HashMap<String, Object> re = new HashMap<>();
+
+            // 使用反射获取所有字段
+            Field[] fields = CrmMyCustomerListQueryVO.class.getDeclaredFields();
+
+            // 遍历字段并将字段名和字段值放入 HashMap
+            for (Field field : fields) {
+                field.setAccessible(true);  // 允许访问私有字段
+
+                try {
+                    Object value = field.get(vo);  // 获取字段的值
+                    re.put(field.getName(), value);  // 将字段名和值放入 HashMap
+                } catch (IllegalAccessException e) {
+                    e.printStackTrace();
+                }
+            }
+            re.put("receiveTime", vo.getReceiveTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getReceiveTime()));
+            re.put("poolTime", vo.getPoolTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getPoolTime()));
+            re.put("createTime", vo.getCreateTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getCreateTime()));
+            re.put("customerCreateTime", vo.getCustomerCreateTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getCustomerCreateTime()));
+            re.put("startTime", vo.getStartTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd", vo.getStartTime()));
+            re.put("nextTime", vo.getNextTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd", vo.getNextTime()));
+            re.put("visitTime", vo.getVisitTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getVisitTime()));
+            if (ext != null) {
+                re.putAll(ext);  // 将 extraFields 中的键值对添加到 re 中
+            }
+            res.add(re);
+        }
+        tableDataInfo.setRows(res);
+        return tableDataInfo;
+    }
+
     @Override
     @DataScope(deptAlias = "c",userAlias = "c")
     public List<CrmCustomerListQueryVO> selectCrmCustomerListQuery(CrmCustomerListQueryParam param) {
@@ -344,6 +401,61 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
         return crmCustomerMapper.selectCrmLineCustomerListQuery(param);
     }
 
+    /**
+     * 响应请求分页数据
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    protected TableDataInfo getDataTable(List<?> list) {
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(list);
+        rspData.setTotal(new PageInfo(list).getTotal());
+        return rspData;
+    }
+
+    @Override
+    public TableDataInfo selectCrmLineCustomerListQueryInfo(CrmLineCustomerListQueryParam param) {
+
+        List<CrmLineCustomerListQueryVO> list = crmCustomerMapper.selectCrmLineCustomerListQueryInfo(param);
+        TableDataInfo resTable = getDataTable(list);
+        ArrayList<Map<String, Object>> res = new ArrayList<>();
+        for (CrmLineCustomerListQueryVO vo : list) {
+
+            HashMap<String, Object> map = new HashMap<>();
+            map.put("correlate_id", vo.getCustomerId());
+            map.put("correlate_type", "customer_id");
+            Map<String, Object> ext = crmExtDetailService.selectCrmExtDetailByCondition(map);
+            HashMap<String, Object> re = new HashMap<>();
+
+            // 使用反射获取所有字段
+            Field[] fields = CrmLineCustomerListQueryVO.class.getDeclaredFields();
+
+            // 遍历字段并将字段名和字段值放入 HashMap
+            for (Field field : fields) {
+                field.setAccessible(true);  // 允许访问私有字段
+
+                try {
+                    Object value = field.get(vo);  // 获取字段的值
+                    re.put(field.getName(), value);  // 将字段名和值放入 HashMap
+                } catch (IllegalAccessException e) {
+                    e.printStackTrace();
+                }
+            }
+            re.put("receiveTime", vo.getReceiveTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getReceiveTime()));
+            re.put("poolTime", vo.getPoolTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getPoolTime()));
+            re.put("createTime", vo.getCreateTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getCreateTime()));
+            re.put("visitTime", vo.getVisitTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getVisitTime()));
+            re.put("nextTime", vo.getNextTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd", vo.getNextTime()));
+            if (ext != null) {
+                re.putAll(ext);  // 将 extraFields 中的键值对添加到 re 中
+            }
+            res.add(re);
+        }
+        resTable.setRows(res);
+        return resTable;
+    }
+
 //    @Override
 //    @Transactional
 //    public R assignDept(CrmCustomeAssignParam param, String operName) {
@@ -583,6 +695,59 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
         return R.ok();
     }
 
+    @Override
+    public R recoverR(CrmCustomerRecoverParam param, String operName) {
+        CrmCustomerUser crmCustomerUser = crmCustomerUserMapper.selectCrmCustomerUserById(param.getCustomerUserId());
+        CrmCustomer customer = null;
+        if (crmCustomerUser == null) {
+            customer = crmCustomerMapper.selectCrmCustomerById(param.getCustomerId());
+        } else {
+            customer = crmCustomerMapper.selectCrmCustomerById(crmCustomerUser.getCustomerId());
+            if (crmCustomerUser != null && crmCustomerUser.getIsPool() == 1) {
+                return R.error("客户已在公海中");
+            }
+            if (customer != null && customer.getStatus() == 0) {
+                return R.error("已锁定");
+            }
+            crmCustomerUser.setIsPool(1);
+            crmCustomerUser.setPoolTime(new Date());
+            crmCustomerUserMapper.updateCrmCustomerUser(crmCustomerUser);
+
+        }
+
+
+        if (customer != null && customer.getStatus() == 0) {
+            return R.error("已锁定");
+        }
+        customer.setIsPool(1);
+        customer.setIsReceive(0);
+        customer.setPoolTime(new Date());
+        customer.setCustomerUserId(null);
+        crmCustomerMapper.updateCrmCustomer(customer);
+        //写日志
+        CrmCustomerLogs logs = new CrmCustomerLogs();
+        logs.setCustomerId(customer.getCustomerId());
+        logs.setCreateTime(new Date());
+        logs.setLogsType(CustomerLogEnum.RECOVER.getValue());
+        logs.setTitle(CustomerLogEnum.RECOVER.getDesc());
+        logs.setRemark(operName + "回收客户" + customer.getCustomerName());
+        logs.setCompanyUserId(param.getCompanyUserId());
+        logsMapper.insertCrmCustomerLogs(logs);
+        msgService.insertCrmMsg(new CrmMsg(1, "回收客户", "客户:" + customer.getCustomerName() + "已回收", customer.getCompanyId(), param.getCompanyUserId(), customer.getCustomerId()));
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
+        if (StringUtils.isNotEmpty(companyUser.getJpushId())) {
+            Map<String, String> extrasMap = new HashMap<>();
+            extrasMap.put("customerId", customer.getCustomerId().toString());
+            extrasMap.put("type", "1");
+            try {
+                jpushService.sendRegisterIdPush("客户消息", "您回收了一个客户", extrasMap, companyUser.getJpushId());
+            } catch (APIConnectionException e) {
+            } catch (APIRequestException e) {
+            }
+        }
+        return R.ok();
+    }
+
     @Override
     public R assignUser(CrmCustomeAssignUserParam param, String operName) {
         CompanyUser companyUser=companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
@@ -802,6 +967,155 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
         return importMsg.toString();
     }
 
+    @Override
+    public String importCompanyLineCustomerType(List<CrmCompanyLineCustomerImportParam> list, String operName, Long companyId, Long companyUserId, Integer type) {
+        long startTime = System.currentTimeMillis();
+        if (StringUtils.isNull(list) || list.size() == 0) {
+            throw new CustomException("导入数据不能为空!");
+        }
+        AtomicInteger successNum = new AtomicInteger();
+        AtomicInteger failureNum = new AtomicInteger();
+        StringBuffer successMsg = new StringBuffer();
+        StringBuffer failureMsg = new StringBuffer();
+        StringBuffer importMsg = new StringBuffer();
+        List<CompletableFuture<Void>> futures = new ArrayList<>();
+        for (CrmCompanyLineCustomerImportParam customer : list) {
+            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+                try {
+//                String regex = "^1[3456789]\\d{9}$";
+//                if(!customer.getMobile().matches(regex)){
+//                    failureNum++;
+//                    String msg = "<br/>" + failureNum + "、客户 " + customer.getMobile() + " 导入失败:电话号码格式不正确";
+//                    failureMsg.append(msg );
+//                    continue;
+//                }
+                    CrmCustomerUpdateOrAddParam crmCustomer = new CrmCustomerUpdateOrAddParam();
+                    BeanUtils.copyProperties(customer, crmCustomer);
+                    CompanyUser companyUser = companyUserMapper.selectCompanyUserById(companyUserId);
+                    crmCustomer.setDeptId(companyUser == null ? null : companyUser.getDeptId());
+                    //导入类型
+                    switch (type) {
+                        case 0:
+                            crmCustomer.setIsReceive(0);
+                            break;
+                        case 1:
+                            crmCustomer.setIsReceive(1);
+                            break;
+                        default:
+                            break;
+                    }
+                    if (StringUtils.isNotEmpty(customer.getSource())) {
+                        crmCustomer.setSource(customer.getSource());
+                        //业务场景 多选
+
+                        //电话或者公司名字重复 不能新增
+                        CrmCustomer condition = new CrmCustomer();
+                        condition.setCustomerCompanyName(crmCustomer.getCustomerCompanyName());
+                        condition.setMobile(crmCustomer.getMobile());
+                        List<CrmCustomer> temp = crmCustomerMapper.selectCrmCustomerByCondition(condition);
+                        if (temp != null && !temp.isEmpty()) {
+                            failureNum.getAndIncrement();
+                            String msg = "<br/>" + failureNum + "、客户 " + customer.getCustomerName() + ",电话:" + customer.getMobile() + " 导入失败:已经存在";
+                            failureMsg.append(msg);
+                        } else {
+                            crmCustomer.setIsDel(0);
+                            crmCustomer.setIsLine(1);
+                            crmCustomer.setCompanyId(companyId);
+                            crmCustomer.setStatus(1);
+                            crmCustomer.setImportType(0); //表格导入
+                            //                crmCustomer.setIsReceive(1);
+                            crmCustomer.setCustomerCode(OrderUtils.getOrderNo());
+                            crmCustomer.setCreateTime(new Date());
+                            crmCustomer.setCreateUserId(companyUserId);
+                            crmCustomerMapper.insertCrmCustomer(crmCustomer);
+                            //添加客户日志
+                            CrmCustomerLogs log=new CrmCustomerLogs();
+                            log.setCustomerId(crmCustomer.getCustomerId());
+                            log.setCreateTime(crmCustomer.getCreateTime());
+                            log.setLogsType(CustomerLogEnum.CREATE.getValue());
+                            log.setTitle(CustomerLogEnum.CREATE.getDesc());
+                            log.setRemark(operName+"表格导入创建客户");
+                            crmCustomerLogsMapper.insertCrmCustomerLogs(log);
+                            //新增 扩展字段
+                            Map<String, Object> ext = crmCustomer.getExt();
+                            if (ext != null && !ext.isEmpty()) {
+                                ext.put("correlate_id", crmCustomer.getCustomerId());
+                                ext.put("correlate_type", "customer_id");
+                                crmExtDetailService.insertCrmExtDetail(ext);
+                            }
+                            //是否为商机
+                            String isBusiness = customer.getIsBusiness();
+                            if (StringUtils.isNotBlank(isBusiness) && "是".equals(isBusiness)) {
+                                //建立商机
+                                CrmBusinessAddAndUpdateParam crmBusiness = new CrmBusinessAddAndUpdateParam();
+                                crmBusiness.setCustomerId(crmCustomer.getCustomerId());
+                                crmBusiness.setSource(Integer.valueOf(crmCustomer.getSource()));
+                                crmBusiness.setManager(crmCustomer.getCustomerName());
+                                String customerCompanyName = crmCustomer.getCustomerCompanyName();
+                                crmBusiness.setCompanyName(StringUtils.isNotBlank(customerCompanyName) ? customerCompanyName : crmCustomer.getCustomerName());
+                                crmBusiness.setBusinessScenario(crmCustomer.getBusinessScenario());
+                                crmBusiness.setProduct(crmCustomer.getProduct());
+                                crmBusiness.setCreateBy(operName);
+                                crmBusiness.setRemark("表格导入");
+                                crmBusiness.setOpeName(operName);
+                                crmBusinessService.insertCrmBusiness(crmBusiness);
+                            }
+
+                            successNum.getAndIncrement();
+                            successMsg.append("<br/>" + successNum + "、客户 " + customer.getCustomerName() + " 导入成功");
+                            //若存在归属员工编号 就将线索客户分配给该业务员  updated by qxj 2023年05月12日16:51:37
+                            if (StringUtils.isNotEmpty(customer.getOwnerCompanyUserCode())) {
+                                companyUser = companyUserMapper.selectUserByUserName(customer.getOwnerCompanyUserCode());
+                                if (companyUser != null) {
+                                    Boolean isSuccess = assignUserAfterImport(operName, crmCustomer.getCustomerId(), companyUser);
+                                    if (isSuccess) {
+                                        successMsg.append(" <br/> " + customer.getOwnerCompanyUserCode() + "客户分配成功");
+                                    } else {
+                                        successMsg.append(" <br/> " + customer.getOwnerCompanyUserCode() + "客户分配失败");
+                                    }
+                                }
+                            } else if (type == 1) {
+                                if (companyUser != null) {
+                                    Boolean isSuccess = assignUserAfterImport(operName, crmCustomer.getCustomerId(), companyUser);
+                                    if (isSuccess) {
+                                        successMsg.append(" <br/> " + customer.getOwnerCompanyUserCode() + "客户分配成功");
+                                    } else {
+                                        successMsg.append(" <br/> " + customer.getOwnerCompanyUserCode() + "客户分配失败");
+                                    }
+                                }
+                            }
+
+                        }
+                    } else {
+                        failureNum.getAndIncrement();
+                        String msg = "<br/>" + failureNum + "、客户 " + customer.getCustomerName() + ",电话:" + customer.getMobile() + " 导入失败:客户来源必填";
+                        failureMsg.append(msg);
+                    }
+
+                } catch (Exception e) {
+                    failureNum.getAndIncrement();
+                    String msg = "<br/>" + failureNum + "、客户 " + customer.getCustomerName() + ",电话:" + customer.getMobile() + " 导入失败:";
+                    failureMsg.append(msg + e.getMessage());
+                }
+            }, threadPoolTaskExecutor);
+            futures.add(future);
+
+        }
+        // 等待所有任务完成
+        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
+
+        if (failureNum.get() > 0) {
+            failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
+            //throw new CustomException(failureMsg.toString());
+        } else {
+            successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
+        }
+        importMsg.append(failureMsg);
+        importMsg.append(successMsg);
+        log.info("导入所花时间: {} ms", System.currentTimeMillis() - startTime);
+        return importMsg.toString();
+    }
+
     // 导入线索客户后给指定业务员分配客户 updated by qxj 2023年05月12日16:51:37
     public Boolean assignUserAfterImport(String operName,Long customerId, CompanyUser companyUser) {
 
@@ -1315,4 +1629,185 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
         }
     }
 
+    @Override
+    public TableDataInfo selectTransferCustomerList(CrmLineCustomerListQueryParam param) {
+        List<CrmLineCustomerListQueryVO> list = crmCustomerMapper.selectTransferCustomerList(param);
+        TableDataInfo resTable = getDataTable(list);
+        ArrayList<Map<String, Object>> res = new ArrayList<>();
+        for (CrmLineCustomerListQueryVO vo : list) {
+            HashMap<String, Object> map = new HashMap<>();
+            map.put("correlate_id", vo.getCustomerId());
+            map.put("correlate_type", "customer_id");
+            Map<String, Object> ext = crmExtDetailService.selectCrmExtDetailByCondition(map);
+            HashMap<String, Object> re = new HashMap<>();
+
+            // 使用反射获取所有字段
+            Field[] fields = CrmLineCustomerListQueryVO.class.getDeclaredFields();
+
+            // 遍历字段并将字段名和字段值放入 HashMap
+            for (Field field : fields) {
+                field.setAccessible(true);  // 允许访问私有字段
+
+                try {
+                    Object value = field.get(vo);  // 获取字段的值
+                    re.put(field.getName(), value);  // 将字段名和值放入 HashMap
+                } catch (IllegalAccessException e) {
+                    e.printStackTrace();
+                }
+            }
+            re.put("receiveTime", vo.getReceiveTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getReceiveTime()));
+            re.put("poolTime", vo.getPoolTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getPoolTime()));
+            re.put("createTime", vo.getCreateTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getCreateTime()));
+            re.put("visitTime", vo.getVisitTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getVisitTime()));
+            re.put("nextTime", vo.getNextTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd", vo.getNextTime()));
+            if (ext != null) {
+                re.putAll(ext);
+            }
+            res.add(re);
+        }
+        resTable.setRows(res);
+        return resTable;
+    }
+
+    @Override
+    public TableDataInfo selectUnPoolCrmCustomerList(CrmUnPoolListQueryParam param) {
+
+        //区分公司 查询配置文件
+        CompanyConfig companyConfig = companyConfigService.selectCompanyConfigByKey(param.getCompanyId(), "sys:config");
+        if (companyConfig != null) {
+            String configValue = companyConfig.getConfigValue();
+            SystemConfig config = JSON.parseObject(configValue, SystemConfig.class);
+            if (config != null) {
+                LinkedHashSet<CrmCustomerUnPoolListQueryVO> vos = new LinkedHashSet<>();
+                //1.查询 新增/导入 n天内没有跟进的线索
+                Integer visitLimit = config.getVisitLimt();
+                CrmUnPoolListQueryParam param1 = null;
+                if (visitLimit != null && visitLimit > 0) {
+                    param1 = new CrmUnPoolListQueryParam();
+                    BeanUtils.copyProperties(param, param1);
+                    param1.setLimitDay(visitLimit);
+                }
+                //2.查询 有跟进的线索n天内没有跟进的线索
+                Integer visitLimit1 = config.getVisitLimt1();
+                CrmUnPoolListQueryParam param2 = null;
+                if (visitLimit1 != null && visitLimit1 > 0) {
+                    param2 = new CrmUnPoolListQueryParam();
+                    BeanUtils.copyProperties(param, param2);
+                    param2.setLimitDay(visitLimit1);
+                }
+                //3.查询 n天无商机
+                Integer visitLimit2 = config.getVisitLimt2();
+                CrmUnPoolListQueryParam param3 = null;
+                if (visitLimit2 != null && visitLimit2 > 0) {
+                    param3 = new CrmUnPoolListQueryParam();
+                    BeanUtils.copyProperties(param, param3);
+                    param3.setLimitDay(visitLimit2);
+                }
+                Integer pageSize = param.getPageSize();
+                Integer pageNum = param.getPageNum();
+                param.setStart((pageNum - 1) * pageSize);
+                vos = crmCustomerMapper.selectCrmCustomerListByUnPool(param1, param2, param3, param);
+                ArrayList<Map<String, Object>> res = new ArrayList<>();
+                for (CrmCustomerUnPoolListQueryVO vo : vos) {
+//                    if(StringUtils.isNotBlank(vo.getMobile())){
+//                        vo.setMobile(vo.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+//                    }
+
+                    HashMap<String, Object> re = new HashMap<>();
+                    // 使用反射获取所有字段
+                    Field[] fields = CrmCustomerUnPoolListQueryVO.class.getDeclaredFields();
+
+                    // 遍历字段并将字段名和字段值放入 HashMap
+                    for (Field field : fields) {
+                        field.setAccessible(true);  // 允许访问私有字段
+                        try {
+                            Object value = field.get(vo);  // 获取字段的值
+                            re.put(field.getName(), value);  // 将字段名和值放入 HashMap
+                        } catch (IllegalAccessException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                    re.put("receiveTime", vo.getReceiveTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getReceiveTime()));
+                    re.put("poolTime", vo.getPoolTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getPoolTime()));
+                    re.put("createTime", vo.getCreateTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getCreateTime()));
+                    re.put("visitTime", vo.getVisitTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getVisitTime()));
+                    re.put("nextTime", vo.getNextTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd", vo.getNextTime()));
+                    re.put("sysVisitTime", vo.getSysVisitTime() == null ? null : DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", vo.getSysVisitTime()));
+                    re.put("timeStr", vo.getTime() / (24 * 60) + "天" + (vo.getTime() % (24 * 60)) / 60 + "小时");
+                    res.add(re);
+                }
+                TableDataInfo rspData = new TableDataInfo();
+                rspData.setCode(HttpStatus.SUCCESS);
+                rspData.setMsg("查询成功");
+                rspData.setRows(res);
+                rspData.setTotal(crmCustomerMapper.countCrmCustomerListByUnPool(param1, param2, param3, param));
+                return rspData;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public R batchReceive(CrmCustomerBatchReceiveParam param, String operName) {
+        List<Long> customerIds = param.getCustomerIds();
+        if (customerIds != null && !customerIds.isEmpty()) {
+            for (Long customerId : customerIds) {
+                CrmCustomeReceiveParam receiveParam = new CrmCustomeReceiveParam();
+                BeanUtils.copyProperties(param, receiveParam);
+                receiveParam.setCustomerId(customerId);
+                R receive = receive(receiveParam, operName);
+                if (Integer.parseInt(receive.get("code").toString()) != 200) {
+                    String msg = customerIds.toString() + " 其中" + customerId + "及其后所有失败,原因:" + receive.get("msg").toString();
+                    return R.error(msg);
+                }
+            }
+        }
+        return R.ok();
+    }
+
+    @Override
+    public R recoverClueBatch(CrmLineCustomerListQueryParam param) {
+        crmCustomerMapper.recoverCrmLineCustomerList(param);
+        return R.ok();
+    }
+
+    /**
+     * 未分配线索投入公海池
+     *
+     * @param customerIds
+     * @return r
+     */
+    @Override
+    public R recoverBatchByIds(Long[] customerIds,Long companyId,String opeName,Long opeUserId) {
+//        int i = crmCustomerMapper.recoverBatchByIds(customerIds, companyId);
+//        return i == customerIds.length ? R.ok() : R.error("未全部投入公海池");
+        if (customerIds == null || customerIds.length < 1) {
+            return R.error("请选择需要回收的线索客户");
+        }
+        for (Long customerId : customerIds) {
+            CrmCustomerRecoverParam recoverParam = new CrmCustomerRecoverParam();
+            recoverParam.setCustomerId(customerId);
+            recoverParam.setCompanyId(companyId);
+            recoverParam.setCompanyUserId(opeUserId);
+            recoverR(recoverParam, opeName);
+        }
+        return R.ok();
+    }
+
+    @Override
+    public R recoverCustomerBatchByIds(CrmCustomerBatchRecoverParam param, String operName) {
+        Long[] customerUserIds = param.getCustomerUserIds();
+        if (customerUserIds == null || customerUserIds.length < 1) {
+            return R.error("请选择需要回收的客户");
+        }
+        for (Long customerUserId : customerUserIds) {
+            CrmCustomerRecoverParam recoverParam = new CrmCustomerRecoverParam();
+            BeanUtils.copyProperties(param, recoverParam);
+            recoverParam.setCustomerUserId(customerUserId);
+            recoverR(recoverParam, operName);
+        }
+        return R.ok();
+    }
+
+
 }

+ 143 - 0
fs-service/src/main/java/com/fs/crm/vo/CrmCustomerUnPoolListQueryVO.java

@@ -0,0 +1,143 @@
+package com.fs.crm.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.Objects;
+
+@Data
+public class CrmCustomerUnPoolListQueryVO {
+    private Long customerId;
+
+    /** 组织机构代码 */
+    private String customerCode;
+
+    /** 客户名称 */
+    private String customerName;
+
+    /** 公司名称 */
+    private String customerCompanyName;
+
+
+    /** 手机 */
+    private String mobile;
+
+    /** 性别 */
+    private Integer sex;
+
+    private String weixin;
+
+    /** 关联用户ID */
+    private Long userId;
+
+    /** 认领ID */
+    @Excel(name = "认领ID")
+    private Long customerUserId;
+
+    /** 省市区 */
+    @Excel(name = "省市区")
+    private String address;
+
+    /** 定位信息 */
+    @Excel(name = "定位信息")
+    private String location;
+
+    /** 详细地址 */
+    @Excel(name = "详细地址")
+    private String detailAddress;
+
+    /** 地理位置经度 */
+    @Excel(name = "地理位置经度")
+    private String lng;
+
+    /** 地理位置维度 */
+    @Excel(name = "地理位置维度")
+    private String lat;
+
+    /** 客户状态  0锁定 1 正常 */
+    @Excel(name = "客户状态  0锁定 1 正常")
+    private Long status;
+
+    /** 1 已认领 0未认领 */
+    @Excel(name = "1 已认领 0未认领")
+    private Long isReceive;
+
+    /** 所属部门ID */
+    @Excel(name = "所属部门ID")
+    private Long deptId;
+
+    /** 客户类型 */
+    @Excel(name = "客户类型")
+    private Integer customerType;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /** 最后一次跟进时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date receiveTime;
+
+    /** 入公海时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date poolTime;
+
+    private Long companyId;
+
+    private Integer source;
+    private Integer visitStatus;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date visitTime;
+    private String content;
+
+    private String tags;
+
+    private String deptName;
+
+    private String remark;
+    private String registerDate;
+    private String registerLinkUrl;
+    private String registerDesc;
+    private String registerSubmitTime;
+    private String registerType;
+    private String sourceCode;
+    private String pushTime;
+    private String pushCode;
+
+    //0:非重客户  1:重客户
+    private Integer isDuplicate;
+
+    /** 非重客户Id(重客户最早录入手机号码的客户id) */
+    private Long dCustomerId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date poolIngTime;
+
+    private Long time;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date nextTime;
+    private String companyUserNickName;
+
+    private String poolType; //掉保类型
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date sysVisitTime;
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        CrmCustomerUnPoolListQueryVO myObject = (CrmCustomerUnPoolListQueryVO) o;
+        return Objects.equals(customerId, myObject.customerId); // 只比较id字段
+    }
+
+    @Override
+    public int hashCode() {
+        return Long.hashCode(customerId); // 只使用id字段计算hashcode
+    }
+
+}

+ 7 - 0
fs-service/src/main/java/com/fs/crm/vo/CrmLineCustomerListQueryVO.java

@@ -123,4 +123,11 @@ public class CrmLineCustomerListQueryVO implements Serializable
      * 客户关注点
      */
     private String customerFocusJson;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date visitTime;
+
+    /** 下次跟进时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date nextTime;
+
 }

+ 7 - 0
fs-service/src/main/java/com/fs/crm/vo/CrmMyCustomerListQueryVO.java

@@ -138,4 +138,11 @@ public class CrmMyCustomerListQueryVO implements Serializable
 
     @Excel(name = "最新跟进内容")
     private String visitContent;
+
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date nextTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date visitTime;
 }

+ 96 - 0
fs-service/src/main/java/com/fs/system/domain/SysUserShow.java

@@ -0,0 +1,96 @@
+package com.fs.system.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 用户展示字段对象 sys_user_show
+ *
+ * @author fs
+ * @date 2025-02-10
+ */
+public class SysUserShow extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** Id */
+    private Long id;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 列表类型 */
+    @Excel(name = "列表类型")
+    private String type;
+
+    /** 列表字段 */
+    @Excel(name = "列表字段")
+    private String columns;
+
+    /** 是否删除 0:否 1:是 */
+    @Excel(name = "是否删除 0:否 1:是")
+    private Long isDel;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+    public void setType(String type)
+    {
+        this.type = type;
+    }
+
+    public String getType()
+    {
+        return type;
+    }
+    public void setColumns(String columns)
+    {
+        this.columns = columns;
+    }
+
+    public String getColumns()
+    {
+        return columns;
+    }
+    public void setIsDel(Long isDel)
+    {
+        this.isDel = isDel;
+    }
+
+    public Long getIsDel()
+    {
+        return isDel;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("userId", getUserId())
+            .append("type", getType())
+            .append("columns", getColumns())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("isDel", getIsDel())
+            .toString();
+    }
+}

+ 79 - 0
fs-service/src/main/java/com/fs/system/mapper/SysUserShowMapper.java

@@ -0,0 +1,79 @@
+package com.fs.system.mapper;
+
+import com.fs.system.domain.SysUserShow;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 用户展示字段Mapper接口
+ *
+ * @author fs
+ * @date 2025-02-10
+ */
+public interface SysUserShowMapper
+{
+    /**
+     * 查询用户展示字段
+     *
+     * @param id 用户展示字段ID
+     * @return 用户展示字段
+     */
+    public SysUserShow selectSysUserShowById(Long id);
+
+    /**
+     * 查询用户展示字段列表
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 用户展示字段集合
+     */
+    public List<SysUserShow> selectSysUserShowList(SysUserShow sysUserShow);
+
+    /**
+     * 新增用户展示字段
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 结果
+     */
+    public int insertSysUserShow(SysUserShow sysUserShow);
+
+    /**
+     * 修改用户展示字段
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 结果
+     */
+    public int updateSysUserShow(SysUserShow sysUserShow);
+
+    /**
+     * 删除用户展示字段
+     *
+     * @param id 用户展示字段ID
+     * @return 结果
+     */
+    public int deleteSysUserShowById(Long id);
+
+    /**
+     * 批量删除用户展示字段
+     *
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteSysUserShowByIds(Long[] ids);
+
+    /**
+     * 根据userId type查询详情
+     * @param userId 用户id
+     * @param type 列表类型
+     * @return 详情
+     */
+    SysUserShow selectSysUserShowByUserId(@Param("userId") Long userId, @Param("type")String type);
+
+    /**
+     * 修改用户展示字段
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 结果
+     */
+    int updateByUserIdAndType(SysUserShow sysUserShow);
+}

+ 106 - 0
fs-service/src/main/java/com/fs/system/param/SysUserExcelParam.java

@@ -0,0 +1,106 @@
+package com.fs.system.param;
+
+import com.fs.common.annotation.Excel;
+
+import java.io.Serializable;
+
+/**
+ * 用户和岗位关联 sys_user_post
+ * 
+ 
+ */
+public class SysUserExcelParam implements Serializable
+{
+    /** 用户账号 */
+    @Excel(name = "工号")
+    private String userName;
+    @Excel(name = "所属区县")
+    private String deptName;
+    @Excel(name = "姓名")
+    private String nickName;
+    @Excel(name = "用户邮箱")
+    private String email;
+    @Excel(name = "手机号码")
+    private String phonenumber;
+    @Excel(name = "用户性别")
+    private String sex;
+    @Excel(name = "岗位")
+    private String postName;
+    @Excel(name = "角色")
+    private String roleName;
+    @Excel(name = "身份证号")
+    private String idCard;
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getDeptName() {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName) {
+        this.deptName = deptName;
+    }
+
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(String nickName) {
+        this.nickName = nickName;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getPhonenumber() {
+        return phonenumber;
+    }
+
+    public void setPhonenumber(String phonenumber) {
+        this.phonenumber = phonenumber;
+    }
+
+    public String getSex() {
+        return sex;
+    }
+
+    public void setSex(String sex) {
+        this.sex = sex;
+    }
+
+
+    public String getPostName() {
+        return postName;
+    }
+
+    public void setPostName(String postName) {
+        this.postName = postName;
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
+    public String getIdCard() {
+        return idCard;
+    }
+
+    public void setIdCard(String idCard) {
+        this.idCard = idCard;
+    }
+}

+ 22 - 0
fs-service/src/main/java/com/fs/system/param/SysUserShowEditParam.java

@@ -0,0 +1,22 @@
+package com.fs.system.param;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SysUserShowEditParam {
+    /** Id */
+    private Long id;
+
+    /** 用户id */
+    private Long userId;
+
+    /** 列表类型 */
+    private String type;
+
+    /** 列表字段 */
+    @Excel(name = "列表字段")
+    private List<String> columns;
+}

+ 72 - 0
fs-service/src/main/java/com/fs/system/service/ISysUserShowService.java

@@ -0,0 +1,72 @@
+package com.fs.system.service;
+
+import com.fs.system.domain.SysUserShow;
+
+import java.util.List;
+
+/**
+ * 用户展示字段Service接口
+ *
+ * @author fs
+ * @date 2025-02-10
+ */
+public interface ISysUserShowService
+{
+    /**
+     * 查询用户展示字段
+     *
+     * @param id 用户展示字段ID
+     * @return 用户展示字段
+     */
+    public SysUserShow selectSysUserShowById(Long id);
+
+    /**
+     * 查询用户展示字段列表
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 用户展示字段集合
+     */
+    public List<SysUserShow> selectSysUserShowList(SysUserShow sysUserShow);
+
+    /**
+     * 新增用户展示字段
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 结果
+     */
+    public int insertSysUserShow(SysUserShow sysUserShow);
+
+    /**
+     * 修改用户展示字段
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 结果
+     */
+    public int updateSysUserShow(SysUserShow sysUserShow);
+
+    /**
+     * 批量删除用户展示字段
+     *
+     * @param ids 需要删除的用户展示字段ID
+     * @return 结果
+     */
+    public int deleteSysUserShowByIds(Long[] ids);
+
+    /**
+     * 删除用户展示字段信息
+     *
+     * @param id 用户展示字段ID
+     * @return 结果
+     */
+    public int deleteSysUserShowById(Long id);
+
+    /**
+     * 根据userId type查询详情
+     * @param userId 用户id
+     * @param type 列表类型
+     * @return 详情
+     */
+    SysUserShow selectSysUserShowByUserId(Long userId,String type);
+
+    int updateByUserIdAndType(SysUserShow sysUserShow);
+}

+ 119 - 0
fs-service/src/main/java/com/fs/system/service/impl/SysUserShowServiceImpl.java

@@ -0,0 +1,119 @@
+package com.fs.system.service.impl;
+
+import com.fs.common.utils.DateUtils;
+import com.fs.system.domain.SysUserShow;
+import com.fs.system.mapper.SysUserShowMapper;
+import com.fs.system.service.ISysUserShowService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 用户展示字段Service业务层处理
+ *
+ * @author fs
+ * @date 2025-02-10
+ */
+@Service
+public class SysUserShowServiceImpl implements ISysUserShowService
+{
+    @Autowired
+    private SysUserShowMapper sysUserShowMapper;
+
+    /**
+     * 查询用户展示字段
+     *
+     * @param id 用户展示字段ID
+     * @return 用户展示字段
+     */
+    @Override
+    public SysUserShow selectSysUserShowById(Long id)
+    {
+        return sysUserShowMapper.selectSysUserShowById(id);
+    }
+
+    /**
+     * 查询用户展示字段列表
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 用户展示字段
+     */
+    @Override
+    public List<SysUserShow> selectSysUserShowList(SysUserShow sysUserShow)
+    {
+        return sysUserShowMapper.selectSysUserShowList(sysUserShow);
+    }
+
+    /**
+     * 新增用户展示字段
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 结果
+     */
+    @Override
+    public int insertSysUserShow(SysUserShow sysUserShow)
+    {
+        sysUserShow.setCreateTime(DateUtils.getNowDate());
+        return sysUserShowMapper.insertSysUserShow(sysUserShow);
+    }
+
+    /**
+     * 修改用户展示字段
+     *
+     * @param sysUserShow 用户展示字段
+     * @return 结果
+     */
+    @Override
+    public int updateSysUserShow(SysUserShow sysUserShow)
+    {
+        sysUserShow.setUpdateTime(DateUtils.getNowDate());
+        return sysUserShowMapper.updateSysUserShow(sysUserShow);
+    }
+
+    /**
+     * 批量删除用户展示字段
+     *
+     * @param ids 需要删除的用户展示字段ID
+     * @return 结果
+     */
+    @Override
+    public int deleteSysUserShowByIds(Long[] ids)
+    {
+        return sysUserShowMapper.deleteSysUserShowByIds(ids);
+    }
+
+    /**
+     * 删除用户展示字段信息
+     *
+     * @param id 用户展示字段ID
+     * @return 结果
+     */
+    @Override
+    public int deleteSysUserShowById(Long id)
+    {
+        return sysUserShowMapper.deleteSysUserShowById(id);
+    }
+
+    /**
+     * 根据userId type查询详情
+     * @param userId 用户id
+     * @param type 列表类型
+     * @return 详情
+     */
+    @Override
+    public SysUserShow selectSysUserShowByUserId(Long userId,String type) {
+        return sysUserShowMapper.selectSysUserShowByUserId(userId,type);
+    }
+
+    @Override
+    public int updateByUserIdAndType(SysUserShow sysUserShow) {
+        sysUserShow.setUpdateTime(DateUtils.getNowDate());
+        int i = sysUserShowMapper.updateByUserIdAndType(sysUserShow);
+        if (i<1){
+           //如果不存在则新增
+            i = insertSysUserShow(sysUserShow);
+        }
+        return i;
+    }
+}

+ 105 - 0
fs-service/src/main/resources/mapper/company/CompanyUserShowMapper.xml

@@ -0,0 +1,105 @@
+<?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.company.mapper.CompanyUserShowMapper">
+
+    <resultMap type="CompanyUserShow" id="CompanyUserShowResult">
+        <result property="id"    column="id"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="type"    column="type"    />
+        <result property="columns"    column="columns"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="isDel"    column="is_del"    />
+    </resultMap>
+
+    <sql id="selectCompanyUserShowVo">
+        select id, company_id, user_id, type, columns, create_time, update_by, update_time, is_del from company_user_show
+    </sql>
+
+    <select id="selectCompanyUserShowList" parameterType="CompanyUserShow" resultMap="CompanyUserShowResult">
+        <include refid="selectCompanyUserShowVo"/>
+        <where>
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="type != null  and type != ''"> and type = #{type}</if>
+            <if test="columns != null  and columns != ''"> and columns = #{columns}</if>
+            <if test="isDel != null "> and is_del = #{isDel}</if>
+        </where>
+    </select>
+
+    <select id="selectCompanyUserShowById" parameterType="Long" resultMap="CompanyUserShowResult">
+        <include refid="selectCompanyUserShowVo"/>
+        where id = #{id}
+    </select>
+
+    <select id="selectShowByCompanyIdUserId" resultType="com.fs.company.domain.CompanyUserShow">
+        <include refid="selectCompanyUserShowVo"/>
+        where is_del = 0 and company_id = #{companyId} and user_id = #{userId} and `type` like #{type}
+    </select>
+
+    <insert id="insertCompanyUserShow" parameterType="CompanyUserShow" useGeneratedKeys="true" keyProperty="id">
+        insert into company_user_show
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="companyId != null">company_id,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="type != null and type != ''">type,</if>
+            <if test="columns != null">columns,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="isDel != null">is_del,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="companyId != null">#{companyId},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="type != null and type != ''">#{type},</if>
+            <if test="columns != null">#{columns},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="isDel != null">#{isDel},</if>
+         </trim>
+    </insert>
+
+    <update id="updateCompanyUserShow" parameterType="CompanyUserShow">
+        update company_user_show
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="type != null and type != ''">type = #{type},</if>
+            <if test="columns != null">columns = #{columns},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="isDel != null">is_del = #{isDel},</if>
+        </trim>
+        where id = #{id}
+    </update>
+    <update id="updateByCompanyIdAndUserIdAndType">
+        update company_user_show
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="columns != null">columns = #{columns},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="isDel != null">is_del = #{isDel},</if>
+        </trim>
+        where company_id= #{companyId} and user_id = #{userId} and `type` = #{type}
+    </update>
+
+    <delete id="deleteCompanyUserShowById" parameterType="Long">
+        delete from company_user_show where id = #{id}
+    </delete>
+
+    <delete id="deleteCompanyUserShowByIds" parameterType="String">
+        delete from company_user_show where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+</mapper>

+ 538 - 0
fs-service/src/main/resources/mapper/crm/CrmCustomerMapper.xml

@@ -629,5 +629,543 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             SELECT b.customer_id FROM crm_business b GROUP BY b.customer_id HAVING b.customer_id IS NOT NULL )
     </select>
 
+    <select id="selectCrmLineCustomerListQuery" resultType="com.fs.crm.vo.CrmLineCustomerListQueryVO">
+        select c.*,u.nick_name as company_user_nick_name,u2.nick_name as create_user_name
+        from  crm_customer c
+        left join company_user u on u.user_id=c.receive_user_id
+        left join company_user u2 on u2.user_id=c.create_user_id
+        where c.is_del = 0
+        <if test="maps.isLine != null">
+            and c.is_line = #{maps.isLine}
+        </if>
+        <if test="maps.customerCode != null and  maps.customerCode !='' ">
+            and c.customer_code like CONCAT('%',#{maps.customerCode},'%')
+        </if>
+        <if test="maps.customerName != null and  maps.customerName !='' ">
+            and c.customer_name like CONCAT('%',#{maps.customerName},'%')
+        </if>
+        <if test="maps.customerCompanyName != null and  maps.customerCompanyName !='' ">
+            and c.customer_company_name like CONCAT('%',#{maps.customerCompanyName},'%')
+        </if>
+        <if test="maps.companyUserNickName != null and  maps.companyUserNickName !=''">
+            and u.nick_name like CONCAT('%',#{maps.companyUserNickName},'%')
+        </if>
+        <if test="maps.createUserName != null and  maps.createUserName !='' ">
+            and u2.nick_name like CONCAT('%',#{maps.createUserName},'%')
+        </if>
+        <if test="maps.mobile != null and  maps.mobile !='' ">
+            and c.mobile like CONCAT('%',#{maps.mobile},'%')
+        </if>
+        <if test="maps.receiveUserId == -1">
+            and c.receive_user_id is NULL
+        </if>
+        <if test="maps.receiveUserId == 0">
+            and c.receive_user_id is NOT NULL
+        </if>
+        <if test="maps.receiveUserId != null and maps.receiveUserId != 0 and maps.receiveUserId != -1">
+            and c.receive_user_id = #{maps.receiveUserId}
+        </if>
+        <if test="maps.status != null and maps.status !='' ">
+            and c.status =#{maps.status}
+        </if>
+        <if test="maps.isReceive != null ">
+            and c.is_receive =#{maps.isReceive}
+        </if>
+        <if test="maps.customerType != null ">
+            and c.customer_type =#{maps.customerType}
+        </if>
+        <if test="maps.companyId != null ">
+            and c.company_id =#{maps.companyId}
+        </if>
+        <if test="maps.source != null and maps.source !='' ">
+            and c.source =#{maps.source}
+        </if>
+        <if test="maps.tags != null ">
+            and
+            <foreach collection="maps.tags.split(',')" item="tag" open="(" close=")" separator="OR">
+                find_in_set(#{tag},c.tags)
+            </foreach>
+        </if>
+        <if test="maps.isPool != null ">
+            and c.is_pool = #{maps.isPool}
+        </if>
+        <if test="maps.createTime != null ">
+            and  DATE_FORMAT(c.create_time, '%Y-%m-%d')  = DATE_FORMAT(#{maps.createTime}, '%Y-%m-%d')
+        </if>
+        <if test="maps.beginTime != null and maps.beginTime !='' ">
+            and date_format(c.create_time,'%y%m%d') &gt;= date_format(#{maps.beginTime},'%y%m%d')
+        </if>
+        <if test="maps.endTime != null and maps.endTime !='' ">
+            and date_format(c.create_time,'%y%m%d') &lt;= date_format(#{maps.endTime},'%y%m%d')
+        </if>
+        <if test="maps.beginReceiveTime != null and maps.beginReceiveTime !='' ">
+            and date_format(c.receive_time,'%y%m%d%H%i%s') &gt;= date_format(#{maps.beginReceiveTime},'%y%m%d%H%i%s')
+        </if>
+        <if test="maps.endReceiveTime != null and maps.endReceiveTime !='' ">
+            and date_format(c.receive_time,'%y%m%d%H%i%s') &lt;= date_format(#{maps.endReceiveTime},'%y%m%d%H%i%s')
+        </if>
+
+
+        ${maps.params.dataScope}
+        <if test="maps.orderBy != null and maps.orderBy != ''">
+            order by c.next_time ${maps.orderBy} ,c.customer_id desc
+        </if>
+        <if test="maps.orderBy == null or maps.orderBy == ''">
+            order by c.customer_id desc
+        </if>
+
+
+    </select>
+
+    <select id="selectTransferCustomerList" resultType="com.fs.crm.vo.CrmLineCustomerListQueryVO">
+        select c.*,u.nick_name as company_user_nick_name,u2.nick_name as create_user_name
+        from  crm_customer c
+        left join company_user u on u.user_id=c.receive_user_id
+        left join company_user u2 on u2.user_id=c.create_user_id
+        where c.is_del = 0 and (u.status = 1 or u.del_flag = 2)
+        <if test="maps.isLine != null">
+            and c.is_line = #{maps.isLine}
+        </if>
+        <if test="maps.customerCode != null and  maps.customerCode !='' ">
+            and c.customer_code like CONCAT('%',#{maps.customerCode},'%')
+        </if>
+        <if test="maps.customerName != null and  maps.customerName !='' ">
+            and c.customer_name like CONCAT('%',#{maps.customerName},'%')
+        </if>
+        <if test="maps.customerCompanyName != null and  maps.customerCompanyName !='' ">
+            and c.customer_company_name like CONCAT('%',#{maps.customerCompanyName},'%')
+        </if>
+        <if test="maps.companyUserNickName != null and  maps.companyUserNickName !=''">
+            and u.nick_name like CONCAT('%',#{maps.companyUserNickName},'%')
+        </if>
+        <if test="maps.createUserName != null and  maps.createUserName !='' ">
+            and u2.nick_name like CONCAT('%',#{maps.createUserName},'%')
+        </if>
+        <if test="maps.mobile != null and  maps.mobile !='' ">
+            and c.mobile like CONCAT('%',#{maps.mobile},'%')
+        </if>
+        <if test="maps.receiveUserId == -1">
+            and c.receive_user_id is NULL
+        </if>
+        <if test="maps.receiveUserId == 0">
+            and c.receive_user_id is NOT NULL
+        </if>
+        <if test="maps.receiveUserId != null and maps.receiveUserId != 0 and maps.receiveUserId != -1">
+            and c.receive_user_id = #{maps.receiveUserId}
+        </if>
+        <if test="maps.status != null and maps.status !='' ">
+            and c.status =#{maps.status}
+        </if>
+        <if test="maps.isReceive != null ">
+            and c.is_receive =#{maps.isReceive}
+        </if>
+        <if test="maps.customerType != null ">
+            and c.customer_type =#{maps.customerType}
+        </if>
+        <if test="maps.companyId != null ">
+            and c.company_id =#{maps.companyId}
+        </if>
+        <if test="maps.source != null and maps.source !='' ">
+            and c.source =#{maps.source}
+        </if>
+        <if test="maps.tags != null ">
+            and
+            <foreach collection="maps.tags.split(',')" item="tag" open="(" close=")" separator="OR">
+                find_in_set(#{tag},c.tags)
+            </foreach>
+        </if>
+        <if test="maps.isPool != null ">
+            and c.is_pool = #{maps.isPool}
+        </if>
+        <if test="maps.createTime != null ">
+            and  DATE_FORMAT(c.create_time, '%Y-%m-%d')  = DATE_FORMAT(#{maps.createTime}, '%Y-%m-%d')
+        </if>
+        <if test="maps.beginTime != null and maps.beginTime !='' ">
+            and date_format(c.create_time,'%y%m%d') &gt;= date_format(#{maps.beginTime},'%y%m%d')
+        </if>
+        <if test="maps.endTime != null and maps.endTime !='' ">
+            and date_format(c.create_time,'%y%m%d') &lt;= date_format(#{maps.endTime},'%y%m%d')
+        </if>
+        <if test="maps.beginReceiveTime != null and maps.beginReceiveTime !='' ">
+            and date_format(c.receive_time,'%y%m%d') &gt;= date_format(#{maps.beginReceiveTime},'%y%m%d')
+        </if>
+        <if test="maps.endReceiveTime != null and maps.endReceiveTime !='' ">
+            and date_format(c.receive_time,'%y%m%d') &lt;= date_format(#{maps.endReceiveTime},'%y%m%d')
+        </if>
+
+
+        ${maps.params.dataScope}
+        <if test="maps.orderBy != null and maps.orderBy != ''">
+            order by c.next_time ${maps.orderBy} ,c.customer_id desc
+        </if>
+        <if test="maps.orderBy == null or maps.orderBy == ''">
+            order by c.customer_id desc
+        </if>
+    </select>
+
+    <select id="selectCrmMyCustomerListQueryInfo" resultType="com.fs.crm.vo.CrmMyCustomerListQueryVO">
+        select cu.*,c.create_time as customer_create_time,c.visit_status,c.visit_time,c.remark,c.register_desc,c.register_submit_time,
+        c.customer_code,c.customer_name,c.mobile,c.sex,c.weixin,c.address,c.is_receive,c.customer_type,c.source,
+        c.tags,c.receive_time,c.content,c.next_time,c.customer_company_name
+        from crm_customer_user cu
+        inner join crm_customer c on c.customer_user_id=cu.customer_user_id
+        where cu.is_pool=0 and c.is_pool = 0
+        <if test="maps.companyId != null ">
+            and cu.company_id =#{maps.companyId}
+        </if>
+        <if test="maps.companyUserId != null ">
+            and cu.company_user_id =#{maps.companyUserId}
+        </if>
+        <if test="maps.isLine != null ">
+            and c.is_line = #{maps.isLine}
+        </if>
+        <if test="maps.address != null and  maps.address !='' ">
+            and c.address like CONCAT('%',#{maps.address},'%')
+        </if>
+        <if test="maps.customerCode != null and  maps.customerCode !='' ">
+            and c.customer_code like CONCAT('%',#{maps.customerCode},'%')
+        </if>
+        <if test="maps.customerName != null and  maps.customerName !='' ">
+            and c.customer_name like CONCAT('%',#{maps.customerName},'%')
+        </if>
+        <if test="maps.customerCompanyName != null and  maps.customerCompanyName !='' ">
+            and c.customer_company_name like CONCAT('%',#{maps.customerCompanyName},'%')
+        </if>
+
+        <if test="maps.mobile != null and  maps.mobile !='' ">
+            and c.mobile like CONCAT('%',#{maps.mobile},'%')
+        </if>
+        <if test="maps.status != null and  maps.status !='' ">
+            and c.visit_status IN
+            <foreach collection="maps.status.split(',')" item="item" index="index" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="maps.isHisOrder != null and maps.isHisOrder==1 ">
+            and (select ifnull(count(1),0) from crm_customer_his_order h where h.customer_id=c.customer_id )  &gt; 0
+        </if>
+        <if test="maps.isHisOrder != null and maps.isHisOrder==0 ">
+            and (select ifnull(count(1),0) from crm_customer_his_order h where h.customer_id=c.customer_id )  = 0
+        </if>
+
+        <if test="maps.customerType != null ">
+            and c.customer_type IN
+            <foreach collection="maps.customerType.split(',')"  item="item" index="index"  open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="maps.source != null and  maps.source !='' ">
+            and c.source IN
+            <foreach collection="maps.source.split(',')" item="item" index="index" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        <if test="maps.tags != null and  maps.tags !='' ">
+            and
+            <foreach collection="maps.tags.split(',')" item="tag" index="index" open="(" close=")" separator="OR">
+                find_in_set(#{tag},c.tags)
+            </foreach>
+        </if>
+        <if test="maps.customerCreateTime != null ">
+            AND date_format(c.create_time,'%y%m%d') &gt;= date_format(#{maps.customerCreateTime[0]},'%y%m%d')
+            AND date_format(c.create_time,'%y%m%d') &lt;= date_format(#{maps.customerCreateTime[1]},'%y%m%d')
+        </if>
+        <if test="maps.beginTime != null and  maps.beginTime !='' ">
+            and date_format(c.receive_time,'%y%m%d') &gt;= date_format(#{maps.beginTime},'%y%m%d')
+        </if>
+        <if test="maps.endTime != null and  maps.endTime !='' ">
+            and date_format(c.receive_time,'%y%m%d') &lt;= date_format(#{maps.endTime},'%y%m%d')
+        </if>
+        ${maps.params.dataScope}
+        <if test="maps.orderBy != null and maps.orderBy != ''">
+            order by c.next_time ${maps.orderBy} ,cu.customer_user_id desc
+        </if>
+        <if test="maps.orderBy == null or maps.orderBy == ''">
+            order by cu.customer_user_id desc
+        </if>
+
+    </select>
+
+    <select id="selectCrmCustomerListByUnPool" resultType="com.fs.crm.vo.CrmCustomerUnPoolListQueryVO">
+        WITH RankedCustomers AS (
+        select c.*,ROW_NUMBER() OVER (PARTITION BY c.customer_id ORDER BY c.create_time DESC) AS rn from (
+        <if test="param1 != null">
+            (SELECT
+            *,
+            '领取未跟进' AS pool_type,
+            (receive_time+ INTERVAL ${param1.limitDay} DAY) AS pooling_time,
+            TIMESTAMPDIFF(MINUTE, NOW(), (receive_time + INTERVAL ${param1.limitDay} DAY)) AS `time`
+            from crm_customer n
+            WHERE n.is_del = 0
+            AND n.is_pool = 0
+            AND n.is_receive = 1
+            <if test="param2 != null">
+                AND n.visit_status IS NULL
+                AND n.receive_user_id IS NOT NULL
+                AND n.customer_id NOT IN (SELECT v.customer_id FROM `crm_customer_visit` v GROUP BY v.customer_id HAVING v.customer_id is NOT NULL)
+            </if>
+
+            )
+
+        </if>
+        <if test="param2 != null">
+            UNION(
+            SELECT *,
+            '未继续跟进' AS pool_type,
+            (GREATEST(
+            IFNULL(visit_time, '1000-01-01'),
+            IFNULL(sys_visit_time, '1000-01-01')
+            ) + INTERVAL ${param2.limitDay} DAY) AS pooling_time,
+            TIMESTAMPDIFF(
+            MINUTE,
+            NOW(),
+            (GREATEST(
+            IFNULL(visit_time, '1000-01-01'),
+            IFNULL(sys_visit_time, '1000-01-01')
+            ) + INTERVAL ${param2.limitDay} DAY)
+            ) AS `time`
+            FROM crm_customer
+            WHERE is_del = 0
+            AND is_pool = 0
+            AND visit_status IS NOT NULL
+            AND visit_time IS NOT NULL
+            )
+        </if>
+        <if test="param3!=null">
+            UNION(SELECT c.*,
+            '未有商机' AS pool_type,
+            (c.create_time + INTERVAL ${param3.limitDay} DAY) AS pooling_time,
+            TIMESTAMPDIFF(MINUTE, NOW(), (c.create_time + INTERVAL ${param3.limitDay} DAY)) AS `time`
+            FROM `crm_customer` c
+            WHERE c.is_del = 0
+            AND c.is_pool = 0
+            AND c.customer_id NOT IN (
+            SELECT b.customer_id FROM crm_business b WHERE b.create_time > (NOW()-INTERVAL ${param3.limitDay} DAY)
+            AND b.customer_id
+            IS NOT NULL GROUP BY b.customer_id)
+            )
+        </if>
+
+        ) as c
+        where c.is_del = 0 and c.is_pool_rule = 1
+        <if test="param.customerCode != null  and param.customerCode != ''"> and c.customer_code = #{param.customerCode}</if>
+        <if test="param.customerName != null  and param.customerName !=''"> and c.customer_name like concat('%', #{param.customerName}, '%')</if>
+        <if test="param.customerCompanyName != null  and param.customerCompanyName !=''"> and c.customer_company_name like concat('%', #{param.customerCompanyName}, '%')</if>
+        <if test="param.mobile != null  and param.mobile != ''"> and c.mobile= #{param.mobile}</if>
+        <if test="param.sex != null "> and c.sex =#{param.sex}</if>
+        <if test="param.weixin != null  and param.weixin != ''"> and c.weixin= #{param.weixin}</if>
+        <if test="param.createUserId != null "> and c.create_user_id = #{param.createUserId}</if>
+        <if test="param.receiveUserId != null "> and c.receive_user_id = #{param.receiveUserId}</if>
+        <if test="param.customerUserId != null "> and c.customer_user_id = #{param.customerUserId}</if>
+        <if test="param.deptId != null "> and c.dept_id = #{deptId}</if>
+        <if test="param.customerType != null "> and c.customer_type = #{param.customerType}</if>
+        <if test="param.companyId != null "> and c.company_id = #{param.companyId}</if>
+        <if test="param.source != null and param.source != ''"> and c.source = #{param.source}</if>
+        <if test="param.tags != null  and param.tags != ''"> and c.tags = #{param.tags}</if>
+        <if test="param.beginTime != null and param.beginTime !='' ">
+            and date_format(c.create_time,'%y%m%d') &gt;= date_format(#{param.beginTime},'%y%m%d')
+        </if>
+        <if test="param.endTime != null and param.endTime !='' ">
+            and date_format(c.create_time,'%y%m%d') &lt;= date_format(#{param.endTime},'%y%m%d')
+        </if>
+        <if test="param.beginReceiveTime != null and param.beginReceiveTime !='' ">
+            and date_format(c.receive_time,'%y%m%d%H%i%s') &gt;= date_format(#{param.beginReceiveTime},'%y%m%d%H%i%s')
+        </if>
+        <if test="param.endReceiveTime != null and param.endReceiveTime !='' ">
+            and date_format(c.receive_time,'%y%m%d%H%i%s') &lt;= date_format(#{param.endReceiveTime},'%y%m%d%H%i%s')
+        </if>
+        <if test="param.companyUserNickName != null and  param.companyUserNickName !='' ">
+            and cu.nick_name like CONCAT('%',#{param.companyUserNickName},'%')
+        </if>
+        )
+        SELECT r.*,cu.nick_name as company_user_nick_name
+        FROM RankedCustomers r
+        left join company_user cu on cu.user_id=r.receive_user_id
+        WHERE r.rn = 1
+        <if test="param.orderBy != null and param.orderBy != ''">
+            order by r.next_time ${param.orderBy} ,r.`time` asc
+        </if>
+        <if test="param.orderBy == null or param.orderBy == ''">
+            order by r.`time` asc
+        </if>
+        limit #{param.start}, #{param.pageSize};
+    </select>
+
+    <select id="countCrmCustomerListByUnPool" resultType="long">
+        WITH RankedCustomers AS (
+        select c.*,ROW_NUMBER() OVER (PARTITION BY c.customer_id ORDER BY c.create_time DESC) AS rn from (
+        <if test="param1 != null">
+            (SELECT *,
+            (receive_time+ INTERVAL ${param1.limitDay} DAY) AS pooling_time,
+            TIMESTAMPDIFF(MINUTE, NOW(), (receive_time + INTERVAL ${param1.limitDay} DAY)) AS `time`
+            from crm_customer
+            WHERE is_del = 0
+            AND is_pool = 0
+            AND is_receive = 1
+            <if test="param2 != null">
+                AND visit_status IS NULL
+                AND receive_user_id IS NOT NULL
+                AND customer_id NOT IN (SELECT v.customer_id FROM `crm_customer_visit` v GROUP BY v.customer_id HAVING v.customer_id is NOT NULL)
+            </if>
+            )
+
+        </if>
+        <if test="param2 != null">
+            UNION(
+            SELECT *,
+            (GREATEST(
+            IFNULL(visit_time, '1000-01-01'),
+            IFNULL(sys_visit_time, '1000-01-01')
+            ) + INTERVAL ${param2.limitDay} DAY) AS pooling_time,
+            TIMESTAMPDIFF(
+            MINUTE,
+            NOW(),
+            (GREATEST(
+            IFNULL(visit_time, '1000-01-01'),
+            IFNULL(sys_visit_time, '1000-01-01')
+            ) + INTERVAL ${param2.limitDay} DAY)
+            ) AS `time`
+            FROM crm_customer
+            WHERE is_del = 0
+            AND is_pool = 0
+            AND visit_status IS NOT NULL
+            AND visit_time IS NOT NULL
+            )
+        </if>
+        <if test="param3!=null">
+            UNION(SELECT c.*,
+            (c.create_time + INTERVAL ${param3.limitDay} DAY) AS pooling_time,
+            TIMESTAMPDIFF(MINUTE, NOW(), (c.create_time + INTERVAL ${param3.limitDay} DAY)) AS `time`
+            FROM `crm_customer` c
+            WHERE c.is_del = 0
+            AND c.is_pool = 0
+            AND c.customer_id NOT IN (
+            SELECT b.customer_id FROM crm_business b WHERE b.create_time > (NOW()-INTERVAL ${param3.limitDay} DAY)
+            AND b.customer_id
+            IS NOT NULL GROUP BY b.customer_id)
+            )
+        </if>
+        ) as c
+        where c.is_del = 0 and c.is_pool_rule = 1
+        <if test="param.customerCode != null  and param.customerCode != ''"> and c.customer_code = #{param.customerCode}</if>
+        <if test="param.customerName != null  and param.customerName !=''"> and c.customer_name like concat('%', #{param.customerName}, '%')</if>
+        <if test="param.customerCompanyName != null  and param.customerCompanyName !=''"> and c.customer_company_name like concat('%', #{param.customerCompanyName}, '%')</if>
+        <if test="param.mobile != null  and param.mobile != ''"> and c.mobile= #{param.mobile}</if>
+        <if test="param.sex != null "> and c.sex =#{param.sex}</if>
+        <if test="param.weixin != null  and param.weixin != ''"> and c.weixin= #{param.weixin}</if>
+        <if test="param.createUserId != null "> and c.create_user_id = #{param.createUserId}</if>
+        <if test="param.receiveUserId != null "> and c.receive_user_id = #{param.receiveUserId}</if>
+        <if test="param.customerUserId != null "> and c.customer_user_id = #{param.customerUserId}</if>
+        <if test="param.deptId != null "> and c.dept_id = #{deptId}</if>
+        <if test="param.customerType != null "> and c.customer_type = #{param.customerType}</if>
+        <if test="param.companyId != null "> and c.company_id = #{param.companyId}</if>
+        <if test="param.source != null and param.source != ''"> and c.source = #{param.source}</if>
+        <if test="param.tags != null  and param.tags != ''"> and c.tags = #{param.tags}</if>
+        <if test="param.beginTime != null and param.beginTime !='' ">
+            and date_format(c.create_time,'%y%m%d') &gt;= date_format(#{param.beginTime},'%y%m%d')
+        </if>
+        <if test="param.endTime != null and param.endTime !='' ">
+            and date_format(c.create_time,'%y%m%d') &lt;= date_format(#{param.endTime},'%y%m%d')
+        </if>
+        <if test="param.beginReceiveTime != null and param.beginReceiveTime !='' ">
+            and date_format(c.receive_time,'%y%m%d%H%i%s') &gt;= date_format(#{param.beginReceiveTime},'%y%m%d%H%i%s')
+        </if>
+        <if test="param.endReceiveTime != null and param.endReceiveTime !='' ">
+            and date_format(c.receive_time,'%y%m%d%H%i%s') &lt;= date_format(#{param.endReceiveTime},'%y%m%d%H%i%s')
+        </if>
+        <if test="param.companyUserNickName != null and  param.companyUserNickName !='' ">
+            and cu.nick_name like CONCAT('%',#{param.companyUserNickName},'%')
+        </if>
+        )
+        SELECT count(1)
+        FROM RankedCustomers r
+        left join company_user cu on cu.user_id=r.receive_user_id
+        WHERE r.rn = 1
+
+        ;
+    </select>
+
+    <select id="selectCrmCustomerByCondition" resultType="com.fs.crm.domain.CrmCustomer">
+        <include refid="selectCrmCustomerVo"/>
+        where is_del = 0
+        <if test="(customerCompanyName != null and  customerCompanyName !='') and (mobile != null and  mobile !='')">
+            and(
+            <if test="customerCompanyName != null and  customerCompanyName !=''">
+                customer_company_name like #{customerCompanyName}
+            </if>
+            <if test="mobile != null and  mobile !=''">
+                or mobile like #{mobile}
+            </if>
+            )
+        </if>
+        <if test="(customerCompanyName != null and  customerCompanyName !='') and (mobile == null or  mobile =='')">
+            and customer_company_name like #{customerCompanyName}
+        </if>
+        <if test="(customerCompanyName == null or  customerCompanyName =='') and (mobile != null and  mobile !='')">
+            and mobile like #{mobile}
+        </if>
+
+    </select>
+
+
+    <update id="recoverCrmLineCustomerList">
+        update crm_customer c set  c.is_pool = 1,c.pool_time = now()
+        <where>
+            <if test="maps.isLine != null">
+                and c.is_line = #{maps.isLine}
+            </if>
+            <if test="maps.customerCode != null and  maps.customerCode !='' ">
+                and c.customer_code like CONCAT('%',#{maps.customerCode},'%')
+            </if>
+            <if test="maps.customerName != null and  maps.customerName !='' ">
+                and c.customer_name like CONCAT('%',#{maps.customerName},'%')
+            </if>
+            <if test="maps.mobile != null and  maps.mobile !='' ">
+                and c.mobile like CONCAT('%',#{maps.mobile},'%')
+            </if>
+            <if test="maps.receiveUserId == -1">
+                and c.receive_user_id is NULL
+            </if>
+            <if test="maps.receiveUserId == 0">
+                and c.receive_user_id is NOT NULL
+            </if>
+            <if test="maps.receiveUserId != null and maps.receiveUserId != 0 and maps.receiveUserId != -1">
+                and c.receive_user_id = #{maps.receiveUserId}
+            </if>
+            <if test="maps.status != null and maps.status !='' ">
+                and c.status =#{maps.status}
+            </if>
+            <if test="maps.isReceive != null ">
+                and c.is_receive =#{maps.isReceive}
+            </if>
+            <if test="maps.customerType != null ">
+                and c.customer_type =#{maps.customerType}
+            </if>
+            <if test="maps.companyId != null ">
+                and c.company_id =#{maps.companyId}
+            </if>
+            <if test="maps.source != null and maps.source !='' ">
+                and c.source =#{maps.source}
+            </if>
+            <if test="maps.tags != null ">
+                and
+                <foreach collection="maps.tags.split(',')" item="tag" open="(" close=")" separator="OR">
+                    find_in_set(#{tag},c.tags)
+                </foreach>
+            </if>
+            <if test="maps.isPool != null ">
+                and c.is_pool = #{maps.isPool}
+            </if>
+            <if test="maps.createTime != null ">
+                and  DATE_FORMAT(c.create_time, '%Y-%m-%d')  = DATE_FORMAT(#{maps.createTime}, '%Y-%m-%d')
+            </if>
+            <if test="maps.beginTime != null and maps.beginTime !='' ">
+                and date_format(c.create_time,'%y%m%d') &gt;= date_format(#{maps.beginTime},'%y%m%d')
+            </if>
+            <if test="maps.endTime != null and maps.endTime !='' ">
+                and date_format(c.create_time,'%y%m%d') &lt;= date_format(#{maps.endTime},'%y%m%d')
+            </if>
+        </where>
+    </update>
 
 </mapper>

+ 1 - 1
fs-service/src/main/resources/mapper/crm/CrmCustomerVisitMapper.xml

@@ -69,7 +69,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="customerUserStatus != null">customer_user_status,</if>
             <if test="isShow != null">is_show,</if>
             <if test="businessId != null">#{businessId},</if>
-            <if test="type != null">#{type},</if>
+            <if test="type != null">`type`,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="customerId != null">#{customerId},</if>

+ 100 - 0
fs-service/src/main/resources/mapper/system/SysUserShowMapper.xml

@@ -0,0 +1,100 @@
+<?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.system.mapper.SysUserShowMapper">
+
+    <resultMap type="SysUserShow" id="SysUserShowResult">
+        <result property="id"    column="id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="type"    column="type"    />
+        <result property="columns"    column="columns"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="isDel"    column="is_del"    />
+    </resultMap>
+
+    <sql id="selectSysUserShowVo">
+        select id, user_id, type, columns, create_time, update_by, update_time, is_del from sys_user_show
+    </sql>
+
+    <select id="selectSysUserShowList" parameterType="SysUserShow" resultMap="SysUserShowResult">
+        <include refid="selectSysUserShowVo"/>
+        <where>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="type != null  and type != ''"> and type = #{type}</if>
+            <if test="columns != null  and columns != ''"> and columns = #{columns}</if>
+            <if test="isDel != null "> and is_del = #{isDel}</if>
+        </where>
+    </select>
+
+    <select id="selectSysUserShowById" parameterType="Long" resultMap="SysUserShowResult">
+        <include refid="selectSysUserShowVo"/>
+        where id = #{id}
+    </select>
+
+    <select id="selectSysUserShowByUserId" resultType="com.fs.system.domain.SysUserShow">
+        <include refid="selectSysUserShowVo"/>
+        where is_del = 0 and user_id = #{userId} and `type` like #{type}
+    </select>
+
+    <insert id="insertSysUserShow" parameterType="SysUserShow" useGeneratedKeys="true" keyProperty="id">
+        insert into sys_user_show
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="userId != null">user_id,</if>
+            <if test="type != null">type,</if>
+            <if test="columns != null">columns,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="isDel != null">is_del,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="userId != null">#{userId},</if>
+            <if test="type != null">#{type},</if>
+            <if test="columns != null">#{columns},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="isDel != null">#{isDel},</if>
+         </trim>
+    </insert>
+
+    <update id="updateSysUserShow" parameterType="SysUserShow">
+        update sys_user_show
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="type != null">type = #{type},</if>
+            <if test="columns != null">columns = #{columns},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="isDel != null">is_del = #{isDel},</if>
+        </trim>
+        where id = #{id}
+    </update>
+    <update id="updateByUserIdAndType">
+        update sys_user_show
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="columns != null">columns = #{columns},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="isDel != null">is_del = #{isDel},</if>
+        </trim>
+        where user_id = #{userId} and `type` = #{type}
+    </update>
+
+    <delete id="deleteSysUserShowById" parameterType="Long">
+        delete from sys_user_show where id = #{id}
+    </delete>
+
+    <delete id="deleteSysUserShowByIds" parameterType="String">
+        delete from sys_user_show where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+</mapper>