客户管理记录修改日志
This commit is contained in:
+11
@@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.bms.common.annotation.Log;
|
||||
import com.bms.common.core.controller.BaseController;
|
||||
@@ -73,6 +74,16 @@ public class BmsCustomerController extends BaseController
|
||||
return success(bmsCustomerService.selectBmsCustomerByCustomerId(customerId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询客户业务操作日志(新建/修改/删除及字段级变更明细)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('customersupplier:customerinfo:query')")
|
||||
@GetMapping("/log/list")
|
||||
public AjaxResult logList(@RequestParam("customerId") Long customerId)
|
||||
{
|
||||
return success(bmsCustomerService.selectCustomerLogList(customerId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增客户信息
|
||||
*/
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.bms.customer.customerinfo.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
import com.bms.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 客户业务操作日志对象 ctr_customer_log
|
||||
*
|
||||
* @author bms
|
||||
* @date 2026-09-30
|
||||
*/
|
||||
@Data
|
||||
public class BmsCustomerLog extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 操作类型:新建 */
|
||||
public static final String OP_INSERT = "1";
|
||||
/** 操作类型:修改 */
|
||||
public static final String OP_UPDATE = "2";
|
||||
/** 操作类型:删除 */
|
||||
public static final String OP_DELETE = "3";
|
||||
|
||||
/** 日志ID */
|
||||
private Long logId;
|
||||
|
||||
/** 客户ID */
|
||||
private Long customerId;
|
||||
|
||||
/** 客户编码(操作时快照) */
|
||||
private String customerCode;
|
||||
|
||||
/** 客户名称(操作时快照) */
|
||||
private String customerName;
|
||||
|
||||
/** 操作类型(1新建 2修改 3删除) */
|
||||
private String operationType;
|
||||
|
||||
/** 变更明细JSON(落库内容):[{field,fieldLabel,oldValue,newValue}] */
|
||||
private String changeContent;
|
||||
|
||||
/** 操作人姓名 */
|
||||
private String createByName;
|
||||
|
||||
/** 变更明细(由 changeContent 解析,供前端直接展示) */
|
||||
private List<FieldChange> changes;
|
||||
|
||||
/**
|
||||
* 单个字段的变更明细
|
||||
*/
|
||||
@Data
|
||||
public static class FieldChange
|
||||
{
|
||||
/** 字段名 */
|
||||
private String field;
|
||||
|
||||
/** 字段中文名 */
|
||||
private String fieldLabel;
|
||||
|
||||
/** 修改前的值 */
|
||||
private String oldValue;
|
||||
|
||||
/** 修改后的值 */
|
||||
private String newValue;
|
||||
|
||||
public FieldChange()
|
||||
{
|
||||
}
|
||||
|
||||
public FieldChange(String field, String fieldLabel, String oldValue, String newValue)
|
||||
{
|
||||
this.field = field;
|
||||
this.fieldLabel = fieldLabel;
|
||||
this.oldValue = oldValue;
|
||||
this.newValue = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.bms.customer.customerinfo.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerLog;
|
||||
|
||||
/**
|
||||
* 客户业务操作日志Mapper接口
|
||||
*
|
||||
* @author bms
|
||||
* @date 2026-09-30
|
||||
*/
|
||||
public interface BmsCustomerLogMapper
|
||||
{
|
||||
/**
|
||||
* 新增客户操作日志
|
||||
*
|
||||
* @param customerLog 日志
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsCustomerLog(BmsCustomerLog customerLog);
|
||||
|
||||
/**
|
||||
* 按客户查询全部业务日志(时间倒序)
|
||||
*
|
||||
* @param customerId 客户ID
|
||||
* @return 日志列表
|
||||
*/
|
||||
public List<BmsCustomerLog> selectBmsCustomerLogList(Long customerId);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.bms.customer.customerinfo.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomer;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerLog;
|
||||
|
||||
/**
|
||||
* 客户业务操作日志Service接口
|
||||
*
|
||||
* @author bms
|
||||
* @date 2026-09-30
|
||||
*/
|
||||
public interface IBmsCustomerLogService
|
||||
{
|
||||
/**
|
||||
* 记录新建客户日志(含建档时的字段初始值)
|
||||
*/
|
||||
void recordInsert(BmsCustomer customer);
|
||||
|
||||
/**
|
||||
* 记录修改客户日志(字段级 修改前→修改后,无实际变更时不记录)
|
||||
*/
|
||||
void recordUpdate(BmsCustomer oldCustomer, BmsCustomer newCustomer);
|
||||
|
||||
/**
|
||||
* 记录删除客户日志
|
||||
*/
|
||||
void recordDelete(BmsCustomer customer);
|
||||
|
||||
/**
|
||||
* 查询某客户的全部业务日志(时间倒序,含已解析的变更明细)
|
||||
*/
|
||||
List<BmsCustomerLog> selectByCustomerId(Long customerId);
|
||||
}
|
||||
+9
@@ -5,6 +5,7 @@ import com.bms.customer.customerinfo.domain.BmsCustomer;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerAttachment;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerCompany;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerContact;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerLog;
|
||||
|
||||
/**
|
||||
* 客户主Service接口
|
||||
@@ -22,6 +23,14 @@ public interface IBmsCustomerService
|
||||
*/
|
||||
public BmsCustomer selectBmsCustomerByCustomerId(Long customerId);
|
||||
|
||||
/**
|
||||
* 查询某客户的全部业务操作日志(时间倒序)
|
||||
*
|
||||
* @param customerId 客户ID
|
||||
* @return 业务日志列表
|
||||
*/
|
||||
public List<BmsCustomerLog> selectCustomerLogList(Long customerId);
|
||||
|
||||
/**
|
||||
* 查询客户主列表
|
||||
*
|
||||
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
package com.bms.customer.customerinfo.service.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.bms.common.core.domain.entity.SysUser;
|
||||
import com.bms.common.utils.DateUtils;
|
||||
import com.bms.common.utils.SecurityUtils;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomer;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerLog;
|
||||
import com.bms.customer.customerinfo.mapper.BmsCustomerLogMapper;
|
||||
import com.bms.customer.customerinfo.service.IBmsCustomerLogService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 客户业务操作日志Service实现
|
||||
*
|
||||
* @author bms
|
||||
* @date 2026-09-30
|
||||
*/
|
||||
@Service
|
||||
public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
{
|
||||
@Autowired
|
||||
private BmsCustomerLogMapper bmsCustomerLogMapper;
|
||||
|
||||
/** 业务类型字典 */
|
||||
private static final Map<String, String> CUSTOMER_TYPE_MAP = Map.of(
|
||||
"0", "直客", "1", "同行", "2", "集运");
|
||||
|
||||
/** 启用状态字典 */
|
||||
private static final Map<String, String> ENABLE_MAP = Map.of("0", "正常", "1", "停用");
|
||||
|
||||
/** 结算方式字典 */
|
||||
private static final Map<String, String> SETTLEMENT_TYPE_MAP = Map.of(
|
||||
"0", "月结", "1", "周结", "2", "日结");
|
||||
|
||||
/**
|
||||
* 需要记录日志的主表字段(顺序即展示顺序)。
|
||||
* requireNonBlank 为 true 的字段对应 update SQL 的 <if test="x!=null and x!=''">,
|
||||
* 其余动态字段仅在新值非 null 时落库;业务员/结算员/客服为无条件写入。
|
||||
*/
|
||||
private static final List<FieldDef> FIELD_DEFS = List.of(
|
||||
new FieldDef("customerCode", "客户编码", BmsCustomer::getCustomerCode, true, Function.identity()),
|
||||
new FieldDef("customerName", "客户名称", BmsCustomer::getCustomerName, true, Function.identity()),
|
||||
new FieldDef("customerCodeDw", "对外代码", BmsCustomer::getCustomerCodeDw, false, Function.identity()),
|
||||
new FieldDef("creditCode", "统一社会信用代码", BmsCustomer::getCreditCode, false, Function.identity()),
|
||||
new FieldDef("customerType", "业务类型", BmsCustomer::getCustomerType, false, CUSTOMER_TYPE_MAP::get),
|
||||
new FieldDef("isEnable", "启用状态", BmsCustomer::getIsEnable, false, ENABLE_MAP::get),
|
||||
new FieldDef("salesUserId", "业务员", c -> userDisplay(c.getSalesUserId(), c.getSalesUser()), false, Function.identity()),
|
||||
new FieldDef("ed", "资金额度(元)", BmsCustomer::getEd, false, BmsCustomerLogServiceImpl::numText),
|
||||
new FieldDef("zq", "回款账期(天)", BmsCustomer::getZq, false, BmsCustomerLogServiceImpl::numText),
|
||||
new FieldDef("settlementUserId", "结算员", c -> userDisplay(c.getSettlementUserId(), c.getSettlementUser()), false, Function.identity()),
|
||||
new FieldDef("serviceUserId", "客服", c -> userDisplay(c.getServiceUserId(), c.getServiceUser()), false, Function.identity()),
|
||||
new FieldDef("settlementType", "结算方式", BmsCustomer::getSettlementType, false, SETTLEMENT_TYPE_MAP::get),
|
||||
new FieldDef("accountBalance", "账户余额(元)", BmsCustomer::getAccountBalance, false, BmsCustomerLogServiceImpl::numText),
|
||||
new FieldDef("foreignCurrencyBalance", "外币余额(元)", BmsCustomer::getForeignCurrencyBalance, false, BmsCustomerLogServiceImpl::numText),
|
||||
new FieldDef("weightThreshold", "重量阈值(kg)", BmsCustomer::getWeightThreshold, false, BmsCustomerLogServiceImpl::numText),
|
||||
new FieldDef("throwRatio", "抛比(%)", BmsCustomer::getThrowRatio, false, BmsCustomerLogServiceImpl::numText),
|
||||
new FieldDef("productCodes", "绑定产品", BmsCustomer::getProductCodes, false, Function.identity()),
|
||||
new FieldDef("remark", "备注", BmsCustomer::getRemark, false, Function.identity()));
|
||||
|
||||
@Override
|
||||
public void recordInsert(BmsCustomer customer)
|
||||
{
|
||||
if (customer == null || customer.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<BmsCustomerLog.FieldChange> changes = new ArrayList<>();
|
||||
for (FieldDef def : FIELD_DEFS)
|
||||
{
|
||||
String value = def.display(customer);
|
||||
if (value != null && !value.isEmpty())
|
||||
{
|
||||
changes.add(new BmsCustomerLog.FieldChange(def.field, def.label, "", value));
|
||||
}
|
||||
}
|
||||
saveLog(customer, BmsCustomerLog.OP_INSERT, changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordUpdate(BmsCustomer oldCustomer, BmsCustomer newCustomer)
|
||||
{
|
||||
if (oldCustomer == null || newCustomer == null || newCustomer.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<BmsCustomerLog.FieldChange> changes = new ArrayList<>();
|
||||
for (FieldDef def : FIELD_DEFS)
|
||||
{
|
||||
// 与 update SQL 的动态条件保持一致:未提交(null/空串)的字段本次不落库,不参与比对
|
||||
Object raw = def.rawGetter.apply(newCustomer);
|
||||
if (raw == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (def.requireNonBlank && raw.toString().trim().isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String oldValue = def.display(oldCustomer);
|
||||
String newValue = def.display(newCustomer);
|
||||
if (!sameValue(def.rawGetter.apply(oldCustomer), raw))
|
||||
{
|
||||
changes.add(new BmsCustomerLog.FieldChange(def.field, def.label,
|
||||
oldValue == null ? "" : oldValue, newValue == null ? "" : newValue));
|
||||
}
|
||||
}
|
||||
if (changes.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
// 日志快照以修改后的客户编码/名称为准
|
||||
saveLog(newCustomer, BmsCustomerLog.OP_UPDATE, changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordDelete(BmsCustomer customer)
|
||||
{
|
||||
if (customer == null || customer.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
saveLog(customer, BmsCustomerLog.OP_DELETE, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BmsCustomerLog> selectByCustomerId(Long customerId)
|
||||
{
|
||||
List<BmsCustomerLog> list = bmsCustomerLogMapper.selectBmsCustomerLogList(customerId);
|
||||
for (BmsCustomerLog log : list)
|
||||
{
|
||||
if (log.getChangeContent() != null && !log.getChangeContent().isEmpty())
|
||||
{
|
||||
log.setChanges(JSON.parseArray(log.getChangeContent(), BmsCustomerLog.FieldChange.class));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void saveLog(BmsCustomer customer, String operationType, List<BmsCustomerLog.FieldChange> changes)
|
||||
{
|
||||
BmsCustomerLog log = new BmsCustomerLog();
|
||||
log.setCustomerId(customer.getCustomerId());
|
||||
log.setCustomerCode(customer.getCustomerCode());
|
||||
log.setCustomerName(customer.getCustomerName());
|
||||
log.setOperationType(operationType);
|
||||
if (changes != null)
|
||||
{
|
||||
log.setChangeContent(JSON.toJSONString(changes));
|
||||
}
|
||||
try
|
||||
{
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
log.setCreateBy(user.getUserName());
|
||||
log.setCreateByName(user.getNickName());
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
// 无登录上下文(如系统任务)时不阻断业务
|
||||
}
|
||||
log.setCreateTime(DateUtils.getNowDate());
|
||||
bmsCustomerLogMapper.insertBmsCustomerLog(log);
|
||||
}
|
||||
|
||||
/** 人员字段展示:姓名(工号),缺姓名时只显示工号 */
|
||||
private static String userDisplay(String code, String name)
|
||||
{
|
||||
String c = trimToNull(code);
|
||||
String n = trimToNull(name);
|
||||
if (c == null && n == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
if (c == null)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
if (n == null || n.equals(c))
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return n + "(" + c + ")";
|
||||
}
|
||||
|
||||
private static String numText(Object num)
|
||||
{
|
||||
return num == null ? "" : num.toString();
|
||||
}
|
||||
|
||||
private static String trimToNull(String s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String t = s.trim();
|
||||
return t.isEmpty() ? null : t;
|
||||
}
|
||||
|
||||
/** 数值按大小比较(规避 BigDecimal 精度差异),其余按字符串比较 */
|
||||
private static boolean sameValue(Object a, Object b)
|
||||
{
|
||||
if (a instanceof BigDecimal && b instanceof BigDecimal)
|
||||
{
|
||||
return ((BigDecimal) a).compareTo((BigDecimal) b) == 0;
|
||||
}
|
||||
return Objects.equals(a == null ? null : a.toString(), b == null ? null : b.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段定义
|
||||
*/
|
||||
private static final class FieldDef
|
||||
{
|
||||
private final String field;
|
||||
private final String label;
|
||||
/** 取原始值(用于变更判断) */
|
||||
private final Function<BmsCustomer, Object> rawGetter;
|
||||
/** 动态写入时是否要求非空串(对应 update SQL 的 != '' 判断) */
|
||||
private final boolean requireNonBlank;
|
||||
/** 原始值 -> 字典翻译(查不到字典时回退原值) */
|
||||
private final Function<String, String> dictTranslator;
|
||||
|
||||
private FieldDef(String field, String label, Function<BmsCustomer, ?> rawGetter,
|
||||
boolean requireNonBlank, Function<String, String> dictTranslator)
|
||||
{
|
||||
this.field = field;
|
||||
this.label = label;
|
||||
this.rawGetter = rawGetter::apply;
|
||||
this.requireNonBlank = requireNonBlank;
|
||||
this.dictTranslator = dictTranslator;
|
||||
}
|
||||
|
||||
/** 取日志展示值:人员/数字类直接是文本;字典类翻译失败回退原值 */
|
||||
private String display(BmsCustomer c)
|
||||
{
|
||||
Object raw = rawGetter.apply(c);
|
||||
if (raw == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
String text = raw.toString();
|
||||
if (text.isEmpty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
if (dictTranslator == null)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
String translated = dictTranslator.apply(text);
|
||||
return translated != null ? translated : text;
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
-4
@@ -1,5 +1,6 @@
|
||||
package com.bms.customer.customerinfo.service.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bms.common.annotation.DataScope;
|
||||
@@ -14,6 +15,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.bms.customer.customerinfo.mapper.BmsCustomerMapper;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomer;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerLog;
|
||||
import com.bms.customer.customerinfo.service.IBmsCustomerLogService;
|
||||
import com.bms.customer.customerinfo.service.IBmsCustomerService;
|
||||
import com.bms.customer.customermoney.service.ICustomerMoneyService;
|
||||
|
||||
@@ -32,6 +35,9 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
@Autowired
|
||||
private ICustomerMoneyService customerMoneyService;
|
||||
|
||||
@Autowired
|
||||
private IBmsCustomerLogService customerLogService;
|
||||
|
||||
/**
|
||||
* 查询客户主
|
||||
*
|
||||
@@ -58,9 +64,18 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
return bmsCustomer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询某客户的全部业务操作日志(时间倒序)
|
||||
*/
|
||||
@Override
|
||||
public List<BmsCustomerLog> selectCustomerLogList(Long customerId)
|
||||
{
|
||||
return customerLogService.selectByCustomerId(customerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询客户主列表
|
||||
*
|
||||
*
|
||||
* @param bmsCustomer 客户主
|
||||
* @return 客户主
|
||||
*/
|
||||
@@ -235,6 +250,8 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
saveBmsCustomerContacts(bmsCustomer.getCustomerId(), bmsCustomer.getContactList());
|
||||
// 新建客户即初始化默认CNY账户:余额0、总额度1000 CNY,写INIT流水
|
||||
customerMoneyService.initDefaultCnyAccount(bmsCustomer.getCustomerId());
|
||||
// 业务日志:新建(含建档初始值)
|
||||
customerLogService.recordInsert(bmsCustomer);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
@@ -252,6 +269,8 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
bmsCustomer.setUpdateTime(DateUtils.getNowDate());
|
||||
bmsCustomer.setUpdateBy(user.getUserName());
|
||||
// 修改前先取旧值快照,用于业务日志记录字段级变更
|
||||
BmsCustomer oldCustomer = bmsCustomerMapper.selectBmsCustomerByCustomerId(bmsCustomer.getCustomerId());
|
||||
// 仅重建客户档案模块的附件,收款水单等其他业务模块的附件保留不动
|
||||
bmsCustomerMapper.deleteBmsCustomerProfileAttachmentByCustomerId(bmsCustomer.getCustomerId());
|
||||
if (bmsCustomer.getAttachmentList() != null)
|
||||
@@ -266,7 +285,13 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
saveBmsCustomerCompanies(bmsCustomer.getCustomerId(), bmsCustomer.getCompanyList());
|
||||
// 联系人采用增量 upsert
|
||||
saveBmsCustomerContacts(bmsCustomer.getCustomerId(), bmsCustomer.getContactList());
|
||||
return bmsCustomerMapper.updateBmsCustomer(bmsCustomer);
|
||||
int rows = bmsCustomerMapper.updateBmsCustomer(bmsCustomer);
|
||||
// 业务日志:修改(字段级 修改前→修改后;无实际变更时不记录)
|
||||
if (rows > 0)
|
||||
{
|
||||
customerLogService.recordUpdate(oldCustomer, bmsCustomer);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -279,13 +304,31 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
@Override
|
||||
public int deleteBmsCustomerByCustomerIds(Long[] customerIds)
|
||||
{
|
||||
// 删除前取客户快照,用于业务日志
|
||||
List<BmsCustomer> snapshotList = new ArrayList<>();
|
||||
for (Long customerId : customerIds)
|
||||
{
|
||||
BmsCustomer snapshot = bmsCustomerMapper.selectBmsCustomerByCustomerId(customerId);
|
||||
if (snapshot != null)
|
||||
{
|
||||
snapshotList.add(snapshot);
|
||||
}
|
||||
}
|
||||
for (Long customerId : customerIds)
|
||||
{
|
||||
bmsCustomerMapper.deleteBmsCustomerAttachmentByCustomerId(customerId);
|
||||
bmsCustomerMapper.deleteBmsCustomerCompanyByCustomerId(customerId);
|
||||
bmsCustomerMapper.deleteBmsCustomerContactByCustomerId(customerId);
|
||||
}
|
||||
return bmsCustomerMapper.deleteBmsCustomerByCustomerIds(customerIds);
|
||||
int rows = bmsCustomerMapper.deleteBmsCustomerByCustomerIds(customerIds);
|
||||
if (rows > 0)
|
||||
{
|
||||
for (BmsCustomer snapshot : snapshotList)
|
||||
{
|
||||
customerLogService.recordDelete(snapshot);
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,10 +341,16 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
@Override
|
||||
public int deleteBmsCustomerByCustomerId(Long customerId)
|
||||
{
|
||||
BmsCustomer snapshot = bmsCustomerMapper.selectBmsCustomerByCustomerId(customerId);
|
||||
bmsCustomerMapper.deleteBmsCustomerAttachmentByCustomerId(customerId);
|
||||
bmsCustomerMapper.deleteBmsCustomerCompanyByCustomerId(customerId);
|
||||
bmsCustomerMapper.deleteBmsCustomerContactByCustomerId(customerId);
|
||||
return bmsCustomerMapper.deleteBmsCustomerByCustomerId(customerId);
|
||||
int rows = bmsCustomerMapper.deleteBmsCustomerByCustomerId(customerId);
|
||||
if (rows > 0 && snapshot != null)
|
||||
{
|
||||
customerLogService.recordDelete(snapshot);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?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.bms.customer.customerinfo.mapper.BmsCustomerLogMapper">
|
||||
|
||||
<resultMap type="com.bms.customer.customerinfo.domain.BmsCustomerLog" id="BmsCustomerLogResult">
|
||||
<result property="logId" column="log_id" />
|
||||
<result property="customerId" column="customer_id" />
|
||||
<result property="customerCode" column="customer_code" />
|
||||
<result property="customerName" column="customer_name" />
|
||||
<result property="operationType" column="operation_type" />
|
||||
<result property="changeContent" column="change_content" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createByName" column="create_by_name" />
|
||||
<result property="createTime" column="create_time" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectBmsCustomerLogVo">
|
||||
select log_id, customer_id, customer_code, customer_name, operation_type, change_content,
|
||||
create_by, create_by_name, create_time
|
||||
from ctr_customer_log
|
||||
</sql>
|
||||
|
||||
<insert id="insertBmsCustomerLog" parameterType="com.bms.customer.customerinfo.domain.BmsCustomerLog"
|
||||
useGeneratedKeys="true" keyProperty="logId">
|
||||
insert into ctr_customer_log
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="customerId != null">customer_id,</if>
|
||||
<if test="customerCode != null">customer_code,</if>
|
||||
<if test="customerName != null">customer_name,</if>
|
||||
<if test="operationType != null">operation_type,</if>
|
||||
<if test="changeContent != null">change_content,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createByName != null">create_by_name,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="customerId != null">#{customerId},</if>
|
||||
<if test="customerCode != null">#{customerCode},</if>
|
||||
<if test="customerName != null">#{customerName},</if>
|
||||
<if test="operationType != null">#{operationType},</if>
|
||||
<if test="changeContent != null">#{changeContent},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createByName != null">#{createByName},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<select id="selectBmsCustomerLogList" parameterType="Long" resultMap="BmsCustomerLogResult">
|
||||
<include refid="selectBmsCustomerLogVo"/>
|
||||
where customer_id = #{customerId}
|
||||
order by create_time desc, log_id desc
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -17,6 +17,15 @@ export function getCustomer(customerId) {
|
||||
})
|
||||
}
|
||||
|
||||
// 查询客户业务操作日志
|
||||
export function listCustomerLog(customerId) {
|
||||
return request({
|
||||
url: '/customersupplier/customerinfo/log/list',
|
||||
method: 'get',
|
||||
params: { customerId }
|
||||
})
|
||||
}
|
||||
|
||||
// 新增客户主
|
||||
export function addCustomer(data) {
|
||||
return request({
|
||||
|
||||
@@ -85,6 +85,16 @@
|
||||
|
||||
>客户余额</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="info"
|
||||
plain
|
||||
icon="Document"
|
||||
:disabled="single"
|
||||
@click="handleViewLog()"
|
||||
v-hasPermi="['customersupplier:customerinfo:query']"
|
||||
>日志</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
@@ -167,11 +177,12 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isColVisible('remark')" label="备注说明" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="240" fixed="right">
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="290" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['customersupplier:customerinfo:edit']">修改</el-button>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['customersupplier:customerinfo:remove']">删除</el-button>
|
||||
<el-button link type="primary" icon="Wallet" @click="handleCustomerMoney(scope.row)">客户余额</el-button>
|
||||
<el-button link type="primary" icon="Document" @click="handleViewLog(scope.row)" v-hasPermi="['customersupplier:customerinfo:query']">日志</el-button>
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
@@ -184,11 +195,62 @@
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 客户业务操作日志弹窗 -->
|
||||
<el-dialog v-model="logOpen" :title="`业务日志 - ${logCustomer.customerName || ''}`" width="820px" append-to-body>
|
||||
<div style="margin-bottom: 10px; color: #909399; font-size: 13px;">
|
||||
客户编码:{{ logCustomer.customerCode || '-' }}
|
||||
<span style="margin-left: 16px;">共 {{ logList.length }} 条日志(按操作时间倒序)</span>
|
||||
</div>
|
||||
<el-table v-loading="logLoading" :data="logList" border size="small" row-key="logId" :empty-text="'暂无业务日志'">
|
||||
<el-table-column type="expand">
|
||||
<template #default="scope">
|
||||
<div style="padding: 8px 16px; background: #fafafa;">
|
||||
<div v-if="!scope.row.changes || !scope.row.changes.length" style="color:#909399;">无字段明细</div>
|
||||
<el-table v-else :data="scope.row.changes" border size="small">
|
||||
<el-table-column label="字段" prop="fieldLabel" width="180" align="center" />
|
||||
<el-table-column label="修改前" align="center">
|
||||
<template #default="cell">
|
||||
<span :style="{ color: cell.row.oldValue === '' ? '#909399' : '' }">{{ cell.row.oldValue === '' ? '(空)' : cell.row.oldValue }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="修改后" align="center">
|
||||
<template #default="cell">
|
||||
<span :style="{ color: cell.row.newValue === '' ? '#909399' : '' }">{{ cell.row.newValue === '' ? '(空)' : cell.row.newValue }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作类型" align="center" width="90">
|
||||
<template #default="scope">
|
||||
<el-tag :type="opTagType(scope.row.operationType)" size="small">{{ opLabel(scope.row.operationType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作人" align="center" width="150">
|
||||
<template #default="scope">{{ scope.row.createByName || scope.row.createBy || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作时间" align="center" width="170">
|
||||
<template #default="scope">{{ fmtTime(scope.row.createTime) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="变更字段" align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.operationType === '1'">新建客户,录入 {{ scope.row.changes?.length || 0 }} 项信息</span>
|
||||
<span v-else-if="scope.row.operationType === '2'">{{ changeSummary(scope.row.changes) }}</span>
|
||||
<span v-else style="color:#f56c6c;">客户被删除</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="logOpen = false">关 闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Customer">
|
||||
import { listCustomer, delCustomer } from "@/api/customersuppliermanagement/customerinfo/customer.js"
|
||||
import { listCustomer, delCustomer, listCustomerLog } from "@/api/customersuppliermanagement/customerinfo/customer.js"
|
||||
import { useProducts, parseProductCodes } from '@/components/ProductSelect/useProducts'
|
||||
import { useColumnSettings } from '@/utils/columnSettings'
|
||||
|
||||
@@ -359,5 +421,49 @@ function handleExport() {
|
||||
}, `customer_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
|
||||
/** ========== 客户业务操作日志 ========== */
|
||||
const logOpen = ref(false)
|
||||
const logLoading = ref(false)
|
||||
const logList = ref([])
|
||||
const logCustomer = ref({})
|
||||
|
||||
const OP_META = {
|
||||
'1': { label: '新建', tag: 'success' },
|
||||
'2': { label: '修改', tag: 'warning' },
|
||||
'3': { label: '删除', tag: 'danger' }
|
||||
}
|
||||
function opLabel(type) {
|
||||
return OP_META[type]?.label || '未知'
|
||||
}
|
||||
function opTagType(type) {
|
||||
return OP_META[type]?.tag || 'info'
|
||||
}
|
||||
function fmtTime(t) {
|
||||
return t ? proxy.parseTime(t, '{y}-{m}-{d} {h}:{i}:{s}') : '-'
|
||||
}
|
||||
/** 修改日志的变更字段摘要 */
|
||||
function changeSummary(changes) {
|
||||
if (!changes || !changes.length) return '-'
|
||||
return changes.map(c => c.fieldLabel).join('、')
|
||||
}
|
||||
|
||||
/** 打开业务日志弹窗(操作列传 row;工具栏按钮取勾选行) */
|
||||
function handleViewLog(row) {
|
||||
const target = (row && row.customerId) ? row : selectedRows.value[0]
|
||||
if (!target || !target.customerId) {
|
||||
proxy.$modal.msgWarning("请先勾选一个客户")
|
||||
return
|
||||
}
|
||||
logCustomer.value = { customerId: target.customerId, customerName: target.customerName, customerCode: target.customerCode }
|
||||
logList.value = []
|
||||
logOpen.value = true
|
||||
logLoading.value = true
|
||||
listCustomerLog(target.customerId).then(res => {
|
||||
logList.value = res.data || []
|
||||
}).finally(() => {
|
||||
logLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
getList()
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user