mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	系统操作日志:集成 mzt-biz-log 4
This commit is contained in:
		| @@ -9,4 +9,8 @@ tenant-id: {{adminTenentId}} | ||||
|   "newOwnerUserId": 127 | ||||
| } | ||||
|  | ||||
| ### 自定义日志记录结果 | ||||
| ### 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=客户转移, bizId=10, content=把客户【张三】的负责人从【芋道源码(15612345678)】变更为了【tttt】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/transfer, userIp=127.0.0.1, userAgent=Apache-HttpClient/4.5.14 (Java/17.0.9)) | ||||
|  | ||||
| ### diff 日志 | ||||
| ### | 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=更新客户, bizId=11, content=更新了客户【所属行业】从【H 住宿和餐饮业】修改为【D 电力、热力、燃气及水生产和供应业】;【客户等级】从【C (非优先客户)】修改为【A (重点客户)】;【客户来源】从【线上咨询】修改为【预约上门】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/update, userIp=0:0:0:0:0:0:0:1, userAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36) | ||||
|   | ||||
| @@ -59,7 +59,7 @@ public class CrmCustomerController { | ||||
|     } | ||||
|  | ||||
|     @PutMapping("/update") | ||||
|     @Operation(summary = "更新客户") | ||||
|     //@Operation(summary = "更新客户") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:update')") | ||||
|     public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { | ||||
|         customerService.updateCustomer(updateReqVO); | ||||
| @@ -123,6 +123,7 @@ public class CrmCustomerController { | ||||
|     } | ||||
|  | ||||
|     @PutMapping("/transfer") | ||||
|     //@Operation(summary = "客户转移") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:update')") | ||||
|     public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { | ||||
|         customerService.transferCustomer(reqVO, getLoginUserId()); | ||||
|   | ||||
| @@ -3,17 +3,20 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||||
| import cn.iocoder.yudao.framework.common.validation.InEnum; | ||||
| import cn.iocoder.yudao.framework.common.validation.Mobile; | ||||
| import cn.iocoder.yudao.framework.common.validation.Telephone; | ||||
| import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | ||||
| import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum; | ||||
| import com.mzt.logapi.starter.annotation.DiffLogField; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import org.springframework.format.annotation.DateTimeFormat; | ||||
|  | ||||
| import jakarta.validation.constraints.Email; | ||||
| import jakarta.validation.constraints.NotEmpty; | ||||
| import jakarta.validation.constraints.Size; | ||||
| import lombok.Data; | ||||
| import org.springframework.format.annotation.DateTimeFormat; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||||
| import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; | ||||
|  | ||||
| /** | ||||
|  * 客户 Base VO,提供给添加、修改、详细的子 VO 使用 | ||||
| @@ -23,57 +26,73 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ | ||||
| public class CrmCustomerBaseVO { | ||||
|  | ||||
|     @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") | ||||
|     @DiffLogField(name = "客户名称") | ||||
|     @NotEmpty(message = "客户名称不能为空") | ||||
|     private String name; | ||||
|  | ||||
|     @Schema(description = "所属行业", example = "1") | ||||
|     @DiffLogField(name = "所属行业", function = "getIndustryById") | ||||
|     @DictFormat(CRM_CUSTOMER_INDUSTRY) | ||||
|     private Integer industryId; | ||||
|  | ||||
|     @Schema(description = "客户等级", example = "2") | ||||
|     @DiffLogField(name = "客户等级", function = "getLevel") | ||||
|     @InEnum(CrmCustomerLevelEnum.class) | ||||
|     private Integer level; | ||||
|  | ||||
|     @Schema(description = "客户来源", example = "3") | ||||
|     @DiffLogField(name = "客户来源", function = "getSource") | ||||
|     private Integer source; | ||||
|  | ||||
|     @Schema(description = "手机", example = "18000000000") | ||||
|     @DiffLogField(name = "手机") | ||||
|     @Mobile | ||||
|     private String mobile; | ||||
|  | ||||
|     @Schema(description = "电话", example = "18000000000") | ||||
|     @DiffLogField(name = "电话") | ||||
|     @Telephone | ||||
|     private String telephone; | ||||
|  | ||||
|     @Schema(description = "网址", example = "https://www.baidu.com") | ||||
|     @DiffLogField(name = "网址") | ||||
|     private String website; | ||||
|  | ||||
|     @Schema(description = "QQ", example = "123456789") | ||||
|     @DiffLogField(name = "QQ") | ||||
|     @Size(max = 20, message = "QQ长度不能超过 20 个字符") | ||||
|     private String qq; | ||||
|  | ||||
|     @Schema(description = "wechat", example = "123456789") | ||||
|     @Schema(description = "微信", example = "123456789") | ||||
|     @DiffLogField(name = "微信") | ||||
|     @Size(max = 255, message = "微信长度不能超过 255 个字符") | ||||
|     private String wechat; | ||||
|  | ||||
|     @Schema(description = "email", example = "123456789@qq.com") | ||||
|     @Schema(description = "邮箱", example = "123456789@qq.com") | ||||
|     @DiffLogField(name = "邮箱") | ||||
|     @Email(message = "邮箱格式不正确") | ||||
|     @Size(max = 255, message = "邮箱长度不能超过 255 个字符") | ||||
|     private String email; | ||||
|  | ||||
|     @Schema(description = "客户描述", example = "任意文字") | ||||
|     @DiffLogField(name = "客户描述") | ||||
|     @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") | ||||
|     private String description; | ||||
|  | ||||
|     @Schema(description = "备注", example = "随便") | ||||
|     @DiffLogField(name = "备注") | ||||
|     private String remark; | ||||
|  | ||||
|     @Schema(description = "地区编号", example = "20158") | ||||
|     @DiffLogField(name = "地区编号", function = "getAreaById") | ||||
|     private Integer areaId; | ||||
|  | ||||
|     @Schema(description = "详细地址", example = "北京市海淀区") | ||||
|     @DiffLogField(name = "详细地址") | ||||
|     private String detailAddress; | ||||
|  | ||||
|     @Schema(description = "下次联系时间") | ||||
|     @DiffLogField(name = "下次联系时间") | ||||
|     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||||
|     private LocalDateTime contactNextTime; | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,46 @@ | ||||
| package cn.iocoder.yudao.module.crm.framework.bizlog.function; | ||||
|  | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; | ||||
| import com.mzt.logapi.service.IParseFunction; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; | ||||
|  | ||||
| /** | ||||
|  * 自定义函数-通过行业编号获取行业信息 | ||||
|  * | ||||
|  * @author HUIHUI | ||||
|  */ | ||||
| @Slf4j | ||||
| @Component | ||||
| public class CrmIndustryParseFunction implements IParseFunction { | ||||
|  | ||||
|     @Override | ||||
|     public boolean executeBefore() { | ||||
|         return true; // 先转换值后对比 | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String functionName() { | ||||
|         return "getIndustryById"; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String apply(Object value) { | ||||
|         if (value == null) { | ||||
|             return ""; | ||||
|         } | ||||
|         if (StrUtil.isEmpty(value.toString())) { | ||||
|             return ""; | ||||
|         } | ||||
|  | ||||
|         // 获取行业信息 | ||||
|         try { | ||||
|             return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, value.toString()); | ||||
|         } catch (Exception ignored) { | ||||
|         } | ||||
|         return ""; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,46 @@ | ||||
| package cn.iocoder.yudao.module.crm.framework.bizlog.function; | ||||
|  | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; | ||||
| import com.mzt.logapi.service.IParseFunction; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL; | ||||
|  | ||||
| /** | ||||
|  * 自定义函数-通过客户等级编号获取客户等级信息 | ||||
|  * | ||||
|  * @author HUIHUI | ||||
|  */ | ||||
| @Slf4j | ||||
| @Component | ||||
| public class CrmLevelParseFunction implements IParseFunction { | ||||
|  | ||||
|     @Override | ||||
|     public boolean executeBefore() { | ||||
|         return true; // 先转换值后对比 | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String functionName() { | ||||
|         return "getLevel"; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String apply(Object value) { | ||||
|         if (value == null) { | ||||
|             return ""; | ||||
|         } | ||||
|         if (StrUtil.isEmpty(value.toString())) { | ||||
|             return ""; | ||||
|         } | ||||
|  | ||||
|         // 获取客户等级信息 | ||||
|         try { | ||||
|             return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_LEVEL, value.toString()); | ||||
|         } catch (Exception ignored) { | ||||
|         } | ||||
|         return ""; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,46 @@ | ||||
| package cn.iocoder.yudao.module.crm.framework.bizlog.function; | ||||
|  | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; | ||||
| import com.mzt.logapi.service.IParseFunction; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE; | ||||
|  | ||||
| /** | ||||
|  * 自定义函数-通过客户来源编号获取客户来源信息 | ||||
|  * | ||||
|  * @author HUIHUI | ||||
|  */ | ||||
| @Slf4j | ||||
| @Component | ||||
| public class CrmSourceParseFunction implements IParseFunction { | ||||
|  | ||||
|     @Override | ||||
|     public boolean executeBefore() { | ||||
|         return true; // 先转换值后对比 | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String functionName() { | ||||
|         return "getSource"; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String apply(Object value) { | ||||
|         if (value == null) { | ||||
|             return ""; | ||||
|         } | ||||
|         if (StrUtil.isEmpty(value.toString())) { | ||||
|             return ""; | ||||
|         } | ||||
|  | ||||
|         // 获取客户来源信息 | ||||
|         try { | ||||
|             return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_SOURCE, value.toString()); | ||||
|         } catch (Exception ignored) { | ||||
|         } | ||||
|         return ""; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1 @@ | ||||
| package cn.iocoder.yudao.module.crm.framework.bizlog; | ||||
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.service.customer; | ||||
|  | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; | ||||
| @@ -16,6 +17,7 @@ import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | ||||
| import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | ||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||
| import com.mzt.logapi.context.LogRecordContext; | ||||
| import com.mzt.logapi.service.impl.DiffParseFunction; | ||||
| import com.mzt.logapi.starter.annotation.LogRecord; | ||||
| import jakarta.annotation.Resource; | ||||
| import org.springframework.stereotype.Service; | ||||
| @@ -63,11 +65,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     @LogRecord(success = "更新了客户{_DIFF{#updateReqVO}}", type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}") | ||||
|     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | ||||
|     public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { | ||||
|         // 校验存在 | ||||
|         validateCustomerExists(updateReqVO.getId()); | ||||
|         CrmCustomerDO oldCustomerDO = validateCustomerExists(updateReqVO.getId()); | ||||
|  | ||||
|         // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null | ||||
|         LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); | ||||
|         // 更新 | ||||
|         CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); | ||||
|         customerMapper.updateById(updateObj); | ||||
| @@ -86,10 +91,12 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|         crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); | ||||
|     } | ||||
|  | ||||
|     private void validateCustomerExists(Long id) { | ||||
|         if (customerMapper.selectById(id) == null) { | ||||
|     private CrmCustomerDO validateCustomerExists(Long id) { | ||||
|         CrmCustomerDO customerDO = customerMapper.selectById(id); | ||||
|         if (customerDO == null) { | ||||
|             throw exception(CUSTOMER_NOT_EXISTS); | ||||
|         } | ||||
|         return customerDO; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -135,7 +142,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|     public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { | ||||
|         // 1. 校验客户是否存在 | ||||
|         validateCustomer(reqVO.getId()); | ||||
|         // 添加 crmCustomer 到日志上下文 | ||||
|         // 添加 crmCustomer 到日志上下文 TODO 日志记录放在 service 里是因为已经过了权限校验查询时不用走两次校验 | ||||
|         LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId())); | ||||
|         // 2.1 数据权限转移 | ||||
|         crmPermissionService.transferPermission( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 puhui999
					puhui999