From 899589cf87f7b1b31de27d04320161bf9327cefc Mon Sep 17 00:00:00 2001 From: wuweihua <1583622118@qq.com> Date: Sat, 10 Oct 2026 09:40:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E6=89=B9=E9=87=8F=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E4=BB=B7=E6=A0=BC=E5=A5=97=E9=A4=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BmsCustomerPriceSetController.java | 14 ++ .../customerinfo/domain/BmsCustomer.java | 7 + .../domain/BmsCustomerPriceSetBatch.java | 44 +++++ .../service/IBmsCustomerPriceSetService.java | 7 + .../impl/BmsCustomerPriceSetServiceImpl.java | 94 ++++++++++ .../mapper/customer/BmsCustomerMapper.xml | 8 +- .../customerinfo/customerPriceSet.js | 9 + .../customerinfo/index.vue | 176 ++++++++++++++++++ 8 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/domain/BmsCustomerPriceSetBatch.java diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/customer/customerinfo/BmsCustomerPriceSetController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/customer/customerinfo/BmsCustomerPriceSetController.java index 3b5b7d66..ba9a0c87 100644 --- a/bms-back/bms-admin/src/main/java/com/bms/web/controller/customer/customerinfo/BmsCustomerPriceSetController.java +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/customer/customerinfo/BmsCustomerPriceSetController.java @@ -15,6 +15,7 @@ import com.bms.common.core.controller.BaseController; import com.bms.common.core.domain.AjaxResult; import com.bms.common.enums.BusinessType; import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet; +import com.bms.customer.customerinfo.domain.BmsCustomerPriceSetBatch; import com.bms.customer.customerinfo.domain.BmsPriceSetOption; import com.bms.customer.customerinfo.service.IBmsCustomerPriceSetService; @@ -65,6 +66,19 @@ public class BmsCustomerPriceSetController extends BaseController return toAjax(customerPriceSetService.saveBind(bind)); } + /** + * 批量绑定套餐(客户管理列表勾选多个客户;一个客户仅一个套餐,已绑定可选择覆盖或跳过) + */ + @PreAuthorize("@ss.hasPermi('customersupplier:customerinfo:edit')") + @Log(title = "客户套餐批量绑定", businessType = BusinessType.UPDATE) + @PostMapping("/bind/batch") + public AjaxResult batchBind(@RequestBody BmsCustomerPriceSetBatch req) + { + req.setCreateBy(getUsername()); + req.setUpdateBy(getUsername()); + return success(customerPriceSetService.batchBind(req)); + } + /** * 解绑客户套餐 */ diff --git a/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/domain/BmsCustomer.java b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/domain/BmsCustomer.java index f2734e38..9d8d7a4d 100644 --- a/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/domain/BmsCustomer.java +++ b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/domain/BmsCustomer.java @@ -116,6 +116,13 @@ public class BmsCustomer extends BaseEntity @Excel(name = "绑定产品代码") private String productCodes; + /** 已绑定价格套餐ID(join prc_customer_price_set,一个客户至多一个套餐;非表字段,仅展示) */ + private Long priceSetId; + + /** 已绑定价格套餐名称(join prc_price_set;非表字段,仅展示) */ + @Excel(name = "绑定套餐") + private String priceSetName; + /** 附件列表(子表 ctr_customer_attachment) */ private List attachmentList; diff --git a/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/domain/BmsCustomerPriceSetBatch.java b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/domain/BmsCustomerPriceSetBatch.java new file mode 100644 index 00000000..c2c84a94 --- /dev/null +++ b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/domain/BmsCustomerPriceSetBatch.java @@ -0,0 +1,44 @@ +package com.bms.customer.customerinfo.domain; + +import java.util.Date; +import java.util.List; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.bms.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 客户套餐批量绑定入参(客户管理列表-批量绑定套餐) + * + * @author bms + * @date 2026-10-10 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class BmsCustomerPriceSetBatch extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 待绑定客户ID集合 */ + private List customerIds; + + /** 价格套餐ID */ + private Long priceSetId; + + /** 绑定优先级,数字越小越优先 */ + private Integer bindPriority; + + /** 绑定生效日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") + private Date prBegindate; + + /** 绑定失效日期(空=长期) */ + @JsonFormat(pattern = "yyyy-MM-dd") + private Date prEnddate; + + /** 绑定备注 */ + private String priceSetNote; + + /** 已绑定套餐的客户是否覆盖更换(false=跳过,true=更换为本次套餐) */ + private Boolean overwriteExisting; +} diff --git a/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/IBmsCustomerPriceSetService.java b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/IBmsCustomerPriceSetService.java index ce9bc218..c3ea10f1 100644 --- a/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/IBmsCustomerPriceSetService.java +++ b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/IBmsCustomerPriceSetService.java @@ -2,6 +2,7 @@ package com.bms.customer.customerinfo.service; import java.util.List; import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet; +import com.bms.customer.customerinfo.domain.BmsCustomerPriceSetBatch; import com.bms.customer.customerinfo.domain.BmsPriceSetOption; /** @@ -23,6 +24,12 @@ public interface IBmsCustomerPriceSetService */ public int saveBind(BmsCustomerPriceSet bind); + /** + * 批量绑定套餐:未绑定的客户新增;已绑定客户按 overwriteExisting 决定更换或跳过。 + * 返回执行结果摘要文案。 + */ + public String batchBind(BmsCustomerPriceSetBatch req); + /** 按绑定主键解绑 */ public int deleteBindByIds(Long[] customerPricesetIds); } diff --git a/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/impl/BmsCustomerPriceSetServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/impl/BmsCustomerPriceSetServiceImpl.java index d14723aa..022d5376 100644 --- a/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/impl/BmsCustomerPriceSetServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/impl/BmsCustomerPriceSetServiceImpl.java @@ -7,6 +7,7 @@ import org.springframework.stereotype.Service; import com.bms.common.exception.ServiceException; import com.bms.customer.customerinfo.domain.BmsCustomer; import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet; +import com.bms.customer.customerinfo.domain.BmsCustomerPriceSetBatch; import com.bms.customer.customerinfo.domain.BmsPriceSetOption; import com.bms.customer.customerinfo.mapper.BmsCustomerPriceSetMapper; import com.bms.customer.customerinfo.service.IBmsCustomerLogService; @@ -122,6 +123,99 @@ public class BmsCustomerPriceSetServiceImpl implements IBmsCustomerPriceSetServi return rows; } + @Override + @org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class) + public String batchBind(BmsCustomerPriceSetBatch req) + { + if (req == null || req.getCustomerIds() == null || req.getCustomerIds().isEmpty()) + { + throw new ServiceException("请先勾选要绑定套餐的客户"); + } + if (req.getPriceSetId() == null) + { + throw new ServiceException("请选择要绑定的套餐"); + } + BmsPriceSetOption set = bindMapper.selectPriceSetOptionById(req.getPriceSetId()); + if (set == null) + { + throw new ServiceException("所选套餐不存在"); + } + if (!"E".equals(set.getStatus())) + { + throw new ServiceException("仅生效中的套餐允许绑定,当前套餐状态不可用"); + } + if (req.getPrBegindate() == null) + { + throw new ServiceException("绑定生效日期不能为空"); + } + if (req.getPrEnddate() != null && req.getPrBegindate().after(req.getPrEnddate())) + { + throw new ServiceException("失效日期不能早于生效日期"); + } + Integer priority = (req.getBindPriority() == null || req.getBindPriority() < 1) ? 1 : req.getBindPriority(); + boolean overwrite = Boolean.TRUE.equals(req.getOverwriteExisting()); + + // 去重,保持勾选顺序 + List customerIds = req.getCustomerIds().stream().distinct().collect(java.util.stream.Collectors.toList()); + int inserted = 0, replaced = 0, skipped = 0; + List skippedNames = new java.util.ArrayList<>(); + for (Long customerId : customerIds) + { + BmsCustomer customer = customerService.selectBmsCustomerByCustomerId(customerId); + if (customer == null) + { + skipped++; + skippedNames.add("ID:" + customerId + "(不存在)"); + continue; + } + BmsCustomerPriceSet existing = bindMapper.selectBindByCustomerId(customerId); + if (existing != null && !overwrite) + { + skipped++; + skippedNames.add(customer.getCustomerName()); + continue; + } + BmsCustomerPriceSet bind = new BmsCustomerPriceSet(); + bind.setCustomerId(customerId); + bind.setPriceSetId(req.getPriceSetId()); + bind.setBindPriority(priority); + bind.setPrBegindate(req.getPrBegindate()); + bind.setPrEnddate(req.getPrEnddate()); + bind.setPriceSetNote(req.getPriceSetNote()); + bind.setCreateBy(req.getCreateBy()); + bind.setUpdateBy(req.getUpdateBy()); + // saveBind 内部完成客户/套餐校验、新增或更新、业务操作日志记录 + saveBind(bind); + if (existing != null) + { + replaced++; + } + else + { + inserted++; + } + } + StringBuilder msg = new StringBuilder(); + msg.append("批量绑定完成:共 ").append(customerIds.size()).append(" 个客户,新绑定 ") + .append(inserted).append(" 个"); + if (overwrite) + { + msg.append(",更换 ").append(replaced).append(" 个"); + } + msg.append(",跳过 ").append(skipped).append(" 个"); + if (skipped > 0 && !overwrite) + { + String names = skippedNames.stream().limit(10).collect(java.util.stream.Collectors.joining("、")); + msg.append("(已绑定套餐:").append(names); + if (skippedNames.size() > 10) + { + msg.append(" 等"); + } + msg.append(",如需更换请勾选覆盖选项)"); + } + return msg.toString(); + } + @Override public int deleteBindByIds(Long[] customerPricesetIds) { diff --git a/bms-back/bms-system/src/main/resources/mapper/customer/BmsCustomerMapper.xml b/bms-back/bms-system/src/main/resources/mapper/customer/BmsCustomerMapper.xml index 29f5d704..09fd91a6 100644 --- a/bms-back/bms-system/src/main/resources/mapper/customer/BmsCustomerMapper.xml +++ b/bms-back/bms-system/src/main/resources/mapper/customer/BmsCustomerMapper.xml @@ -29,6 +29,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -54,7 +56,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" c.product_codes, c.remark, c.create_by, c.create_time, c.update_by, c.update_time, c.del_flag, - su.nick_name as sales_user_nick_name + su.nick_name as sales_user_nick_name, + cps.price_set_id, ps.price_set_name from ctr_customer c + left join prc_customer_price_set cps on cps.customer_id = c.customer_id + left join prc_price_set ps on ps.price_set_id = cps.price_set_id