Răsfoiți Sursa

新增客户部分代码

YPZ 2 săptămâni în urmă
părinte
comite
87b1bd28c0
54 a modificat fișierele cu 1586 adăugiri și 226 ștergeri
  1. 5 28
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/CustomerAiAnalysisController.java
  2. 56 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/CustomerCompanyTradeController.java
  3. 62 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/CustomerTradeController.java
  4. 63 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/LiaisonTradeController.java
  5. 5 5
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/MarketingCampaignSopDetailController.java
  6. 16 2
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/MarketingController.java
  7. 1 2
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/SopController.java
  8. 13 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/CustomerAnalysisResultDTO.java
  9. 68 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/CustomerCompanyDTO.java
  10. 81 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/CustomerDTO.java
  11. 128 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/LiaisonDTO.java
  12. 2 2
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/MarketEmailsDTO.java
  13. 2 2
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/MarketingCampaignDTO.java
  14. 3 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/SopUpdateDTO.java
  15. 2 2
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/entity/CustomerBaseEntity.java
  16. 2 2
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/entity/MarketEmailsEntity.java
  17. 1 1
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/entity/MarketingCampaignEntity.java
  18. 12 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/mapper/CustomerAnalysisResultEntityMapper.java
  19. 29 2
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/mapper/CustomerEntityMapper.java
  20. 11 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerAnalysisResultEntityService.java
  21. 1 1
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerBaseService.java
  22. 0 7
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerCompanyEntityService.java
  23. 17 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerCompanyTradeService.java
  24. 0 7
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerEntityService.java
  25. 36 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerTradeService.java
  26. 0 7
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/LiaisonEntityService.java
  27. 18 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/LiaisonTradeService.java
  28. 9 2
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/MarketingCampaignService.java
  29. 1 1
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/SopService.java
  30. 1 1
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/TagService.java
  31. 1 1
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/TemplateService.java
  32. 1 1
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/TemplateTagService.java
  33. 6 6
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerAiAnalysisServiceImpl.java
  34. 4 4
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerAnalysisDispatchServiceImpl.java
  35. 10 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerAnalysisResultEntityServiceImpl.java
  36. 3 3
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerBaseServiceImpl.java
  37. 0 17
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerCompanyEntityServiceImpl.java
  38. 111 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerCompanyTradeServiceImpl.java
  39. 0 15
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerEntityServiceImpl.java
  40. 95 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerTradeServiceImpl.java
  41. 0 15
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/LiaisonEntityServiceImpl.java
  42. 102 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/LiaisonTradeServiceImpl.java
  43. 27 25
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/MarketEmailsServiceImpl.java
  44. 96 51
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/MarketingCampaignServiceImpl.java
  45. 20 3
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/SopServiceImpl.java
  46. 3 3
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/TagServiceImpl.java
  47. 3 3
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/TempalteServiceImpl.java
  48. 3 3
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/TempalteTagServiceImpl.java
  49. 20 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/CustomerAnalysisResultVO.java
  50. 21 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/CustomerVO.java
  51. 21 0
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/MarketingCampaignDetailVO.java
  52. 3 2
      java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/MarketingCampaignVO.java
  53. 68 0
      java/storlead-sasa/storlead-trade/src/main/resources/mapper/CustomerAnalysisResultEntityMapper.xml
  54. 323 0
      java/storlead-sasa/storlead-trade/src/main/resources/mapper/CustomerEntityMapper.xml

+ 5 - 28
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/CustomerAiAnalysisController.java

@@ -11,6 +11,7 @@ import com.storlead.trade.entity.CustomerAnalysisResultEntity;
 import com.storlead.trade.entity.SopEntity;
 import com.storlead.trade.service.CustomerAiAnalysisService;
 import com.storlead.trade.service.CustomerAnalysisResultEntityService;
+import com.storlead.trade.vo.CustomerAnalysisResultVO;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.BeanUtils;
@@ -49,35 +50,11 @@ public class CustomerAiAnalysisController {
     }
 
     @RequestMapping("/list")
-    @ApiOperation("客户AI分析结果列表")
+    @ApiOperation("客户AI分析结果列表(联表customer)")
     public Result<Object> list(@RequestBody CustomerAnalysisResultDTO dto) {
-        Page<CustomerAnalysisResultEntity> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
-        LambdaQueryWrapper<CustomerAnalysisResultEntity> wrapper = new LambdaQueryWrapper<>();
-        // 按客户ID筛选
-        if (!ObjectUtils.isEmpty(dto.getCustomerId())) {
-            wrapper.eq(CustomerAnalysisResultEntity::getCustomerId, dto.getCustomerId());
-        }
-        // 按分析场景筛选
-        if (!ObjectUtils.isEmpty(dto.getAnalysisScene())) {
-            wrapper.eq(CustomerAnalysisResultEntity::getAnalysisScene, dto.getAnalysisScene());
-        }
-        // 按客户等级筛选
-        if (!ObjectUtils.isEmpty(dto.getCustomerLevel())) {
-            wrapper.eq(CustomerAnalysisResultEntity::getCustomerLevel, dto.getCustomerLevel());
-        }
-        // 按分析状态筛选
-        if (!ObjectUtils.isEmpty(dto.getAnalysisStatus())) {
-            wrapper.eq(CustomerAnalysisResultEntity::getAnalysisStatus, dto.getAnalysisStatus());
-        }
-        // 按优先级筛选
-        if (!ObjectUtils.isEmpty(dto.getPriority())) {
-            wrapper.eq(CustomerAnalysisResultEntity::getPriority, dto.getPriority());
-        }
-        // 按分析时间倒序
-        wrapper.orderByDesc(CustomerAnalysisResultEntity::getAnalysisTime);
-        // 分页查询
-        IPage<CustomerAnalysisResultEntity> iPage = customerAnalysisResultEntityService.page(page, wrapper);
-        return Result.result(page);
+        // 联表分页查询,支持customer表筛选条件,结果含客户名称
+        IPage<CustomerAnalysisResultVO> result = customerAnalysisResultEntityService.getList(dto);
+        return Result.result(result);
     }
 
     @PostMapping(value = "/add")

+ 56 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/CustomerCompanyTradeController.java

@@ -0,0 +1,56 @@
+package com.storlead.trade.controller;
+
+import com.storlead.trade.dto.CustomerCompanyDTO;
+import com.storlead.trade.service.CustomerCompanyTradeService;
+import com.storlead.framework.common.result.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@RestController
+@RequestMapping("/customerCompany-trade")
+@Api(tags = "客户: 客户企业信息")
+public class CustomerCompanyTradeController {
+
+    @Resource
+    private CustomerCompanyTradeService customerCompanyTradeService;
+
+    @PostMapping("/list")
+    @ApiOperation("客户: 客户企业信息列表")
+    public Result<Object> list(@RequestBody CustomerCompanyDTO dto) {
+        return customerCompanyTradeService.getList(dto);
+    }
+
+    @PostMapping("/add")
+    @ApiOperation("客户: 客户企业信息新增")
+    public Result<?> add(@RequestBody CustomerCompanyDTO dto) {
+        return customerCompanyTradeService.add(dto);
+    }
+
+    @PostMapping("/edit")
+    @ApiOperation("客户: 客户企业信息修改")
+    public Result<?> edit(@RequestBody CustomerCompanyDTO dto) {
+        return customerCompanyTradeService.edit(dto);
+    }
+
+    @PostMapping("/delete")
+    @ApiOperation("客户: 客户企业信息删除")
+    public Result<?> delete(@RequestBody CustomerCompanyDTO dto) {
+        return customerCompanyTradeService.delete(dto);
+    }
+
+    @GetMapping("/getById")
+    @ApiOperation("客户: 客户企业信息详情")
+    public Result<Object> getById(Long id) {
+        if (id == null) {
+            return Result.error("id不能为空");
+        }
+        return Result.result(customerCompanyTradeService.getById(id));
+    }
+}

+ 62 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/CustomerTradeController.java

@@ -0,0 +1,62 @@
+package com.storlead.trade.controller;
+
+import com.storlead.framework.common.result.Result;
+import com.storlead.trade.dto.CustomerDTO;
+import com.storlead.trade.service.CustomerTradeService;
+import com.storlead.trade.vo.CustomerVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/customer-trade")
+@Api(tags = "客户: 客户管理")
+public class CustomerTradeController {
+
+    @Autowired
+    private CustomerTradeService customerTradeService;
+
+    @PostMapping("/list")
+    @ApiOperation(value = "客户列表", notes = "联表分页查询,含企业信息和首要联系人")
+    public Result<Object> list(@RequestBody CustomerDTO dto) {
+        return Result.result(customerTradeService.getList(dto));
+    }
+
+    @GetMapping("/getById")
+    @ApiOperation(value = "客户详情", notes = "根据ID查询,含企业信息和首要联系人")
+    public Result<Object> getById(@RequestParam("id") Long id) {
+        if (ObjectUtils.isEmpty(id)) {
+            return Result.error("id不能为空");
+        }
+        CustomerVO vo = customerTradeService.getDetailById(id);
+        if (ObjectUtils.isEmpty(vo)) {
+            return Result.error("记录不存在");
+        }
+        return Result.result(vo);
+    }
+
+    @PostMapping("/add")
+    @ApiOperation(value = "新增客户", notes = "新增客户基本信息")
+    public Result<Object> add(@RequestBody CustomerDTO dto) {
+        return customerTradeService.add(dto);
+    }
+
+    @PostMapping("/edit")
+    @ApiOperation(value = "修改客户", notes = "修改客户基本信息")
+    public Result<Object> edit(@RequestBody CustomerDTO dto) {
+        return customerTradeService.edit(dto);
+    }
+
+    @PostMapping("/delete")
+    @ApiOperation(value = "删除客户", notes = "删除客户(支持单条id或批量idList)")
+    public Result<Object> delete(@RequestBody CustomerDTO dto) {
+        return customerTradeService.delete(dto);
+    }
+}

+ 63 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/LiaisonTradeController.java

@@ -0,0 +1,63 @@
+package com.storlead.trade.controller;
+
+import com.storlead.trade.dto.LiaisonDTO;
+import com.storlead.trade.entity.LiaisonEntity;
+import com.storlead.trade.service.LiaisonTradeService;
+import com.storlead.framework.common.result.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/liaison-trade")
+@Api(tags = "客户: 联系人管理")
+public class LiaisonTradeController {
+
+    @Autowired
+    private LiaisonTradeService liaisonTradeService;
+
+    @PostMapping("/list")
+    @ApiOperation(value = "客户: 联系人列表", notes = "分页多条件筛选联系人")
+    public Result<Object> list(@RequestBody LiaisonDTO dto) {
+        return liaisonTradeService.getList(dto);
+    }
+
+    @PostMapping("/add")
+    @ApiOperation(value = "客户: 新增联系人", notes = "新增联系人")
+    public Result<?> add(@RequestBody LiaisonDTO dto) {
+        return liaisonTradeService.add(dto);
+    }
+
+    @PostMapping("/edit")
+    @ApiOperation(value = "客户: 修改联系人", notes = "修改联系人")
+    public Result<?> edit(@RequestBody LiaisonDTO dto) {
+        return liaisonTradeService.edit(dto);
+    }
+
+    @PostMapping("/delete")
+    @ApiOperation(value = "客户: 删除联系人", notes = "删除联系人(支持单条id或批量idList)")
+    public Result<?> delete(@RequestBody LiaisonDTO dto) {
+        return liaisonTradeService.delete(dto);
+    }
+
+    @GetMapping("/getById")
+    @ApiOperation(value = "客户: 联系人详情", notes = "根据ID获取联系人详情")
+    public Result<Object> getById(@RequestParam("id") Long id) {
+        if (ObjectUtils.isEmpty(id)) {
+            return Result.error("ID不能为空");
+        }
+        LiaisonEntity entity = liaisonTradeService.getById(id);
+        if (ObjectUtils.isEmpty(entity)) {
+            return Result.error("记录不存在");
+        }
+        return Result.result(entity);
+    }
+
+}

+ 5 - 5
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/MarketingCampaignSopDetailController.java

@@ -10,7 +10,7 @@ import com.storlead.trade.dto.MarketingCampaignSopDetailDTO;
 import com.storlead.trade.vo.MarketingCampaignCustomerVO;
 import com.storlead.trade.entity.CustomerBaseEntity;
 import com.storlead.trade.entity.MarketingCampaignSopDetailEntity;
-import com.storlead.trade.service.CustomerBaseEntityService;
+import com.storlead.trade.service.CustomerBaseService;
 import com.storlead.trade.service.MarketingCampaignSopDetailService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -42,7 +42,7 @@ public class MarketingCampaignSopDetailController {
     private MarketingCampaignSopDetailService marketingCampaignSopDetailService;
 
     @Resource
-    private CustomerBaseEntityService customerBaseEntityService;
+    private CustomerBaseService customerBaseService;
 
     @Resource
     private JdbcTemplate jdbcTemplate;
@@ -143,7 +143,7 @@ public class MarketingCampaignSopDetailController {
         }
 
         // 查询该营销活动下的所有客户(customer_base表)
-        List<CustomerBaseEntity> customers = customerBaseEntityService.lambdaQuery()
+        List<CustomerBaseEntity> customers = customerBaseService.lambdaQuery()
                 .eq(CustomerBaseEntity::getMarketingCampaignId, dto.getMarketingCampaignId())
                 .list();
         if (CollectionUtils.isEmpty(customers)) {
@@ -258,7 +258,7 @@ public class MarketingCampaignSopDetailController {
         email.setIsOnlyHead(0);
         email.setSourceType(0);
         // 收件人:用 customerAnalysisId 占位(实际邮箱需关联客户表)
-        email.setCustomerId(customer.getCustomerAnalysisId());
+        email.setCustomerId(customer.getId());
         // 触达渠道作为 folder
         email.setFolder(sop.getType() != null ? sop.getType() : "email");
         // 定时发送
@@ -424,7 +424,7 @@ public class MarketingCampaignSopDetailController {
             return Result.error("营销活动id不能为空");
         }
 
-        IPage<MarketingCampaignCustomerVO> page = customerBaseEntityService.getCampaignCustomers(dto);
+        IPage<MarketingCampaignCustomerVO> page = customerBaseService.getCampaignCustomers(dto);
 
         // 处理状态标签
         for (MarketingCampaignCustomerVO vo : page.getRecords()) {

+ 16 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/MarketingController.java

@@ -1,12 +1,14 @@
 package com.storlead.trade.controller;
 
 import com.storlead.trade.dto.MarketingCampaignDTO;
-import com.storlead.trade.service.MarketingCampaignEntityService;
+import com.storlead.trade.service.MarketingCampaignService;
 import com.storlead.framework.common.result.Result;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -22,7 +24,7 @@ import java.util.List;
 public class MarketingController {
 
     @Autowired
-    private MarketingCampaignEntityService marketingService;
+    private MarketingCampaignService marketingService;
     @PostMapping("/list")
     @ApiOperation("营销: 营销活动列表")
     public Result<Object> list(@RequestBody MarketingCampaignDTO marketingCampaignDTO) {
@@ -76,4 +78,16 @@ public class MarketingController {
         }});
     }
 
+    @GetMapping("/detail/{id}")
+    @ApiOperation("营销: 营销活动详情(含SOP详情列表)")
+    public Result<Object> detail(@PathVariable("id") Long id) {
+        return marketingService.getDetailById(id);
+    }
+
+    @GetMapping("/detail")
+    @ApiOperation("营销: 营销活动详情(含SOP详情列表)- 参数方式")
+    public Result<Object> detailByParam(@RequestParam("id") Long id) {
+        return marketingService.getDetailById(id);
+    }
+
 }

+ 1 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/controller/SopController.java

@@ -97,8 +97,7 @@ public class SopController {
             @PathVariable Long id,
             @Valid @RequestBody SopUpdateDTO dto) {
         try {
-            sopService.updateSop(id, dto.getName(), dto.getDetails());
-            return Result.ok();
+            return sopService.updateSop(id, dto.getName(), dto.getMarketId(),dto.getDetails());
         } catch (Exception e) {
             log.error("更新SOP失败, ID: {}", id, e);
             return Result.error("更新失败: " +e.getMessage());

+ 13 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/CustomerAnalysisResultDTO.java

@@ -113,4 +113,17 @@ public class CustomerAnalysisResultDTO extends Page {
     @ApiModelProperty(value = "是否是暂停客户(0否,1是)")
     @TableField("has_suspend")
     private Integer hasSuspend;
+
+    // ========== 联表查询字段(来自customer表) ==========
+    @ApiModelProperty(value = "客户名称(模糊查询)")
+    private String customerName;
+
+    @ApiModelProperty(value = "客户所在国家")
+    private String country;
+
+    @ApiModelProperty(value = "客户状态")
+    private String customerStatusDictValue;
+
+    @ApiModelProperty(value = "客户类型")
+    private String customerTypeDictValue;
 }

+ 68 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/CustomerCompanyDTO.java

@@ -0,0 +1,68 @@
+package com.storlead.trade.dto;
+
+import com.storlead.framework.mybatis.page.Page;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class CustomerCompanyDTO extends Page {
+
+    @ApiModelProperty(value = "主键ID")
+    private Long id;
+
+    @ApiModelProperty(value = "关联客户ID")
+    private Long customerId;
+
+    @ApiModelProperty(value = "企业名称")
+    private String name;
+
+    @ApiModelProperty(value = "详细地址")
+    private String address;
+
+    @ApiModelProperty(value = "企业规模value")
+    private String scaleDictValue;
+
+    @ApiModelProperty(value = "企业网址")
+    private String website;
+
+    @ApiModelProperty(value = "其他网址1")
+    private String website1;
+
+    @ApiModelProperty(value = "其他网址2")
+    private String website2;
+
+    @ApiModelProperty(value = "其他网址3")
+    private String website3;
+
+    @ApiModelProperty(value = "所属行业")
+    private String industry;
+
+    @ApiModelProperty(value = "通信地址")
+    private String communicationAddress;
+
+    @ApiModelProperty(value = "邮政编码")
+    private String postcode;
+
+    @ApiModelProperty(value = "传真号码")
+    private String faxNumber;
+
+    @ApiModelProperty(value = "电子邮箱")
+    private String email;
+
+    @ApiModelProperty(value = "公司备用邮箱1")
+    private String email1;
+
+    @ApiModelProperty(value = "公司备用邮箱2")
+    private String email2;
+
+    @ApiModelProperty(value = "公司备用邮箱3")
+    private String email3;
+
+    @ApiModelProperty(value = "联系电话")
+    private String telephone;
+
+    @ApiModelProperty(value = "id列表(批量操作用)")
+    private List<Long> idList;
+}

+ 81 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/CustomerDTO.java

@@ -0,0 +1,81 @@
+package com.storlead.trade.dto;
+
+import com.storlead.framework.mybatis.page.Page;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "CustomerDTO", description = "客户查询/操作DTO")
+public class CustomerDTO extends Page {
+
+    // ===== 主键与ID列表 =====
+    @ApiModelProperty(value = "主键ID")
+    private Long id;
+
+    @ApiModelProperty(value = "id列表(批量操作用)")
+    private List<Long> idList;
+
+    // ===== 客户基本信息筛选 =====
+    @ApiModelProperty(value = "客户名称(模糊查询)")
+    private String customerName;
+
+    @ApiModelProperty(value = "客户编码")
+    private String customerCode;
+
+    @ApiModelProperty(value = "所属大洲")
+    private String continent;
+
+    @ApiModelProperty(value = "所属国家")
+    private String country;
+
+    @ApiModelProperty(value = "客户种类(10客户、11线索)")
+    private Integer customerForm;
+
+    @ApiModelProperty(value = "客户状态value")
+    private String customerStatusDictValue;
+
+    @ApiModelProperty(value = "客户类型value")
+    private String customerTypeDictValue;
+
+    @ApiModelProperty(value = "客户来源value")
+    private String customerSourceDictValue;
+
+    @ApiModelProperty(value = "客户等级value")
+    private String customerLevelDictValue;
+
+    @ApiModelProperty(value = "客户信用等级value")
+    private String customerCreditLevelDictValue;
+
+    @ApiModelProperty(value = "客户经济性质value")
+    private String customerEconomicNatureDictValue;
+
+    @ApiModelProperty(value = "是否重点关注(0否,1是)")
+    private Integer hasFollowCustomer;
+
+    @ApiModelProperty(value = "是否公海客户(0否,1是)")
+    private Integer hasPublicCustomer;
+
+    @ApiModelProperty(value = "是否垃圾客户(0否,1是)")
+    private Integer hasGarbageCustomer;
+
+    @ApiModelProperty(value = "是否有订单(0否,1是)")
+    private Integer hasOrderForm;
+
+    // ===== 联表筛选(来自关联表) =====
+    @ApiModelProperty(value = "公司名称(模糊查询,来自customer_company表)")
+    private String companyName;
+
+    @ApiModelProperty(value = "联系人姓名(模糊查询,来自liaison表)")
+    private String liaisonName;
+
+    @ApiModelProperty(value = "联系人手机号(精确查询,来自liaison表)")
+    private String liaisonTelephone;
+
+    @ApiModelProperty(value = "联系人邮箱(精确查询,来自liaison表)")
+    private String liaisonEmail;
+}

+ 128 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/LiaisonDTO.java

@@ -0,0 +1,128 @@
+package com.storlead.trade.dto;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+import com.storlead.framework.mybatis.page.Page;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+@ApiModel(value = "LiaisonDTO", description = "联系人")
+public class LiaisonDTO extends Page {
+
+    @TableId(type = IdType.AUTO)
+    @ApiModelProperty(value = "主键ID")
+    private Long id;
+
+    @ApiModelProperty(value = "关联客户ID")
+    private Long customerId;
+
+    @ApiModelProperty(value = "是否首要联系人(0否,1是)")
+    private Integer hasPrimaryLialison;
+
+    @ApiModelProperty(value = "联系人姓名")
+    private String name;
+
+    @TableField("`call`")
+    @ApiModelProperty(value = "尊称(0未知,1先生,2女士)")
+    private Integer call;
+
+    @ApiModelProperty(value = "资源类型")
+    private String resourceType;
+
+    @ApiModelProperty(value = "资源类型关联ID")
+    private Long resourceTypeId;
+
+    @ApiModelProperty(value = "联系人角色value")
+    private String liaisonRoleDictValue;
+
+    @ApiModelProperty(value = "生日")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date birthday;
+
+    @ApiModelProperty(value = "部门职务")
+    private String departmentPosition;
+
+    @ApiModelProperty(value = "手机号码")
+    private String telephone;
+
+    @ApiModelProperty(value = "电子邮箱")
+    private String email;
+
+    @ApiModelProperty(value = "备用邮箱1")
+    private String email1;
+
+    @ApiModelProperty(value = "备用邮箱2")
+    private String email2;
+
+    @ApiModelProperty(value = "备用邮箱3")
+    private String email3;
+
+    @ApiModelProperty(value = "传真号码")
+    private String faxNumber;
+
+    @ApiModelProperty(value = "邮政编码")
+    private String postcode;
+
+    @ApiModelProperty(value = "联系方式")
+    private String contactInformation;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "QQ")
+    private String qq;
+
+    @ApiModelProperty(value = "Skype")
+    private String skype;
+
+    @ApiModelProperty(value = "旺旺")
+    private String wangwang;
+
+    @ApiModelProperty(value = "微信")
+    private String wechat;
+
+    @ApiModelProperty(value = "Twitter")
+    private String twitter;
+
+    @ApiModelProperty(value = "LinkedIn")
+    private String linkedin;
+
+    @ApiModelProperty(value = "Facebook")
+    private String facebook;
+
+    @ApiModelProperty(value = "Whatsapp")
+    private String whatsapp;
+
+    @ApiModelProperty(value = "固定电话")
+    private String fixedLineTelephone;
+
+    @ApiModelProperty(value = "宅电")
+    private String homeElectricity;
+
+    @ApiModelProperty(value = "详细地址")
+    private String address;
+
+    @ApiModelProperty(value = "国际区号")
+    private String internationalArea;
+
+    @ApiModelProperty(value = "最后跟进时间")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date lastFollowUpTime;
+
+    @ApiModelProperty(value = "前拥有者")
+    private Long formerOwnerBy;
+
+    @ApiModelProperty(value = "idList(批量操作)")
+    private List<Long> idList;
+
+}

+ 2 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/MarketEmailsDTO.java

@@ -19,8 +19,8 @@ public class MarketEmailsDTO extends Page {
     private Long id;
 
     @ApiModelProperty(value = "客户id")
-    @TableField("customer_analysis_id")
-    private Long customerAnalysisId;
+    @TableField("customer_id")
+    private Long customerId;
 
     @ApiModelProperty(value = "营销活动id")
     @TableField("marketing_campaign_id")

+ 2 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/MarketingCampaignDTO.java

@@ -114,7 +114,7 @@ public class MarketingCampaignDTO extends Page {
 
     @ApiModelProperty(value = "SOP序列id")
     @TableField("sop_id")
-    private Integer sopId;
+    private Long sopId;
 
     @ApiModelProperty(value = "SOP序列详情idList")
     private List<Long> sopDetailIdList;
@@ -195,7 +195,7 @@ public class MarketingCampaignDTO extends Page {
     private List<Long> idList;
 
     @ApiModelProperty(value = "关联客户id")
-    private List<Long> customerAnalysisIdList;
+    private List<Long> customerIdList;
 
 
 }

+ 3 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/dto/SopUpdateDTO.java

@@ -18,6 +18,9 @@ public class SopUpdateDTO {
     @NotBlank(message = "SOP名称不能为空")
     private String name;
 
+    @ApiModelProperty(value = "营销活动id")
+    private Long marketId;
+
     @ApiModelProperty(value = "SOP步骤明细")
     private List<SopDetailUpdateDTO> details;
 }

+ 2 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/entity/CustomerBaseEntity.java

@@ -17,8 +17,8 @@ public class CustomerBaseEntity extends SysBaseField {
     private Long id;
 
     @ApiModelProperty(value = "客户id")
-    @TableField("customer_analysis_id")
-    private Long customerAnalysisId;
+    @TableField("customer_id")
+    private Long customerId;
 
     @ApiModelProperty(value = "营销活动id")
     @TableField("marketing_campaign_id")

+ 2 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/entity/MarketEmailsEntity.java

@@ -20,8 +20,8 @@ public class MarketEmailsEntity extends SysBaseField {
     private Long id;
 
     @ApiModelProperty(value = "客户id")
-    @TableField("customer_analysis_id")
-    private Long customerAnalysisId;
+    @TableField("customer_id")
+    private Long customerId;
 
     @ApiModelProperty(value = "营销活动id")
     @TableField("marketing_campaign_id")

+ 1 - 1
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/entity/MarketingCampaignEntity.java

@@ -112,7 +112,7 @@ public class MarketingCampaignEntity extends SysBaseField {
 
     @ApiModelProperty(value = "SOP序列id")
     @TableField("sop_id")
-    private Integer sopId;
+    private Long sopId;
 
     @ApiModelProperty(value = "sop详情id(逗号分隔)")
     @TableField("sop_detail_ids")

+ 12 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/mapper/CustomerAnalysisResultEntityMapper.java

@@ -1,8 +1,11 @@
 package com.storlead.trade.mapper;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.storlead.trade.dto.CustomerAnalysisResultDTO;
 import com.storlead.trade.mapper.support.TradeBaseMapper;
 
 import com.storlead.trade.entity.CustomerAnalysisResultEntity;
+import com.storlead.trade.vo.CustomerAnalysisResultVO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -45,4 +48,13 @@ public interface CustomerAnalysisResultEntityMapper extends TradeBaseMapper<Cust
             "ORDER BY customer_level")
     List<Map<String, Object>> selectStatisticsByCustomerLevelWithFilter(@Param("analysisScene") String analysisScene,
                                                                         @Param("analysisStatus") Integer analysisStatus);
+
+    /**
+     * 联表分页查询客户分析结果(带customer表筛选条件)
+     * @param page   MyBatis-Plus Page(自动注入,无需手动传)
+     * @param dto    查询条件
+     * @return 分页结果
+     */
+    IPage<CustomerAnalysisResultVO> selectPageWithCustomer(IPage<CustomerAnalysisResultVO> page,
+                                                           @Param("dto") CustomerAnalysisResultDTO dto);
 }

+ 29 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/mapper/CustomerEntityMapper.java

@@ -1,10 +1,37 @@
 package com.storlead.trade.mapper;
 
-import com.storlead.trade.mapper.support.TradeBaseMapper;
-
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.storlead.trade.dto.CustomerDTO;
 import com.storlead.trade.entity.CustomerEntity;
+import com.storlead.trade.mapper.support.TradeBaseMapper;
+import com.storlead.trade.vo.CustomerVO;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 @Mapper
 public interface CustomerEntityMapper extends TradeBaseMapper<CustomerEntity> {
+
+    /**
+     * 联表分页查询客户(含企业信息+首要联系人)
+     * @param page MyBatis-Plus Page(自动注入)
+     * @param dto  查询条件
+     * @return 分页结果
+     */
+    IPage<CustomerVO> selectPageWithRelation(IPage<CustomerVO> page, @Param("dto") CustomerDTO dto);
+
+    /**
+     * 根据客户ID查询详情(含企业信息+首要联系人)
+     * @param customerId 客户ID
+     * @return 客户详情VO
+     */
+    CustomerVO selectDetailByCustomerId(@Param("customerId") Long customerId);
+
+    /**
+     * 批量查询客户ID对应的首要联系人
+     * @param customerIds 客户ID列表
+     * @return 联系人列表
+     */
+    List<CustomerVO> selectPrimaryLiaisonByCustomerIds(@Param("customerIds") List<Long> customerIds);
 }

+ 11 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerAnalysisResultEntityService.java

@@ -1,7 +1,11 @@
 package com.storlead.trade.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.storlead.trade.dto.CustomerAnalysisResultDTO;
 import com.storlead.trade.entity.CustomerAnalysisResultEntity;
+import com.storlead.framework.common.result.Result;
 import com.storlead.framework.mybatis.service.MyBaseService;
+import com.storlead.trade.vo.CustomerAnalysisResultVO;
 
 import java.util.List;
 import java.util.Map;
@@ -21,4 +25,11 @@ public interface CustomerAnalysisResultEntityService extends MyBaseService<Custo
      * @return 每个客户等级的统计信息
      */
     List<Map<String, Object>> getStatisticsByCustomerLevel(String analysisScene, Integer analysisStatus);
+
+    /**
+     * 联表分页查询客户分析结果(带customer表筛选条件)
+     * @param dto 查询条件
+     * @return 分页结果(含客户名称)
+     */
+    IPage<CustomerAnalysisResultVO> getList(CustomerAnalysisResultDTO dto);
 }

+ 1 - 1
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerBaseEntityService.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerBaseService.java

@@ -6,7 +6,7 @@ import com.storlead.trade.entity.CustomerBaseEntity;
 import com.storlead.framework.mybatis.service.MyBaseService;
 import com.storlead.trade.vo.MarketingCampaignCustomerVO;
 
-public interface CustomerBaseEntityService extends MyBaseService<CustomerBaseEntity> {
+public interface CustomerBaseService extends MyBaseService<CustomerBaseEntity> {
 
     /**
      * 查询营销活动关联的客户列表

+ 0 - 7
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerCompanyEntityService.java

@@ -1,7 +0,0 @@
-package com.storlead.trade.service;
-
-import com.storlead.trade.entity.CustomerCompanyEntity;
-import com.storlead.framework.mybatis.service.MyBaseService;
-
-public interface CustomerCompanyEntityService extends MyBaseService<CustomerCompanyEntity> {
-}

+ 17 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerCompanyTradeService.java

@@ -0,0 +1,17 @@
+package com.storlead.trade.service;
+
+import com.storlead.trade.dto.CustomerCompanyDTO;
+import com.storlead.trade.entity.CustomerCompanyEntity;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.mybatis.service.MyBaseService;
+
+public interface CustomerCompanyTradeService extends MyBaseService<CustomerCompanyEntity> {
+
+    Result<Object> getList(CustomerCompanyDTO dto);
+
+    Result<Object> add(CustomerCompanyDTO dto);
+
+    Result<Object> edit(CustomerCompanyDTO dto);
+
+    Result<Object> delete(CustomerCompanyDTO dto);
+}

+ 0 - 7
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerEntityService.java

@@ -1,7 +0,0 @@
-package com.storlead.trade.service;
-
-import com.storlead.trade.entity.CustomerEntity;
-import com.storlead.framework.mybatis.service.MyBaseService;
-
-public interface CustomerEntityService extends MyBaseService<CustomerEntity> {
-}

+ 36 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/CustomerTradeService.java

@@ -0,0 +1,36 @@
+package com.storlead.trade.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.mybatis.service.MyBaseService;
+import com.storlead.trade.dto.CustomerDTO;
+import com.storlead.trade.entity.CustomerEntity;
+import com.storlead.trade.vo.CustomerVO;
+
+public interface CustomerTradeService extends MyBaseService<CustomerEntity> {
+
+    /**
+     * 联表分页查询客户(含企业信息+首要联系人)
+     */
+    IPage<CustomerVO> getList(CustomerDTO dto);
+
+    /**
+     * 根据客户ID查询详情(含企业信息+首要联系人)
+     */
+    CustomerVO getDetailById(Long customerId);
+
+    /**
+     * 新增客户
+     */
+    Result<Object> add(CustomerDTO dto);
+
+    /**
+     * 修改客户
+     */
+    Result<Object> edit(CustomerDTO dto);
+
+    /**
+     * 删除客户(单条/批量)
+     */
+    Result<Object> delete(CustomerDTO dto);
+}

+ 0 - 7
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/LiaisonEntityService.java

@@ -1,7 +0,0 @@
-package com.storlead.trade.service;
-
-import com.storlead.trade.entity.LiaisonEntity;
-import com.storlead.framework.mybatis.service.MyBaseService;
-
-public interface LiaisonEntityService extends MyBaseService<LiaisonEntity> {
-}

+ 18 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/LiaisonTradeService.java

@@ -0,0 +1,18 @@
+package com.storlead.trade.service;
+
+import com.storlead.trade.dto.LiaisonDTO;
+import com.storlead.trade.entity.LiaisonEntity;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.mybatis.service.MyBaseService;
+
+public interface LiaisonTradeService extends MyBaseService<LiaisonEntity> {
+
+    Result<Object> getList(LiaisonDTO dto);
+
+    Result<Object> add(LiaisonDTO dto);
+
+    Result<Object> edit(LiaisonDTO dto);
+
+    Result<Object> delete(LiaisonDTO dto);
+
+}

+ 9 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/MarketingCampaignEntityService.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/MarketingCampaignService.java

@@ -6,11 +6,18 @@ import com.storlead.trade.entity.MarketingCampaignEntity;
 import com.storlead.framework.common.result.Result;
 import com.storlead.framework.mybatis.service.MyBaseService;
 
-public interface MarketingCampaignEntityService extends MyBaseService<MarketingCampaignEntity> {
+public interface MarketingCampaignService extends MyBaseService<MarketingCampaignEntity> {
     Result<Object> getList(MarketingCampaignDTO marketingCampaignDTO);
 
     Result<Object> addMarket(MarketingCampaignDTO marketingCampaignDTO);
 
     Result<Object> editMarket(MarketingCampaignDTO marketingCampaignDTO);
-    
+
+    /**
+     * 根据ID查询营销活动详情(含关联SOP详情列表)
+     * @param id 营销活动ID
+     * @return 详情VO
+     */
+    Result<Object> getDetailById(Long id);
+
 }

+ 1 - 1
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/SopService.java

@@ -23,7 +23,7 @@ public interface SopService extends IService<SopEntity> {
     /**
      * 更新SOP(包含明细)
      */
-    void updateSop(Long id, String name, List<SopDetailUpdateDTO> details);
+    Result<Object> updateSop(Long id, String name,Long marketId, List<SopDetailUpdateDTO> details);
 
     /**
      * 删除SOP(级联删除明细)

+ 1 - 1
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/TagEntityService.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/TagService.java

@@ -3,5 +3,5 @@ package com.storlead.trade.service;
 import com.storlead.trade.entity.TagEntity;
 import com.storlead.framework.mybatis.service.MyBaseService;
 
-public interface TagEntityService extends MyBaseService<TagEntity> {
+public interface TagService extends MyBaseService<TagEntity> {
 }

+ 1 - 1
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/TemplateEntityService.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/TemplateService.java

@@ -3,5 +3,5 @@ package com.storlead.trade.service;
 import com.storlead.trade.entity.TemplateEntity;
 import com.storlead.framework.mybatis.service.MyBaseService;
 
-public interface TemplateEntityService extends MyBaseService<TemplateEntity> {
+public interface TemplateService extends MyBaseService<TemplateEntity> {
 }

+ 1 - 1
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/TemplateTagEntityService.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/TemplateTagService.java

@@ -3,5 +3,5 @@ package com.storlead.trade.service;
 import com.storlead.trade.entity.TemplateTagEntity;
 import com.storlead.framework.mybatis.service.MyBaseService;
 
-public interface TemplateTagEntityService extends MyBaseService<TemplateTagEntity> {
+public interface TemplateTagService extends MyBaseService<TemplateTagEntity> {
 }

+ 6 - 6
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerAiAnalysisServiceImpl.java

@@ -23,11 +23,11 @@ public class CustomerAiAnalysisServiceImpl implements CustomerAiAnalysisService
     private static final String AI_ANALYSIS_URL = "http://127.0.0.1:18080/mock/ai/customer/analyze";
 
     @Resource
-    private CustomerEntityService customerEntityService;
+    private CustomerTradeService customerTradeService;
     @Resource
-    private CustomerCompanyEntityService customerCompanyEntityService;
+    private CustomerCompanyTradeService customerCompanyTradeService;
     @Resource
-    private LiaisonEntityService liaisonEntityService;
+    private LiaisonTradeService liaisonTradeService;
     @Resource
     private CustomerAnalysisResultEntityService customerAnalysisResultEntityService;
 
@@ -37,7 +37,7 @@ public class CustomerAiAnalysisServiceImpl implements CustomerAiAnalysisService
             throw new IllegalArgumentException("customerId不能为空");
         }
 
-        CustomerEntity customer = customerEntityService.getOne(new LambdaQueryWrapper<CustomerEntity>()
+        CustomerEntity customer = customerTradeService.getOne(new LambdaQueryWrapper<CustomerEntity>()
                 .eq(CustomerEntity::getId, customerId)
                 .eq(CustomerEntity::getIsDelete, 0)
                 .last("limit 1"));
@@ -45,13 +45,13 @@ public class CustomerAiAnalysisServiceImpl implements CustomerAiAnalysisService
             throw new IllegalArgumentException("客户不存在");
         }
 
-        CustomerCompanyEntity company = customerCompanyEntityService.getOne(new LambdaQueryWrapper<CustomerCompanyEntity>()
+        CustomerCompanyEntity company = customerCompanyTradeService.getOne(new LambdaQueryWrapper<CustomerCompanyEntity>()
                 .eq(CustomerCompanyEntity::getCustomerId, customerId)
                 .eq(CustomerCompanyEntity::getIsDelete, 0)
                 .orderByDesc(CustomerCompanyEntity::getId)
                 .last("limit 1"));
 
-        List<LiaisonEntity> liaisons = liaisonEntityService.list(new LambdaQueryWrapper<LiaisonEntity>()
+        List<LiaisonEntity> liaisons = liaisonTradeService.list(new LambdaQueryWrapper<LiaisonEntity>()
                 .eq(LiaisonEntity::getCustomerId, customerId)
                 .eq(LiaisonEntity::getIsDelete, 0)
                 .orderByDesc(LiaisonEntity::getHasPrimaryLialison)

+ 4 - 4
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerAnalysisDispatchServiceImpl.java

@@ -10,7 +10,7 @@ import com.storlead.trade.entity.CustomerAnalysisResultEntity;
 import com.storlead.trade.entity.CustomerEntity;
 import com.storlead.trade.service.CustomerAnalysisDispatchService;
 import com.storlead.trade.service.CustomerAnalysisResultEntityService;
-import com.storlead.trade.service.CustomerEntityService;
+import com.storlead.trade.service.CustomerTradeService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -34,7 +34,7 @@ public class CustomerAnalysisDispatchServiceImpl implements CustomerAnalysisDisp
     private static final DateTimeFormatter BATCH_NO_FMT = DateTimeFormatter.BASIC_ISO_DATE;
 
     @Resource
-    private CustomerEntityService customerEntityService;
+    private CustomerTradeService customerTradeService;
 
     @Resource
     private CustomerAnalysisResultEntityService customerAnalysisResultEntityService;
@@ -47,7 +47,7 @@ public class CustomerAnalysisDispatchServiceImpl implements CustomerAnalysisDisp
         Date todayDate = java.sql.Date.valueOf(today);
         Date nextAnalysisDate = java.sql.Date.valueOf(today.plusDays(CustomerAnalysisConstants.NEXT_ANALYSIS_INTERVAL_DAYS));
 
-        List<CustomerEntity> candidates = customerEntityService.list(new LambdaQueryWrapper<CustomerEntity>()
+        List<CustomerEntity> candidates = customerTradeService.list(new LambdaQueryWrapper<CustomerEntity>()
                 .eq(CustomerEntity::getIsDelete, CommonConstant.DEL_FLAG_0)
                 .eq(CustomerEntity::getHasGarbageCustomer, CustomerAnalysisConstants.GARBAGE_CUSTOMER_YES)
                 .and(w -> w.isNull(CustomerEntity::getNextAnalysisDate)
@@ -86,7 +86,7 @@ public class CustomerAnalysisDispatchServiceImpl implements CustomerAnalysisDisp
         }
 
         customerAnalysisResultEntityService.saveBatch(toInsert);
-        customerEntityService.updateBatchById(toUpdate);
+        customerTradeService.updateBatchById(toUpdate);
         log.info("无效客户分析投递完成: batchNo={}, count={}, nextAnalysisDate={}", batchNo, toInsert.size(), nextAnalysisDate);
         return toInsert.size();
     }

+ 10 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerAnalysisResultEntityServiceImpl.java

@@ -1,12 +1,16 @@
 package com.storlead.trade.service.impl;
 
 import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.storlead.framework.common.constant.DSConstants;
 
+import com.storlead.trade.dto.CustomerAnalysisResultDTO;
 import com.storlead.trade.entity.CustomerAnalysisResultEntity;
 import com.storlead.trade.mapper.CustomerAnalysisResultEntityMapper;
 import com.storlead.trade.service.CustomerAnalysisResultEntityService;
 import com.storlead.trade.service.impl.support.TradeDataSourceServiceImpl;
+import com.storlead.trade.vo.CustomerAnalysisResultVO;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -27,4 +31,10 @@ public class CustomerAnalysisResultEntityServiceImpl
     public List<Map<String, Object>> getStatisticsByCustomerLevel(String analysisScene, Integer analysisStatus) {
         return baseMapper.selectStatisticsByCustomerLevelWithFilter(analysisScene, analysisStatus);
     }
+
+    @Override
+    public IPage<CustomerAnalysisResultVO> getList(CustomerAnalysisResultDTO dto) {
+        Page<CustomerAnalysisResultVO> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
+        return baseMapper.selectPageWithCustomer(page, dto);
+    }
 }

+ 3 - 3
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerBaseEntityServiceImpl.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerBaseServiceImpl.java

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.storlead.trade.dto.MarketingCampaignCustomerDTO;
 import com.storlead.trade.entity.CustomerBaseEntity;
 import com.storlead.trade.mapper.CustomerBaseEntityMapper;
-import com.storlead.trade.service.CustomerBaseEntityService;
+import com.storlead.trade.service.CustomerBaseService;
 import com.storlead.trade.vo.MarketingCampaignCustomerVO;
 import com.storlead.trade.service.impl.support.TradeDataSourceServiceImpl;
 import org.springframework.stereotype.Service;
@@ -17,9 +17,9 @@ import javax.annotation.Resource;
 
 @Service
 @DS(DSConstants.DATASOURCE_TRADE)
-public class CustomerBaseEntityServiceImpl
+public class CustomerBaseServiceImpl
         extends TradeDataSourceServiceImpl<CustomerBaseEntityMapper, CustomerBaseEntity>
-        implements CustomerBaseEntityService {
+        implements CustomerBaseService {
 
     @Resource
     private CustomerBaseEntityMapper customerBaseEntityMapper;

+ 0 - 17
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerCompanyEntityServiceImpl.java

@@ -1,17 +0,0 @@
-package com.storlead.trade.service.impl;
-
-import com.baomidou.dynamic.datasource.annotation.DS;
-import com.storlead.framework.common.constant.DSConstants;
-
-import com.storlead.trade.entity.CustomerCompanyEntity;
-import com.storlead.trade.mapper.CustomerCompanyEntityMapper;
-import com.storlead.trade.service.CustomerCompanyEntityService;
-import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
-import org.springframework.stereotype.Service;
-
-@Service
-@DS(DSConstants.DATASOURCE_TRADE)
-public class CustomerCompanyEntityServiceImpl
-        extends MyBaseServiceImpl<CustomerCompanyEntityMapper, CustomerCompanyEntity>
-        implements CustomerCompanyEntityService {
-}

+ 111 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerCompanyTradeServiceImpl.java

@@ -0,0 +1,111 @@
+package com.storlead.trade.service.impl;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.storlead.framework.common.constant.CommonConstant;
+import com.storlead.framework.common.constant.DSConstants;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import com.storlead.trade.dto.CustomerCompanyDTO;
+import com.storlead.trade.entity.CustomerCompanyEntity;
+import com.storlead.trade.mapper.CustomerCompanyEntityMapper;
+import com.storlead.trade.service.CustomerCompanyTradeService;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@DS(DSConstants.DATASOURCE_TRADE)
+public class CustomerCompanyTradeServiceImpl
+        extends MyBaseServiceImpl<CustomerCompanyEntityMapper, CustomerCompanyEntity>
+        implements CustomerCompanyTradeService {
+
+    @Override
+    public Result<Object> getList(CustomerCompanyDTO dto) {
+        Page<CustomerCompanyEntity> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
+        LambdaQueryWrapper<CustomerCompanyEntity> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(CustomerCompanyEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+        wrapper.orderByDesc(CustomerCompanyEntity::getCreateTime);
+
+        if (!ObjectUtils.isEmpty(dto.getId())) {
+            wrapper.eq(CustomerCompanyEntity::getId, dto.getId());
+        }
+        if (!ObjectUtils.isEmpty(dto.getCustomerId())) {
+            wrapper.eq(CustomerCompanyEntity::getCustomerId, dto.getCustomerId());
+        }
+        if (!ObjectUtils.isEmpty(dto.getName())) {
+            wrapper.like(CustomerCompanyEntity::getName, dto.getName());
+        }
+        if (!ObjectUtils.isEmpty(dto.getIndustry())) {
+            wrapper.like(CustomerCompanyEntity::getIndustry, dto.getIndustry());
+        }
+
+        IPage<CustomerCompanyEntity> iPage = this.page(page, wrapper);
+        List<CustomerCompanyEntity> records = iPage.getRecords();
+        if (CollectionUtils.isEmpty(records)) {
+            records = new ArrayList<>();
+        }
+        Page<CustomerCompanyEntity> pageVO = new Page<>();
+        pageVO.setRecords(records);
+        pageVO.setTotal(iPage.getTotal());
+        pageVO.setCurrent(iPage.getCurrent());
+        pageVO.setSize(iPage.getSize());
+
+        return Result.result(pageVO);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<Object> add(CustomerCompanyDTO dto) {
+        CustomerCompanyEntity entity = new CustomerCompanyEntity();
+        BeanUtils.copyProperties(dto, entity);
+        boolean isOk = this.save(entity);
+        if (!isOk) {
+            return Result.error("添加失败");
+        }
+        return Result.ok();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<Object> edit(CustomerCompanyDTO dto) {
+        if (ObjectUtils.isEmpty(dto.getId())) {
+            return Result.error("id不能为空");
+        }
+        CustomerCompanyEntity entity = this.getById(dto.getId());
+        if (ObjectUtils.isEmpty(entity)) {
+            return Result.error("记录不存在");
+        }
+        BeanUtils.copyProperties(dto, entity);
+        boolean isOk = this.updateById(entity);
+        if (!isOk) {
+            return Result.error("修改失败");
+        }
+        return Result.ok();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<Object> delete(CustomerCompanyDTO dto) {
+        boolean isOk = false;
+        Long id = dto.getId();
+        if (!ObjectUtils.isEmpty(id)) {
+            isOk = this.removeById(id);
+        }
+        List<Long> idList = dto.getIdList();
+        if (!CollectionUtils.isEmpty(idList)) {
+            isOk = this.removeByIds(idList);
+        }
+        if (!isOk) {
+            return Result.error("删除失败");
+        }
+        return Result.ok();
+    }
+}

+ 0 - 15
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerEntityServiceImpl.java

@@ -1,15 +0,0 @@
-package com.storlead.trade.service.impl;
-
-import com.baomidou.dynamic.datasource.annotation.DS;
-import com.storlead.framework.common.constant.DSConstants;
-
-import com.storlead.trade.entity.CustomerEntity;
-import com.storlead.trade.mapper.CustomerEntityMapper;
-import com.storlead.trade.service.CustomerEntityService;
-import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
-import org.springframework.stereotype.Service;
-
-@Service
-@DS(DSConstants.DATASOURCE_TRADE)
-public class CustomerEntityServiceImpl extends MyBaseServiceImpl<CustomerEntityMapper, CustomerEntity> implements CustomerEntityService {
-}

+ 95 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/CustomerTradeServiceImpl.java

@@ -0,0 +1,95 @@
+package com.storlead.trade.service.impl;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.storlead.framework.common.constant.DSConstants;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import com.storlead.trade.dto.CustomerDTO;
+import com.storlead.trade.entity.CustomerEntity;
+import com.storlead.trade.mapper.CustomerEntityMapper;
+import com.storlead.trade.service.CustomerTradeService;
+import com.storlead.trade.vo.CustomerVO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@DS(DSConstants.DATASOURCE_TRADE)
+public class CustomerTradeServiceImpl
+        extends MyBaseServiceImpl<CustomerEntityMapper, CustomerEntity>
+        implements CustomerTradeService {
+
+    @Override
+    public IPage<CustomerVO> getList(CustomerDTO dto) {
+        Page<CustomerVO> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
+        IPage<CustomerVO> result = baseMapper.selectPageWithRelation(page, dto);
+        if (result == null || CollectionUtils.isEmpty(result.getRecords())) {
+            result = new Page<>(dto.getPageIndex(), dto.getPageSize());
+            result.setRecords(new ArrayList<>());
+        }
+        return result;
+    }
+
+    @Override
+    public CustomerVO getDetailById(Long customerId) {
+        if (customerId == null) {
+            return null;
+        }
+        return baseMapper.selectDetailByCustomerId(customerId);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<Object> add(CustomerDTO dto) {
+        CustomerEntity entity = new CustomerEntity();
+        BeanUtils.copyProperties(dto, entity);
+        boolean ok = this.save(entity);
+        if (!ok) {
+            return Result.error("添加失败");
+        }
+        return Result.ok();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<Object> edit(CustomerDTO dto) {
+        if (ObjectUtils.isEmpty(dto.getId())) {
+            return Result.error("id不能为空");
+        }
+        CustomerEntity exist = this.getById(dto.getId());
+        if (ObjectUtils.isEmpty(exist)) {
+            return Result.error("记录不存在");
+        }
+        BeanUtils.copyProperties(dto, exist);
+        boolean ok = this.updateById(exist);
+        if (!ok) {
+            return Result.error("修改失败");
+        }
+        return Result.ok();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<Object> delete(CustomerDTO dto) {
+        boolean ok = false;
+        Long id = dto.getId();
+        if (!ObjectUtils.isEmpty(id)) {
+            ok = this.removeById(id);
+        }
+        List<Long> idList = dto.getIdList();
+        if (!CollectionUtils.isEmpty(idList)) {
+            ok = this.removeByIds(idList);
+        }
+        if (!ok) {
+            return Result.error("删除失败");
+        }
+        return Result.ok();
+    }
+}

+ 0 - 15
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/LiaisonEntityServiceImpl.java

@@ -1,15 +0,0 @@
-package com.storlead.trade.service.impl;
-
-import com.baomidou.dynamic.datasource.annotation.DS;
-import com.storlead.framework.common.constant.DSConstants;
-
-import com.storlead.trade.entity.LiaisonEntity;
-import com.storlead.trade.mapper.LiaisonEntityMapper;
-import com.storlead.trade.service.LiaisonEntityService;
-import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
-import org.springframework.stereotype.Service;
-
-@Service
-@DS(DSConstants.DATASOURCE_TRADE)
-public class LiaisonEntityServiceImpl extends MyBaseServiceImpl<LiaisonEntityMapper, LiaisonEntity> implements LiaisonEntityService {
-}

+ 102 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/LiaisonTradeServiceImpl.java

@@ -0,0 +1,102 @@
+package com.storlead.trade.service.impl;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.storlead.framework.common.constant.DSConstants;
+import com.storlead.framework.common.result.Result;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import com.storlead.trade.dto.LiaisonDTO;
+import com.storlead.trade.entity.LiaisonEntity;
+import com.storlead.trade.mapper.LiaisonEntityMapper;
+import com.storlead.trade.service.LiaisonTradeService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+
+import java.util.List;
+
+@Service
+@DS(DSConstants.DATASOURCE_TRADE)
+public class LiaisonTradeServiceImpl extends MyBaseServiceImpl<LiaisonEntityMapper, LiaisonEntity> implements LiaisonTradeService {
+
+    @Override
+    public Result<Object> getList(LiaisonDTO dto) {
+        LambdaQueryWrapper<LiaisonEntity> queryWrapper = new LambdaQueryWrapper<>();
+
+        if (!ObjectUtils.isEmpty(dto.getId())) {
+            queryWrapper.eq(LiaisonEntity::getId, dto.getId());
+        }
+        if (!ObjectUtils.isEmpty(dto.getCustomerId())) {
+            queryWrapper.eq(LiaisonEntity::getCustomerId, dto.getCustomerId());
+        }
+        if (!ObjectUtils.isEmpty(dto.getName())) {
+            queryWrapper.like(LiaisonEntity::getName, dto.getName());
+        }
+        if (!ObjectUtils.isEmpty(dto.getEmail())) {
+            queryWrapper.like(LiaisonEntity::getEmail, dto.getEmail());
+        }
+        if (!ObjectUtils.isEmpty(dto.getHasPrimaryLialison())) {
+            queryWrapper.eq(LiaisonEntity::getHasPrimaryLialison, dto.getHasPrimaryLialison());
+        }
+
+        queryWrapper.orderByDesc(LiaisonEntity::getCreateTime);
+
+        IPage<LiaisonEntity> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
+        IPage<LiaisonEntity> pageList = this.page(page, queryWrapper);
+
+        return Result.result(pageList);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<Object> add(LiaisonDTO dto) {
+        LiaisonEntity entity = new LiaisonEntity();
+        BeanUtils.copyProperties(dto, entity);
+        boolean isOk = this.save(entity);
+        if (!isOk) {
+            return Result.error("新增失败");
+        }
+        return Result.ok();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<Object> edit(LiaisonDTO dto) {
+        if (ObjectUtils.isEmpty(dto.getId())) {
+            return Result.error("ID不能为空");
+        }
+        LiaisonEntity existEntity = this.getById(dto.getId());
+        if (ObjectUtils.isEmpty(existEntity)) {
+            return Result.error("记录不存在");
+        }
+        BeanUtils.copyProperties(dto, existEntity);
+        boolean isOk = this.updateById(existEntity);
+        if (!isOk) {
+            return Result.error("修改失败");
+        }
+        return Result.ok();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<Object> delete(LiaisonDTO dto) {
+        boolean isOk = false;
+        Long id = dto.getId();
+        if (!ObjectUtils.isEmpty(id)) {
+            isOk = this.removeById(id);
+        }
+        List<Long> idList = dto.getIdList();
+        if (!CollectionUtils.isEmpty(idList)) {
+            isOk = this.removeByIds(idList);
+        }
+        if (!isOk) {
+            return Result.error("删除失败");
+        }
+        return Result.ok();
+    }
+
+}

+ 27 - 25
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/MarketEmailsServiceImpl.java

@@ -30,13 +30,13 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
         implements MarketEmailsService {
 
     @Resource
-    private CustomerBaseEntityService customerBaseService;
+    private CustomerBaseService customerBaseService;
 
     @Resource
     private CustomerAnalysisResultEntityService customerAnalysisResultEntityService;
 
     @Resource
-    private CustomerEntityService customerEntityService;
+    private CustomerTradeService customerTradeService;
     @Resource
     private MarketingCampaignSopDetailService marketingCampaignSopDetailEntityService;
     @Resource
@@ -55,8 +55,8 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
         if (!ObjectUtils.isEmpty(dto.getId())) {
             wrapper.eq(MarketEmailsEntity::getId, dto.getId());
         }
-        if (!ObjectUtils.isEmpty(dto.getCustomerAnalysisId())) {
-            wrapper.eq(MarketEmailsEntity::getCustomerAnalysisId, dto.getCustomerAnalysisId());
+        if (!ObjectUtils.isEmpty(dto.getCustomerId())) {
+            wrapper.eq(MarketEmailsEntity::getCustomerId, dto.getCustomerId());
         }
         if (!ObjectUtils.isEmpty(dto.getMarketingCampaignId())) {
             wrapper.eq(MarketEmailsEntity::getMarketingCampaignId, dto.getMarketingCampaignId());
@@ -147,37 +147,39 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
         }
 
         // 2. 提取分析结果id列表
-        List<Long> customerAnalysisIdList = customerBaseList.stream()
-                .map(CustomerBaseEntity::getCustomerAnalysisId)
-                .collect(Collectors.toList());
+//        List<Long> customerAnalysisIdList = customerBaseList.stream()
+//                .map(CustomerBaseEntity::getCustomerAnalysisId)
+//                .collect(Collectors.toList());
 
         // 3. 批量查询分析结果(取 customerId = customer.id)
-        LambdaQueryWrapper<CustomerAnalysisResultEntity> analysisWrapper = new LambdaQueryWrapper<>();
-        analysisWrapper.in(CustomerAnalysisResultEntity::getId, customerAnalysisIdList);
-        analysisWrapper.eq(CustomerAnalysisResultEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
-        List<CustomerAnalysisResultEntity> analysisList = customerAnalysisResultEntityService.list(analysisWrapper);
+//        LambdaQueryWrapper<CustomerAnalysisResultEntity> analysisWrapper = new LambdaQueryWrapper<>();
+//        analysisWrapper.in(CustomerAnalysisResultEntity::getId, customerAnalysisIdList);
+//        analysisWrapper.eq(CustomerAnalysisResultEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+//        List<CustomerAnalysisResultEntity> analysisList = customerAnalysisResultEntityService.list(analysisWrapper);
 
         // 4. 提取客户id列表,批量查询客户基本信息
-        List<Long> customerIdList = analysisList.stream()
-                .map(CustomerAnalysisResultEntity::getCustomerId)
+        List<Long> customerIdList = customerBaseList.stream()
+                .map(CustomerBaseEntity::getCustomerId)
                 .distinct()
                 .collect(Collectors.toList());
-        Map<Long, CustomerEntity> customerMap = customerIdList.isEmpty()
-                ? Collections.emptyMap()
-                : customerEntityService.listByIds(customerIdList).stream()
-                        .collect(Collectors.toMap(CustomerEntity::getId, c -> c));
+//        Map<Long, CustomerEntity> customerMap = customerIdList.isEmpty()
+//                ? Collections.emptyMap()
+//                : customerEntityService.listByIds(customerIdList).stream()
+//                        .collect(Collectors.toMap(CustomerEntity::getId, c -> c));
+        Map<Long, CustomerEntity> customerMap = Collections.emptyMap();
+        if (!CollectionUtils.isEmpty(customerIdList)) {
+            List<CustomerEntity> customerEntityList = customerTradeService.listByIds(customerIdList);
+            customerMap = customerEntityList.stream().collect(Collectors.toMap(CustomerEntity::getId, c -> c));
+        }
 
         // 5. 构造返回结果
         List<MarketEmailsCustomerVO> voList = new ArrayList<>();
-        for (CustomerAnalysisResultEntity analysis : analysisList) {
+        for (CustomerBaseEntity customerBase : customerBaseList) {
             MarketEmailsCustomerVO vo = new MarketEmailsCustomerVO();
-            vo.setAnalysisResultId(analysis.getId());
-            vo.setCustomerId(analysis.getCustomerId());
-            vo.setCustomerLevel(analysis.getCustomerLevel());
-            vo.setPotentialScore(analysis.getPotentialScore());
-            vo.setConfidence(analysis.getConfidence());
+            vo.setAnalysisResultId(customerBase.getId());
+            vo.setCustomerId(customerBase.getCustomerId());
 
-            CustomerEntity customer = customerMap.get(analysis.getCustomerId());
+            CustomerEntity customer = customerMap.get(customerBase.getCustomerId());
             if (customer != null) {
                 vo.setCustomerName(customer.getCustomerName());
                 vo.setCountry(customer.getCountry());
@@ -230,7 +232,7 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
                     }
                     MarketEmailsEntity marketEmail = new MarketEmailsEntity();
                     marketEmail.setMarketingCampaignId(marketingCampaignEntity.getId());
-                    marketEmail.setCustomerAnalysisId(customerVO.getAnalysisResultId());
+                    marketEmail.setCustomerId(customerVO.getCustomerId());
                     marketEmail.setSopDetailId(sopDetail.getId());
                     marketEmail.setExpectSendTime(scheduleStage.getBeijingDatetime());
                     marketEmailList.add(marketEmail);

+ 96 - 51
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/MarketingCampaignEntityServiceImpl.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/MarketingCampaignServiceImpl.java

@@ -8,12 +8,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.storlead.framework.common.util.StringUtil;
-import com.storlead.trade.controller.MarketingCampaignSopDetailController;
 import com.storlead.trade.dto.MarketingCampaignDTO;
 import com.storlead.trade.entity.*;
 import com.storlead.trade.mapper.MarketingCampaignEntityMapper;
 import com.storlead.trade.service.*;
+import com.storlead.trade.vo.MarketingCampaignDetailVO;
 import com.storlead.trade.vo.MarketingCampaignVO;
 import com.storlead.framework.common.constant.CommonConstant;
 import com.storlead.framework.common.result.Result;
@@ -22,7 +21,7 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
+import org.springframework.util.ObjectUtils;
 
 
 import javax.annotation.Resource;
@@ -32,12 +31,12 @@ import java.util.stream.Collectors;
 
 @Service
 @DS(DSConstants.DATASOURCE_TRADE)
-public class MarketingCampaignEntityServiceImpl
+public class MarketingCampaignServiceImpl
         extends TradeDataSourceServiceImpl<MarketingCampaignEntityMapper, MarketingCampaignEntity>
-        implements MarketingCampaignEntityService {
+        implements MarketingCampaignService {
 
     @Resource
-    private CustomerBaseEntityService customerBaseEntityService;
+    private CustomerBaseService customerBaseService;
     @Resource
     private CustomerAnalysisResultEntityService customerAnalysisResultEntityService;
     @Resource
@@ -46,6 +45,9 @@ public class MarketingCampaignEntityServiceImpl
     private MarketingCampaignSopDetailService marketingCampaignSopDetailService;
     @Resource
     private MarketEmailsService marketEmailsService;
+    @Resource
+    private CustomerTradeService customerTradeService;
+
     @Override
     public Result<Object> getList(MarketingCampaignDTO marketingCampaignDTO) {
         IPage<MarketingCampaignVO> pageVO = new Page<>(marketingCampaignDTO.getPageIndex(), marketingCampaignDTO.getPageSize());
@@ -78,36 +80,72 @@ public class MarketingCampaignEntityServiceImpl
         LambdaQueryWrapper<CustomerBaseEntity> customerBaseEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
         customerBaseEntityLambdaQueryWrapper.in(CustomerBaseEntity::getMarketingCampaignId, marketingCampaignIdList);
         customerBaseEntityLambdaQueryWrapper.eq(CustomerBaseEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
-        List<CustomerBaseEntity> customerBaseEntityList = customerBaseEntityService.list(customerBaseEntityLambdaQueryWrapper);
+        List<CustomerBaseEntity> customerBaseEntityList = customerBaseService.list(customerBaseEntityLambdaQueryWrapper);
         //获取全部的关联客户id
-        List<Long> customerAnalysisIdList = customerBaseEntityList.stream().map(CustomerBaseEntity::getCustomerAnalysisId).collect(Collectors.toList());
-        LambdaQueryWrapper<CustomerAnalysisResultEntity> customerAnalysisEntityQueryWrapper = new LambdaQueryWrapper<>();
-        customerAnalysisEntityQueryWrapper.eq(CustomerAnalysisResultEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
-        customerAnalysisEntityQueryWrapper.in(!CollectionUtils.isEmpty(customerAnalysisIdList),CustomerAnalysisResultEntity::getId, customerAnalysisIdList);
-        List<CustomerAnalysisResultEntity> customerAnalysisResultEntityList = customerAnalysisResultEntityService.list(customerAnalysisEntityQueryWrapper);
+        List<Long> customerIdList = customerBaseEntityList.stream().map(CustomerBaseEntity::getCustomerId).collect(Collectors.toList());
+//        LambdaQueryWrapper<CustomerAnalysisResultEntity> customerAnalysisEntityQueryWrapper = new LambdaQueryWrapper<>();
+//        customerAnalysisEntityQueryWrapper.eq(CustomerAnalysisResultEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+//        customerAnalysisEntityQueryWrapper.in(!CollectionUtils.isEmpty(customerAnalysisIdList),CustomerAnalysisResultEntity::getId, customerAnalysisIdList);
+//        List<CustomerAnalysisResultEntity> customerAnalysisResultEntityList = customerAnalysisResultEntityService.list(customerAnalysisEntityQueryWrapper);
+        List<CustomerEntity> customerEntityList = new ArrayList<>();
+        if (!CollectionUtils.isEmpty(customerIdList)){
+            customerEntityList = customerTradeService.listByIds(customerIdList);
+        }
         //将customerAnalysisResultEntityList按照customerBaseEntityList对应的id写入pageVO的customerList中
 
         for (int i = 0; i < marketingCampaignVOList.size(); i++) {
+
             int finalI = i;
             List<CustomerBaseEntity> customerBaseList = customerBaseEntityList.stream()
                     .filter(customerBaseEntity -> customerBaseEntity.getMarketingCampaignId().equals(marketingCampaignVOList.get(finalI).getId()))
                     .collect(Collectors.toList());
-            List<Long> customerAnalysisResultIdList = customerBaseList.stream()
-                    .map(CustomerBaseEntity::getCustomerAnalysisId)
+            List<Long> customerIdNewList = customerBaseList.stream()
+                    .map(CustomerBaseEntity::getCustomerId)
                     .collect(Collectors.toList());
-            if (CollectionUtils.isEmpty(customerAnalysisResultIdList)) {
-                marketingCampaignVOList.get(i).setCustomerList(new ArrayList<>());
-                continue;
-            }
-            List<CustomerAnalysisResultEntity> customerAnalysisResultEntityListI = customerAnalysisResultEntityList.stream()
-                    .filter(customerAnalysisResultEntity -> customerAnalysisResultIdList.contains(customerAnalysisResultEntity.getId()))
+
+
+            List<CustomerEntity> customerListI = customerEntityList.stream()
+                    .filter(customerEntity -> customerIdNewList.contains(customerEntity.getId()))
                     .collect(Collectors.toList());
-            marketingCampaignVOList.get(i).setCustomerList(customerAnalysisResultEntityListI);
+            marketingCampaignVOList.get(i).setCustomerList(customerListI);
         }
 
         return Result.result(pageVO);
     }
 
+    @Override
+    public Result<Object> getDetailById(Long id) {
+        if (id == null) {
+            return Result.error("id不能为空");
+        }
+        // 1. 查询营销活动基本信息
+        MarketingCampaignEntity campaign = this.getById(id);
+        if (campaign == null || campaign.getIsDelete() == 1) {
+            return Result.error("营销活动不存在");
+        }
+
+        // 2. 查询关联的SOP详情列表(通过中间表)
+        LambdaQueryWrapper<MarketingCampaignSopDetailEntity> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(MarketingCampaignSopDetailEntity::getMarketingId, id);
+        wrapper.eq(MarketingCampaignSopDetailEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+        List<MarketingCampaignSopDetailEntity> relationList = marketingCampaignSopDetailService.list(wrapper);
+
+//        List<SopDetailEntity> sopDetailList = Collections.emptyList();
+//        if (!CollectionUtils.isEmpty(relationList)) {
+//            List<Long> sopDetailIds = relationList.stream()
+//                    .map(MarketingCampaignSopDetailEntity::getSopDetailId)
+//                    .collect(Collectors.toList());
+//            sopDetailList = sopDetailService.listByIds(sopDetailIds).stream().collect(Collectors.toList());
+//        }
+
+        // 3. 组装VO
+        MarketingCampaignDetailVO detailVO = new MarketingCampaignDetailVO();
+        detailVO.setCampaign(campaign);
+        detailVO.setSopDetailList(relationList);
+
+        return Result.result(detailVO);
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Result<Object> addMarket(MarketingCampaignDTO marketingCampaignDTO) {
@@ -119,52 +157,49 @@ public class MarketingCampaignEntityServiceImpl
             return Result.error("添加失败");
         }
         //添加关联客户
-        List<Long> customerIdList = marketingCampaignDTO.getCustomerAnalysisIdList();
+        List<Long> customerIdList = marketingCampaignDTO.getCustomerIdList();
         if (!CollectionUtils.isEmpty(customerIdList)) {
             // 去重,避免主键冲突
             List<Long> distinctCustomerIds = customerIdList.stream().distinct().collect(Collectors.toList());
             for (Long customerId : distinctCustomerIds) {
                 CustomerBaseEntity customerBaseEntity = new CustomerBaseEntity();
-                customerBaseEntity.setCustomerAnalysisId(customerId);
+                customerBaseEntity.setCustomerId(customerId);
                 customerBaseEntity.setMarketingCampaignId(marketingCampaignEntity.getId());
-                boolean saveOk = customerBaseEntityService.save(customerBaseEntity);
+                boolean saveOk = customerBaseService.save(customerBaseEntity);
                 if (!saveOk) {
                     return Result.error("添加关联客户失败");
                 }
             }
         }
         //添加关联sopDetailIdList,并调取ai生成邮件内容
-        List<Long> sopDetailIdList = marketingCampaignDTO.getSopDetailIdList();
-        if (!CollectionUtils.isEmpty(sopDetailIdList)) {
-            //将sopDetailIdList转为 逗号分隔的字符串
-            String sopDetailIdListString = StringUtil.longListToString(sopDetailIdList);
-            //判断是否和原有的相同
-            if (!StringUtils.isEmpty(marketingCampaignEntity.getSopDetailIds()) && !marketingCampaignEntity.getSopDetailIds().equals(sopDetailIdListString)) {
-
-                marketingCampaignEntity.setSopDetailIds(sopDetailIdListString);
-                this.updateById(marketingCampaignEntity);
-                //删除原有关联sopDetail
-                LambdaUpdateWrapper<MarketingCampaignSopDetailEntity> MarketingCampaignSopDetailUpdateWrapper = new LambdaUpdateWrapper<>();
-                MarketingCampaignSopDetailUpdateWrapper.eq(MarketingCampaignSopDetailEntity::getMarketingId, marketingCampaignEntity.getId());
-                MarketingCampaignSopDetailUpdateWrapper.set(MarketingCampaignSopDetailEntity::getIsDelete, 1);
-                marketingCampaignSopDetailService.update(MarketingCampaignSopDetailUpdateWrapper);
+//        List<Long> sopDetailIdList = marketingCampaignDTO.getSopDetailIdList();
+        Long sopId = marketingCampaignDTO.getSopId();
+        if (!ObjectUtils.isEmpty(sopId)) {
 
-                List<SopDetailEntity> sopDetailEntityList = sopDetailService.listByIds(sopDetailIdList).stream().toList();
+                LambdaQueryWrapper<SopDetailEntity> sopDetailEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                sopDetailEntityLambdaQueryWrapper.eq(SopDetailEntity::getSopId, sopId);
+                sopDetailEntityLambdaQueryWrapper.eq(SopDetailEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+                List<SopDetailEntity> sopDetailEntityList = sopDetailService.list(sopDetailEntityLambdaQueryWrapper);
                 List<MarketingCampaignSopDetailEntity> marketingCampaignSopDetailEntityList = new ArrayList<>();
                 for (SopDetailEntity sopDetailEntity : sopDetailEntityList) {
                     MarketingCampaignSopDetailEntity marketingCampaignSopDetailEntity = new MarketingCampaignSopDetailEntity();
                     marketingCampaignSopDetailEntity.setMarketingId(marketingCampaignEntity.getId());
                     marketingCampaignSopDetailEntity.setSopDetailId(sopDetailEntity.getId());
+                    marketingCampaignSopDetailEntity.setName(sopDetailEntity.getName());
+                    marketingCampaignSopDetailEntity.setStep(sopDetailEntity.getStep());
+                    marketingCampaignSopDetailEntity.setType(sopDetailEntity.getType());
+                    marketingCampaignSopDetailEntity.setEmailContent(sopDetailEntity.getEmailContent());
                     //预留补充ai生成的邮件内容模板
 //                    marketingCampaignSopDetailEntity.setEmailContent();
                     marketingCampaignSopDetailEntityList.add(marketingCampaignSopDetailEntity);
                 }
                 boolean saveOk = marketingCampaignSopDetailService.saveBatch(marketingCampaignSopDetailEntityList);
 
+
                 //生成每个客户的邮件发送时间
                 marketEmailsService.addSendTime(marketingCampaignEntity);
 
-            }
+
 
         }
         return Result.ok();
@@ -173,6 +208,10 @@ public class MarketingCampaignEntityServiceImpl
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Result<Object> editMarket(MarketingCampaignDTO marketingCampaignDTO) {
+        if (marketingCampaignDTO.getId() == null) {
+            return Result.error("id不能为空");
+        }
+        MarketingCampaignEntity marketingCampaignOld = this.getById(marketingCampaignDTO.getId());
         MarketingCampaignEntity marketingCampaignEntity = new MarketingCampaignEntity();
         BeanUtils.copyProperties(marketingCampaignDTO, marketingCampaignEntity);
         boolean isOk = this.updateById(marketingCampaignEntity);
@@ -180,45 +219,49 @@ public class MarketingCampaignEntityServiceImpl
             return Result.error("修改失败");
         }
         //添加关联客户
-        List<Long> customerIdList = marketingCampaignDTO.getCustomerAnalysisIdList();
+        List<Long> customerIdList = marketingCampaignDTO.getCustomerIdList();
         LambdaUpdateWrapper<CustomerBaseEntity> updateWrapper = new LambdaUpdateWrapper<>();
         updateWrapper.eq(CustomerBaseEntity::getMarketingCampaignId, marketingCampaignEntity.getId());
-        customerBaseEntityService.remove(updateWrapper);
+        customerBaseService.remove(updateWrapper);
         if (!CollectionUtils.isEmpty(customerIdList)) {
             List<CustomerBaseEntity> customerBaseEntityList = new ArrayList<>();
             for (Long customerId : customerIdList) {
                 CustomerBaseEntity customerBaseEntity = new CustomerBaseEntity();
-                customerBaseEntity.setCustomerAnalysisId(customerId);
+                customerBaseEntity.setCustomerId(customerId);
                 customerBaseEntity.setMarketingCampaignId(marketingCampaignEntity.getId());
                 customerBaseEntityList.add(customerBaseEntity);
             }
-            boolean saveOk =customerBaseEntityService.saveBatch(customerBaseEntityList);
+            boolean saveOk = customerBaseService.saveBatch(customerBaseEntityList);
             if (!saveOk){
                 return Result.error("修改失败");
             }
         }
         //添加关联sopDetailIdList,并调取ai生成邮件内容
-        List<Long> sopDetailIdList = marketingCampaignDTO.getSopDetailIdList();
-        if (!CollectionUtils.isEmpty(sopDetailIdList)) {
+        Long sopId = marketingCampaignDTO.getSopId();
+        if (!ObjectUtils.isEmpty(sopId)) {
             //将sopDetailIdList转为 逗号分隔的字符串
-            String sopDetailIdListString = StringUtil.longListToString(sopDetailIdList);
             //判断是否和原有的相同
-            if (!StringUtils.isEmpty(marketingCampaignEntity.getSopDetailIds()) && !marketingCampaignEntity.getSopDetailIds().equals(sopDetailIdListString)) {
+            if (ObjectUtils.isEmpty(marketingCampaignOld.getSopId()) || !sopId.equals(marketingCampaignOld.getSopId())) {
 
-                marketingCampaignEntity.setSopDetailIds(sopDetailIdListString);
-                this.updateById(marketingCampaignEntity);
                 //删除原有关联sopDetail
                 LambdaUpdateWrapper<MarketingCampaignSopDetailEntity> MarketingCampaignSopDetailUpdateWrapper = new LambdaUpdateWrapper<>();
                 MarketingCampaignSopDetailUpdateWrapper.eq(MarketingCampaignSopDetailEntity::getMarketingId, marketingCampaignEntity.getId());
                 MarketingCampaignSopDetailUpdateWrapper.set(MarketingCampaignSopDetailEntity::getIsDelete, 1);
                 marketingCampaignSopDetailService.update(MarketingCampaignSopDetailUpdateWrapper);
 
-                List<SopDetailEntity> sopDetailEntityList = sopDetailService.listByIds(sopDetailIdList).stream().toList();
+                LambdaQueryWrapper<SopDetailEntity> sopDetailEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                sopDetailEntityLambdaQueryWrapper.eq(SopDetailEntity::getSopId, sopId);
+                sopDetailEntityLambdaQueryWrapper.eq(SopDetailEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+                List<SopDetailEntity> sopDetailEntityList = sopDetailService.list(sopDetailEntityLambdaQueryWrapper);
                 List<MarketingCampaignSopDetailEntity> marketingCampaignSopDetailEntityList = new ArrayList<>();
                 for (SopDetailEntity sopDetailEntity : sopDetailEntityList) {
                     MarketingCampaignSopDetailEntity marketingCampaignSopDetailEntity = new MarketingCampaignSopDetailEntity();
                     marketingCampaignSopDetailEntity.setMarketingId(marketingCampaignEntity.getId());
                     marketingCampaignSopDetailEntity.setSopDetailId(sopDetailEntity.getId());
+                    marketingCampaignSopDetailEntity.setName(sopDetailEntity.getName());
+                    marketingCampaignSopDetailEntity.setStep(sopDetailEntity.getStep());
+                    marketingCampaignSopDetailEntity.setType(sopDetailEntity.getType());
+                    marketingCampaignSopDetailEntity.setEmailContent(sopDetailEntity.getEmailContent());
                     //预留补充ai生成的邮件内容模板
 //                    marketingCampaignSopDetailEntity.setEmailContent();
                     marketingCampaignSopDetailEntityList.add(marketingCampaignSopDetailEntity);
@@ -226,6 +269,8 @@ public class MarketingCampaignEntityServiceImpl
                 boolean saveOk = marketingCampaignSopDetailService.saveBatch(marketingCampaignSopDetailEntityList);
             }
 
+            //生成每个客户的邮件发送时间
+            marketEmailsService.addSendTime(marketingCampaignEntity);
         }
         return Result.ok();
     }

+ 20 - 3
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/SopServiceImpl.java

@@ -11,9 +11,11 @@ import com.storlead.trade.dto.SopDetailCreateDTO;
 import com.storlead.trade.dto.SopDetailResponseDTO;
 import com.storlead.trade.dto.SopDetailUpdateDTO;
 import com.storlead.trade.dto.SopResponseDTO;
+import com.storlead.trade.entity.MarketingCampaignEntity;
 import com.storlead.trade.entity.SopDetailEntity;
 import com.storlead.trade.entity.SopEntity;
 import com.storlead.trade.mapper.SopMapper;
+import com.storlead.trade.service.MarketingCampaignService;
 import com.storlead.trade.service.SopDetailService;
 import com.storlead.trade.service.SopService;
 import com.storlead.framework.common.result.Result;
@@ -21,6 +23,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
 
 import javax.annotation.Resource;
 import java.util.List;
@@ -37,6 +41,9 @@ public class SopServiceImpl extends ServiceImpl<SopMapper, SopEntity> implements
 
     @Resource
     private SopDetailService sopDetailService;
+    @Resource
+    private MarketingCampaignService marketingCampaignService;
+
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -67,12 +74,22 @@ public class SopServiceImpl extends ServiceImpl<SopMapper, SopEntity> implements
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void updateSop(Long id, String name, List<SopDetailUpdateDTO> details) {
+    public Result<Object> updateSop(Long id, String name,Long marketId,List<SopDetailUpdateDTO> details) {
         // 1. 更新SOP主表
         SopEntity sop = getById(id);
         if (sop == null) {
-            throw new RuntimeException("SOP不存在,ID: " + id);
+            return Result.error("SOP不存在,ID: " + id);
         }
+        //查询是否已经有使用该sop的营销活动
+        LambdaQueryWrapper<MarketingCampaignEntity> marketWrapper = new LambdaQueryWrapper<>();
+        marketWrapper.eq(MarketingCampaignEntity::getSopId, id);
+        marketWrapper.ne(!ObjectUtils.isEmpty(marketId), MarketingCampaignEntity::getId, marketId);
+        marketWrapper.eq(MarketingCampaignEntity::getIsDelete, 0);
+        List<MarketingCampaignEntity> campaigns = marketingCampaignService.list(marketWrapper);
+        if (!CollectionUtils.isEmpty(campaigns)) {
+            return Result.error("SOP已关联营销活动,无法更新");
+        }
+
         sop.setName(name);
         updateById(sop);
 
@@ -93,7 +110,7 @@ public class SopServiceImpl extends ServiceImpl<SopMapper, SopEntity> implements
             sopDetailService.saveBatch(detailEntities);
         }
 
-        log.info("更新SOP成功,ID: {}", id);
+        return Result.ok("更新SOP成功");
     }
 
     @Override

+ 3 - 3
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/TagEntityServiceImpl.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/TagServiceImpl.java

@@ -6,13 +6,13 @@ import com.storlead.framework.common.constant.DSConstants;
 
 import com.storlead.trade.entity.TagEntity;
 import com.storlead.trade.mapper.TagEntityMapper;
-import com.storlead.trade.service.TagEntityService;
+import com.storlead.trade.service.TagService;
 import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
 import org.springframework.stereotype.Service;
 
 @Service
 @DS(DSConstants.DATASOURCE_TRADE)
-public class TagEntityServiceImpl
+public class TagServiceImpl
         extends MyBaseServiceImpl<TagEntityMapper, TagEntity>
-        implements TagEntityService {
+        implements TagService {
 }

+ 3 - 3
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/TempalteEntityServiceImpl.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/TempalteServiceImpl.java

@@ -6,13 +6,13 @@ import com.storlead.framework.common.constant.DSConstants;
 
 import com.storlead.trade.entity.TemplateEntity;
 import com.storlead.trade.mapper.TemplateEntityMapper;
-import com.storlead.trade.service.TemplateEntityService;
+import com.storlead.trade.service.TemplateService;
 import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
 import org.springframework.stereotype.Service;
 
 @Service
 @DS(DSConstants.DATASOURCE_TRADE)
-public class TempalteEntityServiceImpl
+public class TempalteServiceImpl
         extends MyBaseServiceImpl<TemplateEntityMapper, TemplateEntity>
-        implements TemplateEntityService {
+        implements TemplateService {
 }

+ 3 - 3
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/TempalteTagEntityServiceImpl.java → java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/TempalteTagServiceImpl.java

@@ -6,13 +6,13 @@ import com.storlead.framework.common.constant.DSConstants;
 
 import com.storlead.trade.entity.TemplateTagEntity;
 import com.storlead.trade.mapper.TemplateTagEntityMapper;
-import com.storlead.trade.service.TemplateTagEntityService;
+import com.storlead.trade.service.TemplateTagService;
 import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
 import org.springframework.stereotype.Service;
 
 @Service
 @DS(DSConstants.DATASOURCE_TRADE)
-public class TempalteTagEntityServiceImpl
+public class TempalteTagServiceImpl
         extends MyBaseServiceImpl<TemplateTagEntityMapper, TemplateTagEntity>
-        implements TemplateTagEntityService {
+        implements TemplateTagService {
 }

+ 20 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/CustomerAnalysisResultVO.java

@@ -0,0 +1,20 @@
+package com.storlead.trade.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.storlead.trade.entity.CustomerAnalysisResultEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "CustomerAnalysisResultVO", description = "客户分析结果VO(含客户名称)")
+public class CustomerAnalysisResultVO extends CustomerAnalysisResultEntity {
+
+    @ApiModelProperty(value = "客户名称")
+    private String customerName;
+
+    @ApiModelProperty(value = "客户来源value(对应字典客户来源value)")
+    private String customerSourceDictValue;
+}

+ 21 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/CustomerVO.java

@@ -0,0 +1,21 @@
+package com.storlead.trade.vo;
+
+import com.storlead.trade.entity.CustomerCompanyEntity;
+import com.storlead.trade.entity.CustomerEntity;
+import com.storlead.trade.entity.LiaisonEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "CustomerVO", description = "客户详情VO(含关联企业信息和首要联系人)")
+public class CustomerVO extends CustomerEntity {
+
+    @ApiModelProperty(value = "客户企业信息")
+    private CustomerCompanyEntity customerCompany;
+
+    @ApiModelProperty(value = "首要联系人")
+    private LiaisonEntity liaison;
+}

+ 21 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/MarketingCampaignDetailVO.java

@@ -0,0 +1,21 @@
+package com.storlead.trade.vo;
+
+import com.storlead.trade.entity.MarketingCampaignEntity;
+import com.storlead.trade.entity.MarketingCampaignSopDetailEntity;
+import com.storlead.trade.entity.SopDetailEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel(value = "MarketingCampaignDetailVO", description = "营销活动详情VO")
+public class MarketingCampaignDetailVO {
+
+    @ApiModelProperty(value = "营销活动基本信息")
+    private MarketingCampaignEntity campaign;
+
+    @ApiModelProperty(value = "关联的SOP详情列表")
+    private List<MarketingCampaignSopDetailEntity> sopDetailList;
+}

+ 3 - 2
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/vo/MarketingCampaignVO.java

@@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 import com.storlead.trade.entity.CustomerAnalysisResultEntity;
 import com.storlead.trade.entity.CustomerBaseEntity;
 import com.storlead.framework.mybatis.entity.SysBaseField;
+import com.storlead.trade.entity.CustomerEntity;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -91,7 +92,7 @@ public class MarketingCampaignVO extends SysBaseField {
     private Integer trackConfigReply;
 
     @ApiModelProperty(value = "SOP序列id")
-    private Integer sopId;
+    private Long sopId;
 
     @ApiModelProperty(value = "未打开邮件跟进规则(1是0否)")
     private Integer followUpRulesNotOpened;
@@ -151,5 +152,5 @@ public class MarketingCampaignVO extends SysBaseField {
     private List<Long> customerIdList;
 
     @ApiModelProperty(value = "关联客户信息")
-    private List<CustomerAnalysisResultEntity> customerList;
+    private List<CustomerEntity> customerList;
 }

+ 68 - 0
java/storlead-sasa/storlead-trade/src/main/resources/mapper/CustomerAnalysisResultEntityMapper.xml

@@ -0,0 +1,68 @@
+<?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.storlead.trade.mapper.CustomerAnalysisResultEntityMapper">
+
+    <!-- 联表分页查询:客户分析结果 + 客户基础信息 -->
+    <select id="selectPageWithCustomer" resultType="com.storlead.trade.vo.CustomerAnalysisResultVO">
+        SELECT
+            r.id,
+            r.customer_id,
+            r.analysis_batch_no,
+            r.analysis_scene,
+            r.analysis_status,
+            r.potential_score,
+            r.customer_level,
+            r.confidence,
+            r.priority,
+            r.core_tags,
+            r.reason_summary,
+            r.suggested_actions,
+            r.risk_signals,
+            r.feature_snapshot,
+            r.model_name,
+            r.model_version,
+            r.prompt_version,
+            r.error_code,
+            r.error_message,
+            r.next_follow_up_at,
+            r.analysis_time,
+            r.has_protect,
+            r.has_suspend,
+            c.customer_name
+        FROM customer_analysis_result r
+        LEFT JOIN customer c ON r.customer_id = c.id AND c.is_delete = 0
+        WHERE r.is_delete = 0
+        <!-- 分析结果表筛选条件 -->
+        <if test="dto.customerId != null">
+            AND r.customer_id = #{dto.customerId}
+        </if>
+        <if test="dto.analysisScene != null and dto.analysisScene != ''">
+            AND r.analysis_scene = #{dto.analysisScene}
+        </if>
+        <if test="dto.customerLevel != null and dto.customerLevel != ''">
+            AND r.customer_level = #{dto.customerLevel}
+        </if>
+        <if test="dto.analysisStatus != null">
+            AND r.analysis_status = #{dto.analysisStatus}
+        </if>
+        <if test="dto.priority != null">
+            AND r.priority = #{dto.priority}
+        </if>
+        <!-- customer表筛选条件 -->
+        <if test="dto.customerName != null and dto.customerName != ''">
+            AND c.customer_name LIKE CONCAT('%', #{dto.customerName}, '%')
+        </if>
+        <if test="dto.country != null and dto.country != ''">
+            AND c.country = #{dto.country}
+        </if>
+        <if test="dto.customerStatusDictValue != null and dto.customerStatusDictValue != ''">
+            AND c.customer_status_dict_value = #{dto.customerStatusDictValue}
+        </if>
+        <if test="dto.customerTypeDictValue != null and dto.customerTypeDictValue != ''">
+            AND c.customer_type_dict_value = #{dto.customerTypeDictValue}
+        </if>
+        <!-- 排序:按分析时间倒序 -->
+        ORDER BY r.analysis_time DESC
+    </select>
+
+</mapper>

+ 323 - 0
java/storlead-sasa/storlead-trade/src/main/resources/mapper/CustomerEntityMapper.xml

@@ -0,0 +1,323 @@
+<?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.storlead.trade.mapper.CustomerEntityMapper">
+
+    <!-- CustomerVO 自动映射:继承 CustomerEntity 全部字段 + customerCompany + liaison -->
+
+    <!-- 联表分页查询:客户 + 企业信息 + 首要联系人 -->
+    <select id="selectPageWithRelation" resultType="com.storlead.trade.vo.CustomerVO">
+        SELECT
+            c.id               AS id,
+            c.data_code        AS dataCode,
+            c.customer_form    AS customerForm,
+            c.has_from_clue   AS hasFromClue,
+            c.has_public_customer   AS hasPublicCustomer,
+            c.has_garbage_customer  AS hasGarbageCustomer,
+            c.has_follow_customer   AS hasFollowCustomer,
+            c.customer_code    AS customerCode,
+            c.continent        AS continent,
+            c.country          AS country,
+            c.customer_name    AS customerName,
+            c.collaborator     AS collaborator,
+            c.intended_products_ids    AS intendedProductsIds,
+            c.intended_products_names   AS intendedProductsNames,
+            c.clue_status_dict_value     AS clueStatusDictValue,
+            c.customer_status_dict_value AS customerStatusDictValue,
+            c.customer_source_dict_value AS customerSourceDictValue,
+            c.customer_type_dict_value   AS customerTypeDictValue,
+            c.cooperative_customer_id    AS cooperativeCustomerId,
+            c.customer_level_dict_value  AS customerLevelDictValue,
+            c.customer_credit_level_dict_value  AS customerCreditLevelDictValue,
+            c.customer_economic_nature_dict_value AS customerEconomicNatureDictValue,
+            c.mnemonic_name    AS mnemonicName,
+            c.remark          AS remark,
+            c.opening_bank    AS openingBank,
+            c.tax_number      AS taxNumber,
+            c.bank_account    AS bankAccount,
+            c.reason_public_customer_dict_value AS reasonPublicCustomerDictValue,
+            c.has_order_form  AS hasOrderForm,
+            c.last_follow_up_time AS lastFollowUpTime,
+            c.no_follow_up_date   AS noFollowUpDate,
+            c.public_date     AS publicDate,
+            c.public_remind_date  AS publicRemindDate,
+            c.garbage_date    AS garbageDate,
+            c.garbage_remind_date AS garbageRemindDate,
+            c.delete_date     AS deleteDate,
+            c.delete_remind_date  AS deleteRemindDate,
+            c.owner_time      AS ownerTime,
+            c.give_up_time    AS giveUpTime,
+            c.create_time     AS createTime,
+            c.update_time     AS updateTime,
+            c.is_delete       AS isDelete,
+            c.enabled         AS enabled,
+            c.create_by       AS createBy,
+            c.owner_by        AS ownerBy,
+            c.former_owner_by AS formerOwnerBy,
+            c.next_analysis_date AS nextAnalysisDate,
+            c.update_by       AS updateBy,
+            c.sort            AS sort,
+            <!-- 企业信息 -->
+            cc.id             AS customerCompany.id,
+            cc.customer_id    AS customerCompany.customerId,
+            cc.name           AS customerCompany.name,
+            cc.address        AS customerCompany.address,
+            cc.scale_dict_value AS customerCompany.scaleDictValue,
+            cc.website        AS customerCompany.website,
+            cc.website1       AS customerCompany.website1,
+            cc.website2       AS customerCompany.website2,
+            cc.website3       AS customerCompany.website3,
+            cc.industry       AS customerCompany.industry,
+            cc.communication_address AS customerCompany.communicationAddress,
+            cc.postcode       AS customerCompany.postcode,
+            cc.fax_number     AS customerCompany.faxNumber,
+            cc.email          AS customerCompany.email,
+            cc.email1         AS customerCompany.email1,
+            cc.email2         AS customerCompany.email2,
+            cc.email3         AS customerCompany.email3,
+            cc.telephone      AS customerCompany.telephone,
+            cc.create_time    AS customerCompany.createTime,
+            cc.update_time    AS customerCompany.updateTime,
+            cc.is_delete      AS customerCompany.isDelete,
+            cc.enabled        AS customerCompany.enabled,
+            cc.create_by      AS customerCompany.createBy,
+            cc.owner_by       AS customerCompany.ownerBy,
+            cc.update_by      AS customerCompany.updateBy,
+            cc.sort           AS customerCompany.sort,
+            <!-- 首要联系人 -->
+            l.id              AS liaison.id,
+            l.customer_id     AS liaison.customerId,
+            l.has_primary_lialison   AS liaison.hasPrimaryLialison,
+            l.name            AS liaison.name,
+            l.call            AS liaison.call,
+            l.resource_type  AS liaison.resourceType,
+            l.resource_type_id AS liaison.resourceTypeId,
+            l.liaison_role_dict_value AS liaison.liaisonRoleDictValue,
+            l.birthday        AS liaison.birthday,
+            l.department_position AS liaison.departmentPosition,
+            l.telephone       AS liaison.telephone,
+            l.email           AS liaison.email,
+            l.email1          AS liaison.email1,
+            l.email2          AS liaison.email2,
+            l.email3          AS liaison.email3,
+            l.fax_number      AS liaison.faxNumber,
+            l.postcode        AS liaison.postcode,
+            l.contact_information AS liaison.contactInformation,
+            l.remark          AS liaison.remark,
+            l.qq              AS liaison.qq,
+            l.skype           AS liaison.skype,
+            l.wangwang        AS liaison.wangwang,
+            l.wechat          AS liaison.wechat,
+            l.twitter         AS liaison.twitter,
+            l.linkedin        AS liaison.linkedin,
+            l.facebook        AS liaison.facebook,
+            l.whatsapp        AS liaison.whatsapp,
+            l.fixed_line_telephone AS liaison.fixedLineTelephone,
+            l.home_electricity AS liaison.homeElectricity,
+            l.address         AS liaison.address,
+            l.international_area  AS liaison.internationalArea,
+            l.last_follow_up_time  AS liaison.lastFollowUpTime,
+            l.create_time     AS liaison.createTime,
+            l.update_time     AS liaison.updateTime,
+            l.is_delete       AS liaison.isDelete,
+            l.enabled         AS liaison.enabled,
+            l.create_by       AS liaison.createBy,
+            l.owner_by        AS liaison.ownerBy,
+            l.former_owner_by AS liaison.formerOwnerBy,
+            l.update_by       AS liaison.updateBy,
+            l.sort            AS liaison.sort
+        FROM customer c
+        LEFT JOIN customer_company cc ON cc.customer_id = c.id AND cc.is_delete = 0
+        LEFT JOIN liaison l ON l.customer_id = c.id AND l.is_delete = 0 AND l.has_primary_lialison = 1
+        WHERE c.is_delete = 0
+        <!-- customer 表筛选 -->
+        <if test="dto.id != null">
+            AND c.id = #{dto.id}
+        </if>
+        <if test="dto.customerName != null and dto.customerName != ''">
+            AND c.customer_name LIKE CONCAT('%', #{dto.customerName}, '%')
+        </if>
+        <if test="dto.customerCode != null and dto.customerCode != ''">
+            AND c.customer_code = #{dto.customerCode}
+        </if>
+        <if test="dto.continent != null and dto.continent != ''">
+            AND c.continent = #{dto.continent}
+        </if>
+        <if test="dto.country != null and dto.country != ''">
+            AND c.country = #{dto.country}
+        </if>
+        <if test="dto.customerForm != null">
+            AND c.customer_form = #{dto.customerForm}
+        </if>
+        <if test="dto.customerStatusDictValue != null and dto.customerStatusDictValue != ''">
+            AND c.customer_status_dict_value = #{dto.customerStatusDictValue}
+        </if>
+        <if test="dto.customerTypeDictValue != null and dto.customerTypeDictValue != ''">
+            AND c.customer_type_dict_value = #{dto.customerTypeDictValue}
+        </if>
+        <if test="dto.customerSourceDictValue != null and dto.customerSourceDictValue != ''">
+            AND c.customer_source_dict_value = #{dto.customerSourceDictValue}
+        </if>
+        <if test="dto.customerLevelDictValue != null and dto.customerLevelDictValue != ''">
+            AND c.customer_level_dict_value = #{dto.customerLevelDictValue}
+        </if>
+        <if test="dto.customerCreditLevelDictValue != null and dto.customerCreditLevelDictValue != ''">
+            AND c.customer_credit_level_dict_value = #{dto.customerCreditLevelDictValue}
+        </if>
+        <if test="dto.customerEconomicNatureDictValue != null and dto.customerEconomicNatureDictValue != ''">
+            AND c.customer_economic_nature_dict_value = #{dto.customerEconomicNatureDictValue}
+        </if>
+        <if test="dto.hasFollowCustomer != null">
+            AND c.has_follow_customer = #{dto.hasFollowCustomer}
+        </if>
+        <if test="dto.hasPublicCustomer != null">
+            AND c.has_public_customer = #{dto.hasPublicCustomer}
+        </if>
+        <if test="dto.hasGarbageCustomer != null">
+            AND c.has_garbage_customer = #{dto.hasGarbageCustomer}
+        </if>
+        <if test="dto.hasOrderForm != null">
+            AND c.has_order_form = #{dto.hasOrderForm}
+        </if>
+        <!-- 联表筛选:customer_company -->
+        <if test="dto.companyName != null and dto.companyName != ''">
+            AND cc.name LIKE CONCAT('%', #{dto.companyName}, '%')
+        </if>
+        <!-- 联表筛选:liaison -->
+        <if test="dto.liaisonName != null and dto.liaisonName != ''">
+            AND l.name LIKE CONCAT('%', #{dto.liaisonName}, '%')
+        </if>
+        <if test="dto.liaisonTelephone != null and dto.liaisonTelephone != ''">
+            AND l.telephone = #{dto.liaisonTelephone}
+        </if>
+        <if test="dto.liaisonEmail != null and dto.liaisonEmail != ''">
+            AND l.email = #{dto.liaisonEmail}
+        </if>
+        ORDER BY c.create_time DESC
+    </select>
+
+    <!-- 根据客户ID查询详情(含企业信息+首要联系人) -->
+    <select id="selectDetailByCustomerId" resultType="com.storlead.trade.vo.CustomerVO">
+        SELECT
+            c.id               AS id,
+            c.data_code        AS dataCode,
+            c.customer_form   AS customerForm,
+            c.has_from_clue    AS hasFromClue,
+            c.has_public_customer  AS hasPublicCustomer,
+            c.has_garbage_customer AS hasGarbageCustomer,
+            c.has_follow_customer  AS hasFollowCustomer,
+            c.customer_code    AS customerCode,
+            c.continent        AS continent,
+            c.country          AS country,
+            c.customer_name    AS customerName,
+            c.collaborator     AS collaborator,
+            c.intended_products_ids   AS intendedProductsIds,
+            c.intended_products_names  AS intendedProductsNames,
+            c.clue_status_dict_value    AS clueStatusDictValue,
+            c.customer_status_dict_value  AS customerStatusDictValue,
+            c.customer_source_dict_value  AS customerSourceDictValue,
+            c.customer_type_dict_value    AS customerTypeDictValue,
+            c.cooperative_customer_id     AS cooperativeCustomerId,
+            c.customer_level_dict_value   AS customerLevelDictValue,
+            c.customer_credit_level_dict_value AS customerCreditLevelDictValue,
+            c.customer_economic_nature_dict_value AS customerEconomicNatureDictValue,
+            c.mnemonic_name     AS mnemonicName,
+            c.remark           AS remark,
+            c.opening_bank     AS openingBank,
+            c.tax_number       AS taxNumber,
+            c.bank_account     AS bankAccount,
+            c.reason_public_customer_dict_value AS reasonPublicCustomerDictValue,
+            c.has_order_form   AS hasOrderForm,
+            c.last_follow_up_time  AS lastFollowUpTime,
+            c.no_follow_up_date   AS noFollowUpDate,
+            c.public_date      AS publicDate,
+            c.public_remind_date  AS publicRemindDate,
+            c.garbage_date     AS garbageDate,
+            c.garbage_remind_date AS garbageRemindDate,
+            c.delete_date      AS deleteDate,
+            c.delete_remind_date AS deleteRemindDate,
+            c.owner_time       AS ownerTime,
+            c.give_up_time     AS giveUpTime,
+            c.create_time      AS createTime,
+            c.update_time      AS updateTime,
+            c.is_delete        AS isDelete,
+            c.enabled          AS enabled,
+            c.create_by        AS createBy,
+            c.owner_by         AS ownerBy,
+            c.former_owner_by  AS formerOwnerBy,
+            c.next_analysis_date AS nextAnalysisDate,
+            c.update_by        AS updateBy,
+            c.sort             AS sort,
+            cc.id              AS customerCompany.id,
+            cc.customer_id     AS customerCompany.customerId,
+            cc.name            AS customerCompany.name,
+            cc.address         AS customerCompany.address,
+            cc.scale_dict_value  AS customerCompany.scaleDictValue,
+            cc.website         AS customerCompany.website,
+            cc.website1        AS customerCompany.website1,
+            cc.website2        AS customerCompany.website2,
+            cc.website3        AS customerCompany.website3,
+            cc.industry        AS customerCompany.industry,
+            cc.communication_address AS customerCompany.communicationAddress,
+            cc.postcode        AS customerCompany.postcode,
+            cc.fax_number      AS customerCompany.faxNumber,
+            cc.email           AS customerCompany.email,
+            cc.email1          AS customerCompany.email1,
+            cc.email2          AS customerCompany.email2,
+            cc.email3          AS customerCompany.email3,
+            cc.telephone       AS customerCompany.telephone,
+            cc.create_time     AS customerCompany.createTime,
+            cc.update_time      AS customerCompany.updateTime,
+            cc.is_delete        AS customerCompany.isDelete,
+            cc.enabled          AS customerCompany.enabled,
+            cc.create_by        AS customerCompany.createBy,
+            cc.owner_by         AS customerCompany.ownerBy,
+            cc.update_by        AS customerCompany.updateBy,
+            cc.sort             AS customerCompany.sort,
+            l.id               AS liaison.id,
+            l.customer_id      AS liaison.customerId,
+            l.has_primary_lialison    AS liaison.hasPrimaryLialison,
+            l.name             AS liaison.name,
+            l.call             AS liaison.call,
+            l.resource_type    AS liaison.resourceType,
+            l.resource_type_id AS liaison.resourceTypeId,
+            l.liaison_role_dict_value  AS liaison.liaisonRoleDictValue,
+            l.birthday         AS liaison.birthday,
+            l.department_position  AS liaison.departmentPosition,
+            l.telephone        AS liaison.telephone,
+            l.email            AS liaison.email,
+            l.email1           AS liaison.email1,
+            l.email2           AS liaison.email2,
+            l.email3           AS liaison.email3,
+            l.fax_number       AS liaison.faxNumber,
+            l.postcode         AS liaison.postcode,
+            l.contact_information  AS liaison.contactInformation,
+            l.remark           AS liaison.remark,
+            l.qq               AS liaison.qq,
+            l.skype            AS liaison.skype,
+            l.wangwang         AS liaison.wangwang,
+            l.wechat           AS liaison.wechat,
+            l.twitter          AS liaison.twitter,
+            l.linkedin         AS liaison.linkedin,
+            l.facebook         AS liaison.facebook,
+            l.whatsapp         AS liaison.whatsapp,
+            l.fixed_line_telephone  AS liaison.fixedLineTelephone,
+            l.home_electricity AS liaison.homeElectricity,
+            l.address          AS liaison.address,
+            l.international_area    AS liaison.internationalArea,
+            l.last_follow_up_time   AS liaison.lastFollowUpTime,
+            l.create_time      AS liaison.createTime,
+            l.update_time      AS liaison.updateTime,
+            l.is_delete        AS liaison.isDelete,
+            l.enabled          AS liaison.enabled,
+            l.create_by        AS liaison.createBy,
+            l.owner_by         AS liaison.ownerBy,
+            l.former_owner_by  AS liaison.formerOwnerBy,
+            l.update_by        AS liaison.updateBy,
+            l.sort             AS liaison.sort
+        FROM customer c
+        LEFT JOIN customer_company cc ON cc.customer_id = c.id AND cc.is_delete = 0
+        LEFT JOIN liaison l ON l.customer_id = c.id AND l.is_delete = 0 AND l.has_primary_lialison = 1
+        WHERE c.is_delete = 0 AND c.id = #{customerId}
+    </select>
+
+</mapper>