From 750445cbddb28b3b241bb66631982c2a8a4372c8 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 7 Sep 2026 17:15:28 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E7=94=9F=E6=80=81?= =?UTF-8?q?=E8=B0=83=E6=9F=A5=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_base/domain/vo/EngStBaseInfoVo.java | 6 + .../qgc_base/domain/vo/EngVmsstbprptVo.java | 2 + .../service/impl/SdEngInfoBHServiceImpl.java | 32 +- .../wte/controller/WeFishController.java | 12 + .../qgc_env/wte/entity/vo/WeAnmlDictVo.java | 101 +++++ .../qgc_env/wte/entity/vo/WeAnmlRunVo.java | 56 +++ .../qgc_env/wte/service/WeFishService.java | 10 + .../wte/service/impl/WeFishServiceImpl.java | 396 ++++++++++++++++++ 8 files changed, 601 insertions(+), 14 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeAnmlDictVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeAnmlRunVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java index b4a0f370..1f3ee348 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java @@ -48,4 +48,10 @@ public class EngStBaseInfoVo { @Schema(description = "所属流域名称") private String rvcdName; + + @Schema(description = "监测方式") + private Integer mway; + + @Schema(description = "监测方式名称") + private String mwayName; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index c05664ae..33b6bdbd 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java @@ -19,6 +19,8 @@ public class EngVmsstbprptVo implements Serializable { private String id; private String sttp; private String sttpCode; + private Integer mway; + private String mwayName; private String sttpMap; private String logo; private String sttpName; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 3b5e04fc..7936bd4d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -1027,20 +1027,15 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl paramMap = new HashMap<>(); paramMap.put("stcd", stcd); - String selectCols = "STCD AS stcd, STNM AS stnm, STTP_CODE AS sttpCode, STTP_NAME AS sttpName, " + + String selectCols = "STCD AS stcd,MWAY mway, STNM AS stnm, STTP_CODE AS sttpCode, STTP_NAME AS sttpName, " + "STTP_FULL_PATH AS sttpFullPath, STTP_TREE_LEVEL AS sttpTreeLevel, " + "BASE_ID AS baseId, BASE_NAME AS baseName, HBRVCD AS hbrvcd, " + "HBRVCD_NAME AS hbrvcdName, RVCD AS rvcd, RVCD_NAME AS rvcdName "; - - EngStInfoResultVo vo = new EngStInfoResultVo(); - - // 主站点基础信息 - vo.setStBaseInfo(microservicDynamicSQLMapper.getOneBySqlWithResultType( - "SELECT " + selectCols + - "FROM V_MS_STBPRP_T " + - "WHERE STCD = #{map.stcd} AND NVL(IS_DELETED, 0) = 0", - paramMap, - EngStBaseInfoVo.class)); +// +// EngStInfoResultVo vo = new EngStInfoResultVo(); +// +// // 主站点基础信息 +// vo.setStBaseInfo(oneBySqlWithResultType); // 关联站点列表(站类全路径包含当前站点的其他站点) List relList = microservicDynamicSQLMapper.getAllListWithResultType( @@ -1050,12 +1045,21 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl getTeSpecialAnimalList(DataSourceRequest dataSourceRequest); + /** + * 按动物ID查询动物字典信息(SD_ANIMALDICTORY_B) + */ + DataSourceResult getQgcWeAnmlDictByAnimalId(DataSourceRequest dataSourceRequest); + + /** + * 根据 STCD + ANIMAL_ID + 年份查询动物监测数据(SD_ANML_R) + */ + DataSourceResult getQgcWeAnmlRunList(DataSourceRequest dataSourceRequest); + List getWeDefaultData(String stcd); DataSourceResult getWeYr(String stcd); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java index 31a77bea..03d5c268 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java @@ -1437,6 +1437,402 @@ public class WeFishServiceImpl implements WeFishService { return result; } + @Override + public DataSourceResult getQgcWeAnmlDictByAnimalId(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT a.ID AS id, a.CODE AS code, a.NAME AS name, a.NAME_EN AS nameEn, a.ALIAS AS alias, ") + .append("a.CATEGORY AS category, a.TYPE AS type, a.RARE AS rare, a.SPEC_ORIGIN AS specOrigin, a.PTYPE AS ptype, ") + .append("a.SITUATION AS situation, a.HABITAT AS habitat, a.FILUM AS filum, a.CLASSIS AS classis, ") + .append("a.ORDERS AS orders, a.FAMILY AS family, a.GENUS AS genus, a.SPECIES AS species, a.FSZ AS fsz, ") + .append("a.FEEDING_HABIT AS feedingHabit, a.ACTIVITY_TIME AS activityTime, a.DISTRIBUTION AS distribution, ") + .append("a.SYMBOL AS symbol, a.HABITATION AS habitation, a.LOGO AS logo, a.INTRODUCE AS introduce, ") + .append("a.INFFILE AS inffile, a.FID AS fid, a.DESCRIPTION AS description, a.ORDER_INDEX AS orderIndex ") + .append("FROM SD_ANIMALDICTORY_B a WHERE NVL(a.IS_DELETED, 0) = 0 "); + String filterSql = buildWeAnmlDictFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + sql.append(buildWeAnmlDictOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, WeAnmlDictVo.class + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getQgcWeAnmlRunList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + String filterSql = buildWeAnmlRunFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT r.ID AS id, r.STCD AS stcd, ai.STNM AS stnm, ") + .append("r.ANIMAL_ID AS animalId, a.NAME AS animalName, a.CODE AS animalCode, ") + .append("r.TM AS tm, r.SHOOT_TIME AS shootTime, r.RECOGNIZE_TIME AS recognizeTime, ") + .append("r.BEHAVIOR AS behavior, r.FLNM AS flnm, r.IMG_PATH AS imgPath, ") + .append("r.FLPTH AS flpth, r.FID AS fid, r.DESCRIPTION AS description ") + .append("FROM SD_ANML_R r ") + .append("LEFT JOIN SD_ANIMALDICTORY_B a ON a.ID = r.ANIMAL_ID AND NVL(a.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_AIMONITOR_B_H ai ON ai.STCD = r.STCD AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(r.IS_DELETED, 0) = 0 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + String groupedSql = buildWeAnmlRunGroupSql(sql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + sql.append(buildWeAnmlRunOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, WeAnmlRunVo.class + ); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildWeAnmlDictFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeAnmlDictLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeAnmlDictFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeAnmlDictLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeAnmlDictColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List placeholders = new ArrayList<>(); + for (Object value : normalizeWeFishQgcValues(filter.getValue())) { + if (value == null || StrUtil.isBlank(String.valueOf(value).trim())) { + continue; + } + String key = "weAnmlDictP" + indexHolder[0]++; + paramMap.put(key, String.valueOf(value).trim()); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + Object rawValue = filter.getValue(); + if (rawValue == null || StrUtil.isBlank(String.valueOf(rawValue).trim())) { + return ""; + } + String key = "weAnmlDictP" + indexHolder[0]++; + String text = String.valueOf(rawValue).trim(); + return switch (operator) { + case "eq" -> { + paramMap.put(key, text); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, text); + yield column + " <> #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + text + "%"); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapWeAnmlDictColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "a.ID"; + case "code" -> "a.CODE"; + case "name" -> "a.NAME"; + case "nameEn" -> "a.NAME_EN"; + case "alias" -> "a.ALIAS"; + case "category" -> "a.CATEGORY"; + case "type" -> "a.TYPE"; + case "rare" -> "a.RARE"; + case "specOrigin" -> "a.SPEC_ORIGIN"; + case "ptype" -> "a.PTYPE"; + case "situation" -> "a.SITUATION"; + case "filum" -> "a.FILUM"; + case "classis" -> "a.CLASSIS"; + case "orders" -> "a.ORDERS"; + case "family" -> "a.FAMILY"; + case "genus" -> "a.GENUS"; + case "species" -> "a.SPECIES"; + case "orderIndex" -> "a.ORDER_INDEX"; + default -> null; + }; + } + + private String buildWeAnmlDictOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY a.ORDER_INDEX ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeAnmlDictColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return " ORDER BY a.ORDER_INDEX ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildWeAnmlRunFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeAnmlRunLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeAnmlRunFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeAnmlRunLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeAnmlRunColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List placeholders = new ArrayList<>(); + for (Object value : normalizeWeFishQgcValues(filter.getValue())) { + if (value == null || StrUtil.isBlank(String.valueOf(value).trim())) { + continue; + } + String key = "weAnmlRunP" + indexHolder[0]++; + paramMap.put(key, normalizeWeAnmlRunValue(filter.getField(), String.valueOf(value).trim())); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + Object rawValue = filter.getValue(); + if (rawValue == null || StrUtil.isBlank(String.valueOf(rawValue).trim())) { + return ""; + } + String key = "weAnmlRunP" + indexHolder[0]++; + Object normalized = normalizeWeAnmlRunValue(filter.getField(), String.valueOf(rawValue).trim()); + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalized); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalized); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalized); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalized); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalized); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalized); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + String.valueOf(normalized).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + String.valueOf(normalized).trim() + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapWeAnmlRunColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "r.ID"; + case "stcd" -> "r.STCD"; + case "stnm" -> "ai.STNM"; + case "animalId" -> "r.ANIMAL_ID"; + case "animalName" -> "a.NAME"; + case "animalCode" -> "a.CODE"; + case "tm" -> "r.TM"; + case "year", "yr" -> "TO_CHAR(r.TM, 'YYYY')"; + case "shootTime" -> "r.SHOOT_TIME"; + case "recognizeTime" -> "r.RECOGNIZE_TIME"; + case "behavior" -> "r.BEHAVIOR"; + case "flnm" -> "r.FLNM"; + case "imgPath" -> "r.IMG_PATH"; + case "flpth" -> "r.FLPTH"; + case "fid" -> "r.FID"; + case "description" -> "r.DESCRIPTION"; + default -> null; + }; + } + + private Object normalizeWeAnmlRunValue(String field, String text) { + if ("tm".equals(field) || "shootTime".equals(field) || "recognizeTime".equals(field)) { + return parseDateTimeSafely(text); + } + return text; + } + + private String buildWeAnmlRunGroupSql(String baseSql, GroupingInfo[] groupInfos) { + if (groupInfos == null || groupInfos.length == 0) { + return baseSql; + } + List groupFields = new ArrayList<>(); + List selectItems = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + if (item == null || StrUtil.isBlank(item.getSelector())) { + continue; + } + String column = mapWeAnmlRunColumn(item.getSelector()); + if (StrUtil.isBlank(column)) { + continue; + } + String alias = column.substring(column.indexOf('.') + 1); + groupFields.add(alias); + selectItems.add(alias + " AS " + item.getSelector().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + item.getSelector().toUpperCase()); + } + if (groupFields.isEmpty()) { + return baseSql; + } + StringBuilder sql = new StringBuilder("SELECT "); + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(baseSql) + .append(") T GROUP BY ") + .append(String.join(", ", groupFields)); + return sql.toString(); + } + + private String buildWeAnmlRunOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY r.TM DESC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeAnmlRunColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return " ORDER BY r.TM DESC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + private String buildWeAnimalListDetailSql() { return "SELECT " + "a.ID AS id, a.NAME AS name, a.CODE AS code, " +