feat: 添加各模块的操作日志

This commit is contained in:
caiyuchao
2025-09-22 19:01:14 +08:00
parent b38c9db4ff
commit c4a1fcb2e9
21 changed files with 776 additions and 15 deletions

View File

@@ -0,0 +1,40 @@
package org.agt.module.license.enums;
/**
* System 字典类型的枚举类
*
* @author 千通源码
*/
public interface DictTypeConstants {
String LIC_CUSTOMER_TYPE = "lic_customer_type"; // 客户类型
String LIC_BUSINESS_STATUS = "lic_business_status"; // 商务状态
// ========== 客户 模块 ==========
String LIC_PROJECT_STATUS = "lic_project_status"; // 项目状态
String LIC_LICENSE_STATUS = "lic_license_status"; // License状态
String LIC_NE_ALL = "lic_ne_all"; // 网元-一体化
String LIC_NE_5_G = "lic_ne_5g"; // 网元-5G
String LIC_NE_4_G = "lic_ne_4g"; // 网元-4G
String LIC_NE_23_G = "lic_ne_23g"; // 网元-2/3G
String LIC_NE_ADD = "lic_ne_add"; // 网元-增值业务
String LIC_ENV_INFO = "lic_env_info"; // 项目-环境信息
String LIC_SOFTWARE_VERSION = "lic_software_version"; // 项目-软件版本
String LIC_OPERATING_SYSTEM = "lic_operating_system"; // 项目-操作系统平台
}

View File

@@ -0,0 +1,42 @@
package org.agt.module.license.enums;
/**
* System 操作日志枚举
* 目的:统一管理,也减少 Service 里各种“复杂”字符串
*
* @author 千通源码
*/
public interface LogRecordConstants {
// ======================= SYSTEM_CUSTOMER 客户 =======================
String SYSTEM_CUSTOMER_TYPE = "客户管理";
String SYSTEM_CUSTOMER_CREATE_SUB_TYPE = "新增客户";
String SYSTEM_CUSTOMER_CREATE_SUCCESS = "新增了客户【{{#customer.name}}】";
String SYSTEM_CUSTOMER_UPDATE_SUB_TYPE = "修改客户";
String SYSTEM_CUSTOMER_UPDATE_SUCCESS = "修改了客户【{{#customer.name}}】: {_DIFF{#updateReqVO}}";
String SYSTEM_CUSTOMER_DELETE_SUB_TYPE = "删除客户";
String SYSTEM_CUSTOMER_DELETE_SUCCESS = "删除了客户【{{#customer.name}}】";
// ======================= SYSTEM_PROJECT 项目 =======================
String SYSTEM_PROJECT_TYPE = "项目管理";
String SYSTEM_PROJECT_CREATE_SUB_TYPE = "新增项目";
String SYSTEM_PROJECT_CREATE_SUCCESS = "新增了项目【{{#project.name}}】";
String SYSTEM_PROJECT_UPDATE_SUB_TYPE = "修改项目";
String SYSTEM_PROJECT_UPDATE_SUCCESS = "修改了项目【{{#project.name}}】: {_DIFF{#updateReqVO}}";
String SYSTEM_PROJECT_DELETE_SUB_TYPE = "删除项目";
String SYSTEM_PROJECT_DELETE_SUCCESS = "删除了项目【{{#project.name}}】";
// ======================= SYSTEM_LICENSE LICENSE =======================
String SYSTEM_LICENSE_TYPE = "License管理";
String SYSTEM_LICENSE_CREATE_SUB_TYPE = "申请LICENSE";
String SYSTEM_LICENSE_CREATE_SUCCESS = "申请了LICENSE【{{#license.serialNo}}】";
String SYSTEM_LICENSE_UPDATE_SUB_TYPE = "修改LICENSE";
String SYSTEM_LICENSE_UPDATE_SUCCESS = "修改了LICENSE【{{#license.serialNo}}】: {_DIFF{#updateReqVO}}";
String SYSTEM_LICENSE_DELETE_SUB_TYPE = "删除LICENSE";
String SYSTEM_LICENSE_DELETE_SUCCESS = "删除了LICENSE【{{#license.serialNo}}】";
String SYSTEM_LICENSE_REAPPLY_SUB_TYPE = "重新申请LICENSE";
String SYSTEM_LICENSE_REAPPLY_SUCCESS = "重新申请了LICENSE【{{#license.serialNo}}】";
String SYSTEM_LICENSE_GENERATE_SUB_TYPE = "生成LICENSE";
String SYSTEM_LICENSE_GENERATE_SUCCESS = "生成了LICENSE【{{#license.serialNo}}】";
}

View File

@@ -1,9 +1,12 @@
package org.agt.module.license.controller.admin.customer.vo;
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.agt.module.license.framework.operatelog.core.CustomerAreaParseFunction;
import org.agt.module.license.framework.operatelog.core.CustomerTypeParseFunction;
@Schema(description = "管理后台 - 客户新增/修改 Request VO")
@Data
@@ -14,33 +17,42 @@ public class CustomerSaveReqVO {
@Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@NotEmpty(message = "客户名称不能为空")
@DiffLogField(name = "客户名称")
private String name;
@Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
@NotEmpty(message = "客户编号不能为空")
@DiffLogField(name = "客户编号")
private String code;
@Schema(description = "客户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "客户类型不能为空")
@DiffLogField(name = "客户类型", function = CustomerTypeParseFunction.NAME)
private Integer type;
@Schema(description = "地区", requiredMode = Schema.RequiredMode.REQUIRED, example = "5186")
@NotNull(message = "地区不能为空")
@DiffLogField(name = "地区", function = CustomerAreaParseFunction.NAME)
private Long areaId;
@Schema(description = "联系人", requiredMode = Schema.RequiredMode.REQUIRED)
@DiffLogField(name = "联系人")
private String contacts;
@Schema(description = "角色")
@DiffLogField(name = "角色")
private String role;
@Schema(description = "联系电话")
@DiffLogField(name = "联系电话")
private String phone;
@Schema(description = "邮箱")
@DiffLogField(name = "邮箱")
private String email;
@Schema(description = "备注", example = "随便")
@DiffLogField(name = "备注")
private String remark;
}

View File

@@ -1,9 +1,12 @@
package org.agt.module.license.controller.admin.license.vo;
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.agt.module.license.framework.operatelog.core.CommonAdminUserParseFunction;
import org.agt.module.license.framework.operatelog.core.LocalDateParseFunction;
import java.time.LocalDateTime;
import java.util.List;
@@ -25,15 +28,19 @@ public class LicenseSaveReqVO {
@Schema(description = "sn", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "sn不能为空")
@DiffLogField(name = "SN")
private String serialNo;
@Schema(description = "到期时间")
@DiffLogField(name = "到期时间", function = LocalDateParseFunction.NAME)
private LocalDateTime expiryDate;
@Schema(description = "用户数")
@DiffLogField(name = "用户数")
private Integer userNumber;
@Schema(description = "基站数")
@DiffLogField(name = "基站数")
private Integer ranNumber;
@Schema(description = "网元激活码列表")
@@ -45,15 +52,17 @@ public class LicenseSaveReqVO {
@Schema(description = "申请人")
private Long applicant;
@Schema(description = "到期时间")
@Schema(description = "申请时间")
private LocalDateTime applicationTime;
@Schema(description = "审批人")
@DiffLogField(name = "审批人", function = CommonAdminUserParseFunction.NAME)
private Long approver;
@Schema(description = "状态", example = "1")
private Integer status;
@Schema(description = "备注", example = "随便")
@Schema(description = "说明", example = "随便")
@DiffLogField(name = "说明")
private String remark;
}

View File

@@ -1,12 +1,24 @@
package org.agt.module.license.controller.admin.project.vo;
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.agt.module.license.framework.operatelog.core.BusinessStatusParseFunction;
import org.agt.module.license.framework.operatelog.core.CommonAdminUserParseFunction;
import org.agt.module.license.framework.operatelog.core.CustomerNameParseFunction;
import org.agt.module.license.framework.operatelog.core.EnvInfoParseFunction;
import org.agt.module.license.framework.operatelog.core.LocalDateTimeParseFunction;
import org.agt.module.license.framework.operatelog.core.OperatingSystemParseFunction;
import org.agt.module.license.framework.operatelog.core.ProjectStatusParseFunction;
import org.agt.module.license.framework.operatelog.core.SoftwareVersionParseFunction;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.agt.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 项目新增/修改 Request VO")
@Data
public class ProjectSaveReqVO {
@@ -16,61 +28,78 @@ public class ProjectSaveReqVO {
@Schema(description = "客户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10982")
@NotNull(message = "客户ID不能为空")
@DiffLogField(name = "所属客户", function = CustomerNameParseFunction.NAME)
private Long customerId;
@Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "aa")
@NotEmpty(message = "项目名称不能为空")
@DiffLogField(name = "项目名称")
private String name;
@Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
@NotEmpty(message = "项目编号不能为空")
@DiffLogField(name = "项目编号")
private String code;
@Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1111")
@NotEmpty(message = "合同编号不能为空")
@DiffLogField(name = "合同编号")
private String contractCode;
@Schema(description = "商务状态", example = "2")
@DiffLogField(name = "商务状态", function = BusinessStatusParseFunction.NAME)
private Integer businessStatus;
@Schema(description = "业务负责人", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "业务负责人不能为空")
@DiffLogField(name = "业务负责人", function = CommonAdminUserParseFunction.NAME)
private Long businessOwner;
@Schema(description = "客户对接人", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "客户对接人不能为空")
@DiffLogField(name = "客户对接人")
private String customerOwner;
@Schema(description = "技术负责人1", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "技术负责人1不能为空")
@DiffLogField(name = "技术负责人1", function = CommonAdminUserParseFunction.NAME)
private Long technicalOwnerA;
@Schema(description = "技术负责人2")
@DiffLogField(name = "技术负责人2", function = CommonAdminUserParseFunction.NAME)
private Long technicalOwnerB;
@Schema(description = "技术负责人3")
private Long technicalOwnerC;
@Schema(description = "项目开始时间")
@DiffLogField(name = "项目开始时间", function = LocalDateTimeParseFunction.NAME)
private LocalDateTime startTime;
@Schema(description = "项目结束时间")
@DiffLogField(name = "项目结束时间", function = LocalDateTimeParseFunction.NAME)
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime endTime;
@Schema(description = "项目状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "项目状态不能为空")
@DiffLogField(name = "项目状态", function = ProjectStatusParseFunction.NAME)
private Integer status;
@Schema(description = "环境信息")
@DiffLogField(name = "环境信息", function = EnvInfoParseFunction.NAME)
private Integer envInfo;
@Schema(description = "操作系统平台")
@DiffLogField(name = "操作系统平台", function = OperatingSystemParseFunction.NAME)
private Integer operatingSystem;
@Schema(description = "软件版本")
@DiffLogField(name = "软件版本", function = SoftwareVersionParseFunction.NAME)
private Integer softwareVersion;
@Schema(description = "备注", example = "随便")
@DiffLogField(name = "备注")
private String remark;
@Schema(description = "文件url")

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.module.license.enums.DictTypeConstants;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class BusinessStatusParseFunction implements IParseFunction {
public static final String NAME = "getLicenseBusinessStatus";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.LIC_BUSINESS_STATUS, value.toString());
}
}

View File

@@ -0,0 +1,53 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.common.pojo.CommonResult;
import org.agt.module.system.api.user.AdminUserApi;
import org.agt.module.system.api.user.dto.AdminUserRespDTO;
import org.springframework.stereotype.Component;
/**
* 管理员名字的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Slf4j
@Component
public class CommonAdminUserParseFunction implements IParseFunction {
public static final String NAME = "getCommonAdminUserById";
@Resource
private AdminUserApi adminUserApi;
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
// 获取用户信息
CommonResult<AdminUserRespDTO> result = adminUserApi.getUser(Convert.toLong(value));
AdminUserRespDTO user = result.getData();
if (user == null) {
log.warn("[apply][获取用户{{}}为空", value);
return "";
}
// 返回格式 千通源码(13888888888)
String nickname = user.getNickname();
if (StrUtil.isEmpty(user.getMobile())) {
return nickname;
}
return StrUtil.format("{}({})", nickname, user.getMobile());
}
}

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.ip.core.utils.AreaUtils;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class CustomerAreaParseFunction implements IParseFunction {
public static final String NAME = "getArea";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return AreaUtils.format(Convert.toInt(value));
}
}

View File

@@ -0,0 +1,46 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.agt.module.license.dal.dataobject.customer.CustomerDO;
import org.agt.module.license.dal.mysql.customer.CustomerMapper;
import org.springframework.stereotype.Component;
/**
* 管理员名字的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Slf4j
@Component
public class CustomerNameParseFunction implements IParseFunction {
public static final String NAME = "getCustomerName";
@Resource
private CustomerMapper customerMapper;
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
// 获取用户信息
CustomerDO customer = customerMapper.selectById(Convert.toLong(value));
if (customer == null) {
log.warn("[apply][获取客户{{}}为空", value);
return "";
}
return customer.getName();
}
}

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.module.license.enums.DictTypeConstants;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class CustomerTypeParseFunction implements IParseFunction {
public static final String NAME = "getCustomerType";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.LIC_CUSTOMER_TYPE, value.toString());
}
}

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.module.license.enums.DictTypeConstants;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class EnvInfoParseFunction implements IParseFunction {
public static final String NAME = "getEnvInfo";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.LIC_ENV_INFO, value.toString());
}
}

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.module.license.enums.DictTypeConstants;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class LicenseStatusParseFunction implements IParseFunction {
public static final String NAME = "getLicenseStatus";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.LIC_LICENSE_STATUS, value.toString());
}
}

View File

@@ -0,0 +1,40 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class LocalDateParseFunction implements IParseFunction {
public static final String NAME = "getLocalDate";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return LocalDateTimeUtil.format(Convert.toLocalDateTime(value), DatePattern.NORM_DATE_PATTERN);
}
}

View File

@@ -0,0 +1,40 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class LocalDateTimeParseFunction implements IParseFunction {
public static final String NAME = "getLocalDateTime";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return LocalDateTimeUtil.format(Convert.toLocalDateTime(value), DatePattern.NORM_DATETIME_PATTERN);
}
}

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.module.license.enums.DictTypeConstants;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class NeParseFunction implements IParseFunction {
public static final String NAME = "getLicenseNe";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.LIC_NE_ALL, value.toString());
}
}

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.module.license.enums.DictTypeConstants;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class OperatingSystemParseFunction implements IParseFunction {
public static final String NAME = "getOperatingSystem";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.LIC_OPERATING_SYSTEM, value.toString());
}
}

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.module.license.enums.DictTypeConstants;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class ProjectStatusParseFunction implements IParseFunction {
public static final String NAME = "getProjectStatus";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.LIC_PROJECT_STATUS, value.toString());
}
}

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.module.license.enums.DictTypeConstants;
import org.springframework.stereotype.Component;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Component
@Slf4j
public class SoftwareVersionParseFunction implements IParseFunction {
public static final String NAME = "getSoftwareVersion";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
}
@Override
public String functionName() {
return NAME;
}
@Override
public String apply(Object value) {
if (StrUtil.isEmptyIfStr(value)) {
return "";
}
return DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.LIC_SOFTWARE_VERSION, value.toString());
}
}

View File

@@ -3,6 +3,9 @@ package org.agt.module.license.service.customer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
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.agt.framework.common.pojo.PageResult;
import org.agt.framework.common.util.object.BeanUtils;
@@ -36,6 +39,13 @@ import static org.agt.module.license.enums.ErrorCodeConstants.CUSTOMER_CODE_DUPL
import static org.agt.module.license.enums.ErrorCodeConstants.CUSTOMER_IMPORT_LIST_IS_EMPTY;
import static org.agt.module.license.enums.ErrorCodeConstants.CUSTOMER_NAME_DUPLICATE;
import static org.agt.module.license.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_CUSTOMER_CREATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_CUSTOMER_CREATE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_CUSTOMER_DELETE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_CUSTOMER_DELETE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_CUSTOMER_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_CUSTOMER_UPDATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_CUSTOMER_UPDATE_SUCCESS;
/**
* 客户 Service 实现类
@@ -77,39 +87,64 @@ public class CustomerServiceImpl implements CustomerService {
}
@Override
@LogRecord(type = SYSTEM_CUSTOMER_TYPE, subType = SYSTEM_CUSTOMER_CREATE_SUB_TYPE, bizNo = "{{#customer.id}}",
success = SYSTEM_CUSTOMER_CREATE_SUCCESS)
public Long createCustomer(CustomerSaveReqVO createReqVO) {
// 校验客户名称和编号是否唯一
validateCustomerNameAndCodeUnique(createReqVO.getName(), createReqVO.getCode(), createReqVO.getId());
// 插入
CustomerDO customer = BeanUtils.toBean(createReqVO, CustomerDO.class);
customerMapper.insert(customer);
LogRecordContext.putVariable("customer", customer);
// 返回
return customer.getId();
}
@LogRecord(type = SYSTEM_CUSTOMER_TYPE, subType = SYSTEM_CUSTOMER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
success = SYSTEM_CUSTOMER_UPDATE_SUCCESS)
@Override
public void updateCustomer(CustomerSaveReqVO updateReqVO) {
// 校验客户名称和编号是否唯一
validateCustomerNameAndCodeUnique(updateReqVO.getName(), updateReqVO.getCode(), updateReqVO.getId());
// 校验存在
validateCustomerExists(updateReqVO.getId());
CustomerDO customerDO = validateCustomerExists(updateReqVO.getId());
// 更新
CustomerDO updateObj = BeanUtils.toBean(updateReqVO, CustomerDO.class);
customerMapper.updateById(updateObj);
if (updateReqVO.getPhone() == null) {
updateReqVO.setPhone(customerDO.getPhone());
}
if (updateReqVO.getContacts() == null) {
updateReqVO.setContacts(customerDO.getContacts());
}
if (updateReqVO.getRole() == null) {
updateReqVO.setRole(customerDO.getRole());
}
// 记录操作日志上下文
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(customerDO, CustomerSaveReqVO.class));
LogRecordContext.putVariable("customer", customerDO);
}
@Override
@LogRecord(type = SYSTEM_CUSTOMER_TYPE, subType = SYSTEM_CUSTOMER_DELETE_SUB_TYPE, bizNo = "{{#id}}",
success = SYSTEM_CUSTOMER_DELETE_SUCCESS)
public void deleteCustomer(Long id) {
// 校验存在
validateCustomerExists(id);
CustomerDO customerDO = validateCustomerExists(id);
// 删除
customerMapper.deleteById(id);
LogRecordContext.putVariable("customer", customerDO);
}
private void validateCustomerExists(Long id) {
if (customerMapper.selectById(id) == null) {
private CustomerDO validateCustomerExists(Long id) {
CustomerDO customerDO = customerMapper.selectById(id);
if (customerDO == null) {
throw exception(CUSTOMER_NOT_EXISTS);
}
return customerDO;
}
private void validateCustomerNameAndCodeUnique(String name, String code, Long id) {

View File

@@ -10,6 +10,9 @@ import cn.hutool.extra.compress.archiver.Archiver;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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 jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@@ -71,6 +74,17 @@ import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_IMPORT_LIS
import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_NOT_EXISTS;
import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_SN_DUPLICATE;
import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_UPDATE_FAILED;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_CREATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_CREATE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_DELETE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_DELETE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_GENERATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_GENERATE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_REAPPLY_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_REAPPLY_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_UPDATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_UPDATE_SUCCESS;
/**
* License Service 实现类
@@ -114,6 +128,8 @@ public class LicenseServiceImpl implements LicenseService {
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_CREATE_SUB_TYPE, bizNo = "{{#license.id}}",
success = SYSTEM_LICENSE_CREATE_SUCCESS)
public Long createLicense(LicenseSaveReqVO createReqVO, boolean isReapply) {
// 校验项目Sn是否唯一, boolean isReapply
if (!validateLicenseSnUnique(createReqVO.getSerialNo(), createReqVO.getId())) {
@@ -145,22 +161,25 @@ public class LicenseServiceImpl implements LicenseService {
createReqVO.setId(license.getId());
applyLicense(createReqVO, licenseDetails);
LogRecordContext.putVariable("license", license);
// 返回
return license.getId();
}
@Override
@LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
success = SYSTEM_LICENSE_UPDATE_SUCCESS)
public void updateLicense(LicenseSaveReqVO updateReqVO) {
// 校验项目Sn是否唯一
if (!validateLicenseSnUnique(updateReqVO.getSerialNo(), updateReqVO.getId())) {
throw exception(LICENSE_SN_DUPLICATE, updateReqVO.getSerialNo());
}
// 校验存在
validateLicenseExists(updateReqVO.getId());
LicenseDO licenseDO = validateLicenseExists(updateReqVO.getId());
if (updateReqVO.getExpiryDate() != null) {
updateReqVO.setExpiryDate(LocalDateTime.of(updateReqVO.getExpiryDate().toLocalDate(), LocalTime.of(23, 59, 59)));
}
LicenseDO licenseDO = licenseMapper.selectById(updateReqVO.getId());
if (!(LicenseStatusEnum.IN_APPLICATION.getCode().equals(licenseDO.getStatus())
|| LicenseStatusEnum.REAPPLYING.getCode().equals(licenseDO.getStatus()) || licenseDO.getDataType() == 1)) {
throw exception(LICENSE_UPDATE_FAILED);
@@ -173,6 +192,10 @@ public class LicenseServiceImpl implements LicenseService {
licenseDetailMapper.delete(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, updateObj.getId()));
updateLicenseDetail(updateReqVO.getNeCodeList(), updateObj);
// 记录操作日志上下文
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(licenseDO, LicenseSaveReqVO.class));
LogRecordContext.putVariable("license", licenseDO);
}
private List<LicenseDetailDO> updateLicenseDetail(List<LicenseDetailVO> neCodeList, LicenseDO updateObj) {
@@ -218,6 +241,8 @@ public class LicenseServiceImpl implements LicenseService {
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_REAPPLY_SUB_TYPE, bizNo = "{{#license.id}}",
success = SYSTEM_LICENSE_REAPPLY_SUCCESS)
public void reapplyLicense(LicenseSaveReqVO updateReqVO) {
// 校验存在
validateLicenseExists(updateReqVO.getId());
@@ -254,6 +279,8 @@ public class LicenseServiceImpl implements LicenseService {
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_GENERATE_SUB_TYPE, bizNo = "{{#license.id}}",
success = SYSTEM_LICENSE_GENERATE_SUCCESS)
public String generate(Long id) {
LicenseDO licenseDO = licenseMapper.selectById(id);
@@ -323,6 +350,8 @@ public class LicenseServiceImpl implements LicenseService {
licenseDO.setStatus(LicenseStatusEnum.GENERATING.getCode());
licenseMapper.updateById(licenseDO);
LogRecordContext.putVariable("license", licenseDO);
return "";
}
@@ -447,9 +476,11 @@ public class LicenseServiceImpl implements LicenseService {
}
@Override
@LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_DELETE_SUB_TYPE, bizNo = "{{#id}}",
success = SYSTEM_LICENSE_DELETE_SUCCESS)
public void deleteLicense(Long id) {
// 校验存在
validateLicenseExists(id);
LicenseDO license = validateLicenseExists(id);
// 删除
licenseMapper.deleteById(id);
@@ -461,12 +492,15 @@ public class LicenseServiceImpl implements LicenseService {
}
licenseHistoryMapper.delete(Wrappers.<LicenseHistoryDO>lambdaQuery().eq(LicenseHistoryDO::getLicenseId, id));
LogRecordContext.putVariable("license", license);
}
private void validateLicenseExists(Long id) {
if (licenseMapper.selectById(id) == null) {
private LicenseDO validateLicenseExists(Long id) {
LicenseDO licenseDO = licenseMapper.selectById(id);
if (licenseDO == null) {
throw exception(LICENSE_NOT_EXISTS);
}
return licenseDO;
}
@Override

View File

@@ -5,6 +5,9 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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 lombok.extern.slf4j.Slf4j;
import org.agt.framework.common.pojo.PageResult;
@@ -34,6 +37,13 @@ import static org.agt.module.license.enums.ErrorCodeConstants.PROJECT_CODE_DUPLI
import static org.agt.module.license.enums.ErrorCodeConstants.PROJECT_IMPORT_LIST_IS_EMPTY;
import static org.agt.module.license.enums.ErrorCodeConstants.PROJECT_NAME_DUPLICATE;
import static org.agt.module.license.enums.ErrorCodeConstants.PROJECT_NOT_EXISTS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_PROJECT_CREATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_PROJECT_CREATE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_PROJECT_DELETE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_PROJECT_DELETE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_PROJECT_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_PROJECT_UPDATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_PROJECT_UPDATE_SUCCESS;
/**
* 项目 Service 实现类
@@ -61,39 +71,59 @@ public class ProjectServiceImpl implements ProjectService {
private LicenseHistoryMapper licenseHistoryMapper;
@Override
@LogRecord(type = SYSTEM_PROJECT_TYPE, subType = SYSTEM_PROJECT_CREATE_SUB_TYPE, bizNo = "{{#project.id}}",
success = SYSTEM_PROJECT_CREATE_SUCCESS)
public Long createProject(ProjectSaveReqVO createReqVO) {
// 校验项目名称和编号是否唯一
validateProjectNameAndCodeUnique(createReqVO.getName(), createReqVO.getCode(), createReqVO.getId());
// 插入
ProjectDO project = BeanUtils.toBean(createReqVO, ProjectDO.class);
projectMapper.insert(project);
LogRecordContext.putVariable("project", project);
// 返回
return project.getId();
}
@Override
@LogRecord(type = SYSTEM_PROJECT_TYPE, subType = SYSTEM_PROJECT_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
success = SYSTEM_PROJECT_UPDATE_SUCCESS)
public void updateProject(ProjectSaveReqVO updateReqVO) {
// 校验项目名称和编号是否唯一
validateProjectNameAndCodeUnique(updateReqVO.getName(), updateReqVO.getCode(), updateReqVO.getId());
// 校验存在
validateProjectExists(updateReqVO.getId());
ProjectDO project = validateProjectExists(updateReqVO.getId());
// 更新
ProjectDO updateObj = BeanUtils.toBean(updateReqVO, ProjectDO.class);
projectMapper.updateById(updateObj);
if (updateReqVO.getEndTime() == null) {
projectMapper.update(Wrappers.<ProjectDO>lambdaUpdate().eq(ProjectDO::getId, updateObj.getId())
.set(ProjectDO::getEndTime, updateObj.getEndTime()));
}
// 记录操作日志上下文
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(project, ProjectSaveReqVO.class));
LogRecordContext.putVariable("project", project);
}
@Override
@LogRecord(type = SYSTEM_PROJECT_TYPE, subType = SYSTEM_PROJECT_DELETE_SUB_TYPE, bizNo = "{{#id}}",
success = SYSTEM_PROJECT_DELETE_SUCCESS)
public void deleteProject(Long id) {
// 校验存在
validateProjectExists(id);
ProjectDO project = validateProjectExists(id);
// 删除
projectMapper.deleteById(id);
LogRecordContext.putVariable("project", project);
}
private void validateProjectExists(Long id) {
if (projectMapper.selectById(id) == null) {
private ProjectDO validateProjectExists(Long id) {
ProjectDO projectDO = projectMapper.selectById(id);
if (projectDO == null) {
throw exception(PROJECT_NOT_EXISTS);
}
return projectDO;
}
private void validateProjectNameAndCodeUnique(String name, String code, Long id) {