Merge branch 'dev-tw'

This commit is contained in:
tangwei 2026-07-01 08:50:29 +08:00
commit ffaaf3c85a
55 changed files with 6266 additions and 126 deletions

View File

@ -65,6 +65,7 @@ public class SecurityConfig {
.requestMatchers("/eq/**").permitAll()
.requestMatchers("/env/**").permitAll()
.requestMatchers("/warn/**").permitAll()
.requestMatchers("/overview/**").permitAll()
.requestMatchers("/wt/**").permitAll()
.requestMatchers("/fb/**").permitAll()
.requestMatchers("/zq/**").permitAll()

View File

@ -151,6 +151,15 @@ public class SwaggerConfig {
.build();
}
@Bean
public GroupedOpenApi groupEnvOverviewApi() {
return GroupedOpenApi.builder()
.group("3.10 全过程-生态环保数据服务-首页(overview)")
.packagesToScan("com.yfd.platform.qgc_env.overview.controller")
.build();
}

View File

@ -93,6 +93,14 @@ public class SdEngInfoBHController {
return ResponseResult.successData(engInfoBHService.getVmsstbprptKendoList(dataSourceRequest));
}
@PostMapping("/stbprpData/GetKendoListCust")
@Operation(summary = "电站通用实时监测数据查询")
public ResponseResult getStbprpDataKendoListCust(@RequestBody DataSourceRequest dataSourceRequest,
@RequestParam("tbCode") String tbCode,
@RequestParam(value = "ignorePageLimit", required = false) Boolean ignorePageLimit) {
return ResponseResult.successData(engInfoBHService.getStbprpDataKendoListCust(dataSourceRequest, tbCode, ignorePageLimit));
}
@Log(module = "电站管理", value = "新增电站")
@PostMapping("/add")
@Operation(summary = "新增电站")

View File

@ -29,4 +29,11 @@ public class MsOperationLog implements Serializable {
@TableField("REMARK")
private String remark;
@TableField("TABLE_NAME")
private String tableName;
@TableField("RECORD_ID")
private String recordId;
}

View File

@ -0,0 +1,24 @@
package com.yfd.platform.qgc_base.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
@Schema(description = "电站通用监测数据动态行")
public class EngStbprpDataVo extends LinkedHashMap<String, Object> implements Serializable {
private static final long serialVersionUID = 1L;
public EngStbprpDataVo() {
super();
}
public EngStbprpDataVo(Map<String, Object> source) {
super();
if (source != null && !source.isEmpty()) {
putAll(source);
}
}
}

View File

@ -12,6 +12,9 @@ public class BatchDeleteAo implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "数据来源")
private String source;
@Schema(description = "数据类型")
private String dataType;

View File

@ -84,4 +84,6 @@ public interface ISdEngInfoBHService extends IService<SdEngInfoBH> {
DataSourceResult<EngVmsstbprptVo> getVmsstbprptKendoList(DataSourceRequest dataSourceRequest);
DataSourceResult<EngOperatVo> getOperatKendoList(DataSourceRequest dataSourceRequest);
DataSourceResult getStbprpDataKendoListCust(DataSourceRequest dataSourceRequest, String tbCode, Boolean ignorePageLimit);
}

View File

@ -275,7 +275,7 @@ public class MsOperationLogServiceImpl implements IMsOperationLogService {
if (engInfo == null) {
return;
}
MsOperationLog mainLog = buildMainLog("新增电站", source);
MsOperationLog mainLog = buildMainLog(null,"新增电站", source);
msOperationLogMapper.insert(mainLog);
List<MsOperationLogDetail> details = new ArrayList<>();
@ -311,7 +311,7 @@ public class MsOperationLogServiceImpl implements IMsOperationLogService {
return;
}
MsOperationLog mainLog = buildMainLog("修改电站", source);
MsOperationLog mainLog = buildMainLog(before.getStcd(),"修改电站", source);
msOperationLogMapper.insert(mainLog);
List<MsOperationLogDetail> details = new ArrayList<>();
@ -348,7 +348,7 @@ public class MsOperationLogServiceImpl implements IMsOperationLogService {
if (engInfo == null) {
return;
}
MsOperationLog mainLog = buildMainLog("删除电站", source);
MsOperationLog mainLog = buildMainLog(engInfo.getStcd(),"删除电站", source);
msOperationLogMapper.insert(mainLog);
List<MsOperationLogDetail> details = new ArrayList<>();
@ -378,10 +378,12 @@ public class MsOperationLogServiceImpl implements IMsOperationLogService {
batchInsertDetails(details);
}
private MsOperationLog buildMainLog(String remark, String source) {
private MsOperationLog buildMainLog(String recordId,String remark, String source) {
MsOperationLog log = new MsOperationLog();
log.setOperator(resolveOperator());
log.setOperateTime(new Date());
log.setTableName(ENG_TABLE_NAME);
log.setRecordId(recordId);
log.setSource(StrUtil.trimToNull(source));
log.setRemark(remark);
return log;

View File

@ -27,12 +27,14 @@ import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest;
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.EngOperatVo;
import com.yfd.platform.qgc_base.domain.vo.EngStbprpDataVo;
import com.yfd.platform.qgc_base.domain.vo.EngStBaseInfoVo;
import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo;
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.system.service.IAdminAuthService;
import com.yfd.platform.utils.QgcQueryWrapperUtil;
import com.yfd.platform.utils.SecurityUtils;
import jakarta.annotation.Resource;
@ -41,15 +43,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -88,6 +82,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
@Resource
private ObjectMapper objectMapper;
@Resource
private IAdminAuthService adminAuthService;
@Override
public Page<SdEngInfoBH> queryPageList(Page<SdEngInfoBH> page, String ennm, String rvcd, String baseId, String hycd) {
LambdaQueryWrapper<SdEngInfoBH> wrapper = new LambdaQueryWrapper<>();
@ -100,7 +97,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
Set<String> authorizedStations = getUserAuthorizedStationCodes();
if (authorizedStations != null && !authorizedStations.isEmpty()) {
wrapper.in(SdEngInfoBH::getStcd, authorizedStations);
}else if (!"admin".equals(SecurityUtils.getCurrentUsername())){
}else if (!adminAuthService.isCurrentManagedAdmin()){
return page;
}
return this.page(page, wrapper);
@ -142,7 +139,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
.select(SdEngInfoBH::getStcd, SdEngInfoBH::getEnnm, SdEngInfoBH::getReachcdName, SdEngInfoBH::getYrgeb, SdEngInfoBH::getBaseId)
.orderByAsc(SdEngInfoBH::getBaseId,SdEngInfoBH::getOrderIndex);
if("admin".equals(SecurityUtils.getCurrentUsername())){
if(adminAuthService.isCurrentManagedAdmin()){
return this.list(wrapper);
}
Set<String> authorizedStations = getUserAuthorizedStationCodes();
@ -709,6 +706,59 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
return queryOperatGroupList(dataSourceRequest, loadOptions);
}
@Override
public DataSourceResult getStbprpDataKendoListCust(DataSourceRequest dataSourceRequest, String tbCode, Boolean ignorePageLimit) {
DataSourceResult<EngStbprpDataVo> result = new DataSourceResult<>();
result.setAggregates(new HashMap<>());
if (StrUtil.isBlank(tbCode)) {
result.setData(new ArrayList<>());
result.setTotal(0L);
return result;
}
DataSourceRequest request = dataSourceRequest == null ? new DataSourceRequest() : dataSourceRequest;
if (!Boolean.TRUE.equals(ignorePageLimit) && request.getTake() == 0) {
request.setTake(2000);
}
DataSourceLoadOptionsBase loadOptions = request.toDevRequest();
List<StbprpTableMeta> tableMetaList = queryStbprpTableMeta(tbCode);
if (CollUtil.isEmpty(tableMetaList)) {
return result;
}
String firstTableName = tableMetaList.getFirst().tableName();
String detailSql = buildStbprpDataDetailSql(request, tableMetaList);
Map<String, Object> paramMap = new HashMap<>();
String filterSql = buildStbprpDataFilterCondition(request.getFilter(), paramMap, new int[]{0}, tableMetaList);
if (StrUtil.isNotBlank(filterSql)) {
detailSql = detailSql + " AND " + filterSql;
}
if (CollUtil.isEmpty(request.getGroup())) {
String sql = detailSql + buildStbprpDataOrderBySql(request.getSort(), tableMetaList);
Page<?> page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
List<Map<String, Object>> rows = microservicDynamicSQLMapper.pageAllList(page, sql, paramMap);
List<EngStbprpDataVo> list = new ArrayList<>();
for (Map<String, Object> row : rows) {
list.add(new EngStbprpDataVo(row));
}
result.setData(list);
result.setTotal(page == null ? list.size() : page.getTotal());
return result;
}
GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup();
String groupSql = buildStbprpDataGroupSql(detailSql, request.getGroup(), tableMetaList);
List<Map<String, Object>> rows = microservicDynamicSQLMapper.pageAllList(null, groupSql, paramMap);
if (Boolean.TRUE.equals(request.getGroupResultFlat())) {
result.setData((List<EngStbprpDataVo>) (List<?>) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos)));
} else {
result.setData((List<EngStbprpDataVo>) (List<?>) new GroupHelper().group(rows, Arrays.asList(groupInfos)));
}
result.setTotal((long) rows.size());
return result;
}
private DataSourceResult<EngOperatVo> queryOperatSummaryList(DataSourceRequest dataSourceRequest,
DataSourceLoadOptionsBase loadOptions) {
StringBuilder sql = new StringBuilder();
@ -1039,6 +1089,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
"CAST(NULL AS NUMBER) AS actcp, " +
"CAST(NULL AS NUMBER) AS ddcp, " +
"eng.CPSC AS cpsc, " +
"eng.PRSC AS prsc, " +
"eng.RGCP AS rgcp, " +
"CASE eng.RGCP " +
" WHEN '1' THEN '多年调节' " +
@ -1080,6 +1131,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
" WHEN '3' THEN '混合式' " +
" ELSE NULL END AS dvtpName, " +
"eng.DTIN AS dtin, " +
"eng.RUN_STATE AS runSTATE, " +
"eng.DTIN_ENV AS dtinEnv, " +
"CASE NVL(eng.DTIN, 0) " +
" WHEN 0 THEN '否' " +
@ -1841,6 +1893,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
case "id" -> "t.id";
case "sttp" -> "t.sttp";
case "sttpCode" -> "t.sttpCode";
case "runState" -> "t.runState";
case "sttpName" -> "t.sttpName";
case "stcd" -> "t.stcd";
case "stnm", "ennm" -> "t.stnm";
@ -1850,6 +1903,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
case "hbrvcd" -> "t.hbrvcd";
case "hbrvcdName" -> "t.hbrvcdName";
case "rvcd" -> "t.rvcd";
case "prsc" -> "t.prsc";
case "rvcdName" -> "t.rvcdName";
case "addvcdName" -> "t.addvcdName";
case "hynm" -> "t.hynm";
@ -2303,4 +2357,311 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
default -> null;
};
}
private List<StbprpTableMeta> queryStbprpTableMeta(String tbCode) {
// 1. 解析参数
List<String> tbCodes = StrUtil.split(tbCode, ',')
.stream()
.map(StrUtil::trim)
.filter(StrUtil::isNotBlank)
.distinct()
.toList();
if (tbCodes.isEmpty()) {
return Collections.emptyList();
}
// 2. 构建 SQL 和参数
Map<String, Object> paramMap = new HashMap<>();
List<String> placeholders = new ArrayList<>();
for (int i = 0; i < tbCodes.size(); i++) {
String key = "tbCode" + i;
paramMap.put(key, tbCodes.get(i));
placeholders.add("#{map." + key + "}");
}
String sql = "SELECT ID, TB, TB_CODE, STCD_MAPPING, TM_MAPPING " +
"FROM ST_TB_B " +
"WHERE NVL(IS_DELETED, 0) = 0 " +
"AND TB_CODE IN (" + StrUtil.join(", ", placeholders) + ") " +
"ORDER BY TB_CODE";
// 3. 执行查询
List<Map<String, Object>> rows = microservicDynamicSQLMapper.pageAllList(null, sql, paramMap);
// 4. 转换结果
List<StbprpTableMeta> result = new ArrayList<>();
for (Map<String, Object> row : rows) {
result.add(new StbprpTableMeta(
asString(row.get("ID")),
asString(row.get("TB")),
asString(row.get("TB_CODE")),
StrUtil.blankToDefault(asString(row.get("STCD_MAPPING")), "STCD"),
StrUtil.blankToDefault(asString(row.get("TM_MAPPING")), "TM")
));
}
return result;
}
/**
* 安全转为字符串
*/
private String asString(Object obj) {
return obj == null ? null : obj.toString();
}
private String buildStbprpDataDetailSql(DataSourceRequest request, List<StbprpTableMeta> tableMetaList) {
List<String> selectItems = resolveStbprpSelectItems(request == null ? null : request.getSelect(), tableMetaList);
StringBuilder sql = new StringBuilder("SELECT ");
sql.append(String.join(", ", selectItems)).append(" FROM ");
for (int i = 0; i < tableMetaList.size(); i++) {
StbprpTableMeta meta = tableMetaList.get(i);
String alias = "t" + (i + 1);
if (i == 0) {
sql.append(meta.tableName()).append(" ").append(alias).append(" ");
} else {
StbprpTableMeta first = tableMetaList.getFirst();
sql.append(" LEFT JOIN ").append(meta.tableName()).append(" ").append(alias)
.append(" ON t1.").append(first.stcdMapping()).append(" = ").append(alias).append(".").append(meta.stcdMapping())
.append(" AND t1.").append(first.tmMapping()).append(" = ").append(alias).append(".").append(meta.tmMapping()).append(" ");
}
}
sql.append(" WHERE 1 = 1");
return sql.toString();
}
private List<String> resolveStbprpSelectItems(List<String> selectFields, List<StbprpTableMeta> tableMetaList) {
if (CollUtil.isEmpty(selectFields)) {
return List.of("t1.*");
}
List<String> items = new ArrayList<>();
for (String field : selectFields) {
if (StrUtil.isBlank(field)) {
continue;
}
String mapped = mapStbprpField(field, tableMetaList);
if (StrUtil.isNotBlank(mapped)) {
items.add(mapped + " AS \"" + field.trim() + "\"");
}
}
if (items.isEmpty()) {
items.add("t1.*");
}
return items;
}
private String buildStbprpDataFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder,
List<StbprpTableMeta> tableMetaList) {
if (filter == null) {
return "";
}
if (StrUtil.isNotBlank(filter.getField())) {
return buildStbprpDataLeafCondition(filter, paramMap, indexHolder, tableMetaList);
}
if (CollUtil.isEmpty(filter.getFilters())) {
return "";
}
List<String> childConditions = new ArrayList<>();
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
String childSql = buildStbprpDataFilterCondition(child, paramMap, indexHolder, tableMetaList);
if (StrUtil.isNotBlank(childSql)) {
childConditions.add("(" + childSql + ")");
}
}
if (childConditions.isEmpty()) {
return "";
}
String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND ";
return String.join(logic, childConditions);
}
private String buildStbprpDataLeafCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder,
List<StbprpTableMeta> tableMetaList) {
String column = mapStbprpField(filter.getField(), tableMetaList);
if (StrUtil.isBlank(column)) {
return "";
}
String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase();
Object value = filter.getValue();
if ("isnull".equals(operator)) {
return column + " IS NULL";
}
if ("isnotnull".equals(operator)) {
return column + " IS NOT NULL";
}
if ("isempty".equals(operator)) {
return "(" + column + " IS NULL OR " + column + " = '')";
}
if ("isnotempty".equals(operator)) {
return "(" + column + " IS NOT NULL AND " + column + " <> '')";
}
boolean dateField = isStbprpDateField(filter);
if ("in".equals(operator) || "ni".equals(operator)) {
List<Object> values = normalizeFilterValues(value);
if (values.isEmpty()) {
return "";
}
List<String> placeholders = new ArrayList<>();
for (Object item : values) {
String key = "stbprpParam" + indexHolder[0]++;
paramMap.put(key, item);
placeholders.add(buildStbprpDataValueExpr(key, dateField, item));
}
return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")";
}
if (value == null) {
return "";
}
String key = "stbprpParam" + indexHolder[0]++;
String expr = buildStbprpDataValueExpr(key, dateField, value);
return switch (operator) {
case "eq" -> {
paramMap.put(key, value);
yield column + " = " + expr;
}
case "neq" -> {
paramMap.put(key, value);
yield column + " <> " + expr;
}
case "contains" -> {
paramMap.put(key, "%" + value + "%");
yield column + " LIKE #{map." + key + "}";
}
case "doesnotcontain" -> {
paramMap.put(key, "%" + value + "%");
yield column + " NOT LIKE #{map." + key + "}";
}
case "startswith" -> {
paramMap.put(key, value + "%");
yield column + " LIKE #{map." + key + "}";
}
case "endswith" -> {
paramMap.put(key, "%" + value);
yield column + " LIKE #{map." + key + "}";
}
case "gt" -> {
paramMap.put(key, value);
yield column + " > " + expr;
}
case "gte" -> {
paramMap.put(key, value);
yield column + " >= " + expr;
}
case "lt" -> {
paramMap.put(key, value);
yield column + " < " + expr;
}
case "lte" -> {
paramMap.put(key, value);
yield column + " <= " + expr;
}
default -> "";
};
}
private String buildStbprpDataValueExpr(String paramKey, boolean dateField, Object value) {
if (!dateField || value == null) {
return "#{map." + paramKey + "}";
}
String text = String.valueOf(value).trim();
if (text.length() <= 10) {
return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')";
}
return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')";
}
private boolean isStbprpDateField(DataSourceRequest.FilterDescriptor filter) {
if (filter == null) {
return false;
}
if ("date".equalsIgnoreCase(filter.getDataType())) {
return true;
}
String field = StrUtil.blankToDefault(filter.getField(), "").trim().toLowerCase();
if (field.contains(".")) {
field = field.substring(field.lastIndexOf('.') + 1);
}
return "tm".equals(field) || "dt".equals(field);
}
private String buildStbprpDataOrderBySql(List<DataSourceRequest.SortDescriptor> sortList, List<StbprpTableMeta> tableMetaList) {
if (CollUtil.isEmpty(sortList)) {
return "";
}
List<String> orderItems = new ArrayList<>();
for (DataSourceRequest.SortDescriptor sort : sortList) {
if (sort == null || StrUtil.isBlank(sort.getField())) {
continue;
}
String column = mapStbprpField(sort.getField(), tableMetaList);
if (StrUtil.isBlank(column)) {
continue;
}
String dir = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC";
orderItems.add(column + " " + dir);
}
if (orderItems.isEmpty()) {
return "";
}
return " ORDER BY " + String.join(", ", orderItems);
}
private String buildStbprpDataGroupSql(String detailSql,
List<DataSourceRequest.GroupDescriptor> groups,
List<StbprpTableMeta> tableMetaList) {
List<String> selectItems = new ArrayList<>();
List<String> groupItems = new ArrayList<>();
List<String> orderItems = new ArrayList<>();
for (DataSourceRequest.GroupDescriptor descriptor : groups) {
if (descriptor == null || StrUtil.isBlank(descriptor.getField())) {
continue;
}
String column = mapStbprpField(descriptor.getField(), tableMetaList);
if (StrUtil.isBlank(column)) {
continue;
}
String upperField = descriptor.getField().trim().toUpperCase();
selectItems.add(column + " AS " + upperField);
selectItems.add("COUNT(*) AS COUNT_" + upperField);
groupItems.add(column);
String dir = "desc".equalsIgnoreCase(descriptor.getDir()) || "des".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC";
orderItems.add(column + " " + dir);
}
if (selectItems.isEmpty()) {
selectItems.add("t1.STCD AS STCD");
selectItems.add("COUNT(*) AS COUNT_STCD");
groupItems.add("t1.STCD");
orderItems.add("t1.STCD ASC");
}
return "SELECT " + String.join(", ", selectItems) +
" FROM (" + detailSql + ") t1 GROUP BY " + String.join(", ", groupItems) +
" ORDER BY " + String.join(", ", orderItems);
}
private String mapStbprpField(String field, List<StbprpTableMeta> tableMetaList) {
if (StrUtil.isBlank(field) || CollUtil.isEmpty(tableMetaList)) {
return null;
}
String normalized = field.trim();
if (!normalized.contains(".")) {
return "t1." + normalized.toUpperCase();
}
String[] parts = normalized.split("\\.", 2);
if (parts.length != 2) {
return null;
}
for (int i = 0; i < tableMetaList.size(); i++) {
if (StrUtil.equalsIgnoreCase(tableMetaList.get(i).tbCode(), parts[0])) {
return "t" + (i + 1) + "." + parts[1].toUpperCase();
}
}
return null;
}
private record StbprpTableMeta(String id, String tableName, String tbCode, String stcdMapping, String tmMapping) {
}
}

View File

@ -10,6 +10,7 @@ import com.yfd.platform.qgc_base.domain.SdFpssBH;
import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper;
import com.yfd.platform.qgc_base.mapper.SdFpssBHMapper;
import com.yfd.platform.qgc_base.service.ISdFpssBHService;
import com.yfd.platform.system.service.IAdminAuthService;
import com.yfd.platform.utils.SecurityUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
@ -29,6 +30,9 @@ public class SdFpssBHServiceImpl extends ServiceImpl<SdFpssBHMapper, SdFpssBH> i
@Resource
private SdEngInfoBHMapper sdEngInfoBHMapper;
@Resource
private IAdminAuthService adminAuthService;
@Override
public Page<SdFpssBH> selectPage(String stcd, String sttp, String rstcd, Integer usfl, Page<SdFpssBH> page) {
@ -50,7 +54,7 @@ public class SdFpssBHServiceImpl extends ServiceImpl<SdFpssBHMapper, SdFpssBH> i
Set<String> authorizedStations = getUserAuthorizedStationCodes();
if (authorizedStations != null && !authorizedStations.isEmpty()) {
wrapper.in(SdFpssBH::getRstcd, authorizedStations);
}else if (!"admin".equals(SecurityUtils.getCurrentUsername())){
}else if (!adminAuthService.isCurrentManagedAdmin()){
return page;
}
@ -68,7 +72,7 @@ public class SdFpssBHServiceImpl extends ServiceImpl<SdFpssBHMapper, SdFpssBH> i
@Override
public List<SdFpssBH> selectForDropdown(String rstcd, String stnm, String baseId,String rvcd,String reachcd) {
// 管理员直接查询无需权限过滤
if ("admin".equals(SecurityUtils.getCurrentUsername())) {
if (adminAuthService.isCurrentManagedAdmin()) {
return queryFpssList(rstcd, stnm, baseId,rvcd,reachcd);
}

View File

@ -15,6 +15,9 @@ import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper;
import com.yfd.platform.qgc_base.mapper.SdHbrvDicMapper;
import com.yfd.platform.qgc_base.mapper.SdHydrobaseMapper;
import com.yfd.platform.qgc_base.service.ISdHbrvDicService;
import com.yfd.platform.system.service.IAdminAuthService;
import com.yfd.platform.utils.CodeToNameMetadataBo;
import com.yfd.platform.utils.DictCodeToNameConverter;
import com.yfd.platform.utils.QgcQueryWrapperUtil;
import com.yfd.platform.utils.SecurityUtils;
import jakarta.annotation.Resource;
@ -46,7 +49,39 @@ public class SdHbrvDicServiceImpl extends ServiceImpl<SdHbrvDicMapper, SdHbrvDic
@Resource
private SdHydrobaseMapper hydrobaseMapper;
@Resource
private IAdminAuthService adminAuthService;
private SdHbrvDicMapper hbrvDicMapper;
@Resource
private DictCodeToNameConverter dictCodeToNameConverter;
/**
* 代码转名称元数据配置列表静态初始化
* <p>
* 每个模块的 ServiceImpl 中可按需定义自己的 codeToNameMetadataBoList
* 在查询方法返回前调用 dictCodeToNameConverter.convertCodeToName(voList, codeToNameMetadataBoList)
* 即可自动将 code 字段转为对应的 name 字段
* </p>
*
* <pre>
* 使用示例
* // 在查询方法末尾调用
* dictCodeToNameConverter.convertCodeToName(voList, CODE_TO_NAME_META_LIST);
* </pre>
*/
private static final List<CodeToNameMetadataBo> CODE_TO_NAME_META_LIST = new ArrayList<>();
// static {
//
// CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("grd").modifyProperty("grdName").dictType("STATIC").dictSource("TEST").build());
// CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("baseid").modifyProperty("basename").dictType("DYNAMIC").dictSource("SD_HYDROBASE").codeColumn("BASEID").nameColumn("BASENAME").filter("NVL(IS_DELETED, 0) = 0 ").build());
// }
@Override
public Page<SdHbrvDic> queryPageList(Page<SdHbrvDic> page, String hbrvnm, String baseid) {
return this.page(page, this.lambdaQuery()
@ -110,7 +145,7 @@ public class SdHbrvDicServiceImpl extends ServiceImpl<SdHbrvDicMapper, SdHbrvDic
.eq(baseid != null && !baseid.isEmpty(), SdHbrvDic::getBaseid, baseid)
.eq(SdHbrvDic::getEnabled, 1)
.orderByAsc(SdHbrvDic::getBaseid,SdHbrvDic::getOrderIndex);
if("admin".equals(SecurityUtils.getCurrentUsername())){
if(adminAuthService.isCurrentManagedAdmin()){
return this.list(wrapper);
}
Set<String> authorizedStations = getUserAuthorizedStationCodes();

View File

@ -13,6 +13,7 @@ import com.yfd.platform.qgc_base.entity.vo.HydrobaseWbsVo;
import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper;
import com.yfd.platform.qgc_base.mapper.SdHydrobaseMapper;
import com.yfd.platform.qgc_base.service.ISdHydrobaseService;
import com.yfd.platform.system.service.IAdminAuthService;
import com.yfd.platform.utils.SecurityUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
@ -39,6 +40,9 @@ public class SdHydrobaseServiceImpl extends ServiceImpl<SdHydrobaseMapper, SdHyd
@Resource
private SdEngInfoBHMapper sdEngInfoBHMapper;
@Resource
private IAdminAuthService adminAuthService;
@Override
public Page<SdHydrobase> queryPageList(Page<SdHydrobase> page, String basename, String pbaseid) {
return this.page(page, this.lambdaQuery()
@ -91,7 +95,7 @@ public class SdHydrobaseServiceImpl extends ServiceImpl<SdHydrobaseMapper, SdHyd
} else {
return new ArrayList<>();
}
}else if (!"admin".equals(SecurityUtils.getCurrentUsername())){
}else if (!adminAuthService.isCurrentManagedAdmin()){
return new ArrayList<>();
}
// else {

View File

@ -11,6 +11,7 @@ import com.yfd.platform.qgc_base.mapper.SdRvcdDicMapper;
import com.yfd.platform.qgc_base.service.ISdRvcdDicService;
import com.yfd.platform.qgc_data.domain.SysUserDataScope;
import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper;
import com.yfd.platform.system.service.IAdminAuthService;
import com.yfd.platform.utils.SecurityUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
@ -33,6 +34,9 @@ public class SdRvcdDicServiceImpl extends ServiceImpl<SdRvcdDicMapper, SdRvcdDic
@Resource
private SysUserDataScopeMapper sysUserDataScopeMapper;
@Resource
private IAdminAuthService adminAuthService;
@Override
public Page<SdRvcdDic> queryPageList(Page<SdRvcdDic> page, String rvnm, String prvcd) {
return this.page(page, this.lambdaQuery()
@ -120,7 +124,7 @@ public class SdRvcdDicServiceImpl extends ServiceImpl<SdRvcdDicMapper, SdRvcdDic
@Override
public List<SdRvcdDic> selectForDropdown(String rvnm, String rvcd) {
List<SdRvcdDic> dropdownList = this.baseMapper.selectRegDropdown(rvnm, rvcd);
if("admin".equals(SecurityUtils.getCurrentUsername())){
if(adminAuthService.isCurrentManagedAdmin()){
return dropdownList;
}
Set<String> authorizedStations = getUserAuthorizedStationCodes();

View File

@ -5746,7 +5746,8 @@ public class EngEqDataServiceImpl implements EngEqDataService {
}
return switch (field) {
case "id" -> "t.id";
case "stcd" -> "t.stcd";
case "rstcd" -> "t.stcd";
// case "rstcd" -> "t.rstcd";
case "stnm", "ennm" -> "t.ennm";
case "baseId" -> "t.baseId";
case "baseName" -> "t.baseName";

View File

@ -0,0 +1,35 @@
package com.yfd.platform.qgc_env.overview.controller;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.qgc_env.overview.service.OverviewService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/overview")
@Tag(name = "首页概览")
@Validated
public class OverviewController {
@Resource
private OverviewService overviewService;
@PostMapping("/msstbprpt/GetKendoList")
@Operation(summary = "首页基础设施概览列表")
public ResponseResult getMsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(overviewService.getMsstbprptList(dataSourceRequest));
}
@PostMapping("/oped/GetKendoListCust")
@Operation(summary = "首页环保设施运行状况明细")
public ResponseResult getOpedList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(overviewService.getOpedList(dataSourceRequest));
}
}

View File

@ -0,0 +1,72 @@
package com.yfd.platform.qgc_env.overview.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
@Schema(description = "首页基础设施概览列表")
public class OverviewMsstbprptVo implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String stcd;
private String stnm;
private String sttp;
private String sttpCode;
private String sttpName;
private String sttpFullPath;
private Integer sttpTreeLevel;
private String blprdId;
private Double lgtd;
private Double lttd;
private Double dtmel;
private String stlc;
private Integer usfl;
private String rstcd;
private String ennm;
private String baseId;
private String baseName;
private String hbrvcd;
private String hbrvcdName;
private String rvcd;
private String rvcdName;
private String addvcd;
private String addvcdName;
private String country;
private String countryName;
private String stCode;
private String stName;
private Date stdsdt;
private Date pststdt;
private Date pesstdt;
private Date ststdt;
private Date jcdt;
private Date stwddt;
private String introduce;
private String precis;
private String logo;
private String inffile;
private Integer dtin;
private String dtinName;
private Date dtinTm;
private Integer bldsttCode;
private String bldsttCcode;
private String bldsttCcodeName;
private Double inv;
private Integer invinmn;
private String dsun;
private String jbtxcs;
private Integer dtfrqcy;
private String remark;
private String vlsr;
private Date vlsrTm;
private Integer orderIndex;
private Integer baseStepSort;
private Integer rvcdStepSort;
private Integer rstcdStepSort;
private Integer siteStepSort;
}

View File

@ -0,0 +1,65 @@
package com.yfd.platform.qgc_env.overview.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Data
@Schema(description = "首页环保设施运行状况明细")
public class OverviewOpedVo implements Serializable {
private static final long serialVersionUID = 1L;
private Map<String, Object> _tls = new HashMap<>();
private String id;
private String recordUser;
private Date recordTime;
private Date modifyTime;
private String displayRecordUser;
private String repCode;
private String pcode;
private String pname;
private String psttpName;
private String sttpName;
private String baseId;
private String stcd;
private String stnm;
private String sttpCode;
private String baseName;
private String rstcd;
private String ennm;
private String bldsttCcode;
private String bldsttCcodeName;
private Date dtinTm;
private Integer dtin;
private String dtinName;
private Integer runState;
private String runStateName;
private Integer stdState;
private String stdStateName;
private Integer stdSstate;
private String stdSstateName;
private Integer runSstate;
private String runSstateName;
private Integer mway;
private String mwayName;
private String hbrvcd;
private String hbrvcdName;
private String addvcdName;
private String rvcdName;
private Integer baseStepSort;
private Integer baseStepsort;
private Integer rvcdStepSort;
private Integer rstcdStepSort;
private Integer rstcdStepsort;
private Integer siteStepSort;
private Integer count;
private Date jcdt;
private String departmentId;
private String displayDepartment;
}

View File

@ -0,0 +1,13 @@
package com.yfd.platform.qgc_env.overview.service;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.qgc_env.overview.entity.vo.OverviewMsstbprptVo;
import com.yfd.platform.qgc_env.overview.entity.vo.OverviewOpedVo;
public interface OverviewService {
DataSourceResult<OverviewMsstbprptVo> getMsstbprptList(DataSourceRequest dataSourceRequest);
DataSourceResult<OverviewOpedVo> getOpedList(DataSourceRequest dataSourceRequest);
}

View File

@ -2,7 +2,9 @@ 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;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -57,13 +59,18 @@ public class EnvWqDataController {
return ResponseResult.successData(envWqDataService.getDrtpKendoListCust(dataSourceRequest));
}
@Log(module = "水质统计分析", value = "修改水质小时数据")
@PostMapping("/updateWqRsData")
@Operation(summary = "修改水质小时数据")
public ResponseResult updateWqRsData(@RequestBody Map<String, Object> updateData) {
envWqDataService.updateWqRsData(updateData);
public ResponseResult updateWqRsData(@RequestBody WqOperateRequest wqOperateRequest) {
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) {

View File

@ -0,0 +1,13 @@
package com.yfd.platform.qgc_env.wq.entity.vo;
import lombok.Data;
import java.util.Map;
@Data
public class WqOperateRequest {
private String source;
private Map<String, Object> updateData;
}

View File

@ -39,7 +39,7 @@ public interface EnvWqDataService {
DataSourceResult getStTbYsBVoKendoListCust(DataSourceRequest dataSourceRequest);
boolean updateWqRsData(Map<String, Object> updateData);
boolean updateWqRsData(Map<String, Object> updateData, String source);
boolean removeKendoByIds(BatchDeleteAo batchDeleteAo);
}

View File

@ -1,12 +1,18 @@
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.ObjectUtil;
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 +42,114 @@ 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<String, String> WQ_UPDATE_COLUMN_MAP = new LinkedHashMap<>();
private static final Map<String, String> WQ_FIELD_MEANING_MAP = new LinkedHashMap<>();
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", "是否达标湖内饮用水源");
}
@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 +3779,18 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateWqRsData(Map<String, Object> updateData) {
public boolean updateWqRsData(Map<String, Object> 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<String, Object> beforeHour = queryWqHourRow(stcd, tm);
Map<String, Object> 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 +3815,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<DataParam> subList = dataList.subList(i, Math.min(i + batchSize, dataList.size()));
if ("MON".equals(dataType)) {
List<Map<String, Object>> beforeRows = queryWqMonthRows(subList);
softDeleteWqMonthData(subList);
recordWqDeleteLog(beforeRows, WQ_MONTH_TABLE_NAME, "删除水质月数据", source);
}
if ("DATE".equals(dataType)) {
List<Map<String, Object>> beforeRows = queryWqDayRows(subList);
softDeleteWqDayData(subList);
recordWqDeleteLog(beforeRows, WQ_DAY_TABLE_NAME, "删除水质日数据", source);
}
if ("TIME".equals(dataType)) {
List<Map<String, Object>> beforeRows = queryWqHourRows(subList);
deleteWqHourData(subList);
recordWqDeleteLog(beforeRows, WQ_HOUR_TABLE_NAME, "删除水质小时数据", source);
Map<String, String[]> dateRangeMap = new HashMap<>();
Map<String, String[]> monthRangeMap = new HashMap<>();
@ -3765,50 +3883,9 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
}
private void updateWqHourData(Map<String, Object> updateData) {
LinkedHashMap<String, String> 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<String> setClauses = new ArrayList<>();
List<Object> params = new ArrayList<>();
for (Map.Entry<String, String> entry : columnMap.entrySet()) {
for (Map.Entry<String, String> entry : WQ_UPDATE_COLUMN_MAP.entrySet()) {
if (updateData.containsKey(entry.getKey())) {
setClauses.add(entry.getValue() + " = ?");
params.add(updateData.get(entry.getKey()));
@ -3909,6 +3986,286 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
jdbcTemplate.update(sql.toString(), params.toArray());
}
private Map<String, Object> 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<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, stcd, tm);
return rows.isEmpty() ? new HashMap<>() : normalizeLogRow(rows.getFirst());
}
private Map<String, Object> 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<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, stcd);
return rows.isEmpty() ? new HashMap<>() : normalizeLogRow(rows.getFirst());
}
private List<Map<String, Object>> queryWqHourRows(List<DataParam> dataParamList) {
if (CollUtil.isEmpty(dataParamList)) {
return new ArrayList<>();
}
StringBuilder sql = new StringBuilder("SELECT ")
.append(buildWqHourLogSelectColumns())
.append(" FROM SD_WQ_R WHERE ");
List<Object> params = new ArrayList<>();
appendHourRowConditions(sql, params, dataParamList);
return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray()));
}
private List<Map<String, Object>> queryWqDayRows(List<DataParam> dataParamList) {
if (CollUtil.isEmpty(dataParamList)) {
return new ArrayList<>();
}
StringBuilder sql = new StringBuilder("SELECT ")
.append(buildWqDayLogSelectColumns())
.append(" FROM SD_WQDAY_S WHERE ");
List<Object> 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<Map<String, Object>> queryWqMonthRows(List<DataParam> dataParamList) {
if (CollUtil.isEmpty(dataParamList)) {
return new ArrayList<>();
}
StringBuilder sql = new StringBuilder("SELECT ")
.append(buildWqMonthLogSelectColumns())
.append(" FROM SD_WQDRTP_S WHERE ");
List<Object> 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<Object> params, List<DataParam> 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 "ID,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<Map<String, Object>> normalizeLogRows(List<Map<String, Object>> rows) {
List<Map<String, Object>> result = new ArrayList<>();
if (CollUtil.isEmpty(rows)) {
return result;
}
for (Map<String, Object> row : rows) {
result.add(normalizeLogRow(row));
}
return result;
}
private Map<String, Object> normalizeLogRow(Map<String, Object> row) {
Map<String, Object> normalized = new LinkedHashMap<>();
if (row == null || row.isEmpty()) {
return normalized;
}
for (Map.Entry<String, Object> entry : row.entrySet()) {
normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue());
}
return normalized;
}
private void recordWqUpdateLog(Map<String, Object> beforeHour,
Map<String, Object> beforeStation,
Map<String, Object> updateData,
String source) {
if (updateData == null || updateData.isEmpty()) {
return;
}
String stcd = asString(updateData.get("stcd"));
List<MsOperationLogDetail> details = new ArrayList<>();
for (Map.Entry<String, String> 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;
}
String recordId = ObjectUtil.isNotEmpty(beforeHour) && ObjectUtil.isNotEmpty(beforeHour.get("ID"))
? beforeHour.get("ID").toString()
: null; MsOperationLog mainLog = buildWqMainLog(recordId,"修改水质小时数据", source);
msOperationLogMapper.insert(mainLog);
for (MsOperationLogDetail detail : details) {
detail.setMainId(mainLog.getId());
}
batchInsertWqLogDetails(details);
}
private void recordWqDeleteLog(List<Map<String, Object>> rows, String tableName, String remark, String source) {
if (CollUtil.isEmpty(rows)) {
return;
}
List<MsOperationLogDetail> details = new ArrayList<>();
for (Map<String, Object> row : rows) {
String stcd = asString(row.get("STCD"));
String recordId = asString(row.get("ID"));
MsOperationLog mainLog = buildWqMainLog(recordId,remark, source);
msOperationLogMapper.insert(mainLog);
for (Map.Entry<String, Object> entry : row.entrySet()) {
String fieldCode = entry.getKey();
if (StrUtil.isBlank(fieldCode)) {
continue;
}
Object oldValue = entry.getValue();
if (oldValue == null) {
continue;
}
details.add(buildWqDetail(mainLog.getId(), tableName, stcd, fieldCode,
oldValue, resolveWqDisplayValue(fieldCode, oldValue),
null, null, "删除字段值"));
}
}
batchInsertWqLogDetails(details);
}
private MsOperationLog buildWqMainLog(String recordId,String remark, String source) {
MsOperationLog log = new MsOperationLog();
log.setOperator(resolveLogOperator());
log.setRecordId(recordId);
log.setOperateTime(new Date());
log.setTableName(WQ_HOUR_TABLE_NAME);
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<MsOperationLogDetail> details) {
if (CollUtil.isEmpty(details)) {
return;
}
for (MsOperationLogDetail detail : details) {
if (detail == null) {
continue;
}
msOperationLogDetailMapper.insert(detail);
}
}
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);

View File

@ -2,12 +2,14 @@ package com.yfd.platform.qgc_env.wt.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.annotation.Log;
import com.yfd.platform.common.DataSourceLoadOptionsBase;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.common.exception.BizException;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo;
import com.yfd.platform.qgc_env.wt.entity.vo.WtOperateRequest;
import com.yfd.platform.qgc_env.wt.entity.vo.WtrvInfo;
import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendSaveVo;
import com.yfd.platform.qgc_env.wt.service.*;
@ -54,10 +56,14 @@ public class SdWTMonitorController {
return ResponseResult.successData(result);
}
@Log(module = "水温监测", value = "修改表层水温日数据")
@PostMapping("/alongDetail/updateWtrvRData")
@Operation(summary = "修改表层水温日数据")
public ResponseResult updateWtrvRData(@RequestBody Map<String, Object> updateData) {
alongDetailService.updateWtrvRData(updateData);
public ResponseResult updateWtrvRData(@RequestBody WtOperateRequest wtOperateRequest) {
alongDetailService.updateWtrvRData(
wtOperateRequest == null ? null : wtOperateRequest.getUpdateData(),
wtOperateRequest == null ? null : wtOperateRequest.getSource()
);
return ResponseResult.success();
}
@ -75,6 +81,7 @@ public class SdWTMonitorController {
return ResponseResult.successData(result);
}
@Log(module = "水温监测", value = "删除出库水温周旬月季年数据")
@PostMapping("/alongDetail/drtp/removeKendoByIds")
@Operation(summary = "删除出库水温周旬月季年数据")
public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) {
@ -236,6 +243,7 @@ public class SdWTMonitorController {
return ResponseResult.successData(sdWtMonitorService.getCxDetailList(dataSourceRequest));
}
@Log(module = "水温监测", value = "删除垂向水温数据")
@PostMapping("/cxDetail/removeKendoByIds")
@Operation(summary = "删除垂向水温数据")
public ResponseResult removeCxDetailByIds(@RequestBody BatchDeleteAo batchDeleteAo) {
@ -243,10 +251,14 @@ public class SdWTMonitorController {
return ResponseResult.success();
}
@Log(module = "水温监测", value = "修改垂向水温数据")
@PostMapping("/cxDetail/updateWtvtRData")
@Operation(summary = "修改垂向水温数据")
public ResponseResult updateWtvtRData(@RequestBody Map<String, Object> updateData) {
sdWtvtRService.updateWtvtRData(updateData);
public ResponseResult updateWtvtRData(@RequestBody WtOperateRequest wtOperateRequest) {
sdWtvtRService.updateWtvtRData(
wtOperateRequest == null ? null : wtOperateRequest.getUpdateData(),
wtOperateRequest == null ? null : wtOperateRequest.getSource()
);
return ResponseResult.success();
}

View File

@ -0,0 +1,13 @@
package com.yfd.platform.qgc_env.wt.entity.vo;
import lombok.Data;
import java.util.Map;
@Data
public class WtOperateRequest {
private String source;
private Map<String, Object> updateData;
}

View File

@ -43,6 +43,6 @@ public interface AlongDetailService extends IService<SdAlongDetailVO> {
boolean removeKendoByIds(BatchDeleteAo batchDeleteAo);
void updateWtrvRData(Map<String, Object> updateData);
void updateWtrvRData(Map<String, Object> updateData, String source);
}

View File

@ -24,5 +24,5 @@ public interface SdWtvtRService {
boolean removeKendoByIds(BatchDeleteAo batchDeleteAo);
void updateWtvtRData(Map<String, Object> updateData);
void updateWtvtRData(Map<String, Object> updateData, String source);
}

View File

@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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_env.wt.mapper.AlongDetailMapper;
import com.yfd.platform.qgc_env.wt.mapper.SdWtrvdrtpSMapper;
import com.yfd.platform.qgc_env.wt.service.AlongDetailService;
@ -17,6 +19,8 @@ import com.yfd.platform.qgc_env.wt.entity.vo.SdAlongDrtpDetailVO;
import com.yfd.platform.qgc_env.wt.entity.vo.WtrvInfo;
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.utils.CollectionExtUtils;
import com.yfd.platform.utils.QgcQueryWrapperUtil;
import com.yfd.platform.utils.SecurityUtils;
@ -37,6 +41,29 @@ import java.util.stream.Collectors;
*/
@Service
public class AlongDetailServiceImpl extends ServiceImpl<AlongDetailMapper, SdAlongDetailVO> implements AlongDetailService {
private static final String WT_HOUR_TABLE_NAME = "SD_WTRV_R";
private static final Map<String, String> WT_UPDATE_COLUMN_MAP = new LinkedHashMap<>();
private static final Map<String, String> WT_FIELD_MEANING_MAP = new LinkedHashMap<>();
static {
WT_UPDATE_COLUMN_MAP.put("wt", "WT");
WT_FIELD_MEANING_MAP.put("ID", "主键ID");
WT_FIELD_MEANING_MAP.put("STCD", "水温站编码");
WT_FIELD_MEANING_MAP.put("TM", "数据时间");
WT_FIELD_MEANING_MAP.put("WT", "水温");
WT_FIELD_MEANING_MAP.put("REMARK", "备注");
WT_FIELD_MEANING_MAP.put("FID", "附件ID");
WT_FIELD_MEANING_MAP.put("WER_ID", "所属水生生态调查数据表ID");
WT_FIELD_MEANING_MAP.put("RECORD_USER", "创建人");
WT_FIELD_MEANING_MAP.put("RECORD_TIME", "创建时间");
WT_FIELD_MEANING_MAP.put("MODIFY_USER", "更新人");
WT_FIELD_MEANING_MAP.put("MODIFY_TIME", "更新时间");
WT_FIELD_MEANING_MAP.put("IS_DELETED", "是否已删除");
WT_FIELD_MEANING_MAP.put("DELETE_USER", "删除人");
WT_FIELD_MEANING_MAP.put("DELETE_TIME", "删除时间");
}
@Resource
private DynamicSQLMapper dynamicSQLMapper;
@Resource
@ -50,6 +77,12 @@ public class AlongDetailServiceImpl extends ServiceImpl<AlongDetailMapper, SdAlo
@Resource
private JdbcTemplate jdbcTemplate;
@Resource
private MsOperationLogMapper msOperationLogMapper;
@Resource
private MsOperationLogDetailMapper msOperationLogDetailMapper;
@Override
public DataSourceResult processKendoList(DataSourceRequest dataSourceRequest, Map<String, GroupResult> filterResult, Page page) {
DataSourceResult dataSourceResult = new DataSourceResult();
@ -799,6 +832,7 @@ public class AlongDetailServiceImpl extends ServiceImpl<AlongDetailMapper, SdAlo
public boolean removeKendoByIds(BatchDeleteAo batchDeleteAo) {
String dataType = batchDeleteAo.getDataType();
List<DataParam> dataList = batchDeleteAo.getDataList();
String source = batchDeleteAo == null ? null : batchDeleteAo.getSource();
if(CollUtil.isEmpty(dataList)){
return true;
}
@ -816,7 +850,9 @@ public class AlongDetailServiceImpl extends ServiceImpl<AlongDetailMapper, SdAlo
}
if ("TIME".equals(dataType)) {
List<Map<String, Object>> beforeRows = queryWtHourRows(subList);
sdWtrvdrtpSMapper.deleteWtrvRData(subList, DateUtil.now(), SecurityUtils.getCurrentUsername());
recordWtDeleteLog(beforeRows, "删除表层水温日数据", source);
// 删除小时数据后需要重新统计对应的日数据和月数据
Map<String, String[]> dateRangeMap = new HashMap<>();
Map<String, String[]> monthRangeMap = new HashMap<>();
@ -1048,13 +1084,14 @@ public class AlongDetailServiceImpl extends ServiceImpl<AlongDetailMapper, SdAlo
@Override
public void updateWtrvRData(Map<String, Object> updateData) {
public void updateWtrvRData(Map<String, Object> updateData, String source) {
String stcd = asString(getValueIgnoreCase(updateData, "stcd"));
String tm = asString(getValueIgnoreCase(updateData, "dt"));
Map<String, Object> beforeRow = queryWtHourRow(stcd, tm);
sdWtrvdrtpSMapper.updateWtrvRData(updateData);
recordWtUpdateLog(beforeRow, updateData, source);
// 获取测站编码和时间
String stcd = (String) updateData.get("stcd");
String tm = (String) updateData.get("dt");
if (StrUtil.isNotBlank(stcd) && StrUtil.isNotBlank(tm)) {
// 提取日期部分yyyy-MM-dd
String dateStr = tm.substring(0, 10);
@ -1074,4 +1111,204 @@ public class AlongDetailServiceImpl extends ServiceImpl<AlongDetailMapper, SdAlo
}
}
}
private Map<String, Object> queryWtHourRow(String stcd, String tm) {
if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm)) {
return new HashMap<>();
}
String sql = "SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, WT, REMARK, FID, WER_ID, " +
"RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME " +
"FROM SD_WTRV_R WHERE STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS')";
List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, stcd, tm);
return rows.isEmpty() ? new HashMap<>() : normalizeWtLogRow(rows.getFirst());
}
private List<Map<String, Object>> queryWtHourRows(List<DataParam> dataParamList) {
if (CollUtil.isEmpty(dataParamList)) {
return new ArrayList<>();
}
StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, WT, REMARK, FID, WER_ID, ")
.append("RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME ")
.append("FROM SD_WTRV_R WHERE ");
List<Object> params = new ArrayList<>();
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.getDt());
}
return normalizeWtLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray()));
}
private List<Map<String, Object>> normalizeWtLogRows(List<Map<String, Object>> rows) {
List<Map<String, Object>> result = new ArrayList<>();
if (CollUtil.isEmpty(rows)) {
return result;
}
for (Map<String, Object> row : rows) {
result.add(normalizeWtLogRow(row));
}
return result;
}
private Map<String, Object> normalizeWtLogRow(Map<String, Object> row) {
Map<String, Object> normalized = new LinkedHashMap<>();
if (row == null || row.isEmpty()) {
return normalized;
}
for (Map.Entry<String, Object> entry : row.entrySet()) {
normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue());
}
return normalized;
}
private void recordWtUpdateLog(Map<String, Object> beforeRow, Map<String, Object> updateData, String source) {
if (updateData == null || updateData.isEmpty()) {
return;
}
String stcd = asString(getValueIgnoreCase(updateData, "stcd"));
String recordId = asString(getValueIgnoreCase(beforeRow, "id"));
List<MsOperationLogDetail> details = new ArrayList<>();
for (Map.Entry<String, String> entry : WT_UPDATE_COLUMN_MAP.entrySet()) {
if (!containsKeyIgnoreCase(updateData, entry.getKey())) {
continue;
}
String column = entry.getValue();
Object oldValue = beforeRow == null ? null : beforeRow.get(column);
Object newValue = getValueIgnoreCase(updateData, entry.getKey());
if (StrUtil.equals(formatWtLogValue(oldValue), formatWtLogValue(newValue))) {
continue;
}
details.add(buildWtDetail(null, stcd, column,
oldValue, resolveWtDisplayValue(column, oldValue),
newValue, resolveWtDisplayValue(column, newValue), "修改字段值"));
}
if (details.isEmpty()) {
return;
}
MsOperationLog mainLog = buildWtMainLog(recordId,"修改表层水温日数据", source);
msOperationLogMapper.insert(mainLog);
for (MsOperationLogDetail detail : details) {
detail.setMainId(mainLog.getId());
}
batchInsertWtLogDetails(details);
}
private void recordWtDeleteLog(List<Map<String, Object>> rows, String remark, String source) {
if (CollUtil.isEmpty(rows)) {
return;
}
List<MsOperationLogDetail> details = new ArrayList<>();
for (Map<String, Object> row : rows) {
String stcd = asString(row.get("STCD"));
String recordId = asString(row.get("ID"));
MsOperationLog mainLog = buildWtMainLog(recordId,remark, source);
msOperationLogMapper.insert(mainLog);
for (Map.Entry<String, Object> entry : row.entrySet()) {
String fieldCode = entry.getKey();
Object oldValue = entry.getValue();
if (StrUtil.isBlank(fieldCode) || oldValue == null) {
continue;
}
details.add(buildWtDetail(mainLog.getId(), stcd, fieldCode,
oldValue, resolveWtDisplayValue(fieldCode, oldValue),
null, null, "删除字段值"));
}
}
batchInsertWtLogDetails(details);
}
private MsOperationLog buildWtMainLog(String recordId,String remark, String source) {
MsOperationLog log = new MsOperationLog();
log.setOperator(resolveWtLogOperator());
log.setOperateTime(new Date());
log.setRecordId(recordId);
log.setTableName(WT_HOUR_TABLE_NAME);
log.setSource(StrUtil.trimToNull(source));
log.setRemark(remark);
return log;
}
private MsOperationLogDetail buildWtDetail(String mainId,
String stationCode,
String fieldCode,
Object oldValueCode,
Object oldValueName,
Object newValueCode,
Object newValueName,
String remark) {
MsOperationLogDetail detail = new MsOperationLogDetail();
detail.setMainId(mainId);
detail.setTableName(WT_HOUR_TABLE_NAME);
detail.setStationCode(stationCode);
detail.setFieldCode(fieldCode);
detail.setFieldMeaning(WT_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode));
detail.setOldValueCode(formatWtLogValue(oldValueCode));
detail.setOldValueName(formatWtLogValue(oldValueName));
detail.setNewValueCode(formatWtLogValue(newValueCode));
detail.setNewValueName(formatWtLogValue(newValueName));
detail.setRemark(remark);
return detail;
}
private void batchInsertWtLogDetails(List<MsOperationLogDetail> details) {
if (CollUtil.isEmpty(details)) {
return;
}
for (MsOperationLogDetail detail : details) {
if (detail == null) {
continue;
}
msOperationLogDetailMapper.insert(detail);
}
}
private Object resolveWtDisplayValue(String fieldCode, Object rawValue) {
return formatWtLogValue(rawValue);
}
private String resolveWtLogOperator() {
try {
return SecurityUtils.getCurrentUsername();
} catch (Exception ignored) {
try {
return SecurityUtils.getUserId();
} catch (Exception ex) {
return null;
}
}
}
private String formatWtLogValue(Object value) {
if (value == null) {
return null;
}
if (value instanceof Date date) {
return DateUtil.formatDateTime(date);
}
return String.valueOf(value);
}
private String asString(Object value) {
return value == null ? null : String.valueOf(value);
}
private boolean containsKeyIgnoreCase(Map<String, Object> data, String key) {
if (data == null || StrUtil.isBlank(key)) {
return false;
}
if (data.containsKey(key)) {
return true;
}
for (String mapKey : data.keySet()) {
if (StrUtil.equalsIgnoreCase(mapKey, key)) {
return true;
}
}
return false;
}
}

View File

@ -1,13 +1,18 @@
package com.yfd.platform.qgc_env.wt.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.common.DataSourceLoadOptionsBase;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
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.wt.entity.vo.SdWtvtYearVo;
import com.yfd.platform.qgc_env.wt.mapper.SdWtvtRMapper;
import com.yfd.platform.qgc_env.wt.service.SdWtvtRService;
@ -22,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.HashMap;
import java.util.List;
@ -37,6 +43,28 @@ import java.util.Set;
*/
@Service
public class SdWtvtRServiceImpl extends ServiceImpl<SdWtvtRMapper, SdWtvtYearVo> implements SdWtvtRService {
private static final String WT_CX_TABLE_NAME = "SD_WTVT_R";
private static final Map<String, String> WT_CX_FIELD_MEANING_MAP = new LinkedHashMap<>();
static {
WT_CX_FIELD_MEANING_MAP.put("ID", "主键ID");
WT_CX_FIELD_MEANING_MAP.put("STCD", "垂向水温站编码");
WT_CX_FIELD_MEANING_MAP.put("TM", "时间");
WT_CX_FIELD_MEANING_MAP.put("WTHG", "水温深度");
WT_CX_FIELD_MEANING_MAP.put("VWT", "水温");
WT_CX_FIELD_MEANING_MAP.put("FID", "附件ID");
WT_CX_FIELD_MEANING_MAP.put("RECORD_USER", "创建人");
WT_CX_FIELD_MEANING_MAP.put("RECORD_TIME", "创建时间");
WT_CX_FIELD_MEANING_MAP.put("MODIFY_USER", "更新人");
WT_CX_FIELD_MEANING_MAP.put("MODIFY_TIME", "更新时间");
WT_CX_FIELD_MEANING_MAP.put("IS_DELETED", "是否已删除");
WT_CX_FIELD_MEANING_MAP.put("DELETE_USER", "删除人");
WT_CX_FIELD_MEANING_MAP.put("DELETE_TIME", "删除时间");
WT_CX_FIELD_MEANING_MAP.put("RZ", "坝前水位");
WT_CX_FIELD_MEANING_MAP.put("HGT", "测点高程");
WT_CX_FIELD_MEANING_MAP.put("REMARK", "备注");
WT_CX_FIELD_MEANING_MAP.put("WER_ID", "所属水生生态调查数据表ID");
}
@Resource
private SdWtvtRMapper sdWtvtRMapper;
@ -47,6 +75,12 @@ public class SdWtvtRServiceImpl extends ServiceImpl<SdWtvtRMapper, SdWtvtYearVo>
@Resource
private JdbcTemplate jdbcTemplate;
@Resource
private MsOperationLogMapper msOperationLogMapper;
@Resource
private MsOperationLogDetailMapper msOperationLogDetailMapper;
@Override
public DataSourceResult getWtrvDefaultYear(DataSourceRequest dataSourceRequest) {
DataSourceResult<SdWtvtYearVo> dataSourceResult = new DataSourceResult<>();
@ -91,6 +125,7 @@ public class SdWtvtRServiceImpl extends ServiceImpl<SdWtvtRMapper, SdWtvtYearVo>
public boolean removeKendoByIds(BatchDeleteAo batchDeleteAo) {
String dataType = batchDeleteAo == null ? null : batchDeleteAo.getDataType();
List<DataParam> dataList = batchDeleteAo == null ? null : batchDeleteAo.getDataList();
String source = batchDeleteAo == null ? null : batchDeleteAo.getSource();
if (CollUtil.isEmpty(dataList)) {
return true;
}
@ -104,7 +139,9 @@ public class SdWtvtRServiceImpl extends ServiceImpl<SdWtvtRMapper, SdWtvtYearVo>
continue;
}
if ("TIME".equalsIgnoreCase(dataType)) {
List<Map<String, Object>> beforeRows = queryWtvtRows(subList);
deleteWtvtRData(subList);
recordWtvtDeleteLog(beforeRows, "删除垂向水温数据", source);
Map<String, String[]> dateRangeMap = new HashMap<>();
Map<String, String[]> monthRangeMap = new HashMap<>();
for (DataParam param : subList) {
@ -160,7 +197,7 @@ public class SdWtvtRServiceImpl extends ServiceImpl<SdWtvtRMapper, SdWtvtYearVo>
@Override
@Transactional(rollbackFor = Exception.class)
public void updateWtvtRData(Map<String, Object> updateData) {
public void updateWtvtRData(Map<String, Object> updateData, String source) {
if (updateData == null || updateData.isEmpty()) {
return;
}
@ -171,7 +208,10 @@ public class SdWtvtRServiceImpl extends ServiceImpl<SdWtvtRMapper, SdWtvtYearVo>
return;
}
Map<String, Map<String, Object>> beforeRowMap = buildWtvtBeforeRowMap(stcd, dt);
List<Map<String, Object>> dataList = new ArrayList<>();
List<MsOperationLogDetail> logDetails = new ArrayList<>();
rawMap.forEach((wthgObj, vwtObj) -> {
if (wthgObj == null) {
return;
@ -192,12 +232,32 @@ public class SdWtvtRServiceImpl extends ServiceImpl<SdWtvtRMapper, SdWtvtYearVo>
// item.put("recordUser", "admin");
item.put("recordUser", SecurityUtils.getUserId());
dataList.add(item);
String depthKey = buildWtvtDepthKey(item.get("wthg"));
Map<String, Object> beforeRow = beforeRowMap.get(depthKey);
Object oldValue = beforeRow == null ? null : beforeRow.get("VWT");
Object newValue = item.get("vwt");
if (StringUtils.equals(formatWtvtLogValue(oldValue), formatWtvtLogValue(newValue))) {
return;
}
logDetails.add(buildWtvtDetail(null, stcd, "VWT",
oldValue, resolveWtvtDisplayValue("VWT", oldValue),
newValue, resolveWtvtDisplayValue("VWT", newValue),
buildWtvtDepthRemark("修改字段值", item.get("wthg"))));
});
if (dataList.isEmpty()) {
return;
}
batchUpdateWtvtRData(dataList);
if (CollUtil.isNotEmpty(logDetails)) {
MsOperationLog mainLog = buildWtvtMainLog(null,"修改垂向水温数据", source);
msOperationLogMapper.insert(mainLog);
for (MsOperationLogDetail detail : logDetails) {
detail.setMainId(mainLog.getId());
}
batchInsertWtvtLogDetails(logDetails);
}
String dateStr = dt.substring(0, 10);
statisticsDayDataFromHour(stcd, dateStr, dateStr);
@ -363,4 +423,163 @@ public class SdWtvtRServiceImpl extends ServiceImpl<SdWtvtRMapper, SdWtvtYearVo>
private String asString(Object value) {
return value == null ? null : String.valueOf(value);
}
private List<Map<String, Object>> queryWtvtRows(List<DataParam> dataParamList) {
if (CollUtil.isEmpty(dataParamList)) {
return new ArrayList<>();
}
StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, WTHG, VWT, FID, ")
.append("RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME, RZ, HGT, REMARK, WER_ID ")
.append("FROM SD_WTVT_R WHERE ");
List<Object> params = new ArrayList<>();
List<String> conditions = new ArrayList<>();
for (DataParam item : dataParamList) {
if (item == null || StringUtils.isBlank(item.getId()) || StringUtils.isBlank(item.getDt())) {
continue;
}
conditions.add("(STCD = ? AND TM = TO_DATE(SUBSTR(?, 1, 19), 'YYYY-MM-DD HH24:MI:SS'))");
params.add(item.getId());
params.add(item.getDt());
}
if (conditions.isEmpty()) {
return new ArrayList<>();
}
sql.append(String.join(" OR ", conditions));
return normalizeWtvtRows(jdbcTemplate.queryForList(sql.toString(), params.toArray()));
}
private Map<String, Map<String, Object>> buildWtvtBeforeRowMap(String stcd, String dt) {
Map<String, Map<String, Object>> result = new HashMap<>();
if (StringUtils.isBlank(stcd) || StringUtils.isBlank(dt)) {
return result;
}
String sql = "SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, WTHG, VWT, FID, " +
"RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME, RZ, HGT, REMARK, WER_ID " +
"FROM SD_WTVT_R WHERE WTHG IS NOT NULL AND VWT IS NOT NULL AND STCD = ? AND TM = TO_DATE(SUBSTR(?, 1, 19), 'YYYY-MM-DD HH24:MI:SS')";
List<Map<String, Object>> rows = normalizeWtvtRows(jdbcTemplate.queryForList(sql, stcd, dt));
for (Map<String, Object> row : rows) {
result.put(String.valueOf(Double.parseDouble(row.get("WTHG").toString())), row);
}
return result;
}
private List<Map<String, Object>> normalizeWtvtRows(List<Map<String, Object>> rows) {
List<Map<String, Object>> result = new ArrayList<>();
if (CollUtil.isEmpty(rows)) {
return result;
}
for (Map<String, Object> row : rows) {
Map<String, Object> normalized = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : row.entrySet()) {
normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue());
}
result.add(normalized);
}
return result;
}
private void recordWtvtDeleteLog(List<Map<String, Object>> rows, String remark, String source) {
if (CollUtil.isEmpty(rows)) {
return;
}
MsOperationLog mainLog = buildWtvtMainLog(null,remark, source);
msOperationLogMapper.insert(mainLog);
List<MsOperationLogDetail> details = new ArrayList<>();
for (Map<String, Object> row : rows) {
String stcd = asString(row.get("STCD"));
Object depth = row.get("WTHG");
for (Map.Entry<String, Object> entry : row.entrySet()) {
String fieldCode = entry.getKey();
Object oldValue = entry.getValue();
if (StringUtils.isBlank(fieldCode) || oldValue == null) {
continue;
}
details.add(buildWtvtDetail(mainLog.getId(), stcd, fieldCode,
oldValue, resolveWtvtDisplayValue(fieldCode, oldValue),
null, null, buildWtvtDepthRemark("删除字段值", depth)));
}
}
batchInsertWtvtLogDetails(details);
}
private MsOperationLog buildWtvtMainLog(String recordId,String remark, String source) {
MsOperationLog log = new MsOperationLog();
log.setOperator(resolveWtvtLogOperator());
log.setOperateTime(new Date());
log.setTableName(WT_CX_TABLE_NAME);
log.setRecordId(remark);
log.setSource(StringUtils.trimToNull(source));
log.setRemark(remark);
return log;
}
private MsOperationLogDetail buildWtvtDetail(String mainId,
String stationCode,
String fieldCode,
Object oldValueCode,
Object oldValueName,
Object newValueCode,
Object newValueName,
String remark) {
MsOperationLogDetail detail = new MsOperationLogDetail();
detail.setMainId(mainId);
detail.setTableName(WT_CX_TABLE_NAME);
detail.setStationCode(stationCode);
detail.setFieldCode(fieldCode);
detail.setFieldMeaning(WT_CX_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode));
detail.setOldValueCode(formatWtvtLogValue(oldValueCode));
detail.setOldValueName(formatWtvtLogValue(oldValueName));
detail.setNewValueCode(formatWtvtLogValue(newValueCode));
detail.setNewValueName(formatWtvtLogValue(newValueName));
detail.setRemark(remark);
return detail;
}
private void batchInsertWtvtLogDetails(List<MsOperationLogDetail> details) {
if (CollUtil.isEmpty(details)) {
return;
}
for (MsOperationLogDetail detail : details) {
if (detail == null) {
continue;
}
msOperationLogDetailMapper.insert(detail);
}
}
private Object resolveWtvtDisplayValue(String fieldCode, Object rawValue) {
return formatWtvtLogValue(rawValue);
}
private String resolveWtvtLogOperator() {
try {
return SecurityUtils.getCurrentUsername();
} catch (Exception ignored) {
try {
return SecurityUtils.getUserId();
} catch (Exception ex) {
return null;
}
}
}
private String formatWtvtLogValue(Object value) {
if (value == null) {
return null;
}
if (value instanceof Date date) {
return DateUtil.formatDateTime(date);
}
return String.valueOf(value);
}
private String buildWtvtDepthKey(Object depth) {
return formatWtvtLogValue(depth);
}
private String buildWtvtDepthRemark(String action, Object depth) {
String depthText = formatWtvtLogValue(depth);
return depthText == null ? action : action + "(深度:" + depthText + ")";
}
}

View File

@ -21,6 +21,12 @@ public class WeFishController {
@Resource
private WeFishService weFishService;
@PostMapping("/we/fisht/GetKendoListCust")
@Operation(summary = "条件过滤数据列表定制")
public ResponseResult getWeFishTKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getWeFishTKendoListCust(dataSourceRequest));
}
@PostMapping("/we/fisht/qgc/GetKendoListCust")
@Operation(summary = "全过程沿程鱼类变化情况")
public ResponseResult getQgcWeFishTKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
@ -57,6 +63,30 @@ public class WeFishController {
return ResponseResult.successData(weFishService.getWvaList(dataSourceRequest));
}
@PostMapping("/wva/default/GetKendoListCust")
@Operation(summary = "野生动物监测默认数据")
public ResponseResult getWvaDefaultList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getWvaDefaultList(dataSourceRequest));
}
@PostMapping("/we/compareBar/GetKendoListCust")
@Operation(summary = "水生生态调查对比(柱状图)")
public ResponseResult getWeCompareBarList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getWeCompareBarList(dataSourceRequest));
}
@PostMapping("/we/fishPage/qgc/GetKendoListCust")
@Operation(summary = "环保部-水生生态调查二级页面")
public ResponseResult getQgcWeFishPageList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeFishPageList(dataSourceRequest));
}
@PostMapping("/base/evnmAutoMonitor/GetKendoListCust")
@Operation(summary = "环保自动监测开展情况")
public ResponseResult getEnvmAutoMonitorList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getEnvmAutoMonitorList(dataSourceRequest));
}
@PostMapping("/we/fisht/year/qgc/GetKendoListCust")
@Operation(summary = "全过程沿程鱼类变化情况有数据的流域和年份")
public ResponseResult getQgcFishStaticsYearList(@RequestBody DataSourceRequest dataSourceRequest) {
@ -69,12 +99,48 @@ public class WeFishController {
return ResponseResult.successData(weFishService.getQgcWeFishStatics(dataSourceRequest));
}
@PostMapping("/we/fisht/statics/getWeStaticsSecond")
@Operation(summary = "水生生态调查概况二级页面")
public ResponseResult getWeStaticsSecond(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getWeStaticsSecond(dataSourceRequest));
}
@PostMapping("/we/fisht/stat/qgc/GetKendoListCust")
@Operation(summary = "环保部-沿程鱼类变化情况柱状图")
public ResponseResult getQgcWeFishStatList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeFishStatList(dataSourceRequest));
}
@PostMapping("/we/fisht/stat/GetKendoListCust")
@Operation(summary = "沿程鱼类变化情况柱状图")
public ResponseResult getWeFishStatList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getWeFishStatList(dataSourceRequest));
}
@PostMapping("/we/fisht/qgcDetail/GetKendoListCust")
@Operation(summary = "沿程鱼类变化情况二级弹窗-按照新逻辑重写")
public ResponseResult getQgcWeFishDetailList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeFishDetailList(dataSourceRequest));
}
@PostMapping("/we/fisht/qgcDetail/qgc/GetKendoListCust")
@Operation(summary = "环保部-沿程鱼类变化情况二级弹窗")
public ResponseResult getHbbQgcWeFishDetailList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getHbbQgcWeFishDetailList(dataSourceRequest));
}
@PostMapping("/we/fisht/detail/GetKendoListCust")
@Operation(summary = "沿程鱼类变化情况二级弹窗")
public ResponseResult getWeFishDetailList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getWeFishDetailList(dataSourceRequest));
}
@PostMapping("/we/fisht/statTab/GetKendoListCust")
@Operation(summary = "沿程鱼类变化情况二级页面tab页签数据")
public ResponseResult getWeFishStatTabList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getWeFishStatTabList(dataSourceRequest));
}
@PostMapping("/we/fishList/stat/qgc/GetKendoListCust")
@Operation(summary = "环保部-水生生态调查-水生生态面板")
public ResponseResult getQgcFishListStat(@RequestBody DataSourceRequest dataSourceRequest) {

View File

@ -0,0 +1,33 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
@AllArgsConstructor
@Schema(description = "水生生态调查对比柱状图表头")
public class WeCompareBarHeadColumnVo {
@Schema(description = "字段名")
private String dataIndex;
@Schema(description = "标题")
private String title;
@Schema(description = "是否可见")
private Boolean visible;
@Schema(description = "")
private String key;
@Schema(description = "单位")
private boolean merge;
@Schema(description = "子列")
private List<WeCompareBarHeadColumnVo> children;
}

View File

@ -0,0 +1,22 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
@Schema(description = "水生生态调查对比柱状图表格")
public class WeCompareBarTableVo {
@Schema(description = "表头")
private List<WeCompareBarHeadColumnVo> columns;
@Schema(description = "表格数据")
private Object dataSource;
@Schema(description = "总数")
private Long total;
}

View File

@ -0,0 +1,29 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(description = "水生生态调查对比柱状图数据")
public class WeCompareBarVo {
@Schema(description = "鱼类名称")
private String ftp;
@Schema(description = "科属")
private String genus;
@Schema(description = "调查批次")
private String dcpc;
@Schema(description = "对比批次")
private String dcpc2;
@Schema(description = "鱼类数量")
private Integer fcnt;
@Schema(description = "对比鱼类数量")
private Integer fcnt2;
}

View File

@ -0,0 +1,27 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "环保自动监测开展情况")
public class WeEnvmAutoMonitorVo {
@Schema(description = "数量")
private Integer cnt;
@Schema(description = "功能序号")
private Integer orderInx;
@Schema(description = "功能序号名称")
private String orderInxName;
@Schema(description = "类型路径")
private String sttpFullPath;
@Schema(description = "站点类型")
private String sttpCode;
@Schema(description = "站点类型名称")
private String sttpName;
}

View File

@ -0,0 +1,36 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
@Schema(description = "沿程鱼类变化情况二级弹窗")
public class WeFishDetailVo {
@Schema(description = "电站编码")
private String rsctd;
@Schema(description = "电站名称")
private String rsctdName;
@Schema(description = "鱼类列表")
private List<String> fishList;
@Schema(description = "断面列表")
private List<StationItem> stcdList;
@Data
@Accessors(chain = true)
@Schema(description = "断面信息")
public static class StationItem {
@Schema(description = "断面编码")
private String stcd;
@Schema(description = "断面名称")
private String stnm;
}
}

View File

@ -0,0 +1,29 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(description = "环保部-沿程鱼类变化情况二级弹窗")
public class WeFishHbbQgcDetailVo {
@Schema(description = "电站编码")
private String rstcd;
@Schema(description = "电站名称")
private String rstcdName;
@Schema(description = "断面编码")
private String stcd;
@Schema(description = "断面名称")
private String stnm;
@Schema(description = "鱼类名称")
private String name;
@Schema(description = "鱼类对应ID")
private String id;
}

View File

@ -0,0 +1,37 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Data
@Accessors(chain = true)
@Schema(description = "环保部-水生生态调查二级页面数据")
public class WeFishPageQgcVo {
@Schema(description = "鱼类名称")
private String ftp;
@Schema(description = "科属")
private String genus;
@Schema(description = "开始年份鱼类总量")
private Integer startFtpCnt;
@Schema(description = "开始年份总量")
private Integer startCnt;
@Schema(description = "开始年份占比")
private BigDecimal startYear;
@Schema(description = "结束年份鱼类总量")
private Integer endFtpCnt;
@Schema(description = "结束年份总量")
private Integer endCnt;
@Schema(description = "结束年份占比")
private BigDecimal endYear;
}

View File

@ -0,0 +1,22 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
@Schema(description = "环保部-水生生态调查二级页面表格")
public class WeFishPageTableVo {
@Schema(description = "表头")
private List<WeCompareBarHeadColumnVo> columns;
@Schema(description = "表格数据")
private Object dataSource;
@Schema(description = "总数")
private Long total;
}

View File

@ -0,0 +1,20 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(description = "沿程鱼类变化情况二级页面tab页签数据")
public class WeFishStatTabVo {
@Schema(description = "鱼类类型")
private String ty;
@Schema(description = "鱼类类型名称")
private String tyName;
@Schema(description = "鱼类数量")
private Long num;
}

View File

@ -4,11 +4,37 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@Data
@Accessors(chain = true)
@Schema(description = "水生生态调查概况")
public class WeStaticsVo {
@Schema(description = "断面编码")
private String stcd;
@Schema(description = "断面名称")
private String stnm;
@Schema(description = "调查批次")
private String dcpc;
@Schema(description = "调查鱼类")
private String ftp;
@Schema(description = "调查鱼类名称")
private String ftpName;
@Schema(description = "鱼类数量")
private Long fcnt;
@Schema(description = "附件ID")
private String fid;
@Schema(description = "调查时间")
private Date tm;
@Schema(description = "调查批次数量")
private Long dcpcCount;

View File

@ -0,0 +1,28 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@Data
@Schema(description = "野生动物监测默认数据")
public class WeWvaDefaultVo {
@Schema(description = "站点编码")
private String stcd;
@Schema(description = "站点名称")
private String stnm;
@Schema(description = "站类编码")
private String sttpCode;
@Schema(description = "站类名称")
private String sttpName;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "最新时间")
private Date tm;
}

View File

@ -4,13 +4,20 @@ import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListStatQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeCompareBarTableVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeEnvmAutoMonitorVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishDetailVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishHbbQgcDetailVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeMsstbprptVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPageTableVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPointQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatTabVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeFishTQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeStaticsVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeTeSpecialAnimalVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeVmsstbprptVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaDefaultVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaQgcVo;
import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaYearQgcVo;
@ -19,6 +26,8 @@ import java.util.Map;
public interface WeFishService {
DataSourceResult<WeFishTQgcVo> getWeFishTKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishTQgcVo> getQgcWeFishTKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishListQgcVo> getQgcWeFishList(DataSourceRequest dataSourceRequest);
@ -29,14 +38,34 @@ public interface WeFishService {
DataSourceResult<WeWvaQgcVo> getWvaList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeWvaDefaultVo> getWvaDefaultList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeWvaYearQgcVo> getWvaDefaultYearList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeCompareBarTableVo> getWeCompareBarList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishPageTableVo> getQgcWeFishPageList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeEnvmAutoMonitorVo> getEnvmAutoMonitorList(DataSourceRequest dataSourceRequest);
DataSourceResult<Map<String, List<String>>> getQgcFishStaticsYearList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeStaticsVo> getQgcWeFishStatics(DataSourceRequest dataSourceRequest);
DataSourceResult<WeStaticsVo> getWeStaticsSecond(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishStatQgcVo> getQgcWeFishStatList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishStatQgcVo> getWeFishStatList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishDetailVo> getQgcWeFishDetailList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishHbbQgcDetailVo> getHbbQgcWeFishDetailList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishDetailVo> getWeFishDetailList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishStatTabVo> getWeFishStatTabList(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishListStatQgcVo> getQgcFishListStat(DataSourceRequest dataSourceRequest);
DataSourceResult<WeFishPointQgcVo> getQgcWeFishPoint(DataSourceRequest dataSourceRequest);

View File

@ -1,8 +1,10 @@
package com.yfd.platform.qgc_env.zq.controller;
import com.yfd.platform.annotation.Log;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo;
import com.yfd.platform.qgc_env.zq.entity.vo.ZqOperateRequest;
import com.yfd.platform.qgc_env.zq.service.ZqMonitorService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -56,6 +58,7 @@ public class ZqMonitorController {
return ResponseResult.successData(zqMonitorService.getRiverDrtpKendoListCust(dataSourceRequest));
}
@Log(module = "水文流量站监测", value = "删除流量站小时/日/月数据")
@PostMapping("/river/removeKendoByIds")
@Operation(summary = "删除流量站小时/日/月数据")
public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) {
@ -63,10 +66,14 @@ public class ZqMonitorController {
return ResponseResult.success();
}
@Log(module = "水文流量站监测", value = "修改流量站小时数据")
@PostMapping("/river/updateRiverRData")
@Operation(summary = "修改流量站小时数据")
public ResponseResult updateRiverRData(@RequestBody Map<String, Object> updateData) {
zqMonitorService.updateRiverRData(updateData);
public ResponseResult updateRiverRData(@RequestBody ZqOperateRequest zqOperateRequest) {
zqMonitorService.updateRiverRData(
zqOperateRequest == null ? null : zqOperateRequest.getUpdateData(),
zqOperateRequest == null ? null : zqOperateRequest.getSource()
);
return ResponseResult.success();
}

View File

@ -0,0 +1,13 @@
package com.yfd.platform.qgc_env.zq.entity.vo;
import lombok.Data;
import java.util.Map;
@Data
public class ZqOperateRequest {
private String source;
private Map<String, Object> updateData;
}

View File

@ -22,7 +22,7 @@ public interface ZqMonitorService {
boolean removeKendoByIds(BatchDeleteAo batchDeleteAo);
boolean updateRiverRData(java.util.Map<String, Object> updateData);
boolean updateRiverRData(java.util.Map<String, Object> updateData, String source);
ZqBaseInfoVo getStcdInfo(String stcd);
}

View File

@ -10,8 +10,12 @@ import com.yfd.platform.common.GroupHelper;
import com.yfd.platform.common.GroupingInfo;
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
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.fh.entity.vo.HabitatVo;
import com.yfd.platform.qgc_env.zq.entity.vo.ZqBaseInfoVo;
import com.yfd.platform.qgc_env.zq.entity.vo.ZqRiverDayDataVo;
@ -19,23 +23,58 @@ import com.yfd.platform.qgc_env.zq.entity.vo.ZqRiverDrtpDataVo;
import com.yfd.platform.qgc_env.zq.entity.vo.ZqRiverDataVo;
import com.yfd.platform.qgc_env.zq.service.ZqMonitorService;
import com.yfd.platform.utils.QgcQueryWrapperUtil;
import com.yfd.platform.utils.SecurityUtils;
import jakarta.annotation.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Service
public class ZqMonitorServiceImpl implements ZqMonitorService {
private static final String ZQ_HOUR_TABLE_NAME = "SD_RIVER_R";
private static final String ZQ_DAY_TABLE_NAME = "SD_RIVERDAY_S";
private static final String ZQ_MONTH_TABLE_NAME = "SD_RIVERDRTP_S";
private static final Map<String, String> ZQ_UPDATE_COLUMN_MAP = new LinkedHashMap<>();
private static final Map<String, String> ZQ_FIELD_MEANING_MAP = new LinkedHashMap<>();
static {
ZQ_UPDATE_COLUMN_MAP.put("z", "Z");
ZQ_UPDATE_COLUMN_MAP.put("q", "Q");
ZQ_UPDATE_COLUMN_MAP.put("v", "V");
ZQ_FIELD_MEANING_MAP.put("ID", "主键ID");
ZQ_FIELD_MEANING_MAP.put("STCD", "站码");
ZQ_FIELD_MEANING_MAP.put("TM", "时间");
ZQ_FIELD_MEANING_MAP.put("DT", "时间");
ZQ_FIELD_MEANING_MAP.put("DRTP", "维度类型");
ZQ_FIELD_MEANING_MAP.put("YEAR", "");
ZQ_FIELD_MEANING_MAP.put("MONTH", "");
ZQ_FIELD_MEANING_MAP.put("DR", "时段类型");
ZQ_FIELD_MEANING_MAP.put("Z", "水位");
ZQ_FIELD_MEANING_MAP.put("Q", "流量");
ZQ_FIELD_MEANING_MAP.put("V", "流速");
ZQ_FIELD_MEANING_MAP.put("MSQMT", "测流方法");
ZQ_FIELD_MEANING_MAP.put("RECORD_USER", "创建人");
ZQ_FIELD_MEANING_MAP.put("RECORD_TIME", "创建时间");
ZQ_FIELD_MEANING_MAP.put("MODIFY_USER", "更新人");
ZQ_FIELD_MEANING_MAP.put("MODIFY_TIME", "更新时间");
ZQ_FIELD_MEANING_MAP.put("IS_DELETED", "是否已删除");
ZQ_FIELD_MEANING_MAP.put("DELETE_USER", "删除人");
ZQ_FIELD_MEANING_MAP.put("DELETE_TIME", "删除时间");
ZQ_FIELD_MEANING_MAP.put("FID", "附件ID");
ZQ_FIELD_MEANING_MAP.put("REMARK", "备注");
}
@Resource
private MicroservicDynamicSQLMapper microservicDynamicSQLMapper;
@ -43,6 +82,12 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
@Resource
private JdbcTemplate jdbcTemplate;
@Resource
private MsOperationLogMapper msOperationLogMapper;
@Resource
private MsOperationLogDetailMapper msOperationLogDetailMapper;
@Override
public DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest) {
return getMsstbprptListInternal(dataSourceRequest, false);
@ -170,11 +215,14 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
}
String dataType = batchDeleteAo.getDataType();
List<DataParam> dataList = batchDeleteAo.getDataList();
String source = batchDeleteAo.getSource();
int batchSize = 500;
for (int i = 0; i < dataList.size(); i += batchSize) {
List<DataParam> subList = dataList.subList(i, Math.min(i + batchSize, dataList.size()));
if ("TIME".equals(dataType)) {
List<Map<String, Object>> beforeRows = queryRiverHourRows(subList);
deleteRiverRData(subList);
recordRiverDeleteLog(beforeRows, ZQ_HOUR_TABLE_NAME, "删除流量站小时数据", source);
Map<String, String[]> dateRangeMap = new HashMap<>();
Map<String, String[]> monthRangeMap = new HashMap<>();
for (DataParam param : subList) {
@ -209,10 +257,14 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
}
}
if ("DATE".equals(dataType)) {
List<Map<String, Object>> beforeRows = queryRiverDayRows(subList);
deleteRiverDayData(subList);
recordRiverDeleteLog(beforeRows, ZQ_DAY_TABLE_NAME, "删除流量站日数据", source);
}
if ("MON".equals(dataType)) {
List<Map<String, Object>> beforeRows = queryRiverMonthRows(subList);
deleteRiverMonthData(subList);
recordRiverDeleteLog(beforeRows, ZQ_MONTH_TABLE_NAME, "删除流量站月数据", source);
}
}
return true;
@ -220,10 +272,12 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateRiverRData(Map<String, Object> updateData) {
updateRiverHourData(updateData);
public boolean updateRiverRData(Map<String, Object> updateData, String source) {
String stcd = updateData == null ? null : asString(updateData.get("stcd"));
String tm = updateData == null ? null : asString(updateData.get("tm"));
Map<String, Object> beforeRow = queryRiverHourRow(stcd, tm);
updateRiverHourData(updateData);
recordRiverUpdateLog(beforeRow, updateData, source);
if (StrUtil.isNotBlank(stcd) && StrUtil.isNotBlank(tm) && tm.length() >= 10) {
String dateStr = tm.substring(0, 10);
statisticsDayDataFromHour(stcd, dateStr, dateStr);
@ -1612,6 +1666,273 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
return value == null ? null : String.valueOf(value);
}
private Map<String, Object> queryRiverHourRow(String stcd, String tm) {
if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm)) {
return new HashMap<>();
}
String sql = "SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, Z, Q, V, MSQMT, RECORD_USER, " +
"RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME, FID, REMARK " +
"FROM SD_RIVER_R WHERE STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS')";
List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, stcd, tm);
return rows.isEmpty() ? new HashMap<>() : normalizeRiverLogRow(rows.getFirst());
}
private List<Map<String, Object>> queryRiverHourRows(List<DataParam> dataList) {
if (CollUtil.isEmpty(dataList)) {
return new ArrayList<>();
}
StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, Z, Q, V, MSQMT, RECORD_USER, ")
.append("RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME, FID, REMARK ")
.append("FROM SD_RIVER_R WHERE ");
List<Object> args = new ArrayList<>();
List<String> conditions = new ArrayList<>();
for (DataParam item : dataList) {
if (item == null || StrUtil.isBlank(item.getId()) || StrUtil.isBlank(item.getTm())) {
continue;
}
conditions.add("(STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))");
args.add(item.getId());
args.add(item.getTm());
}
if (conditions.isEmpty()) {
return new ArrayList<>();
}
sql.append(String.join(" OR ", conditions));
return normalizeRiverLogRows(jdbcTemplate.queryForList(sql.toString(), args.toArray()));
}
private List<Map<String, Object>> queryRiverDayRows(List<DataParam> dataList) {
if (CollUtil.isEmpty(dataList)) {
return new ArrayList<>();
}
StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(DT, 'YYYY-MM-DD HH24:MI:SS') AS DT, Z, Q, V, MSQMT, RECORD_USER, ")
.append("RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME ")
.append("FROM SD_RIVERDAY_S WHERE ");
List<Object> args = new ArrayList<>();
List<String> conditions = new ArrayList<>();
for (DataParam item : dataList) {
if (item == null || StrUtil.isBlank(item.getId()) || StrUtil.isBlank(item.getDt())) {
continue;
}
conditions.add("(STCD = ? AND DT = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))");
args.add(item.getId());
args.add(item.getDt());
}
if (conditions.isEmpty()) {
return new ArrayList<>();
}
sql.append(String.join(" OR ", conditions));
return normalizeRiverLogRows(jdbcTemplate.queryForList(sql.toString(), args.toArray()));
}
private List<Map<String, Object>> queryRiverMonthRows(List<DataParam> dataList) {
if (CollUtil.isEmpty(dataList)) {
return new ArrayList<>();
}
StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, DRTP, YEAR, MONTH, DR, Z, Q, V, MSQMT, ")
.append("RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME ")
.append("FROM SD_RIVERDRTP_S WHERE ");
List<Object> args = new ArrayList<>();
List<String> conditions = new ArrayList<>();
for (DataParam item : dataList) {
if (item == null || StrUtil.isBlank(item.getId()) || StrUtil.isBlank(item.getDrtp())
|| StrUtil.isBlank(item.getYear()) || StrUtil.isBlank(item.getMonth())) {
continue;
}
conditions.add("(STCD = ? AND DRTP = ? AND YEAR = ? AND MONTH = ?)");
args.add(item.getId());
args.add(item.getDrtp());
args.add(Integer.parseInt(item.getYear()));
args.add(Integer.parseInt(item.getMonth()));
}
if (conditions.isEmpty()) {
return new ArrayList<>();
}
sql.append(String.join(" OR ", conditions));
return normalizeRiverLogRows(jdbcTemplate.queryForList(sql.toString(), args.toArray()));
}
private List<Map<String, Object>> normalizeRiverLogRows(List<Map<String, Object>> rows) {
List<Map<String, Object>> result = new ArrayList<>();
if (CollUtil.isEmpty(rows)) {
return result;
}
for (Map<String, Object> row : rows) {
result.add(normalizeRiverLogRow(row));
}
return result;
}
private Map<String, Object> normalizeRiverLogRow(Map<String, Object> row) {
Map<String, Object> normalized = new LinkedHashMap<>();
if (row == null || row.isEmpty()) {
return normalized;
}
for (Map.Entry<String, Object> entry : row.entrySet()) {
normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue());
}
return normalized;
}
private void recordRiverUpdateLog(Map<String, Object> beforeRow, Map<String, Object> updateData, String source) {
if (updateData == null || updateData.isEmpty()) {
return;
}
String stcd = asString(updateData.get("stcd"));
String recordId = asString(beforeRow.get("ID"));
List<MsOperationLogDetail> details = new ArrayList<>();
for (Map.Entry<String, String> entry : ZQ_UPDATE_COLUMN_MAP.entrySet()) {
if (!containsKeyIgnoreCase(updateData, entry.getKey())) {
continue;
}
String column = entry.getValue();
Object oldValue = beforeRow == null ? null : beforeRow.get(column);
Object newValue = getValueIgnoreCase(updateData, entry.getKey());
if (StrUtil.equals(formatRiverLogValue(oldValue), formatRiverLogValue(newValue))) {
continue;
}
details.add(buildRiverLogDetail(null, ZQ_HOUR_TABLE_NAME, stcd, column,
oldValue, resolveRiverDisplayValue(column, oldValue),
newValue, resolveRiverDisplayValue(column, newValue), "修改字段值"));
}
if (details.isEmpty()) {
return;
}
MsOperationLog mainLog = buildRiverMainLog(recordId,"修改流量站小时数据", source);
msOperationLogMapper.insert(mainLog);
for (MsOperationLogDetail detail : details) {
detail.setMainId(mainLog.getId());
}
batchInsertRiverLogDetails(details);
}
private void recordRiverDeleteLog(List<Map<String, Object>> rows, String tableName, String remark, String source) {
if (CollUtil.isEmpty(rows)) {
return;
}
List<MsOperationLogDetail> details = new ArrayList<>();
for (Map<String, Object> row : rows) {
String stcd = asString(row.get("STCD"));
String recordId = asString(row.get("ID"));
MsOperationLog mainLog = buildRiverMainLog(recordId,remark, source);
msOperationLogMapper.insert(mainLog);
for (Map.Entry<String, Object> entry : row.entrySet()) {
String fieldCode = entry.getKey();
Object oldValue = entry.getValue();
if (StrUtil.isBlank(fieldCode) || oldValue == null) {
continue;
}
details.add(buildRiverLogDetail(mainLog.getId(), tableName, stcd, fieldCode,
oldValue, resolveRiverDisplayValue(fieldCode, oldValue),
null, null, "删除字段值"));
}
}
batchInsertRiverLogDetails(details);
}
private MsOperationLog buildRiverMainLog(String recordId,String remark, String source) {
MsOperationLog log = new MsOperationLog();
log.setOperator(resolveRiverLogOperator());
log.setOperateTime(new Date());
log.setRecordId(recordId);
log.setTableName(ZQ_HOUR_TABLE_NAME);
log.setSource(StrUtil.trimToNull(source));
log.setRemark(remark);
return log;
}
private MsOperationLogDetail buildRiverLogDetail(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(ZQ_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode));
detail.setOldValueCode(formatRiverLogValue(oldValueCode));
detail.setOldValueName(formatRiverLogValue(oldValueName));
detail.setNewValueCode(formatRiverLogValue(newValueCode));
detail.setNewValueName(formatRiverLogValue(newValueName));
detail.setRemark(remark);
return detail;
}
private void batchInsertRiverLogDetails(List<MsOperationLogDetail> details) {
if (CollUtil.isEmpty(details)) {
return;
}
for (MsOperationLogDetail detail : details) {
if (detail == null) {
continue;
}
msOperationLogDetailMapper.insert(detail);
}
}
private Object resolveRiverDisplayValue(String fieldCode, Object rawValue) {
return formatRiverLogValue(rawValue);
}
private Object getValueIgnoreCase(Map<String, Object> data, String key) {
if (data == null || StrUtil.isBlank(key)) {
return null;
}
if (data.containsKey(key)) {
return data.get(key);
}
for (Map.Entry<String, Object> entry : data.entrySet()) {
if (StrUtil.equalsIgnoreCase(entry.getKey(), key)) {
return entry.getValue();
}
}
return null;
}
private boolean containsKeyIgnoreCase(Map<String, Object> data, String key) {
if (data == null || StrUtil.isBlank(key)) {
return false;
}
if (data.containsKey(key)) {
return true;
}
for (String mapKey : data.keySet()) {
if (StrUtil.equalsIgnoreCase(mapKey, key)) {
return true;
}
}
return false;
}
private String resolveRiverLogOperator() {
try {
return SecurityUtils.getCurrentUsername();
} catch (Exception ignored) {
try {
return SecurityUtils.getUserId();
} catch (Exception ex) {
return null;
}
}
}
private String formatRiverLogValue(Object value) {
if (value == null) {
return null;
}
if (value instanceof Date date) {
return cn.hutool.core.date.DateUtil.formatDateTime(date);
}
return String.valueOf(value);
}
private void statisticsDayDataFromHour(String stcd, String startDate, String endDate) {
String deleteSql = "DELETE FROM SD_RIVERDAY_S T " +
"WHERE T.STCD = ? " +

View File

@ -0,0 +1,39 @@
package com.yfd.platform.system.service;
import java.util.List;
import java.util.Set;
/**
* 超级管理员判断服务
*/
public interface IAdminAuthService {
/**
* 查询超级管理员用户名列表SYS_USER.USERTYPE = 0
*
* @return 超级管理员用户名列表
*/
List<String> getSuperAdminUsernames();
/**
* 查询统一管理的管理员用户名集合
*
* @return 管理员用户名集合
*/
Set<String> getManagedAdminUsernames();
/**
* 判断指定用户名是否为超级管理员
*
* @param username 用户名
* @return 是否为超级管理员
*/
boolean isManagedAdminUsername(String username);
/**
* 判断当前登录用户是否为超级管理员
*
* @return 是否为超级管理员
*/
boolean isCurrentManagedAdmin();
}

View File

@ -103,6 +103,13 @@ public interface IUserService extends IService<SysUser> {
************************************/
ResponseResult resetPassword(String id) throws Exception;
/**
* 查询超级管理员用户名列表SYS_USER.USERTYPE = 0
*
* @return 超级管理员用户名列表
*/
List<String> getSuperAdminUsernames();
/***********************************
* 用途说明设置账号状态(管理员)
* 参数说明

View File

@ -0,0 +1,79 @@
package com.yfd.platform.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yfd.platform.system.domain.SysUser;
import com.yfd.platform.system.mapper.SysUserMapper;
import com.yfd.platform.system.service.IAdminAuthService;
import com.yfd.platform.system.service.IUserService;
import com.yfd.platform.utils.SecurityUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 超级管理员判断服务实现
*/
@Service
public class AdminAuthServiceImpl implements IAdminAuthService {
private static final Set<String> BUILT_IN_ADMIN_USERNAMES =
new LinkedHashSet<>(Collections.singletonList("admin"));
@Resource
private SysUserMapper userMapper;
@Override
public List<String> getSuperAdminUsernames() {
// 获取当前请求
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getUsertype, 0).select(SysUser::getUsername);
//根据用户名称或手机号查询用户信息
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
String tenantId = request.getHeader("Tenant_Id");
if(StrUtil.isNotBlank(tenantId)){
queryWrapper.eq(SysUser::getTenantId, tenantId);
}
}
List<SysUser> userList = userMapper.selectList(queryWrapper);
if (CollUtil.isEmpty(userList)) {
return new ArrayList<>();
}
return userList.stream()
.map(SysUser::getUsername)
.filter(StrUtil::isNotBlank)
.distinct()
.collect(Collectors.toList());
}
@Override
public Set<String> getManagedAdminUsernames() {
LinkedHashSet<String> usernames = new LinkedHashSet<>(BUILT_IN_ADMIN_USERNAMES);
usernames.addAll(getSuperAdminUsernames());
return usernames;
}
@Override
public boolean isManagedAdminUsername(String username) {
return StrUtil.isNotBlank(username) && getManagedAdminUsernames().contains(username);
}
@Override
public boolean isCurrentManagedAdmin() {
return isManagedAdminUsername(SecurityUtils.getCurrentUsername());
}
}

View File

@ -11,6 +11,7 @@ import com.yfd.platform.system.domain.SysRole;
import com.yfd.platform.system.domain.SysUser;
import com.yfd.platform.system.mapper.SysOrganizationMapper;
import com.yfd.platform.system.mapper.SysRoleMapper;
import com.yfd.platform.system.service.IAdminAuthService;
import com.yfd.platform.system.service.ISysOrganizationService;
import com.yfd.platform.system.service.IUserService;
import com.yfd.platform.utils.ObjectConverterUtil;
@ -38,6 +39,9 @@ public class SysOrganizationServiceImpl extends ServiceImpl<SysOrganizationMappe
@Resource
private UserServiceImpl currentUser;
@Resource
private IAdminAuthService adminAuthService;
@Resource
private IUserService userService;
@ -297,7 +301,7 @@ public class SysOrganizationServiceImpl extends ServiceImpl<SysOrganizationMappe
public List<Map<String, Object>> getOrgScopeTree(String roleId, String tenantId) {
LambdaQueryWrapper<SysOrganization> queryWrapper = new LambdaQueryWrapper<>();
if(!"admin".equals(SecurityUtils.getCurrentUsername())){
if(!adminAuthService.isCurrentManagedAdmin()){
String userId = SecurityUtils.getUserId();
List<SysRole> roles = sysRoleMapper.getRoleByUserId(userId);
List<String> ids = new ArrayList<>();

View File

@ -1,18 +1,23 @@
package com.yfd.platform.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yfd.platform.datasource.DataSource;
import com.yfd.platform.system.domain.LoginUser;
import com.yfd.platform.system.domain.SysUser;
import com.yfd.platform.system.mapper.SysMenuMapper;
import com.yfd.platform.system.service.IUserService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.List;
/**
@ -35,9 +40,19 @@ public class UserDetailsServiceImpl implements UserDetailsService {
@Override
@DataSource(name = "master")
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 获取当前请求
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//根据用户名称或手机号查询用户信息
QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
queryWrapper.and(wrapper -> wrapper.eq("username", username).or().eq("phone", username));
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
String tenantId = request.getHeader("Tenant_Id");
if(StrUtil.isNotBlank(tenantId)){
queryWrapper.eq("TENANT_ID", tenantId);
}
}
SysUser user = userService.getOne(queryWrapper);
if (ObjectUtil.isEmpty(user)) {
throw new RuntimeException("用户账号不存在!");

View File

@ -22,6 +22,7 @@ import com.yfd.platform.system.domain.SysRole;
import com.yfd.platform.system.domain.SysUser;
import com.yfd.platform.system.mapper.SysRoleMapper;
import com.yfd.platform.system.mapper.SysUserMapper;
import com.yfd.platform.system.service.IAdminAuthService;
import com.yfd.platform.system.service.IUserService;
import com.yfd.platform.utils.FileUtil;
import com.yfd.platform.utils.PasswordGenerator;
@ -80,6 +81,9 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
@Resource
private SysUserDataScopeMapper sysUserDataScopeMapper;
@Resource
private IAdminAuthService adminAuthService;
/**********************************
* 用途说明:获取当前用户账号及名称
* 参数说明
@ -162,7 +166,7 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
//账号有效
sysUser.setStatus(1);
//判断注册的登录账号是否存在
if (isExistAccount(sysUser.getUsername())) {
if (isExistAccount(sysUser.getUsername(),sysUser.getTenantId() )) {
//新增用户
boolean ok = this.save(sysUser);
//新增用户分配权限
@ -419,7 +423,7 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
//账号头像存储地址
String imgName =
fileSpaceProperties.getSystem() + File.separator + "user" + File.separator + sysUser.getAvatar();
if ("admin".equals(sysUser.getUsername())) {
if (adminAuthService.isManagedAdminUsername(sysUser.getUsername())) {
return false;
} else {
boolean isOk = this.removeById(id);
@ -446,31 +450,30 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
************************************/
@Override
public ResponseResult resetPassword(String id) throws Exception {
//根据当前用户id 查询角色表的级别 currentUser.getUser() 获取当前用户id
String level = sysUserMapper.getMaxLevel(id);
//判断是否获取级别
if ("admin".equals(SecurityUtils.getCurrentUsername()) || StrUtil.isNotEmpty(level)) {
//判断当前用户级别 管理员及以上权限
if ("admin".equals(SecurityUtils.getCurrentUsername()) || Integer.parseInt(level) <= 2) {
SysUser sysUser = sysUserMapper.selectById(id);
UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
String password = PasswordGenerator.generateRandomPassword(sysUser.getUsername());
//根据id 修改密码密码修改时间最近修改者最近修改日期 将密码修改为 123456
String cryptPassword = passwordEncoder.encode(password);
updateWrapper.eq("id", id).set("password", cryptPassword).set(
"pwdresettime",
new Timestamp(System.currentTimeMillis())).set(
"lastmodifydate",
new Timestamp(System.currentTimeMillis())).set(
"lastmodifier", getUsername());
//是否修改成功
this.update(updateWrapper);
return ResponseResult.successData(password);
}
if (hasAdminOperationPermission()) {
SysUser sysUser = sysUserMapper.selectById(id);
UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
String password = PasswordGenerator.generateRandomPassword(sysUser.getUsername());
//根据id 修改密码密码修改时间最近修改者最近修改日期
String cryptPassword = passwordEncoder.encode(password);
updateWrapper.eq("id", id).set("password", cryptPassword).set(
"pwdresettime",
new Timestamp(System.currentTimeMillis())).set(
"lastmodifydate",
new Timestamp(System.currentTimeMillis())).set(
"lastmodifier", getUsername());
//是否修改成功
this.update(updateWrapper);
return ResponseResult.successData(password);
}
return ResponseResult.error();
}
@Override
public List<String> getSuperAdminUsernames() {
return adminAuthService.getSuperAdminUsernames();
}
/***********************************
* 用途说明设置账号状态(管理员)
* 参数说明
@ -481,10 +484,8 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
@Override
public boolean setStatus(String id, String status) {
boolean isOk = false;
//根据当前用户id 查询角色表的级别 currentUser.getUser() 获取当前用户id
String level = sysUserMapper.getMaxLevel(id);
//判断当前用户级别 管理员及以上权限
if ("admin".equals(SecurityUtils.getCurrentUsername()) || Integer.parseInt(level) <= 2) {
if (hasAdminOperationPermission()) {
UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
//根据id修改用户状态最近修改人最近修改时间
updateWrapper.eq("id", id).set("status", status).set(
@ -497,6 +498,35 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
return isOk;
}
private boolean hasAdminOperationPermission() {
if (adminAuthService.isCurrentManagedAdmin()) {
return true;
}
String currentUserId = SecurityUtils.getUserId();
String level = sysUserMapper.getMaxLevel(currentUserId);
Integer roleLevel = parseRoleLevel(level);
return roleLevel != null && roleLevel <= 2;
}
private boolean isCurrentManagedAdmin() {
return adminAuthService.isCurrentManagedAdmin();
}
private boolean isManagedAdminUsername(String username) {
return adminAuthService.isManagedAdminUsername(username);
}
private Set<String> getManagedAdminUsernames() {
return adminAuthService.getManagedAdminUsernames();
}
private Integer parseRoleLevel(String level) {
if (StrUtil.isBlank(level) || !StrUtil.isNumeric(level)) {
return null;
}
return Integer.parseInt(level);
}
/***********************************
* 用途说明上传用户头像
* 参数说明
@ -864,9 +894,9 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
* account 登录名称
* 返回值说明: 重复返回 false 否则返回 true
************************************/
private boolean isExistAccount(String username) {
private boolean isExistAccount(String username,String tenantId) {
QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
if (this.list(queryWrapper.eq("username", username)).size() > 0) {
if (this.list(queryWrapper.eq("username", username).eq("TENANT_ID", tenantId)).size() > 0) {
//判断 查询登录账号 结果集是否为null 重复返回 false 否则返回 tree
return false;
} else {

View File

@ -0,0 +1,94 @@
package com.yfd.platform.utils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 代码转名称元数据配置
* <p>
* 用于配置 VO 中某个 code 字段如何转换为对应的 name 字段
* 支持静态字典SYS_DICTIONARY / SYS_DICTIONARY_ITEMS和动态字典业务表
* </p>
*
* <pre>
* 使用示例
* // 静态字典 vo.typeCode 转为 vo.typeName字典编码为 "PROJECT_TYPE"
* CodeToNameMetadataBo.builder()
* .codeProperty("typeCode")
* .modifyProperty("typeName")
* .dictType("STATIC")
* .dictSource("PROJECT_TYPE")
* .build();
*
* // 动态字典 vo.engCode 转为 vo.engName SD_ENGINFO_B_H
* CodeToNameMetadataBo.builder()
* .codeProperty("engCode")
* .modifyProperty("engName")
* .dictType("DYNAMIC")
* .dictSource("SD_ENGINFO_B_H")
* .codeColumn("STCD")
* .nameColumn("ENNM")
* .filter("NVL(IS_DELETED, 0) = 0")
* .build();
* </pre>
*
* @author Generated
* @since 2025-05-18
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CodeToNameMetadataBo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 编码属性名VO 中存放 code 的字段名
*/
private String codeProperty;
/**
* 名称属性名VO 中需要设置 name 的字段名
*/
private String modifyProperty;
/**
* 字典类型STATIC静态字典 DYNAMIC动态字典
*/
private String dictType;
/**
* 字典来源
* - 静态字典SYS_DICTIONARY 表中的 DICTCODE
* - 动态字典业务表名
*/
private String dictSource;
/**
* 动态字典表中编码列名静态字典不需要
*/
private String codeColumn;
/**
* 动态字典表中名称列名静态字典不需要
*/
private String nameColumn;
/**
* 额外过滤条件可选
* - 静态字典SYS_DICTIONARY_ITEMS 的额外 WHERE 条件
* - 动态字典业务表的额外 WHERE 条件
*/
private String filter;
/**
* 是否多选code 值为逗号分隔的多个编码
*/
@Builder.Default
private boolean isMulti = false;
}

View File

@ -0,0 +1,391 @@
package com.yfd.platform.utils;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
import com.yfd.platform.system.domain.SysDictionary;
import com.yfd.platform.system.domain.SysDictionaryItems;
import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
import com.yfd.platform.system.mapper.SysDictionaryMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* 字典代码转名称转换器
* <p>
* 支持静态字典SYS_DICTIONARY / SYS_DICTIONARY_ITEMS和动态字典业务表查询
* VO 中的 code 字段值转换为对应的 name 字段值
* </p>
*
* <h3>使用方式</h3>
* <pre>
* // 1. ServiceImpl 中注入
* &#64;Resource
* private DictCodeToNameConverter dictCodeToNameConverter;
*
* // 2. 定义元数据列表通常放在 static 静态代码块中
* private static final List&lt;CodeToNameMetadataBo&gt; CODE_TO_NAME_META_LIST = List.of(
* CodeToNameMetadataBo.builder()
* .codeProperty("stationType")
* .modifyProperty("stationTypeName")
* .dictType("STATIC")
* .dictSource("STATION_TYPE")
* .build(),
* CodeToNameMetadataBo.builder()
* .codeProperty("engCode")
* .modifyProperty("engName")
* .dictType("DYNAMIC")
* .dictSource("SD_ENGINFO_B_H")
* .codeColumn("STCD")
* .nameColumn("ENNM")
* .filter("NVL(IS_DELETED, 0) = 0")
* .build()
* );
*
* // 3. 在查询方法中调用转换
* public DataSourceResult&lt;MyVo&gt; queryList(DataSourceRequest request) {
* // ... 查询数据得到 voList ...
* dictCodeToNameConverter.convertCodeToName(voList, CODE_TO_NAME_META_LIST);
* // ... 返回结果 ...
* }
* </pre>
*
* @author Generated
* @since 2025-05-18
*/
@Slf4j
@Component
public class DictCodeToNameConverter {
@Resource
private SysDictionaryMapper sysDictionaryMapper;
@Resource
private SysDictionaryItemsMapper sysDictionaryItemsMapper;
@Resource
private MicroservicDynamicSQLMapper<?> microservicDynamicSQLMapper;
/**
* 静态字典缓存dictCode -> Map<itemCode, dictName>
*/
private final Map<String, Map<String, String>> staticDictCache = new ConcurrentHashMap<>();
/**
* 动态字典缓存缓存key -> Map<code, name>
*/
private final Map<String, Map<String, String>> dynamicDictCache = new ConcurrentHashMap<>();
/**
* 批量转换根据元数据配置 VO 列表中的 code 字段转换为对应的 name 字段
*
* @param voList VO 对象列表
* @param metadataList 元数据配置列表
* @param <T> VO 类型
*/
public <T> void convertCodeToName(List<T> voList, List<CodeToNameMetadataBo> metadataList) {
if (voList == null || voList.isEmpty() || metadataList == null || metadataList.isEmpty()) {
return;
}
for (CodeToNameMetadataBo metadata : metadataList) {
try {
Map<String, String> codeNameMap = loadCodeNameMap(metadata);
if (codeNameMap.isEmpty()) {
continue;
}
applyCodeToName(voList, metadata, codeNameMap);
} catch (Exception e) {
log.error("字典转换失败: codeProperty={}, dictSource={}", metadata.getCodeProperty(), metadata.getDictSource(), e);
}
}
}
/**
* 分页结果转换 Page 中所有记录的 code 字段转换为对应的 name 字段
*
* <pre>
* 使用示例
* Page&lt;SdHbrvDic&gt; page = hbrvDicService.queryPageList(...);
* dictCodeToNameConverter.convertCodeToName(page, CODE_TO_NAME_META_LIST);
* </pre>
*
* @param page 分页对象
* @param metadataList 元数据配置列表
* @param <T> VO 类型
*/
public <T> void convertCodeToName(Page<T> page, List<CodeToNameMetadataBo> metadataList) {
if (page == null || page.getRecords() == null || page.getRecords().isEmpty()) {
return;
}
convertCodeToName(page.getRecords(), metadataList);
}
/**
* 单个对象转换将单个对象的 code 字段转换为对应的 name 字段
*
* <pre>
* 使用示例
* SdHbrvDic hbrvDic = hbrvDicService.getById(hbrvcd);
* dictCodeToNameConverter.convertCodeToName(hbrvDic, CODE_TO_NAME_META_LIST);
* </pre>
*
* @param obj 单个对象
* @param metadataList 元数据配置列表
* @param <T> VO 类型
*/
public <T> void convertCodeToName(T obj, List<CodeToNameMetadataBo> metadataList) {
if (obj == null || metadataList == null || metadataList.isEmpty()) {
return;
}
convertCodeToName(Collections.singletonList(obj), metadataList);
}
/**
* 加载静态字典映射
*
* @param dictCode 字典编码
* @return Map<itemCode, dictName>
*/
public Map<String, String> loadStaticDictMap(String dictCode) {
return staticDictCache.computeIfAbsent(dictCode, key -> {
Map<String, String> map = new LinkedHashMap<>();
try {
SysDictionary dict = sysDictionaryMapper.selectOne(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysDictionary>()
.eq(SysDictionary::getDictCode, key)
);
if (dict == null) {
log.warn("静态字典未找到: dictCode={}", key);
return map;
}
List<SysDictionaryItems> items = sysDictionaryItemsMapper.selectList(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysDictionaryItems>()
.eq(SysDictionaryItems::getDictId, dict.getId())
.orderByAsc(SysDictionaryItems::getOrderNo)
);
for (SysDictionaryItems item : items) {
if (StrUtil.isNotBlank(item.getItemCode())) {
map.put(item.getItemCode(), StrUtil.nullToDefault(item.getDictName(), item.getItemCode()));
}
}
} catch (Exception e) {
log.error("加载静态字典失败: dictCode={}", key, e);
}
return map;
});
}
/**
* 加载动态字典映射从业务表查询
*
* @param tableName 表名
* @param codeColumn 编码列名
* @param nameColumn 名称列名
* @param filter 额外过滤条件
* @return Map<code, name>
*/
public Map<String, String> loadDynamicDictMap(String tableName, String codeColumn, String nameColumn, String filter) {
String cacheKey = tableName + "|" + codeColumn + "|" + nameColumn + "|" + StrUtil.nullToDefault(filter, "");
return dynamicDictCache.computeIfAbsent(cacheKey, key -> {
Map<String, String> map = new LinkedHashMap<>();
try {
StringBuilder sql = new StringBuilder();
sql.append("SELECT ").append(codeColumn).append(" AS code, ")
.append(nameColumn).append(" AS name ")
.append("FROM ").append(tableName)
.append(" WHERE 1=1 ");
if (StrUtil.isNotBlank(filter)) {
sql.append("AND ").append(filter).append(" ");
}
Map<String, Object> params = new HashMap<>();
List<Map<String, Object>> rows = microservicDynamicSQLMapper.getAllList(sql.toString(), params);
for (Map<String, Object> row : rows) {
String code = Objects.toString(row.get("CODE"), null);
String name = Objects.toString(row.get("NAME"), null);
if (StrUtil.isNotBlank(code)) {
map.put(code, StrUtil.nullToDefault(name, code));
}
}
} catch (Exception e) {
log.error("加载动态字典失败: tableName={}", tableName, e);
}
return map;
});
}
/**
* 根据元数据加载 code->name 映射
*/
private Map<String, String> loadCodeNameMap(CodeToNameMetadataBo metadata) {
if ("STATIC".equalsIgnoreCase(metadata.getDictType())) {
return loadStaticDictMap(metadata.getDictSource());
} else if ("DYNAMIC".equalsIgnoreCase(metadata.getDictType())) {
return loadDynamicDictMap(
metadata.getDictSource(),
metadata.getCodeColumn(),
metadata.getNameColumn(),
metadata.getFilter()
);
}
log.warn("未知字典类型: dictType={}", metadata.getDictType());
return Collections.emptyMap();
}
/**
* code->name 映射应用到 VO 列表
*/
private <T> void applyCodeToName(List<T> voList, CodeToNameMetadataBo metadata, Map<String, String> codeNameMap) {
for (T vo : voList) {
try {
String codeValue = getFieldValue(vo, metadata.getCodeProperty());
if (StrUtil.isBlank(codeValue)) {
continue;
}
String nameValue;
if (metadata.isMulti()) {
// 多选逗号分隔的多个code
nameValue = Arrays.stream(codeValue.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.map(c -> codeNameMap.getOrDefault(c, c))
.collect(Collectors.joining(","));
} else {
nameValue = codeNameMap.getOrDefault(codeValue.trim(), codeValue);
}
setFieldValue(vo, metadata.getModifyProperty(), nameValue);
} catch (Exception e) {
log.debug("字段转换跳过: vo={}, codeProperty={}", vo.getClass().getSimpleName(), metadata.getCodeProperty(), e);
}
}
}
/**
* 清除所有缓存
*/
public void clearCache() {
staticDictCache.clear();
dynamicDictCache.clear();
}
/**
* 清除指定静态字典缓存
*/
public void clearStaticDictCache(String dictCode) {
staticDictCache.remove(dictCode);
}
/**
* 清除指定动态字典缓存
*/
public void clearDynamicDictCache(String tableName, String codeColumn, String nameColumn, String filter) {
String cacheKey = tableName + "|" + codeColumn + "|" + nameColumn + "|" + StrUtil.nullToDefault(filter, "");
dynamicDictCache.remove(cacheKey);
}
// ==================== 反射工具方法 ====================
/**
* 通过反射获取对象的字段值转为字符串支持驼峰命名
*/
private <T> String getFieldValue(T obj, String fieldName) {
try {
Field field = findField(obj.getClass(), fieldName);
if (field == null) {
return null;
}
field.setAccessible(true);
Object value = field.get(obj);
return value != null ? value.toString() : null;
} catch (Exception e) {
return null;
}
}
/**
* 通过反射设置对象的字段值支持驼峰命名
*/
private <T> void setFieldValue(T obj, String fieldName, String value) {
try {
Field field = findField(obj.getClass(), fieldName);
if (field == null) {
return;
}
field.setAccessible(true);
field.set(obj, value);
} catch (Exception ignored) {
// 忽略设置失败
}
}
/**
* 查找字段忽略大小写支持驼峰和下划线变体递归查找父类
*/
private Field findField(Class<?> clazz, String fieldName) {
if (clazz == null || clazz == Object.class) {
return null;
}
// 先精确匹配
for (Field field : clazz.getDeclaredFields()) {
if (field.getName().equals(fieldName)) {
return field;
}
}
// 忽略大小写匹配
for (Field field : clazz.getDeclaredFields()) {
if (field.getName().equalsIgnoreCase(fieldName)) {
return field;
}
}
// 驼峰-下划线互转匹配
String camelName = underlineToCamel(fieldName);
String underlineName = camelToUnderline(fieldName);
for (Field field : clazz.getDeclaredFields()) {
String fName = field.getName();
if (fName.equalsIgnoreCase(camelName) || fName.equalsIgnoreCase(underlineName)) {
return field;
}
}
return findField(clazz.getSuperclass(), fieldName);
}
private String underlineToCamel(String str) {
if (StrUtil.isBlank(str) || !str.contains("_")) {
return str;
}
StringBuilder sb = new StringBuilder();
boolean upper = false;
for (char c : str.toCharArray()) {
if (c == '_') {
upper = true;
} else {
sb.append(upper ? Character.toUpperCase(c) : c);
upper = false;
}
}
return sb.toString();
}
private String camelToUnderline(String str) {
if (StrUtil.isBlank(str)) {
return str;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (Character.isUpperCase(c)) {
sb.append('_').append(Character.toLowerCase(c));
} else {
sb.append(c);
}
}
return sb.toString();
}
}