gongchunyi
5 天以前 41b041d72e7451595f9d3e2c25549e57444164fa
feat: 客户档案修改为按照地区进行区分
已添加7个文件
已修改6个文件
596 ■■■■ 文件已修改
doc/河南鹤壁天沐钢化玻璃厂.sql 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/CustomerController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/CustomerRegionsController.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/CustomerDto.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/CustomerRegionsTreeDto.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/CustomerRegionsMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/Customer.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/CustomerRegions.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/ICustomerRegionsService.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/ICustomerService.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/CustomerRegionsServiceImpl.java 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java 121 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/CustomerRegionsMapper.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/ºÓÄϺױÚÌìãå¸Ö»¯²£Á§³§.sql
@@ -61,4 +61,27 @@
ALTER TABLE `product-inventory-management-hbtmblc`.`process_route_item`
    MODIFY COLUMN `product_model_id` bigint NULL DEFAULT 0 COMMENT '产品id' AFTER `route_id`,
    MODIFY COLUMN `process_id` bigint NULL DEFAULT 0 COMMENT '工序id' AFTER `product_model_id`,
    ADD COLUMN `process_name` varchar(255) NULL COMMENT '工序名称' AFTER `process_id`;
    ADD COLUMN `process_name` varchar(255) NULL COMMENT '工序名称' AFTER `process_id`;
-- ----------------------------
-- Table structure for customer_regions
-- ----------------------------
DROP TABLE IF EXISTS `customer_regions`;
CREATE TABLE `customer_regions`
(
    `id`           bigint                                                        NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    `parent_id`    bigint                                                        NULL DEFAULT NULL COMMENT '父类ID',
    `regions_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '地区名称',
    `tenant_id`    bigint                                                        NULL DEFAULT NULL COMMENT '租户ID',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
  CHARACTER SET = utf8mb3
  COLLATE = utf8mb3_general_ci
  ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
ALTER TABLE `product-inventory-management-hbtmblc`.`customer_regions` COMMENT = '客户地区表';
ALTER TABLE `product-inventory-management-hbtmblc`.`customer`
    ADD COLUMN `regions_id` bigint NULL COMMENT '地区ID' AFTER `regions`;
src/main/java/com/ruoyi/basic/controller/CustomerController.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.dto.CustomerDto;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.basic.service.ICustomerService;
import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -9,7 +10,6 @@
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -33,7 +33,7 @@
     * æŸ¥è¯¢å®¢æˆ·æ¡£æ¡ˆåˆ—表
     */
    @GetMapping("/list")
    public IPage<Customer> list(Page<Customer> page, Customer customer) {
    public IPage<CustomerDto> list(Page<Customer> page, Customer customer) {
        return customerService.selectCustomerList(page, customer);
    }
@@ -118,10 +118,4 @@
        return customerService.customerList(customer);
    }
    @GetMapping("/regions")
    @ApiOperation("获取客户地区")
    public AjaxResult getRegions() {
        List<String> regionsList = customerService.regionsList();
        return AjaxResult.success(regionsList);
    }
}
src/main/java/com/ruoyi/basic/controller/CustomerRegionsController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.ruoyi.basic.controller;
import com.ruoyi.basic.dto.CustomerRegionsTreeDto;
import com.ruoyi.basic.pojo.CustomerRegions;
import com.ruoyi.basic.service.ICustomerRegionsService;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * <p>
 * å®¢æˆ·åœ°åŒºè¡¨ å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author deslrey
 * @since 2026-03-27
 */
@RestController
@RequestMapping("/customerRegions")
public class CustomerRegionsController {
    @Autowired
    private ICustomerRegionsService customerRegionsService;
    @GetMapping("list")
    @ApiOperation("客户地区-列表")
    public AjaxResult customerRegionsList(CustomerRegions customerRegions) {
        List<CustomerRegionsTreeDto> list = customerRegionsService.customerRegionsList(customerRegions);
        return AjaxResult.success(list);
    }
    @PostMapping("/add")
    @ApiOperation("客户地区-新增")
    public AjaxResult addCustomerRegions(@RequestBody CustomerRegions customerRegions) {
        customerRegionsService.addCustomerRegions(customerRegions);
        return AjaxResult.success();
    }
    @PutMapping("/update")
    @ApiOperation("客户地区-更新")
    public AjaxResult updateCustomerRegions(@RequestBody CustomerRegions customerRegions) {
        customerRegionsService.updateCustomerRegions(customerRegions);
        return AjaxResult.success();
    }
    @DeleteMapping("/{id}")
    @ApiOperation("客户地区-删除")
    public AjaxResult delCustomerRegions(@PathVariable Long id) {
        customerRegionsService.delCustomerRegions(id);
        return AjaxResult.success();
    }
}
src/main/java/com/ruoyi/basic/dto/CustomerDto.java
@@ -1,6 +1,7 @@
package com.ruoyi.basic.dto;
import com.ruoyi.basic.pojo.Customer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -21,4 +22,10 @@
    private List<CustomerFollowUpDto> followUpList;
    /**
     * åœ°åŒº
     */
    @ApiModelProperty("地区")
    private String regionsName;
}
src/main/java/com/ruoyi/basic/dto/CustomerRegionsTreeDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
package com.ruoyi.basic.dto;
import lombok.Data;
import java.util.List;
/**
 * <br>
 * å®¢æˆ·åœ°åŒºæ ‘å½¢Dto
 * </br>
 *
 * @author deslrey
 * @version 1.0
 * @since 2026/03/27 11:41
 */
@Data
public class CustomerRegionsTreeDto {
    /**
     * ID
     */
    private Long id;
    /**
     * çˆ¶ç±»ID
     */
    private Long parentId;
    /**
     * åœ°åŒºåç§°
     */
    private String regionsName;
    /**
     * åœ°åŒºæ ‡ç­¾
     */
    private String label;
    /**
     * å­åœ°åŒº
     */
    private List<CustomerRegionsTreeDto> children;
}
src/main/java/com/ruoyi/basic/mapper/CustomerRegionsMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.basic.mapper;
import com.ruoyi.basic.pojo.CustomerRegions;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
 * <p>
 * å®¢æˆ·åœ°åŒºè¡¨ Mapper æŽ¥å£
 * </p>
 *
 * @author deslrey
 * @since 2026-03-27
 */
public interface CustomerRegionsMapper extends BaseMapper<CustomerRegions> {
}
src/main/java/com/ruoyi/basic/pojo/Customer.java
@@ -29,6 +29,12 @@
    private Long id;
    /**
     * åœ°åŒºID
     */
    @ApiModelProperty("地区ID")
    private Long regionsId;
    /**
     * å®¢æˆ·åç§°
     */
    @Excel(name = "客户名称")
@@ -117,7 +123,4 @@
    @Excel(name = "开户行号")
    private String bankCode;
    @ApiModelProperty("地区")
    @Excel(name = "地区")
    private String regions;
}
src/main/java/com/ruoyi/basic/pojo/CustomerRegions.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
package com.ruoyi.basic.pojo;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
 * <p>
 * å®¢æˆ·åœ°åŒºè¡¨
 * </p>
 *
 * @author deslrey
 * @since 2026-03-27
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("customer_regions")
@ApiModel(value = "CustomerRegions对象", description = "客户地区表")
public class CustomerRegions implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "主键ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @ApiModelProperty(value = "父类ID")
    private Long parentId;
    @ApiModelProperty(value = "地区名称")
    private String regionsName;
    @ApiModelProperty(value = "租户ID")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
}
src/main/java/com/ruoyi/basic/service/ICustomerRegionsService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.basic.service;
import com.ruoyi.basic.dto.CustomerRegionsTreeDto;
import com.ruoyi.basic.pojo.CustomerRegions;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
 * <p>
 * å®¢æˆ·åœ°åŒºè¡¨ æœåŠ¡ç±»
 * </p>
 *
 * @author deslrey
 * @since 2026-03-27
 */
public interface ICustomerRegionsService extends IService<CustomerRegions> {
    List<CustomerRegionsTreeDto> customerRegionsList(CustomerRegions customerRegions);
    void addCustomerRegions(CustomerRegions customerRegions);
    void updateCustomerRegions(CustomerRegions customerRegions);
    void delCustomerRegions(Long id);
    List<Long> regionsChildrenIds(Long regionsId);
}
src/main/java/com/ruoyi/basic/service/ICustomerService.java
@@ -40,7 +40,7 @@
     * @param customer å®¢æˆ·æ¡£æ¡ˆ
     * @return å®¢æˆ·æ¡£æ¡ˆé›†åˆ
     */
    IPage<Customer> selectCustomerList(Page<Customer> page, Customer customer);
    IPage<CustomerDto> selectCustomerList(Page<Customer> page, Customer customer);
    /**
     * æ–°å¢žå®¢æˆ·æ¡£æ¡ˆ
@@ -78,7 +78,4 @@
    List<Customer> selectCustomerLists(Customer customer);
    AjaxResult importData(MultipartFile file);
    List<String> regionsList();
}
src/main/java/com/ruoyi/basic/service/impl/CustomerRegionsServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,216 @@
package com.ruoyi.basic.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.dto.CustomerRegionsTreeDto;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.mapper.CustomerRegionsMapper;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.basic.pojo.CustomerRegions;
import com.ruoyi.basic.service.ICustomerRegionsService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * å®¢æˆ·åœ°åŒºè¡¨ æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author deslrey
 * @since 2026-03-27
 */
@Service
public class CustomerRegionsServiceImpl extends ServiceImpl<CustomerRegionsMapper, CustomerRegions> implements ICustomerRegionsService {
    @Autowired
    private CustomerMapper customerMapper;
    /**
     * æŸ¥è¯¢æ ‘形地区列表
     */
    @Override
    public List<CustomerRegionsTreeDto> customerRegionsList(CustomerRegions customerRegions) {
        List<CustomerRegions> allRegions = baseMapper.selectList(null);
        if (allRegions == null || allRegions.isEmpty()) {
            return new ArrayList<>();
        }
        Map<Long, CustomerRegionsTreeDto> nodeMap = new HashMap<>();
        List<CustomerRegionsTreeDto> allDtoList = new ArrayList<>();
        for (CustomerRegions region : allRegions) {
            CustomerRegionsTreeDto dto = new CustomerRegionsTreeDto();
            dto.setId(region.getId());
            dto.setParentId(region.getParentId());
            dto.setRegionsName(region.getRegionsName());
            dto.setLabel(region.getRegionsName()); // ç»Ÿä¸€ label å­—段
            dto.setChildren(new ArrayList<>());
            nodeMap.put(dto.getId(), dto);
            allDtoList.add(dto);
        }
        List<CustomerRegionsTreeDto> treeList = new ArrayList<>();
        for (CustomerRegionsTreeDto node : allDtoList) {
            Long parentId = node.getParentId();
            // å¦‚果是根节点 (parentId ä¸º 0 æˆ– null) æˆ– æ‰¾ä¸åˆ°çˆ¶èŠ‚ç‚¹ï¼Œåˆ™ä½œä¸ºé¡¶çº§èŠ‚ç‚¹
            if (parentId == null || parentId == 0 || !nodeMap.containsKey(parentId)) {
                treeList.add(node);
            } else {
                // å¦åˆ™å°†å…¶æ·»åŠ åˆ°çˆ¶èŠ‚ç‚¹çš„ children ä¸­
                nodeMap.get(parentId).getChildren().add(node);
            }
        }
        String keyword = customerRegions != null ? customerRegions.getRegionsName() : null;
        if (StringUtils.isNotEmpty(keyword)) {
            return filterTree(treeList, keyword);
        }
        return treeList;
    }
    /**
     * é€’归过滤树节点
     */
    private List<CustomerRegionsTreeDto> filterTree(List<CustomerRegionsTreeDto> list, String keyword) {
        List<CustomerRegionsTreeDto> filteredList = new ArrayList<>();
        for (CustomerRegionsTreeDto node : list) {
            // é€’归处理子节点
            List<CustomerRegionsTreeDto> filteredChildren = filterTree(node.getChildren(), keyword);
            node.setChildren(filteredChildren);
            // å¦‚果当前节点名称包含关键字,或者子节点过滤后不为空,则保留该节点
            if (node.getRegionsName().contains(keyword) || !filteredChildren.isEmpty()) {
                filteredList.add(node);
            }
        }
        return filteredList;
    }
    /**
     * æ·»åŠ åœ°åŒº
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCustomerRegions(CustomerRegions customerRegions) {
        validateRegion(customerRegions);
        checkUnique(customerRegions);
        if (baseMapper.insert(customerRegions) <= 0) {
            throw new ServiceException("添加失败");
        }
    }
    /**
     * ä¿®æ”¹åœ°åŒº
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCustomerRegions(CustomerRegions customerRegions) {
        if (customerRegions.getId() == null) {
            throw new ServiceException("修改失败, ID不能为空");
        }
        validateRegion(customerRegions);
        if (customerRegions.getId().equals(customerRegions.getParentId())) {
            throw new ServiceException("修改失败, ä¸Šçº§åœ°åŒºä¸èƒ½æ˜¯è‡ªå·±");
        }
        checkUnique(customerRegions);
        if (baseMapper.updateById(customerRegions) <= 0) {
            throw new ServiceException("修改失败");
        }
    }
    /**
     * åˆ é™¤åœ°åŒº
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delCustomerRegions(Long id) {
        if (id == null) {
            throw new ServiceException("删除失败, ID不能为空");
        }
        boolean hasChildren = baseMapper.selectCount(new LambdaQueryWrapper<CustomerRegions>()
                .eq(CustomerRegions::getParentId, id)) > 0;
        if (hasChildren) {
            throw new ServiceException("删除失败, è¯¥åœ°åŒºä¸‹å­˜åœ¨å­åœ°åŒº");
        }
        boolean isUsedByCustomer = customerMapper.selectCount(new LambdaQueryWrapper<Customer>()
                .eq(Customer::getRegionsId, id)) > 0;
        if (isUsedByCustomer) {
            throw new ServiceException("删除失败, è¯¥åœ°åŒºå·²è¢«å®¢æˆ·æ¡£æ¡ˆå¼•用");
        }
        if (baseMapper.deleteById(id) <= 0) {
            throw new ServiceException("删除失败, æ•°æ®ä¸å­˜åœ¨");
        }
    }
    /**
     * æŸ¥è¯¢å½“前地区及其所有子集的 ID é›†åˆ
     */
    @Override
    public List<Long> regionsChildrenIds(Long regionsId) {
        List<Long> childIds = new ArrayList<>();
        if (regionsId == null) {
            return childIds;
        }
        List<CustomerRegions> allRegions = baseMapper.selectList(null);
        if (allRegions == null || allRegions.isEmpty()) {
            return childIds;
        }
        childIds.add(regionsId);
        findAllChildren(allRegions, regionsId, childIds);
        return childIds;
    }
    /**
     * é€’归地区方法
     *
     * @param allRegions æ‰€æœ‰åœ°åŒºåˆ—表
     * @param parentId   å½“前父级 ID
     * @param result     å­˜æ”¾ç»“果的集合
     */
    private void findAllChildren(List<CustomerRegions> allRegions, Long parentId, List<Long> result) {
        for (CustomerRegions region : allRegions) {
            // åˆ¤æ–­ parentId æ˜¯å¦åŒ¹é…
            if (parentId.equals(region.getParentId())) {
                result.add(region.getId());
                // ç»§ç»­é€’归查找该节点的子节点
                findAllChildren(allRegions, region.getId(), result);
            }
        }
    }
    private void validateRegion(CustomerRegions region) {
        if (region == null) {
            throw new ServiceException("操作失败, æ•°æ®ä¸èƒ½ä¸ºç©º");
        }
        if (StringUtils.isEmpty(region.getRegionsName())) {
            throw new ServiceException("操作失败, åœ°åŒºåç§°ä¸èƒ½ä¸ºç©º");
        }
        if (region.getParentId() == null) {
            region.setParentId(0L);
        }
    }
    private void checkUnique(CustomerRegions region) {
        CustomerRegions existing = baseMapper.selectOne(new LambdaQueryWrapper<CustomerRegions>()
                .eq(CustomerRegions::getRegionsName, region.getRegionsName())
                .eq(CustomerRegions::getParentId, region.getParentId())
                .ne(region.getId() != null, CustomerRegions::getId, region.getId()));
        if (existing != null) {
            throw new ServiceException("该层级下已存在名为 [" + region.getRegionsName() + "] çš„地区");
        }
    }
}
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -1,8 +1,6 @@
package com.ruoyi.basic.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -15,16 +13,13 @@
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.basic.pojo.CustomerFollowUp;
import com.ruoyi.basic.pojo.CustomerFollowUpFile;
import com.ruoyi.basic.service.CustomerFollowUpFileService;
import com.ruoyi.basic.service.CustomerFollowUpService;
import com.ruoyi.basic.service.CustomerReturnVisitService;
import com.ruoyi.basic.service.ICustomerService;
import com.ruoyi.basic.pojo.CustomerRegions;
import com.ruoyi.basic.service.*;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.pojo.SalesLedger;
import lombok.AllArgsConstructor;
@@ -35,9 +30,10 @@
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -59,6 +55,8 @@
    private CustomerFollowUpFileService customerFollowUpFileService;
    private CustomerReturnVisitService customerReturnVisitService;
    private final ICustomerRegionsService customerRegionsService;
    /**
     * æŸ¥è¯¢å®¢æˆ·æ¡£æ¡ˆ
@@ -111,73 +109,87 @@
            dto.setFollowUpList(followUpDtoList);
        }
        //  åœ°åŒºåç§°
        CustomerRegions customerRegions = customerRegionsService.getById(customer.getRegionsId());
        dto.setRegionsName(customerRegions.getRegionsName());
        return dto;
    }
    /**
     * æŸ¥è¯¢å®¢æˆ·æ¡£æ¡ˆåˆ—表
     *
     * @param customer å®¢æˆ·æ¡£æ¡ˆ
     * @return å®¢æˆ·æ¡£æ¡ˆ
     * @param page     åˆ†é¡µå¯¹è±¡
     * @param customer å®¢æˆ·æŸ¥è¯¢æ¡ä»¶
     * @return å®¢æˆ·æ¡£æ¡ˆåˆ†é¡µåˆ—表
     */
    @Override
    public IPage<Customer> selectCustomerList(Page<Customer> page, Customer customer) {
        // 1. å¤„理空值场景(参数校验)
        if (page == null) {
            page = Page.of(1, 10); // é»˜è®¤ç¬¬1页,每页10条数据
        }
        if (customer == null) {
            customer = new Customer(); // é¿å…ç©ºå¯¹è±¡å¯¼è‡´çš„NPE
        }
    public IPage<CustomerDto> selectCustomerList(Page<Customer> page, Customer customer) {
        if (page == null) page = Page.of(1, 10);
        if (customer == null) customer = new Customer();
        // 2. æž„建查询条件(增强空值安全)
        LambdaQueryWrapper<Customer> queryWrapper = new LambdaQueryWrapper<>();
        String customerName = customer.getCustomerName();
        String customerType = customer.getCustomerType();
        Long regionsId = customer.getRegionsId();
        if (StringUtils.isNotBlank(customerName)) {
            queryWrapper.like(Customer::getCustomerName, customerName);
        }
        if (StringUtils.isNotBlank(customerType)) {
            queryWrapper.like(Customer::getCustomerType, customerType);
            queryWrapper.eq(Customer::getCustomerType, customerType);
        }
        // 3. æ‰§è¡Œåˆ†é¡µæŸ¥è¯¢ï¼ˆä¿ç•™åˆ†é¡µå…ƒæ•°æ®ï¼‰
        if (regionsId != null) {
            // è°ƒç”¨ regionsService èŽ·å–å½“å‰åœ°åŒºåŠå…¶æ‰€æœ‰åŽä»£çš„ ID é›†åˆ
            List<Long> allRegionsIds = customerRegionsService.regionsChildrenIds(regionsId);
            if (!CollectionUtils.isEmpty(allRegionsIds)) {
                queryWrapper.in(Customer::getRegionsId, allRegionsIds);
            } else {
                queryWrapper.eq(Customer::getRegionsId, regionsId);
            }
        }
        IPage<Customer> customerPage = customerMapper.selectPage(page, queryWrapper);
        // 4. æ•°æ®å¤„理(增强空值安全 & ä»£ç å¯è¯»æ€§ï¼‰
        List<Customer> processedList = customerPage.getRecords().stream()
                .filter(Objects::nonNull) // è¿‡æ»¤ç©ºå¯¹è±¡ï¼ˆé¿å…åŽç»­æ“ä½œNPE)
                .peek(c -> {
                    // å®‰å…¨èŽ·å–å­—æ®µï¼Œé¿å…null值拼接
        List<CustomerDto> dtoList = customerPage.getRecords().stream()
                .filter(Objects::nonNull)
                .map(c -> {
                    CustomerDto dto = new CustomerDto();
                    BeanUtils.copyProperties(c, dto);
                    // åœ°å€ç”µè¯æ‹¼æŽ¥
                    String address = StringUtils.defaultString(c.getCompanyAddress(), "");
                    String phone = StringUtils.defaultString(c.getCompanyPhone(), "");
                    c.setAddressPhone(address + "(" + phone + ")");
                    dto.setAddressPhone(address + "(" + phone + ")");
                    // å¡«å……地区名称
                    if (c.getRegionsId() != null) {
                        CustomerRegions regions = customerRegionsService.getById(c.getRegionsId());
                        if (regions != null) {
                            dto.setRegionsName(regions.getRegionsName());
                        }
                    }
                    // æŸ¥è¯¢æœ€æ–°çš„跟进记录
                    CustomerFollowUp followUp = customerFollowUpService.getOne(
                            new LambdaQueryWrapper<CustomerFollowUp>()
                                    .eq(CustomerFollowUp::getCustomerId, c.getId())
                                    .orderByDesc(CustomerFollowUp::getFollowUpTime)
                                    .last("LIMIT 1")
                    );
                    if (followUp != null) {
                        c.setFollowUpLevel(followUp.getFollowUpLevel());
                        c.setFollowUpTime(
                                Date.from(
                                        followUp.getFollowUpTime().atZone(ZoneId.systemDefault()).toInstant()
                                )
                        );
                    }
//                    CustomerFollowUp followUp = customerFollowUpService.getOne(
//                            new LambdaQueryWrapper<CustomerFollowUp>()
//                                    .eq(CustomerFollowUp::getCustomerId, c.getId())
//                                    .orderByDesc(CustomerFollowUp::getFollowUpTime)
//                                    .last("LIMIT 1")
//                    );
//
//                    if (followUp != null) {
//                        dto.setFollowUpLevel(followUp.getFollowUpLevel());
//                        dto.setFollowUpTime(Date.from(followUp.getFollowUpTime().atZone(ZoneId.systemDefault()).toInstant()));
//                    }
                    return dto;
                })
                .collect(Collectors.toList());
        // 5. æ›´æ–°åˆ†é¡µç»“果中的数据(保持分页信息完整)
        IPage<Customer> resultPage = new Page<>(customerPage.getCurrent(), customerPage.getSize(), customerPage.getTotal());
        resultPage.setRecords(processedList);
        IPage<CustomerDto> resultPage = new Page<>(customerPage.getCurrent(), customerPage.getSize(), customerPage.getTotal());
        resultPage.setRecords(dtoList);
        return customerPage; // è¿”回包含分页信息的IPage对象
        return resultPage;
    }
    /**
@@ -274,17 +286,6 @@
                        entry -> underlineToCamel(entry.getKey()),
                        Map.Entry::getValue))
        ).collect(Collectors.toList());
    }
    @Override
    public List<String> regionsList() {
        return this.baseMapper.selectObjs(new QueryWrapper<Customer>()
                        .select("DISTINCT regions")
                        .isNotNull("regions")
                        .ne("regions", "")
                ).stream()
                .map(Object::toString)
                .collect(Collectors.toList());
    }
    /**
src/main/resources/mapper/basic/CustomerRegionsMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
<?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.ruoyi.basic.mapper.CustomerRegionsMapper">
    <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.CustomerRegions">
        <id column="id" property="id" />
        <result column="parent_id" property="parentId" />
        <result column="regions_name" property="regionsName" />
        <result column="tenant_id" property="tenantId" />
    </resultMap>
</mapper>