From b0ef0ada668fdc05d69dc29d02b9d0dcd7f8c87d Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 22 Jun 2026 16:32:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E7=94=B5=E7=AB=99?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E4=BF=A1=E6=81=AF=E6=93=8D=E4=BD=9C=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdEngInfoBHController.java | 10 +- .../qgc_base/domain/MsOperationLog.java | 32 +++ .../qgc_base/domain/MsOperationLogDetail.java | 49 ++++ .../domain/SdEngInfoBHOperateRequest.java | 11 + .../mapper/MsOperationLogDetailMapper.java | 7 + .../qgc_base/mapper/MsOperationLogMapper.java | 7 + .../service/IMsOperationLogService.java | 10 + .../qgc_base/service/ISdEngInfoBHService.java | 4 + .../impl/MsOperationLogServiceImpl.java | 213 ++++++++++++++++++ .../service/impl/SdEngInfoBHServiceImpl.java | 30 ++- 10 files changed, 367 insertions(+), 6 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java index 866b074c..1faa114d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java @@ -5,6 +5,7 @@ import com.yfd.platform.annotation.Log; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_base.domain.SdEngInfoBH; +import com.yfd.platform.qgc_base.domain.SdEngInfoBHOperateRequest; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; import com.yfd.platform.qgc_base.service.ISdEngInfoBHService; import io.swagger.v3.oas.annotations.Operation; @@ -91,16 +92,16 @@ public class SdEngInfoBHController { @Log(module = "电站管理", value = "新增电站") @PostMapping("/add") @Operation(summary = "新增电站") - public ResponseResult add(@RequestBody SdEngInfoBH engInfo) { - boolean result = engInfoBHService.addEngInfo(engInfo); + public ResponseResult add(@RequestBody SdEngInfoBHOperateRequest request) { + boolean result = engInfoBHService.addEngInfo(request.getEngInfo(), request.getSource()); return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); } @Log(module = "电站管理", value = "修改电站") @PostMapping("/update") @Operation(summary = "修改电站") - public ResponseResult update(@RequestBody SdEngInfoBH engInfo) { - boolean result = engInfoBHService.updateEngInfo(engInfo); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { + boolean result = engInfoBHService.updateEngInfo(request.getEngInfo(), request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } @@ -111,4 +112,5 @@ public class SdEngInfoBHController { boolean result = engInfoBHService.deleteEngInfo(stcd); return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败"); } + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java new file mode 100644 index 00000000..277171ac --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java @@ -0,0 +1,32 @@ +package com.yfd.platform.qgc_base.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("MS_OPERATION_LOG") +public class MsOperationLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + @TableField("OPERATOR") + private String operator; + + @TableField("OPERATE_TIME") + private Date operateTime; + + @TableField("SOURCE") + private String source; + + @TableField("REMARK") + private String remark; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java new file mode 100644 index 00000000..27e06282 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java @@ -0,0 +1,49 @@ +package com.yfd.platform.qgc_base.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + +@Data +@TableName("MS_OPERATION_LOG_DETAIL") +public class MsOperationLogDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + @TableField("MAIN_ID") + private String mainId; + + @TableField("FIELD_CODE") + private String fieldCode; + + @TableField("TABLE_NAME") + private String tableName; + + @TableField("FIELD_MEANING") + private String fieldMeaning; + + @TableField("STATION_CODE") + private String stationCode; + + @TableField("OLD_VALUE_CODE") + private String oldValueCode; + + @TableField("OLD_VALUE_NAME") + private String oldValueName; + + @TableField("NEW_VALUE_CODE") + private String newValueCode; + + @TableField("NEW_VALUE_NAME") + private String newValueName; + + @TableField("REMARK") + private String remark; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java new file mode 100644 index 00000000..bbe53d73 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java @@ -0,0 +1,11 @@ +package com.yfd.platform.qgc_base.domain; + +import lombok.Data; + +@Data +public class SdEngInfoBHOperateRequest { + + private SdEngInfoBH engInfo; + + private String source; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java new file mode 100644 index 00000000..2f28291b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java @@ -0,0 +1,7 @@ +package com.yfd.platform.qgc_base.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; + +public interface MsOperationLogDetailMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java new file mode 100644 index 00000000..1049d713 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java @@ -0,0 +1,7 @@ +package com.yfd.platform.qgc_base.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.qgc_base.domain.MsOperationLog; + +public interface MsOperationLogMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java new file mode 100644 index 00000000..51debb1d --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java @@ -0,0 +1,10 @@ +package com.yfd.platform.qgc_base.service; + +import com.yfd.platform.qgc_base.domain.SdEngInfoBH; + +public interface IMsOperationLogService { + + void recordEngAddLog(SdEngInfoBH engInfo, String source); + + void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH changeSet, String source); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java index bedb9d35..0c3a521c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java @@ -52,11 +52,15 @@ public interface ISdEngInfoBHService extends IService { */ boolean addEngInfo(SdEngInfoBH engInfo); + boolean addEngInfo(SdEngInfoBH engInfo, String source); + /** * 修改电站 */ boolean updateEngInfo(SdEngInfoBH engInfo); + boolean updateEngInfo(SdEngInfoBH engInfo, String source); + /** * 删除电站 */ diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java new file mode 100644 index 00000000..0e2ec828 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -0,0 +1,213 @@ +package com.yfd.platform.qgc_base.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; +import com.yfd.platform.qgc_base.domain.SdEngInfoBH; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; +import com.yfd.platform.qgc_base.service.IMsOperationLogService; +import com.yfd.platform.utils.SecurityUtils; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Service +public class MsOperationLogServiceImpl implements IMsOperationLogService { + + private static final String ENG_TABLE_NAME = "SD_ENGINFO_B_H"; + + private static final Map ENG_FIELD_MEANING_MAP = new LinkedHashMap<>(); + + static { + ENG_FIELD_MEANING_MAP.put("STCD", "电站编码"); + ENG_FIELD_MEANING_MAP.put("ENNM", "电站名称"); + ENG_FIELD_MEANING_MAP.put("BASE_ID", "所属基地编码"); + ENG_FIELD_MEANING_MAP.put("HBRVCD", "所属基地流域编码"); + ENG_FIELD_MEANING_MAP.put("RVCD", "所属流域编码"); + ENG_FIELD_MEANING_MAP.put("ADDVCD", "所属行政区编码"); + ENG_FIELD_MEANING_MAP.put("HYCD", "所属公司编码"); + ENG_FIELD_MEANING_MAP.put("BLPRD", "所属建设阶段"); + ENG_FIELD_MEANING_MAP.put("BLDSTT", "建设状态"); + ENG_FIELD_MEANING_MAP.put("BLDSTT_CODE", "建设状态分类"); + ENG_FIELD_MEANING_MAP.put("DVTP", "开发方式"); + ENG_FIELD_MEANING_MAP.put("DTIN", "数据是否接入"); + ENG_FIELD_MEANING_MAP.put("RGCP", "调节性能"); + ENG_FIELD_MEANING_MAP.put("LGTD", "经度"); + ENG_FIELD_MEANING_MAP.put("LTTD", "纬度"); + ENG_FIELD_MEANING_MAP.put("STLC", "站址"); + ENG_FIELD_MEANING_MAP.put("ORDER_INDEX", "排序"); + } + + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + + @Override + public void recordEngAddLog(SdEngInfoBH engInfo, String source) { + if (engInfo == null) { + return; + } + MsOperationLog mainLog = buildMainLog("新增电站", source); + msOperationLogMapper.insert(mainLog); + + List details = new ArrayList<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + Object newValue = getFieldValue(field, engInfo); + if (newValue == null) { + continue; + } + details.add(buildDetail(mainLog.getId(), engInfo.getStcd(), resolveColumnName(field), + null, newValue, "新增字段值")); + } + batchInsertDetails(details); + } + + @Override + public void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH changeSet, String source) { + if (before == null || changeSet == null) { + return; + } + SdEngInfoBH after = BeanUtil.copyProperties(before, SdEngInfoBH.class); + BeanUtil.copyProperties(changeSet, after, CopyOptions.create().ignoreNullValue()); + + MsOperationLog mainLog = buildMainLog("修改电站", source); + msOperationLogMapper.insert(mainLog); + + List details = new ArrayList<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + Object oldValue = getFieldValue(field, before); + Object newValue = getFieldValue(field, after); + if (equalsValue(oldValue, newValue)) { + continue; + } + details.add(buildDetail(mainLog.getId(), after.getStcd(), resolveColumnName(field), + oldValue, newValue, "修改字段值")); + } + batchInsertDetails(details); + } + + private MsOperationLog buildMainLog(String remark, String source) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveOperator()); + log.setOperateTime(new Date()); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildDetail(String mainId, + String stationCode, + String fieldCode, + Object oldValue, + Object newValue, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(ENG_TABLE_NAME); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(ENG_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatValue(oldValue)); + detail.setOldValueName(formatValue(oldValue)); + detail.setNewValueCode(formatValue(newValue)); + detail.setNewValueName(formatValue(newValue)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertDetails(List details) { + msOperationLogDetailMapper.insert(details); + } + + private boolean shouldSkipField(Field field) { + if (Modifier.isStatic(field.getModifiers())) { + return true; + } + TableField tableField = field.getAnnotation(TableField.class); + if (tableField != null && !tableField.exist()) { + return true; + } + return false; + } + + private String resolveColumnName(Field field) { + TableId tableId = field.getAnnotation(TableId.class); + if (tableId != null) { + return camelToUpperUnderline(field.getName()); + } + TableField tableField = field.getAnnotation(TableField.class); + if (tableField != null && StrUtil.isNotBlank(tableField.value())) { + return tableField.value(); + } + return camelToUpperUnderline(field.getName()); + } + + private Object getFieldValue(Field field, Object target) { + try { + return field.get(target); + } catch (IllegalAccessException e) { + return null; + } + } + + private boolean equalsValue(Object oldValue, Object newValue) { + return StrUtil.equals(formatValue(oldValue), formatValue(newValue)); + } + + private String formatValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + + private String resolveOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String camelToUpperUnderline(String text) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (Character.isUpperCase(ch) && i > 0) { + builder.append('_'); + } + builder.append(Character.toUpperCase(ch)); + } + return builder.toString(); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 848a7c49..90f2cf64 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -22,11 +22,13 @@ import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo; import com.yfd.platform.qgc_base.domain.vo.EngEiaapprovalVo; import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; +import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdEngInfoBHService; import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.ArrayList; @@ -56,6 +58,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl queryPageList(Page page, String ennm, String rvcd, String baseId, String hycd) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -190,12 +195,33 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl