日志记录修改
This commit is contained in:
+17
@@ -16,6 +16,17 @@ public class BmsCustomerLog extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 业务模块:客户档案 */
|
||||
public static final String MODULE_MAIN = "main";
|
||||
/** 业务模块:公司主体 */
|
||||
public static final String MODULE_COMPANY = "company";
|
||||
/** 业务模块:联系人 */
|
||||
public static final String MODULE_CONTACT = "contact";
|
||||
/** 业务模块:附件资料 */
|
||||
public static final String MODULE_ATTACHMENT = "attachment";
|
||||
/** 业务模块:绑定套餐 */
|
||||
public static final String MODULE_PRICE_SET = "priceset";
|
||||
|
||||
/** 操作类型:新建 */
|
||||
public static final String OP_INSERT = "1";
|
||||
/** 操作类型:修改 */
|
||||
@@ -35,6 +46,12 @@ public class BmsCustomerLog extends BaseEntity
|
||||
/** 客户名称(操作时快照) */
|
||||
private String customerName;
|
||||
|
||||
/** 业务模块(main/company/contact/attachment/priceset) */
|
||||
private String bizModule;
|
||||
|
||||
/** 操作对象名称(公司全称/联系人姓名/文件名/套餐名) */
|
||||
private String bizName;
|
||||
|
||||
/** 操作类型(1新建 2修改 3删除) */
|
||||
private String operationType;
|
||||
|
||||
|
||||
+59
@@ -3,7 +3,12 @@ package com.bms.customer.customerinfo.service;
|
||||
import java.util.List;
|
||||
|
||||
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;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet;
|
||||
import com.bms.customer.customerinfo.domain.BmsPriceSetOption;
|
||||
|
||||
/**
|
||||
* 客户业务操作日志Service接口
|
||||
@@ -28,6 +33,60 @@ public interface IBmsCustomerLogService
|
||||
*/
|
||||
void recordDelete(BmsCustomer customer);
|
||||
|
||||
/**
|
||||
* 记录新增公司主体
|
||||
*/
|
||||
void recordCompanyInsert(BmsCustomerCompany company);
|
||||
|
||||
/**
|
||||
* 记录修改公司主体(字段级变更,无变更不记录)
|
||||
*/
|
||||
void recordCompanyUpdate(BmsCustomerCompany oldCompany, BmsCustomerCompany newCompany);
|
||||
|
||||
/**
|
||||
* 记录删除公司主体
|
||||
*/
|
||||
void recordCompanyDelete(BmsCustomerCompany company);
|
||||
|
||||
/**
|
||||
* 记录新增联系人
|
||||
*/
|
||||
void recordContactInsert(BmsCustomerContact contact);
|
||||
|
||||
/**
|
||||
* 记录修改联系人(字段级变更,无变更不记录)
|
||||
*/
|
||||
void recordContactUpdate(BmsCustomerContact oldContact, BmsCustomerContact newContact);
|
||||
|
||||
/**
|
||||
* 记录删除联系人
|
||||
*/
|
||||
void recordContactDelete(BmsCustomerContact contact);
|
||||
|
||||
/**
|
||||
* 客户档案附件全量重建前后的差异记录(新增/删除/修改的文件逐条记录)
|
||||
*
|
||||
* @param oldList 重建前附件(客户档案模块)
|
||||
* @param newList 重建后附件
|
||||
*/
|
||||
void recordAttachmentRebuild(List<BmsCustomerAttachment> oldList, List<BmsCustomerAttachment> newList);
|
||||
|
||||
/**
|
||||
* 记录新增客户档案附件(随客户新建上传)
|
||||
*/
|
||||
void recordAttachmentInsert(BmsCustomerAttachment attachment);
|
||||
|
||||
/**
|
||||
* 记录套餐绑定/更换(existing 为空=首次绑定)
|
||||
*/
|
||||
void recordPriceSetBind(BmsCustomer customer, BmsCustomerPriceSet existing,
|
||||
BmsCustomerPriceSet bind, BmsPriceSetOption newSet);
|
||||
|
||||
/**
|
||||
* 记录套餐解绑
|
||||
*/
|
||||
void recordPriceSetUnbind(BmsCustomerPriceSet bind);
|
||||
|
||||
/**
|
||||
* 查询某客户的全部业务日志(时间倒序,含已解析的变更明细)
|
||||
*/
|
||||
|
||||
+449
-11
@@ -1,7 +1,10 @@
|
||||
package com.bms.customer.customerinfo.service.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -12,9 +15,16 @@ 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.BmsCustomerAttachment;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerCompany;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerContact;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerLog;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet;
|
||||
import com.bms.customer.customerinfo.domain.BmsPriceSetOption;
|
||||
import com.bms.customer.customerinfo.mapper.BmsCustomerLogMapper;
|
||||
import com.bms.customer.customerinfo.service.IBmsCustomerLogService;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -30,6 +40,9 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
@Autowired
|
||||
private BmsCustomerLogMapper bmsCustomerLogMapper;
|
||||
|
||||
private static final ThreadLocal<SimpleDateFormat> DATE_FMT =
|
||||
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
|
||||
|
||||
/** 业务类型字典 */
|
||||
private static final Map<String, String> CUSTOMER_TYPE_MAP = Map.of(
|
||||
"0", "直客", "1", "同行", "2", "集运");
|
||||
@@ -41,6 +54,17 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
private static final Map<String, String> SETTLEMENT_TYPE_MAP = Map.of(
|
||||
"0", "月结", "1", "周结", "2", "日结");
|
||||
|
||||
/** 联系人类型字典 */
|
||||
private static final Map<String, String> CONTACT_TYPE_MAP = Map.of(
|
||||
"0", "业务联系人", "1", "财务联系人", "2", "紧急联系人", "3", "其他");
|
||||
|
||||
/** 是否类字典 */
|
||||
private static final Map<String, String> YES_NO_MAP = Map.of("0", "否", "1", "是");
|
||||
|
||||
/** 附件分类字典 */
|
||||
private static final Map<String, String> ATTACHMENT_TYPE_MAP = Map.of(
|
||||
"0", "附件资料", "1", "客户Logo", "2", "合同文件", "3", "其他");
|
||||
|
||||
/**
|
||||
* 需要记录日志的主表字段(顺序即展示顺序)。
|
||||
* requireNonBlank 为 true 的字段对应 update SQL 的 <if test="x!=null and x!=''">,
|
||||
@@ -66,6 +90,80 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
new FieldDef("productCodes", "绑定产品", BmsCustomer::getProductCodes, false, Function.identity()),
|
||||
new FieldDef("remark", "备注", BmsCustomer::getRemark, false, Function.identity()));
|
||||
|
||||
/** 公司主体需记录的字段(顺序即展示顺序) */
|
||||
private static final LinkedHashMap<String, String> COMPANY_FIELDS = new LinkedHashMap<>();
|
||||
static
|
||||
{
|
||||
COMPANY_FIELDS.put("companyNameFull", "公司全称");
|
||||
COMPANY_FIELDS.put("englishName", "英文名称");
|
||||
COMPANY_FIELDS.put("creditCode", "统一社会信用代码");
|
||||
COMPANY_FIELDS.put("legalPerson", "法定代表人");
|
||||
COMPANY_FIELDS.put("legalPersonPhone", "法定代表人电话");
|
||||
COMPANY_FIELDS.put("registeredCapital", "注册资本(万元)");
|
||||
COMPANY_FIELDS.put("capitalCurrency", "注册资本币种");
|
||||
COMPANY_FIELDS.put("paidInCapital", "实收资本(万元)");
|
||||
COMPANY_FIELDS.put("establishDate", "成立日期");
|
||||
COMPANY_FIELDS.put("businessTermStart", "营业期限起");
|
||||
COMPANY_FIELDS.put("businessTermEnd", "营业期限止");
|
||||
COMPANY_FIELDS.put("businessTermPermanent", "是否长期有效");
|
||||
COMPANY_FIELDS.put("registrationAuthority", "登记机关");
|
||||
COMPANY_FIELDS.put("registrationNumber", "注册号");
|
||||
COMPANY_FIELDS.put("operatingStatus", "经营状态");
|
||||
COMPANY_FIELDS.put("employeeCount", "员工人数");
|
||||
COMPANY_FIELDS.put("businessScope", "经营范围");
|
||||
COMPANY_FIELDS.put("shareholders", "主要股东");
|
||||
COMPANY_FIELDS.put("companyPhone", "公司电话");
|
||||
COMPANY_FIELDS.put("companyFax", "公司传真");
|
||||
COMPANY_FIELDS.put("companyWebsite", "公司网址");
|
||||
COMPANY_FIELDS.put("companyEmail", "公司邮箱");
|
||||
COMPANY_FIELDS.put("registeredProvince", "注册省份");
|
||||
COMPANY_FIELDS.put("registeredCity", "注册城市");
|
||||
COMPANY_FIELDS.put("registeredDistrict", "注册区县");
|
||||
COMPANY_FIELDS.put("registeredAddressDetail", "注册详细地址");
|
||||
COMPANY_FIELDS.put("remark", "备注");
|
||||
}
|
||||
|
||||
/** 联系人需记录的字段 */
|
||||
private static final LinkedHashMap<String, String> CONTACT_FIELDS = new LinkedHashMap<>();
|
||||
static
|
||||
{
|
||||
CONTACT_FIELDS.put("contactName", "联系人姓名");
|
||||
CONTACT_FIELDS.put("position", "职位");
|
||||
CONTACT_FIELDS.put("department", "所属部门");
|
||||
CONTACT_FIELDS.put("phone", "手机号");
|
||||
CONTACT_FIELDS.put("landline", "座机");
|
||||
CONTACT_FIELDS.put("email", "电子邮箱");
|
||||
CONTACT_FIELDS.put("wechat", "微信号");
|
||||
CONTACT_FIELDS.put("qq", "QQ号");
|
||||
CONTACT_FIELDS.put("country", "国家/地区");
|
||||
CONTACT_FIELDS.put("province", "省份");
|
||||
CONTACT_FIELDS.put("city", "城市");
|
||||
CONTACT_FIELDS.put("district", "区/县");
|
||||
CONTACT_FIELDS.put("contactAddress", "详细地址");
|
||||
CONTACT_FIELDS.put("postalCode", "邮政编码");
|
||||
CONTACT_FIELDS.put("contactType", "联系人类型");
|
||||
CONTACT_FIELDS.put("isDefault", "是否默认");
|
||||
CONTACT_FIELDS.put("sortOrder", "排序");
|
||||
}
|
||||
|
||||
/** 附件需记录的字段 */
|
||||
private static final LinkedHashMap<String, String> ATTACHMENT_FIELDS = new LinkedHashMap<>();
|
||||
static
|
||||
{
|
||||
ATTACHMENT_FIELDS.put("fileName", "文件名称");
|
||||
ATTACHMENT_FIELDS.put("attachmentType", "附件分类");
|
||||
ATTACHMENT_FIELDS.put("sortOrder", "排序");
|
||||
ATTACHMENT_FIELDS.put("remark", "备注");
|
||||
}
|
||||
|
||||
private static final Map<String, Map<String, String>> FIELD_DICTS = Map.of(
|
||||
"businessTermPermanent", YES_NO_MAP,
|
||||
"contactType", CONTACT_TYPE_MAP,
|
||||
"isDefault", YES_NO_MAP,
|
||||
"attachmentType", ATTACHMENT_TYPE_MAP);
|
||||
|
||||
/* ============================== 客户主表 ============================== */
|
||||
|
||||
@Override
|
||||
public void recordInsert(BmsCustomer customer)
|
||||
{
|
||||
@@ -82,7 +180,8 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
changes.add(new BmsCustomerLog.FieldChange(def.field, def.label, "", value));
|
||||
}
|
||||
}
|
||||
saveLog(customer, BmsCustomerLog.OP_INSERT, changes);
|
||||
saveLog(customer.getCustomerId(), customer.getCustomerCode(), customer.getCustomerName(),
|
||||
BmsCustomerLog.MODULE_MAIN, null, BmsCustomerLog.OP_INSERT, changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,8 +216,8 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
{
|
||||
return;
|
||||
}
|
||||
// 日志快照以修改后的客户编码/名称为准
|
||||
saveLog(newCustomer, BmsCustomerLog.OP_UPDATE, changes);
|
||||
saveLog(newCustomer.getCustomerId(), newCustomer.getCustomerCode(), newCustomer.getCustomerName(),
|
||||
BmsCustomerLog.MODULE_MAIN, null, BmsCustomerLog.OP_UPDATE, changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,9 +227,236 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
{
|
||||
return;
|
||||
}
|
||||
saveLog(customer, BmsCustomerLog.OP_DELETE, null);
|
||||
saveLog(customer.getCustomerId(), customer.getCustomerCode(), customer.getCustomerName(),
|
||||
BmsCustomerLog.MODULE_MAIN, null, BmsCustomerLog.OP_DELETE, null);
|
||||
}
|
||||
|
||||
/* ============================== 公司主体 ============================== */
|
||||
|
||||
@Override
|
||||
public void recordCompanyInsert(BmsCustomerCompany company)
|
||||
{
|
||||
if (company == null || company.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
saveLog(company.getCustomerId(), null, null, BmsCustomerLog.MODULE_COMPANY,
|
||||
company.getCompanyNameFull(), BmsCustomerLog.OP_INSERT,
|
||||
beanInsertChanges(company, COMPANY_FIELDS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordCompanyUpdate(BmsCustomerCompany oldCompany, BmsCustomerCompany newCompany)
|
||||
{
|
||||
if (oldCompany == null || newCompany == null || newCompany.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<BmsCustomerLog.FieldChange> changes = beanDiff(oldCompany, newCompany, COMPANY_FIELDS);
|
||||
if (changes.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
String bizName = trimToNull(newCompany.getCompanyNameFull());
|
||||
if (bizName == null)
|
||||
{
|
||||
bizName = oldCompany.getCompanyNameFull();
|
||||
}
|
||||
saveLog(newCompany.getCustomerId(), null, null, BmsCustomerLog.MODULE_COMPANY,
|
||||
bizName, BmsCustomerLog.OP_UPDATE, changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordCompanyDelete(BmsCustomerCompany company)
|
||||
{
|
||||
if (company == null || company.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
saveLog(company.getCustomerId(), null, null, BmsCustomerLog.MODULE_COMPANY,
|
||||
company.getCompanyNameFull(), BmsCustomerLog.OP_DELETE, null);
|
||||
}
|
||||
|
||||
/* ============================== 联系人 ============================== */
|
||||
|
||||
@Override
|
||||
public void recordContactInsert(BmsCustomerContact contact)
|
||||
{
|
||||
if (contact == null || contact.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
saveLog(contact.getCustomerId(), null, null, BmsCustomerLog.MODULE_CONTACT,
|
||||
contact.getContactName(), BmsCustomerLog.OP_INSERT,
|
||||
beanInsertChanges(contact, CONTACT_FIELDS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordContactUpdate(BmsCustomerContact oldContact, BmsCustomerContact newContact)
|
||||
{
|
||||
if (oldContact == null || newContact == null || newContact.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<BmsCustomerLog.FieldChange> changes = beanDiff(oldContact, newContact, CONTACT_FIELDS);
|
||||
if (changes.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
String bizName = trimToNull(newContact.getContactName());
|
||||
if (bizName == null)
|
||||
{
|
||||
bizName = oldContact.getContactName();
|
||||
}
|
||||
saveLog(newContact.getCustomerId(), null, null, BmsCustomerLog.MODULE_CONTACT,
|
||||
bizName, BmsCustomerLog.OP_UPDATE, changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordContactDelete(BmsCustomerContact contact)
|
||||
{
|
||||
if (contact == null || contact.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
saveLog(contact.getCustomerId(), null, null, BmsCustomerLog.MODULE_CONTACT,
|
||||
contact.getContactName(), BmsCustomerLog.OP_DELETE, null);
|
||||
}
|
||||
|
||||
/* ============================== 附件 ============================== */
|
||||
|
||||
@Override
|
||||
public void recordAttachmentInsert(BmsCustomerAttachment attachment)
|
||||
{
|
||||
if (attachment == null || attachment.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
saveLog(attachment.getCustomerId(), null, null, BmsCustomerLog.MODULE_ATTACHMENT,
|
||||
attachment.getFileName(), BmsCustomerLog.OP_INSERT,
|
||||
beanInsertChanges(attachment, ATTACHMENT_FIELDS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordAttachmentRebuild(List<BmsCustomerAttachment> oldListIn, List<BmsCustomerAttachment> newListIn)
|
||||
{
|
||||
List<BmsCustomerAttachment> oldList = safe(oldListIn);
|
||||
List<BmsCustomerAttachment> newList = safe(newListIn);
|
||||
Map<String, BmsCustomerAttachment> oldMap = new LinkedHashMap<>();
|
||||
for (BmsCustomerAttachment a : oldList)
|
||||
{
|
||||
if (a.getFilePath() != null)
|
||||
{
|
||||
oldMap.put(a.getFilePath(), a);
|
||||
}
|
||||
}
|
||||
Map<String, BmsCustomerAttachment> newMap = new LinkedHashMap<>();
|
||||
for (BmsCustomerAttachment a : newList)
|
||||
{
|
||||
if (a.getFilePath() != null)
|
||||
{
|
||||
newMap.put(a.getFilePath(), a);
|
||||
}
|
||||
}
|
||||
Long customerId = null;
|
||||
if (!oldList.isEmpty())
|
||||
{
|
||||
customerId = oldList.get(0).getCustomerId();
|
||||
}
|
||||
if (!newList.isEmpty())
|
||||
{
|
||||
customerId = newList.get(0).getCustomerId();
|
||||
}
|
||||
if (customerId == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// 新增的文件
|
||||
for (Map.Entry<String, BmsCustomerAttachment> e : newMap.entrySet())
|
||||
{
|
||||
if (!oldMap.containsKey(e.getKey()))
|
||||
{
|
||||
saveLog(customerId, null, null, BmsCustomerLog.MODULE_ATTACHMENT,
|
||||
e.getValue().getFileName(), BmsCustomerLog.OP_INSERT,
|
||||
beanInsertChanges(e.getValue(), ATTACHMENT_FIELDS));
|
||||
}
|
||||
}
|
||||
// 修改的文件(分类/排序/备注/文件名)
|
||||
for (Map.Entry<String, BmsCustomerAttachment> e : newMap.entrySet())
|
||||
{
|
||||
BmsCustomerAttachment old = oldMap.get(e.getKey());
|
||||
if (old == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
List<BmsCustomerLog.FieldChange> changes = beanDiff(old, e.getValue(), ATTACHMENT_FIELDS);
|
||||
if (!changes.isEmpty())
|
||||
{
|
||||
String fileName = trimToNull(e.getValue().getFileName());
|
||||
saveLog(customerId, null, null, BmsCustomerLog.MODULE_ATTACHMENT,
|
||||
fileName != null ? fileName : old.getFileName(), BmsCustomerLog.OP_UPDATE, changes);
|
||||
}
|
||||
}
|
||||
// 删除的文件
|
||||
for (Map.Entry<String, BmsCustomerAttachment> e : oldMap.entrySet())
|
||||
{
|
||||
if (!newMap.containsKey(e.getKey()))
|
||||
{
|
||||
saveLog(customerId, null, null, BmsCustomerLog.MODULE_ATTACHMENT,
|
||||
e.getValue().getFileName(), BmsCustomerLog.OP_DELETE, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================== 套餐绑定 ============================== */
|
||||
|
||||
@Override
|
||||
public void recordPriceSetBind(BmsCustomer customer, BmsCustomerPriceSet existing,
|
||||
BmsCustomerPriceSet bind, BmsPriceSetOption newSet)
|
||||
{
|
||||
if (bind == null || bind.getCustomerId() == null || newSet == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<BmsCustomerLog.FieldChange> changes = new ArrayList<>();
|
||||
changes.add(new BmsCustomerLog.FieldChange("priceSetName", "套餐",
|
||||
existing == null ? "" : nz(existing.getPriceSetName()), nz(newSet.getPriceSetName())));
|
||||
changes.add(new BmsCustomerLog.FieldChange("bindPriority", "优先级",
|
||||
existing == null ? "" : numText(existing.getBindPriority()), numText(bind.getBindPriority())));
|
||||
changes.add(new BmsCustomerLog.FieldChange("prBegindate", "生效日期",
|
||||
existing == null ? "" : dateText(existing.getPrBegindate()), dateText(bind.getPrBegindate())));
|
||||
changes.add(new BmsCustomerLog.FieldChange("prEnddate", "失效日期",
|
||||
existing == null ? "长期" : dateTextOrLong(existing.getPrEnddate()), dateTextOrLong(bind.getPrEnddate())));
|
||||
changes.add(new BmsCustomerLog.FieldChange("priceSetNote", "备注",
|
||||
existing == null ? "" : nz(existing.getPriceSetNote()), nz(bind.getPriceSetNote())));
|
||||
List<BmsCustomerLog.FieldChange> realChanges = new ArrayList<>();
|
||||
for (BmsCustomerLog.FieldChange c : changes)
|
||||
{
|
||||
if (!Objects.equals(emptyToEmpty(c.getOldValue()), emptyToEmpty(c.getNewValue())))
|
||||
{
|
||||
realChanges.add(c);
|
||||
}
|
||||
}
|
||||
saveLog(bind.getCustomerId(), customer == null ? null : customer.getCustomerCode(),
|
||||
customer == null ? null : customer.getCustomerName(),
|
||||
BmsCustomerLog.MODULE_PRICE_SET, newSet.getPriceSetName(),
|
||||
existing == null ? BmsCustomerLog.OP_INSERT : BmsCustomerLog.OP_UPDATE, realChanges);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordPriceSetUnbind(BmsCustomerPriceSet bind)
|
||||
{
|
||||
if (bind == null || bind.getCustomerId() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
saveLog(bind.getCustomerId(), bind.getCustomerCode(), bind.getCustomerName(),
|
||||
BmsCustomerLog.MODULE_PRICE_SET, bind.getPriceSetName(),
|
||||
BmsCustomerLog.OP_DELETE, null);
|
||||
}
|
||||
|
||||
/* ============================== 查询 ============================== */
|
||||
|
||||
@Override
|
||||
public List<BmsCustomerLog> selectByCustomerId(Long customerId)
|
||||
{
|
||||
@@ -145,12 +471,18 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
return list;
|
||||
}
|
||||
|
||||
private void saveLog(BmsCustomer customer, String operationType, List<BmsCustomerLog.FieldChange> changes)
|
||||
/* ============================== 内部工具 ============================== */
|
||||
|
||||
private void saveLog(Long customerId, String customerCode, String customerName,
|
||||
String module, String bizName, String operationType,
|
||||
List<BmsCustomerLog.FieldChange> changes)
|
||||
{
|
||||
BmsCustomerLog log = new BmsCustomerLog();
|
||||
log.setCustomerId(customer.getCustomerId());
|
||||
log.setCustomerCode(customer.getCustomerCode());
|
||||
log.setCustomerName(customer.getCustomerName());
|
||||
log.setCustomerId(customerId);
|
||||
log.setCustomerCode(customerCode);
|
||||
log.setCustomerName(customerName);
|
||||
log.setBizModule(module);
|
||||
log.setBizName(bizName);
|
||||
log.setOperationType(operationType);
|
||||
if (changes != null)
|
||||
{
|
||||
@@ -170,6 +502,88 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
bmsCustomerLogMapper.insertBmsCustomerLog(log);
|
||||
}
|
||||
|
||||
/** 新增场景:取所有非空字段作为初始值 */
|
||||
private List<BmsCustomerLog.FieldChange> beanInsertChanges(Object bean, LinkedHashMap<String, String> fields)
|
||||
{
|
||||
List<BmsCustomerLog.FieldChange> changes = new ArrayList<>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(bean);
|
||||
for (Map.Entry<String, String> f : fields.entrySet())
|
||||
{
|
||||
String value = displayValue(bw, f.getKey());
|
||||
if (value != null && !value.isEmpty())
|
||||
{
|
||||
changes.add(new BmsCustomerLog.FieldChange(f.getKey(), f.getValue(), "", value));
|
||||
}
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
/** 修改场景:逐字段比对,返回变化项 */
|
||||
private List<BmsCustomerLog.FieldChange> beanDiff(Object oldBean, Object newBean,
|
||||
LinkedHashMap<String, String> fields)
|
||||
{
|
||||
List<BmsCustomerLog.FieldChange> changes = new ArrayList<>();
|
||||
BeanWrapper oldBw = new BeanWrapperImpl(oldBean);
|
||||
BeanWrapper newBw = new BeanWrapperImpl(newBean);
|
||||
for (Map.Entry<String, String> f : fields.entrySet())
|
||||
{
|
||||
Object newRaw = newBw.getPropertyValue(f.getKey());
|
||||
// 与 update 动态 SQL 保持一致:新值为 null 的字段本次不落库,不参与比对
|
||||
if (newRaw == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Object oldRaw = oldBw.getPropertyValue(f.getKey());
|
||||
if (!sameValue(oldRaw, newRaw))
|
||||
{
|
||||
changes.add(new BmsCustomerLog.FieldChange(f.getKey(), f.getValue(),
|
||||
nz(displayValue(oldBw, f.getKey())), nz(displayValue(newBw, f.getKey()))));
|
||||
}
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
/** 字段值 -> 日志展示文本(字典翻译/日期格式化) */
|
||||
private String displayValue(BeanWrapper bw, String field)
|
||||
{
|
||||
Object raw = bw.getPropertyValue(field);
|
||||
if (raw == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
if (raw instanceof Date)
|
||||
{
|
||||
return DATE_FMT.get().format((Date) raw);
|
||||
}
|
||||
String text = raw.toString();
|
||||
if (text.isEmpty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
Map<String, String> dict = FIELD_DICTS.get(field);
|
||||
if (dict != null)
|
||||
{
|
||||
String translated = dict.get(text);
|
||||
return translated != null ? translated : text;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private static List<BmsCustomerAttachment> safe(List<BmsCustomerAttachment> list)
|
||||
{
|
||||
return list == null ? List.of() : list;
|
||||
}
|
||||
|
||||
private static String emptyToEmpty(String s)
|
||||
{
|
||||
return s == null ? "" : s;
|
||||
}
|
||||
|
||||
private static String nz(String s)
|
||||
{
|
||||
return s == null ? "" : s;
|
||||
}
|
||||
|
||||
/** 人员字段展示:姓名(工号),缺姓名时只显示工号 */
|
||||
private static String userDisplay(String code, String name)
|
||||
{
|
||||
@@ -195,6 +609,16 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
return num == null ? "" : num.toString();
|
||||
}
|
||||
|
||||
private static String dateText(Date date)
|
||||
{
|
||||
return date == null ? "" : DATE_FMT.get().format(date);
|
||||
}
|
||||
|
||||
private static String dateTextOrLong(Date date)
|
||||
{
|
||||
return date == null ? "长期" : DATE_FMT.get().format(date);
|
||||
}
|
||||
|
||||
private static String trimToNull(String s)
|
||||
{
|
||||
if (s == null)
|
||||
@@ -205,18 +629,32 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
return t.isEmpty() ? null : t;
|
||||
}
|
||||
|
||||
/** 数值按大小比较(规避 BigDecimal 精度差异),其余按字符串比较 */
|
||||
/** 数值按大小比较(规避 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());
|
||||
if (a instanceof Date && b instanceof Date)
|
||||
{
|
||||
return ((Date) a).getTime() == ((Date) b).getTime();
|
||||
}
|
||||
String sa = a == null ? null : a.toString();
|
||||
String sb = b == null ? null : b.toString();
|
||||
if ("".equals(sa))
|
||||
{
|
||||
sa = null;
|
||||
}
|
||||
if ("".equals(sb))
|
||||
{
|
||||
sb = null;
|
||||
}
|
||||
return Objects.equals(sa, sb);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段定义
|
||||
* 主表字段定义
|
||||
*/
|
||||
private static final class FieldDef
|
||||
{
|
||||
|
||||
+43
-3
@@ -9,6 +9,7 @@ import com.bms.customer.customerinfo.domain.BmsCustomer;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet;
|
||||
import com.bms.customer.customerinfo.domain.BmsPriceSetOption;
|
||||
import com.bms.customer.customerinfo.mapper.BmsCustomerPriceSetMapper;
|
||||
import com.bms.customer.customerinfo.service.IBmsCustomerLogService;
|
||||
import com.bms.customer.customerinfo.service.IBmsCustomerPriceSetService;
|
||||
import com.bms.customer.customerinfo.service.IBmsCustomerService;
|
||||
|
||||
@@ -27,6 +28,9 @@ public class BmsCustomerPriceSetServiceImpl implements IBmsCustomerPriceSetServi
|
||||
@Autowired
|
||||
private IBmsCustomerService customerService;
|
||||
|
||||
@Autowired
|
||||
private IBmsCustomerLogService customerLogService;
|
||||
|
||||
@Override
|
||||
public List<BmsCustomerPriceSet> selectBindList(Long customerId)
|
||||
{
|
||||
@@ -85,19 +89,37 @@ public class BmsCustomerPriceSetServiceImpl implements IBmsCustomerPriceSetServi
|
||||
bind.setCustomerName(customer.getCustomerName());
|
||||
|
||||
BmsCustomerPriceSet existing = bindMapper.selectBindByCustomerId(bind.getCustomerId());
|
||||
// selectBindByCustomerId 未关联套餐表,补取旧套餐名用于日志展示
|
||||
if (existing != null && existing.getPriceSetId() != null)
|
||||
{
|
||||
BmsPriceSetOption oldSet = bindMapper.selectPriceSetOptionById(existing.getPriceSetId());
|
||||
if (oldSet != null)
|
||||
{
|
||||
existing.setPriceSetName(oldSet.getPriceSetName());
|
||||
}
|
||||
}
|
||||
int rows;
|
||||
try
|
||||
{
|
||||
if (existing != null)
|
||||
{
|
||||
bind.setCustomerPricesetId(existing.getCustomerPricesetId());
|
||||
return bindMapper.updateBind(bind);
|
||||
rows = bindMapper.updateBind(bind);
|
||||
}
|
||||
else
|
||||
{
|
||||
rows = bindMapper.insertBind(bind);
|
||||
}
|
||||
return bindMapper.insertBind(bind);
|
||||
}
|
||||
catch (DuplicateKeyException e)
|
||||
{
|
||||
throw new ServiceException("该客户已存在套餐绑定,请勿重复绑定");
|
||||
}
|
||||
if (rows > 0)
|
||||
{
|
||||
customerLogService.recordPriceSetBind(customer, existing, bind, set);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,6 +129,24 @@ public class BmsCustomerPriceSetServiceImpl implements IBmsCustomerPriceSetServi
|
||||
{
|
||||
throw new ServiceException("请选择要解绑的记录");
|
||||
}
|
||||
return bindMapper.deleteBindByIds(customerPricesetIds);
|
||||
// 删除前逐个取快照,用于解绑日志
|
||||
List<BmsCustomerPriceSet> snapshots = new java.util.ArrayList<>();
|
||||
for (Long id : customerPricesetIds)
|
||||
{
|
||||
BmsCustomerPriceSet snapshot = bindMapper.selectBindById(id);
|
||||
if (snapshot != null)
|
||||
{
|
||||
snapshots.add(snapshot);
|
||||
}
|
||||
}
|
||||
int rows = bindMapper.deleteBindByIds(customerPricesetIds);
|
||||
if (rows > 0)
|
||||
{
|
||||
for (BmsCustomerPriceSet snapshot : snapshots)
|
||||
{
|
||||
customerLogService.recordPriceSetUnbind(snapshot);
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
|
||||
+66
-6
@@ -98,6 +98,15 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
*/
|
||||
@Override
|
||||
public void saveBmsCustomerAttachments(Long customerId, List<BmsCustomerAttachment> attachmentList)
|
||||
{
|
||||
saveBmsCustomerAttachments(customerId, attachmentList, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量保存客户附件。
|
||||
* @param logInsert true=随客户新建上传,逐文件记新增日志;false=编辑页全量重建,日志由重建差异统一记录
|
||||
*/
|
||||
private void saveBmsCustomerAttachments(Long customerId, List<BmsCustomerAttachment> attachmentList, boolean logInsert)
|
||||
{
|
||||
if (attachmentList == null || attachmentList.isEmpty())
|
||||
{
|
||||
@@ -123,6 +132,10 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
item.setCreateBy(user.getUserName());
|
||||
item.setCreateTime(DateUtils.getNowDate());
|
||||
bmsCustomerMapper.insertBmsCustomerAttachment(item);
|
||||
if (logInsert)
|
||||
{
|
||||
customerLogService.recordAttachmentInsert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +180,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
{
|
||||
bmsCustomerCompany.setDelFlag("0");
|
||||
}
|
||||
return bmsCustomerMapper.insertBmsCustomerCompany(bmsCustomerCompany);
|
||||
int rows = bmsCustomerMapper.insertBmsCustomerCompany(bmsCustomerCompany);
|
||||
if (rows > 0)
|
||||
{
|
||||
customerLogService.recordCompanyInsert(bmsCustomerCompany);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,10 +194,17 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
@Override
|
||||
public int updateBmsCustomerCompany(BmsCustomerCompany bmsCustomerCompany)
|
||||
{
|
||||
BmsCustomerCompany old = bmsCustomerCompany.getCompanyId() == null ? null
|
||||
: bmsCustomerMapper.selectBmsCustomerCompanyByCompanyId(bmsCustomerCompany.getCompanyId());
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
bmsCustomerCompany.setUpdateBy(user.getUserName());
|
||||
bmsCustomerCompany.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsCustomerMapper.updateBmsCustomerCompany(bmsCustomerCompany);
|
||||
int rows = bmsCustomerMapper.updateBmsCustomerCompany(bmsCustomerCompany);
|
||||
if (rows > 0)
|
||||
{
|
||||
customerLogService.recordCompanyUpdate(old, bmsCustomerCompany);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,7 +216,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
int rows = 0;
|
||||
for (Long companyId : companyIds)
|
||||
{
|
||||
BmsCustomerCompany snapshot = bmsCustomerMapper.selectBmsCustomerCompanyByCompanyId(companyId);
|
||||
rows += bmsCustomerMapper.deleteBmsCustomerCompanyByCompanyId(companyId);
|
||||
if (snapshot != null)
|
||||
{
|
||||
customerLogService.recordCompanyDelete(snapshot);
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
@@ -216,15 +246,18 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
}
|
||||
if (item.getCompanyId() != null)
|
||||
{
|
||||
BmsCustomerCompany old = bmsCustomerMapper.selectBmsCustomerCompanyByCompanyId(item.getCompanyId());
|
||||
item.setUpdateBy(user.getUserName());
|
||||
item.setUpdateTime(DateUtils.getNowDate());
|
||||
bmsCustomerMapper.updateBmsCustomerCompany(item);
|
||||
customerLogService.recordCompanyUpdate(old, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.setCreateBy(user.getUserName());
|
||||
item.setCreateTime(DateUtils.getNowDate());
|
||||
bmsCustomerMapper.insertBmsCustomerCompany(item);
|
||||
customerLogService.recordCompanyInsert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,7 +278,7 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
int rows = bmsCustomerMapper.insertBmsCustomer(bmsCustomer);
|
||||
if (rows > 0)
|
||||
{
|
||||
saveBmsCustomerAttachments(bmsCustomer.getCustomerId(), bmsCustomer.getAttachmentList());
|
||||
saveBmsCustomerAttachments(bmsCustomer.getCustomerId(), bmsCustomer.getAttachmentList(), true);
|
||||
saveBmsCustomerCompanies(bmsCustomer.getCustomerId(), bmsCustomer.getCompanyList());
|
||||
saveBmsCustomerContacts(bmsCustomer.getCustomerId(), bmsCustomer.getContactList());
|
||||
// 新建客户即初始化默认CNY账户:余额0、总额度1000 CNY,写INIT流水
|
||||
@@ -271,6 +304,11 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
bmsCustomer.setUpdateBy(user.getUserName());
|
||||
// 修改前先取旧值快照,用于业务日志记录字段级变更
|
||||
BmsCustomer oldCustomer = bmsCustomerMapper.selectBmsCustomerByCustomerId(bmsCustomer.getCustomerId());
|
||||
// 附件重建前取旧档案附件快照,重建后按文件差异记业务日志
|
||||
BmsCustomerAttachment attachmentQuery = new BmsCustomerAttachment();
|
||||
attachmentQuery.setCustomerId(bmsCustomer.getCustomerId());
|
||||
attachmentQuery.setBizType(BmsCustomerAttachment.BIZ_TYPE_CUSTOMER);
|
||||
List<BmsCustomerAttachment> oldAttachments = bmsCustomerMapper.selectBmsCustomerAttachmentList(attachmentQuery);
|
||||
// 仅重建客户档案模块的附件,收款水单等其他业务模块的附件保留不动
|
||||
bmsCustomerMapper.deleteBmsCustomerProfileAttachmentByCustomerId(bmsCustomer.getCustomerId());
|
||||
if (bmsCustomer.getAttachmentList() != null)
|
||||
@@ -286,10 +324,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
// 联系人采用增量 upsert
|
||||
saveBmsCustomerContacts(bmsCustomer.getCustomerId(), bmsCustomer.getContactList());
|
||||
int rows = bmsCustomerMapper.updateBmsCustomer(bmsCustomer);
|
||||
// 业务日志:修改(字段级 修改前→修改后;无实际变更时不记录)
|
||||
if (rows > 0)
|
||||
{
|
||||
// 业务日志:主表字段级修改(无实际变更时不记录)
|
||||
customerLogService.recordUpdate(oldCustomer, bmsCustomer);
|
||||
// 业务日志:附件新增/删除/修改差异
|
||||
customerLogService.recordAttachmentRebuild(oldAttachments, bmsCustomer.getAttachmentList());
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
@@ -384,7 +424,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
{
|
||||
bmsCustomerContact.setDelFlag("0");
|
||||
}
|
||||
return bmsCustomerMapper.insertBmsCustomerContact(bmsCustomerContact);
|
||||
int rows = bmsCustomerMapper.insertBmsCustomerContact(bmsCustomerContact);
|
||||
if (rows > 0)
|
||||
{
|
||||
customerLogService.recordContactInsert(bmsCustomerContact);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -393,10 +438,17 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
@Override
|
||||
public int updateBmsCustomerContact(BmsCustomerContact bmsCustomerContact)
|
||||
{
|
||||
BmsCustomerContact old = bmsCustomerContact.getContactId() == null ? null
|
||||
: bmsCustomerMapper.selectBmsCustomerContactByContactId(bmsCustomerContact.getContactId());
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
bmsCustomerContact.setUpdateBy(user.getUserName());
|
||||
bmsCustomerContact.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsCustomerMapper.updateBmsCustomerContact(bmsCustomerContact);
|
||||
int rows = bmsCustomerMapper.updateBmsCustomerContact(bmsCustomerContact);
|
||||
if (rows > 0)
|
||||
{
|
||||
customerLogService.recordContactUpdate(old, bmsCustomerContact);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,7 +460,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
int rows = 0;
|
||||
for (Long contactId : contactIds)
|
||||
{
|
||||
BmsCustomerContact snapshot = bmsCustomerMapper.selectBmsCustomerContactByContactId(contactId);
|
||||
rows += bmsCustomerMapper.deleteBmsCustomerContactByContactId(contactId);
|
||||
if (snapshot != null)
|
||||
{
|
||||
customerLogService.recordContactDelete(snapshot);
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
@@ -433,15 +490,18 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
|
||||
}
|
||||
if (item.getContactId() != null)
|
||||
{
|
||||
BmsCustomerContact old = bmsCustomerMapper.selectBmsCustomerContactByContactId(item.getContactId());
|
||||
item.setUpdateBy(user.getUserName());
|
||||
item.setUpdateTime(DateUtils.getNowDate());
|
||||
bmsCustomerMapper.updateBmsCustomerContact(item);
|
||||
customerLogService.recordContactUpdate(old, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.setCreateBy(user.getUserName());
|
||||
item.setCreateTime(DateUtils.getNowDate());
|
||||
bmsCustomerMapper.insertBmsCustomerContact(item);
|
||||
customerLogService.recordContactInsert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
<result property="customerId" column="customer_id" />
|
||||
<result property="customerCode" column="customer_code" />
|
||||
<result property="customerName" column="customer_name" />
|
||||
<result property="bizModule" column="biz_module" />
|
||||
<result property="bizName" column="biz_name" />
|
||||
<result property="operationType" column="operation_type" />
|
||||
<result property="changeContent" column="change_content" />
|
||||
<result property="createBy" column="create_by" />
|
||||
@@ -15,8 +17,8 @@
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectBmsCustomerLogVo">
|
||||
select log_id, customer_id, customer_code, customer_name, operation_type, change_content,
|
||||
create_by, create_by_name, create_time
|
||||
select log_id, customer_id, customer_code, customer_name, biz_module, biz_name,
|
||||
operation_type, change_content, create_by, create_by_name, create_time
|
||||
from ctr_customer_log
|
||||
</sql>
|
||||
|
||||
@@ -27,6 +29,8 @@
|
||||
<if test="customerId != null">customer_id,</if>
|
||||
<if test="customerCode != null">customer_code,</if>
|
||||
<if test="customerName != null">customer_name,</if>
|
||||
<if test="bizModule != null">biz_module,</if>
|
||||
<if test="bizName != null">biz_name,</if>
|
||||
<if test="operationType != null">operation_type,</if>
|
||||
<if test="changeContent != null">change_content,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
@@ -37,6 +41,8 @@
|
||||
<if test="customerId != null">#{customerId},</if>
|
||||
<if test="customerCode != null">#{customerCode},</if>
|
||||
<if test="customerName != null">#{customerName},</if>
|
||||
<if test="bizModule != null">#{bizModule},</if>
|
||||
<if test="bizName != null">#{bizName},</if>
|
||||
<if test="operationType != null">#{operationType},</if>
|
||||
<if test="changeContent != null">#{changeContent},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="modelValue"
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
:title="`业务日志 - ${customerName || ''}`"
|
||||
width="900px"
|
||||
append-to-body
|
||||
@open="handleOpen"
|
||||
>
|
||||
<div style="margin-bottom: 10px; color: #909399; font-size: 13px;">
|
||||
客户编码:{{ customerCode || '-' }}
|
||||
<span style="margin-left: 16px;">共 {{ logList.length }} 条日志(按操作时间倒序)</span>
|
||||
</div>
|
||||
<el-table v-loading="loading" :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="92">
|
||||
<template #default="scope">
|
||||
<el-tag :type="moduleTagType(scope.row.bizModule)" size="small" effect="plain">{{ moduleLabel(scope.row.bizModule) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="76">
|
||||
<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" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<span :title="scope.row.bizName">{{ scope.row.bizName || '客户档案' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作人" align="center" width="130">
|
||||
<template #default="scope">{{ scope.row.createByName || scope.row.createBy || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作时间" align="center" width="160">
|
||||
<template #default="scope">{{ fmtTime(scope.row.createTime) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="变更摘要" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ rowSummary(scope.row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="$emit('update:modelValue', false)">关 闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { listCustomerLog } from "@/api/customersuppliermanagement/customerinfo/customer.js"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { type: Boolean, default: false },
|
||||
customerId: { type: [Number, String], default: null },
|
||||
customerName: { type: String, default: '' },
|
||||
customerCode: { type: String, default: '' }
|
||||
})
|
||||
|
||||
defineEmits(['update:modelValue'])
|
||||
|
||||
const loading = ref(false)
|
||||
const logList = ref([])
|
||||
|
||||
const MODULE_META = {
|
||||
main: { label: '客户档案', tag: '' },
|
||||
company: { label: '公司主体', tag: 'success' },
|
||||
contact: { label: '联系人', tag: 'warning' },
|
||||
attachment: { label: '附件', tag: 'info' },
|
||||
priceset: { label: '绑定套餐', tag: 'danger' }
|
||||
}
|
||||
|
||||
const OP_META = {
|
||||
'1': { label: '新建', tag: 'success' },
|
||||
'2': { label: '修改', tag: 'warning' },
|
||||
'3': { label: '删除', tag: 'danger' }
|
||||
}
|
||||
|
||||
const moduleLabel = (m) => MODULE_META[m]?.label || '客户档案'
|
||||
const moduleTagType = (m) => MODULE_META[m]?.tag ?? ''
|
||||
const opLabel = (op) => OP_META[op]?.label || op
|
||||
const opTagType = (op) => OP_META[op]?.tag || 'info'
|
||||
|
||||
const fmtTime = (t) => t ? proxy.parseTime(t, '{y}-{m}-{d} {h}:{i}:{s}') : '-'
|
||||
|
||||
const changeSummary = (changes) => {
|
||||
if (!changes || !changes.length) return '-'
|
||||
return changes.slice(0, 3).map(c => c.fieldLabel).join('、') + (changes.length > 3 ? ` 等${changes.length}项` : '')
|
||||
}
|
||||
|
||||
const rowSummary = (row) => {
|
||||
const mod = moduleLabel(row.bizModule)
|
||||
const obj = row.bizName ? `「${row.bizName}」` : ''
|
||||
if (row.operationType === '1') {
|
||||
return `新建${mod}${obj},录入 ${row.changes?.length || 0} 项信息`
|
||||
}
|
||||
if (row.operationType === '2') {
|
||||
return changeSummary(row.changes)
|
||||
}
|
||||
return `${mod}${obj}被删除`
|
||||
}
|
||||
|
||||
const handleOpen = async () => {
|
||||
if (!props.customerId) return
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await listCustomerLog(props.customerId)
|
||||
logList.value = res.data || []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -10,6 +10,7 @@
|
||||
</div>
|
||||
<div class="head-code">客户编码:{{ form.customerCode || '保存后可维护子表数据' }}</div>
|
||||
<div class="head-right">
|
||||
<el-button v-if="!isAdd" icon="Document" v-hasPermi="['customersupplier:customerinfo:query']" @click="logOpen = true">日 志</el-button>
|
||||
<el-button @click="goBack">取 消</el-button>
|
||||
<el-button v-if="isAdd" type="primary" :loading="saving" v-hasPermi="['customersupplier:customerinfo:add']" @click="submitForm">保 存</el-button>
|
||||
<el-button v-else type="primary" :loading="saving" v-hasPermi="['customersupplier:customerinfo:edit']" @click="submitForm">保 存</el-button>
|
||||
@@ -711,6 +712,14 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 客户业务操作日志弹窗 -->
|
||||
<customer-log-dialog
|
||||
v-model="logOpen"
|
||||
:customer-id="form.customerId"
|
||||
:customer-name="form.customerName"
|
||||
:customer-code="form.customerCode"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -719,6 +728,7 @@ import {
|
||||
listCustomer, getCustomer, addCustomer, updateCustomer,
|
||||
delCustomerCompany, delCustomerContact
|
||||
} from '@/api/customersuppliermanagement/customerinfo/customer.js'
|
||||
import CustomerLogDialog from '../components/CustomerLogDialog.vue'
|
||||
import {
|
||||
listCustomerPriceSet, listPriceSetOption,
|
||||
saveCustomerPriceSet, delCustomerPriceSet
|
||||
@@ -740,6 +750,7 @@ const { ensureProducts, findProduct } = useProducts()
|
||||
const pageLoading = ref(false)
|
||||
const saving = ref(false)
|
||||
const activeTab = ref('base')
|
||||
const logOpen = ref(false)
|
||||
|
||||
const customerId = computed(() => route.query.customerId ? Number(route.query.customerId) : null)
|
||||
const isAdd = computed(() => !customerId.value)
|
||||
|
||||
@@ -197,61 +197,19 @@
|
||||
/>
|
||||
|
||||
<!-- 客户业务操作日志弹窗 -->
|
||||
<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>
|
||||
<customer-log-dialog
|
||||
v-model="logOpen"
|
||||
:customer-id="logCustomer.customerId"
|
||||
:customer-name="logCustomer.customerName"
|
||||
:customer-code="logCustomer.customerCode"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Customer">
|
||||
import { listCustomer, delCustomer, listCustomerLog } from "@/api/customersuppliermanagement/customerinfo/customer.js"
|
||||
import { listCustomer, delCustomer } from "@/api/customersuppliermanagement/customerinfo/customer.js"
|
||||
import { useProducts, parseProductCodes } from '@/components/ProductSelect/useProducts'
|
||||
import CustomerLogDialog from './components/CustomerLogDialog.vue'
|
||||
import { useColumnSettings } from '@/utils/columnSettings'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
@@ -423,30 +381,8 @@ function handleExport() {
|
||||
|
||||
/** ========== 客户业务操作日志 ========== */
|
||||
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]
|
||||
@@ -455,14 +391,7 @@ function handleViewLog(row) {
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user