From fae68975d49984aa7c9ffce84b7b374398392f35 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 29 Jun 2026 11:41:09 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E6=B0=B4=E8=B4=A8?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=BF=AE=E6=94=B9=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wq/controller/EnvWqDataController.java | 8 +- .../qgc_env/wq/service/EnvWqDataService.java | 2 +- .../wq/service/impl/EnvWqDataServiceImpl.java | 469 ++++++++++++++++-- 3 files changed, 431 insertions(+), 48 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wq/controller/EnvWqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/controller/EnvWqDataController.java index f944ba50..9a6709aa 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wq/controller/EnvWqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wq/controller/EnvWqDataController.java @@ -2,6 +2,7 @@ package com.yfd.platform.qgc_env.wq.controller; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.annotation.Log; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_env.wq.entity.vo.WqOperateRequest; import com.yfd.platform.qgc_env.wq.service.EnvWqDataService; @@ -58,13 +59,18 @@ public class EnvWqDataController { return ResponseResult.successData(envWqDataService.getDrtpKendoListCust(dataSourceRequest)); } + @Log(module = "水质统计分析", value = "修改水质小时数据") @PostMapping("/updateWqRsData") @Operation(summary = "修改水质小时数据") public ResponseResult updateWqRsData(@RequestBody WqOperateRequest wqOperateRequest) { - envWqDataService.updateWqRsData(wqOperateRequest.getUpdateData()); + envWqDataService.updateWqRsData( + wqOperateRequest == null ? null : wqOperateRequest.getUpdateData(), + wqOperateRequest == null ? null : wqOperateRequest.getSource() + ); return ResponseResult.success(); } + @Log(module = "水质统计分析", value = "删除水质小时/日/月数据") @PostMapping("/removeKendoByIds") @Operation(summary = "删除水质小时/日/月数据") public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/EnvWqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/EnvWqDataService.java index f23a3931..6a55e1da 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/EnvWqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/EnvWqDataService.java @@ -39,7 +39,7 @@ public interface EnvWqDataService { DataSourceResult getStTbYsBVoKendoListCust(DataSourceRequest dataSourceRequest); - boolean updateWqRsData(Map updateData); + boolean updateWqRsData(Map updateData, String source); boolean removeKendoByIds(BatchDeleteAo batchDeleteAo); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java index 32f2c970..7ac6d0b1 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java @@ -1,12 +1,17 @@ package com.yfd.platform.qgc_env.wq.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.platform.common.*; import com.yfd.platform.common.exception.BizException; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_base.entity.vo.DataParam; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; import com.yfd.platform.qgc_env.wq.entity.vo.*; import com.yfd.platform.qgc_env.wq.service.EnvWqDataService; import com.yfd.platform.qgc_env.wt.entity.vo.WbsbVo; @@ -36,12 +41,125 @@ import java.util.stream.Collectors; @Service public class EnvWqDataServiceImpl implements EnvWqDataService { + private static final String WQ_HOUR_TABLE_NAME = "SD_WQ_R"; + private static final String WQ_DAY_TABLE_NAME = "SD_WQDAY_S"; + private static final String WQ_MONTH_TABLE_NAME = "SD_WQDRTP_S"; + private static final String WQ_STATION_TABLE_NAME = "SD_WQ_B_H"; + + private static final LinkedHashMap WQ_UPDATE_COLUMN_MAP = new LinkedHashMap<>(); + private static final Map WQ_FIELD_MEANING_MAP = new LinkedHashMap<>(); + private static final List WQ_SNAPSHOT_COLUMNS = Arrays.asList( + "STCD", "TM", "DT", "DRTP", "YEAR", "MONTH", + "WTMP", "PH", "DOX", "CODMN", "CODCR", "BOD5", "NH3N", "TP", "TN", + "CU", "ZN", "F", "SE", "ARS", "HG", "CD", "CR6", "PB", "CN", + "VLPH", "OIL", "LAS", "S2", "FCG", "CL", "SO4", "NO3", "THRD", + "COND", "FE", "MN", "AL", "CHLA", "CLARITY", "TU", "CYANO", + "WQGRD", "SFDB", "WQ_SFDBHN_YS", "IS_DELETED" + ); + + static { + WQ_UPDATE_COLUMN_MAP.put("wtmp", "WTMP"); + WQ_UPDATE_COLUMN_MAP.put("ph", "PH"); + WQ_UPDATE_COLUMN_MAP.put("dox", "DOX"); + WQ_UPDATE_COLUMN_MAP.put("codmn", "CODMN"); + WQ_UPDATE_COLUMN_MAP.put("codcr", "CODCR"); + WQ_UPDATE_COLUMN_MAP.put("bod5", "BOD5"); + WQ_UPDATE_COLUMN_MAP.put("nh3n", "NH3N"); + WQ_UPDATE_COLUMN_MAP.put("tp", "TP"); + WQ_UPDATE_COLUMN_MAP.put("tn", "TN"); + WQ_UPDATE_COLUMN_MAP.put("cu", "CU"); + WQ_UPDATE_COLUMN_MAP.put("zn", "ZN"); + WQ_UPDATE_COLUMN_MAP.put("f", "F"); + WQ_UPDATE_COLUMN_MAP.put("se", "SE"); + WQ_UPDATE_COLUMN_MAP.put("ars", "ARS"); + WQ_UPDATE_COLUMN_MAP.put("hg", "HG"); + WQ_UPDATE_COLUMN_MAP.put("cd", "CD"); + WQ_UPDATE_COLUMN_MAP.put("cr6", "CR6"); + WQ_UPDATE_COLUMN_MAP.put("pb", "PB"); + WQ_UPDATE_COLUMN_MAP.put("cn", "CN"); + WQ_UPDATE_COLUMN_MAP.put("vlph", "VLPH"); + WQ_UPDATE_COLUMN_MAP.put("oil", "OIL"); + WQ_UPDATE_COLUMN_MAP.put("las", "LAS"); + WQ_UPDATE_COLUMN_MAP.put("s2", "S2"); + WQ_UPDATE_COLUMN_MAP.put("fcg", "FCG"); + WQ_UPDATE_COLUMN_MAP.put("cl", "CL"); + WQ_UPDATE_COLUMN_MAP.put("so4", "SO4"); + WQ_UPDATE_COLUMN_MAP.put("no3", "NO3"); + WQ_UPDATE_COLUMN_MAP.put("thrd", "THRD"); + WQ_UPDATE_COLUMN_MAP.put("cond", "COND"); + WQ_UPDATE_COLUMN_MAP.put("fe", "FE"); + WQ_UPDATE_COLUMN_MAP.put("mn", "MN"); + WQ_UPDATE_COLUMN_MAP.put("al", "AL"); + WQ_UPDATE_COLUMN_MAP.put("chla", "CHLA"); + WQ_UPDATE_COLUMN_MAP.put("clarity", "CLARITY"); + WQ_UPDATE_COLUMN_MAP.put("tu", "TU"); + WQ_UPDATE_COLUMN_MAP.put("cyano", "CYANO"); + WQ_UPDATE_COLUMN_MAP.put("wqgrd", "WQGRD"); + WQ_UPDATE_COLUMN_MAP.put("sfdb", "SFDB"); + WQ_UPDATE_COLUMN_MAP.put("wqSfdbhnYs", "WQ_SFDBHN_YS"); + + WQ_FIELD_MEANING_MAP.put("STCD", "站点编码"); + WQ_FIELD_MEANING_MAP.put("TM", "监测时间"); + WQ_FIELD_MEANING_MAP.put("DT", "统计日期"); + WQ_FIELD_MEANING_MAP.put("DRTP", "统计类型"); + WQ_FIELD_MEANING_MAP.put("YEAR", "年份"); + WQ_FIELD_MEANING_MAP.put("MONTH", "月份"); + WQ_FIELD_MEANING_MAP.put("WTMP", "水温"); + WQ_FIELD_MEANING_MAP.put("PH", "酸碱度"); + WQ_FIELD_MEANING_MAP.put("DOX", "溶解氧"); + WQ_FIELD_MEANING_MAP.put("CODMN", "高锰酸盐指数"); + WQ_FIELD_MEANING_MAP.put("CODCR", "化学需氧量"); + WQ_FIELD_MEANING_MAP.put("BOD5", "五日生化需氧量"); + WQ_FIELD_MEANING_MAP.put("NH3N", "氨氮"); + WQ_FIELD_MEANING_MAP.put("TP", "总磷"); + WQ_FIELD_MEANING_MAP.put("TN", "总氮"); + WQ_FIELD_MEANING_MAP.put("CU", "铜"); + WQ_FIELD_MEANING_MAP.put("ZN", "锌"); + WQ_FIELD_MEANING_MAP.put("F", "氟化物"); + WQ_FIELD_MEANING_MAP.put("SE", "硒"); + WQ_FIELD_MEANING_MAP.put("ARS", "砷"); + WQ_FIELD_MEANING_MAP.put("HG", "汞"); + WQ_FIELD_MEANING_MAP.put("CD", "镉"); + WQ_FIELD_MEANING_MAP.put("CR6", "六价铬"); + WQ_FIELD_MEANING_MAP.put("PB", "铅"); + WQ_FIELD_MEANING_MAP.put("CN", "氰化物"); + WQ_FIELD_MEANING_MAP.put("VLPH", "挥发酚"); + WQ_FIELD_MEANING_MAP.put("OIL", "石油类"); + WQ_FIELD_MEANING_MAP.put("LAS", "阴离子表面活性剂"); + WQ_FIELD_MEANING_MAP.put("S2", "硫化物"); + WQ_FIELD_MEANING_MAP.put("FCG", "粪大肠菌群"); + WQ_FIELD_MEANING_MAP.put("CL", "氯化物"); + WQ_FIELD_MEANING_MAP.put("SO4", "硫酸盐"); + WQ_FIELD_MEANING_MAP.put("NO3", "硝酸盐"); + WQ_FIELD_MEANING_MAP.put("THRD", "总硬度"); + WQ_FIELD_MEANING_MAP.put("COND", "电导率"); + WQ_FIELD_MEANING_MAP.put("FE", "铁"); + WQ_FIELD_MEANING_MAP.put("MN", "锰"); + WQ_FIELD_MEANING_MAP.put("AL", "铝"); + WQ_FIELD_MEANING_MAP.put("CHLA", "叶绿素a"); + WQ_FIELD_MEANING_MAP.put("CLARITY", "透明度"); + WQ_FIELD_MEANING_MAP.put("TU", "浊度"); + WQ_FIELD_MEANING_MAP.put("CYANO", "蓝绿藻"); + WQ_FIELD_MEANING_MAP.put("WQGRD", "水质类别"); + WQ_FIELD_MEANING_MAP.put("WWQTG", "水功能区目标"); + WQ_FIELD_MEANING_MAP.put("SFDB", "是否达标"); + WQ_FIELD_MEANING_MAP.put("WQ_SFDBHN_YS", "是否达标湖内饮用水源"); + WQ_FIELD_MEANING_MAP.put("ROW_KEY", "删除记录标识"); + WQ_FIELD_MEANING_MAP.put("ROW_DATA", "删除记录数据"); + } + @Resource private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; @Resource private JdbcTemplate jdbcTemplate; + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + @Override public DataSourceResult processKendoList(DataSourceRequest dataSourceRequest) { boolean calculated = CommonConstant.CALCULATE_SUCCESS.equals( @@ -3671,15 +3789,18 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { @Override @Transactional(rollbackFor = Exception.class) - public boolean updateWqRsData(Map updateData) { + public boolean updateWqRsData(Map updateData, String source) { if (updateData == null || updateData.isEmpty()) { return true; } - updateWqHourData(updateData); - updateWqTargetIfNeeded(updateData); - String stcd = asString(updateData.get("stcd")); String tm = asString(updateData.get("tm")); + Map beforeHour = queryWqHourRow(stcd, tm); + Map beforeStation = queryWqStationRow(stcd); + updateWqHourData(updateData); + updateWqTargetIfNeeded(updateData); + recordWqUpdateLog(beforeHour, beforeStation, updateData, source); + if (StrUtil.isNotBlank(stcd) && StrUtil.isNotBlank(tm) && tm.length() >= 10) { String dateStr = tm.substring(0, 10); statisticsDayDataFromHour(stcd, dateStr, dateStr); @@ -3704,17 +3825,24 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { return true; } String dataType = StrUtil.blankToDefault(batchDeleteAo.getDataType(), "").toUpperCase(); + String source = batchDeleteAo == null ? null : batchDeleteAo.getSource(); int batchSize = 500; for (int i = 0; i < dataList.size(); i += batchSize) { List subList = dataList.subList(i, Math.min(i + batchSize, dataList.size())); if ("MON".equals(dataType)) { + List> beforeRows = queryWqMonthRows(subList); softDeleteWqMonthData(subList); + recordWqDeleteLog(beforeRows, WQ_MONTH_TABLE_NAME, "删除水质月数据", source); } if ("DATE".equals(dataType)) { + List> beforeRows = queryWqDayRows(subList); softDeleteWqDayData(subList); + recordWqDeleteLog(beforeRows, WQ_DAY_TABLE_NAME, "删除水质日数据", source); } if ("TIME".equals(dataType)) { + List> beforeRows = queryWqHourRows(subList); deleteWqHourData(subList); + recordWqDeleteLog(beforeRows, WQ_HOUR_TABLE_NAME, "删除水质小时数据", source); Map dateRangeMap = new HashMap<>(); Map monthRangeMap = new HashMap<>(); @@ -3765,50 +3893,9 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { } private void updateWqHourData(Map updateData) { - LinkedHashMap columnMap = new LinkedHashMap<>(); - columnMap.put("wtmp", "WTMP"); - columnMap.put("ph", "PH"); - columnMap.put("dox", "DOX"); - columnMap.put("codmn", "CODMN"); - columnMap.put("codcr", "CODCR"); - columnMap.put("bod5", "BOD5"); - columnMap.put("nh3n", "NH3N"); - columnMap.put("tp", "TP"); - columnMap.put("tn", "TN"); - columnMap.put("cu", "CU"); - columnMap.put("zn", "ZN"); - columnMap.put("f", "F"); - columnMap.put("se", "SE"); - columnMap.put("ars", "ARS"); - columnMap.put("hg", "HG"); - columnMap.put("cd", "CD"); - columnMap.put("cr6", "CR6"); - columnMap.put("pb", "PB"); - columnMap.put("cn", "CN"); - columnMap.put("vlph", "VLPH"); - columnMap.put("oil", "OIL"); - columnMap.put("las", "LAS"); - columnMap.put("s2", "S2"); - columnMap.put("fcg", "FCG"); - columnMap.put("cl", "CL"); - columnMap.put("so4", "SO4"); - columnMap.put("no3", "NO3"); - columnMap.put("thrd", "THRD"); - columnMap.put("cond", "COND"); - columnMap.put("fe", "FE"); - columnMap.put("mn", "MN"); - columnMap.put("al", "AL"); - columnMap.put("chla", "CHLA"); - columnMap.put("clarity", "CLARITY"); - columnMap.put("tu", "TU"); - columnMap.put("cyano", "CYANO"); - columnMap.put("wqgrd", "WQGRD"); - columnMap.put("sfdb", "SFDB"); - columnMap.put("wqSfdbhnYs", "WQ_SFDBHN_YS"); - List setClauses = new ArrayList<>(); List params = new ArrayList<>(); - for (Map.Entry entry : columnMap.entrySet()) { + for (Map.Entry entry : WQ_UPDATE_COLUMN_MAP.entrySet()) { if (updateData.containsKey(entry.getKey())) { setClauses.add(entry.getValue() + " = ?"); params.add(updateData.get(entry.getKey())); @@ -3909,6 +3996,296 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { jdbcTemplate.update(sql.toString(), params.toArray()); } + private Map queryWqHourRow(String stcd, String tm) { + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm)) { + return new HashMap<>(); + } + String sql = "SELECT " + buildWqHourLogSelectColumns() + + " FROM SD_WQ_R WHERE STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS')"; + List> rows = jdbcTemplate.queryForList(sql, stcd, tm); + return rows.isEmpty() ? new HashMap<>() : normalizeLogRow(rows.getFirst()); + } + + private Map queryWqStationRow(String stcd) { + if (StrUtil.isBlank(stcd)) { + return new HashMap<>(); + } + String sql = "SELECT STCD, WWQTG FROM SD_WQ_B_H WHERE STCD = ? AND NVL(IS_DELETED, 0) = 0"; + List> rows = jdbcTemplate.queryForList(sql, stcd); + return rows.isEmpty() ? new HashMap<>() : normalizeLogRow(rows.getFirst()); + } + + private List> queryWqHourRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildWqHourLogSelectColumns()) + .append(" FROM SD_WQ_R WHERE "); + List params = new ArrayList<>(); + appendHourRowConditions(sql, params, dataParamList); + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> queryWqDayRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildWqDayLogSelectColumns()) + .append(" FROM SD_WQDAY_S WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND DT = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDt()); + } + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> queryWqMonthRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildWqMonthLogSelectColumns()) + .append(" FROM SD_WQDRTP_S WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND DRTP = ? AND YEAR = ? AND MONTH = ?)"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDrtp()); + params.add(item == null ? null : item.getYear()); + params.add(item == null ? null : item.getMonth()); + } + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private void appendHourRowConditions(StringBuilder sql, List params, List dataParamList) { + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getTm()); + } + } + + private String buildWqHourLogSelectColumns() { + return "STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, " + + "WTMP, PH, DOX, CODMN, CODCR, BOD5, NH3N, TP, TN, CU, ZN, F, SE, ARS, HG, CD, CR6, PB, CN, " + + "VLPH, OIL, LAS, S2, FCG, CL, SO4, NO3, THRD, COND, FE, MN, AL, CHLA, CLARITY, TU, CYANO, " + + "WQGRD, SFDB, WQ_SFDBHN_YS"; + } + + private String buildWqDayLogSelectColumns() { + return "STCD, TO_CHAR(DT, 'YYYY-MM-DD HH24:MI:SS') AS DT, " + + "WTMP, PH, DOX, CODMN, CODCR, BOD5, NH3N, TP, TN, CU, ZN, F, SE, ARS, HG, CD, CR6, PB, CN, " + + "VLPH, OIL, LAS, S2, FCG, CL, SO4, NO3, THRD, COND, FE, MN, AL, CHLA, CLARITY, TU, CYANO, " + + "WQGRD, SFDB, IS_DELETED"; + } + + private String buildWqMonthLogSelectColumns() { + return "STCD, DRTP, YEAR, MONTH, " + + "WTMP, PH, DOX, CODMN, CODCR, BOD5, NH3N, TP, TN, CU, ZN, F, SE, ARS, HG, CD, CR6, PB, CN, " + + "VLPH, OIL, LAS, S2, FCG, CL, SO4, NO3, THRD, COND, FE, MN, AL, CHLA, CLARITY, TU, CYANO, " + + "WQGRD, SFDB, IS_DELETED"; + } + + private List> normalizeLogRows(List> rows) { + List> result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + for (Map row : rows) { + result.add(normalizeLogRow(row)); + } + return result; + } + + private Map normalizeLogRow(Map row) { + Map normalized = new LinkedHashMap<>(); + if (row == null || row.isEmpty()) { + return normalized; + } + for (Map.Entry entry : row.entrySet()) { + normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue()); + } + return normalized; + } + + private void recordWqUpdateLog(Map beforeHour, + Map beforeStation, + Map updateData, + String source) { + if (updateData == null || updateData.isEmpty()) { + return; + } + String stcd = asString(updateData.get("stcd")); + List details = new ArrayList<>(); + for (Map.Entry entry : WQ_UPDATE_COLUMN_MAP.entrySet()) { + if (!updateData.containsKey(entry.getKey())) { + continue; + } + String column = entry.getValue(); + Object oldValue = beforeHour == null ? null : beforeHour.get(column); + Object newValue = updateData.get(entry.getKey()); + if (StrUtil.equals(formatLogValue(oldValue), formatLogValue(newValue))) { + continue; + } + details.add(buildWqDetail(null, WQ_HOUR_TABLE_NAME, stcd, column, + oldValue, resolveWqDisplayValue(column, oldValue), + newValue, resolveWqDisplayValue(column, newValue), "修改字段值")); + } + if (updateData.containsKey("wwqtg")) { + Object oldValue = beforeStation == null ? null : beforeStation.get("WWQTG"); + Object newValue = updateData.get("wwqtg"); + if (!StrUtil.equals(formatLogValue(oldValue), formatLogValue(newValue))) { + details.add(buildWqDetail(null, WQ_STATION_TABLE_NAME, stcd, "WWQTG", + oldValue, resolveWqDisplayValue("WWQTG", oldValue), + newValue, resolveWqDisplayValue("WWQTG", newValue), "修改字段值")); + } + } + if (details.isEmpty()) { + return; + } + MsOperationLog mainLog = buildWqMainLog("修改水质小时数据", source); + msOperationLogMapper.insert(mainLog); + for (MsOperationLogDetail detail : details) { + detail.setMainId(mainLog.getId()); + } + batchInsertWqLogDetails(details); + } + + private void recordWqDeleteLog(List> rows, String tableName, String remark, String source) { + if (CollUtil.isEmpty(rows)) { + return; + } + MsOperationLog mainLog = buildWqMainLog(remark, source); + msOperationLogMapper.insert(mainLog); + List details = new ArrayList<>(); + for (Map row : rows) { + String stcd = asString(row.get("STCD")); + String rowKey = buildWqRowKey(tableName, row); + String rowSnapshot = buildWqRowSnapshot(row); + details.add(buildWqDetail(mainLog.getId(), tableName, stcd, "ROW_KEY", + rowKey, rowKey, null, null, "删除记录")); + details.add(buildWqDetail(mainLog.getId(), tableName, stcd, "ROW_DATA", + rowSnapshot, rowSnapshot, null, null, "删除记录")); + } + batchInsertWqLogDetails(details); + } + + private MsOperationLog buildWqMainLog(String remark, String source) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveLogOperator()); + log.setOperateTime(new Date()); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildWqDetail(String mainId, + String tableName, + String stationCode, + String fieldCode, + Object oldValueCode, + Object oldValueName, + Object newValueCode, + Object newValueName, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(tableName); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(WQ_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatLogValue(oldValueCode)); + detail.setOldValueName(formatLogValue(oldValueName)); + detail.setNewValueCode(formatLogValue(newValueCode)); + detail.setNewValueName(formatLogValue(newValueName)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertWqLogDetails(List details) { + if (CollUtil.isEmpty(details)) { + return; + } + msOperationLogDetailMapper.insert(details); + } + + private String buildWqRowKey(String tableName, Map row) { + if (WQ_HOUR_TABLE_NAME.equals(tableName)) { + return "STCD=" + formatLogValue(row.get("STCD")) + ", TM=" + formatLogValue(row.get("TM")); + } + if (WQ_DAY_TABLE_NAME.equals(tableName)) { + return "STCD=" + formatLogValue(row.get("STCD")) + ", DT=" + formatLogValue(row.get("DT")); + } + return "STCD=" + formatLogValue(row.get("STCD")) + ", DRTP=" + formatLogValue(row.get("DRTP")) + + ", YEAR=" + formatLogValue(row.get("YEAR")) + ", MONTH=" + formatLogValue(row.get("MONTH")); + } + + private String buildWqRowSnapshot(Map row) { + if (row == null || row.isEmpty()) { + return null; + } + List parts = new ArrayList<>(); + for (String column : WQ_SNAPSHOT_COLUMNS) { + Object value = row.get(column); + String text = formatLogValue(value); + if (StrUtil.isBlank(text)) { + continue; + } + parts.add(column + "=" + text); + } + return parts.isEmpty() ? null : String.join("; ", parts); + } + + private Object resolveWqDisplayValue(String fieldCode, Object rawValue) { + String text = formatLogValue(rawValue); + if (StrUtil.isBlank(text)) { + return rawValue; + } + return switch (fieldCode) { + case "WQGRD", "WWQTG" -> getWqLevelName(text); + case "SFDB" -> parseInteger(text) == null ? text : getSfdbName(parseInteger(text)); + default -> text; + }; + } + + private String resolveLogOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String formatLogValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + private String getMonthEndDate(Integer year, Integer month) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, 1);