From 0deb1b2e2f24538c523873c1d35f7cdfb4090441 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 17 Jun 2026 11:09:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20(=E5=85=A8=E8=BF=87=E7=A8=8B)=E5=A2=9E?= =?UTF-8?q?=E6=AE=96=E7=AB=99=E4=BA=8C=E7=BA=A7=E9=A1=B5=E9=9D=A2:=20?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E5=9B=BE-=E4=BA=B2=E9=B1=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fb/controller/FbBsmfrController.java | 6 + .../fb/entity/vo/FbBsmfRFishHeadColumnVo.java | 68 +++++ .../fb/entity/vo/FbBsmfRFishSummaryVo.java | 15 + .../fb/entity/vo/FbBsmfRFishTableVo.java | 22 ++ .../qgc_env/fb/service/FbStationService.java | 3 + .../fb/service/impl/FbStationServiceImpl.java | 281 ++++++++++++++++++ .../qgc_env/fpr/entity/vo/FprZyFishDicVo.java | 2 + .../service/impl/FprMonitorServiceImpl.java | 17 +- 8 files changed, 413 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishHeadColumnVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishSummaryVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishTableVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java index da371d91..4eb347f0 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java @@ -26,4 +26,10 @@ public class FbBsmfrController { public ResponseResult getQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getQgcBsmfRKendoListCust(dataSourceRequest)); } + + @PostMapping("/fish/GetKendoListCust") + @Operation(summary = "(全过程)增殖站二级页面: 过程图-亲鱼") + public ResponseResult getFishKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getBsmfRFishKendoListCust(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishHeadColumnVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishHeadColumnVo.java new file mode 100644 index 00000000..320ff47e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishHeadColumnVo.java @@ -0,0 +1,68 @@ +package com.yfd.platform.qgc_env.fb.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 FbBsmfRFishHeadColumnVo { + + @Schema(description = "字段名") + private String dataIndex; + + @Schema(description = "标题") + private String title; + + @Schema(description = "是否展示") + private Boolean visible = true; + + @Schema(description = "唯一键") + private String key; + + @Schema(description = "单位") + private String unit; + + @Schema(description = "是否合并") + private boolean merge; + + @Schema(description = "数据类型") + private String dataType; + + @Schema(description = "数据格式") + private String dataFormat; + + @Schema(description = "子节点") + private List children; + + public FbBsmfRFishHeadColumnVo(String title, String dataIndex) { + this.title = title; + this.dataIndex = dataIndex; + this.key = dataIndex; + } + + public FbBsmfRFishHeadColumnVo(String title, String dataIndex, String key) { + this.title = title; + this.dataIndex = dataIndex; + this.key = key; + } + + public FbBsmfRFishHeadColumnVo(String dataIndex, + String title, + Boolean visible, + String key, + boolean merge, + List children) { + this.title = title; + this.dataIndex = dataIndex; + this.visible = visible; + this.merge = merge; + this.children = children; + this.key = key; + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishSummaryVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishSummaryVo.java new file mode 100644 index 00000000..95d53877 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishSummaryVo.java @@ -0,0 +1,15 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +@Data +public class FbBsmfRFishSummaryVo { + + private String tm; + + private String ftp; + + private String ftpName; + + private String value; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishTableVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishTableVo.java new file mode 100644 index 00000000..efcf8395 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbBsmfRFishTableVo.java @@ -0,0 +1,22 @@ +package com.yfd.platform.qgc_env.fb.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 FbBsmfRFishTableVo { + + @Schema(description = "表头") + private List columns; + + @Schema(description = "表格数据") + private Object dataSource; + + @Schema(description = "总数") + private Long total; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index c5d07774..a768fd7e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -3,6 +3,7 @@ package com.yfd.platform.qgc_env.fb.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStInfoResultVo; @@ -22,6 +23,8 @@ public interface FbStationService { DataSourceResult getQgcBsmfRKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getBsmfRFishKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getFbRelatedYrByStcd(String stcd); FbStInfoResultVo getStInfoByStcd(String stcd); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index bde00724..6a3965a9 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -12,6 +12,9 @@ import com.yfd.platform.common.GroupHelper; import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishHeadColumnVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishSummaryVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFtpStatisticsVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; @@ -87,6 +90,34 @@ public class FbStationServiceImpl implements FbStationService { return queryQgcBsmfRDetailList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getBsmfRFishKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT tm, ") + .append("LISTAGG(ftp, ',') WITHIN GROUP (ORDER BY ftp) AS ftp, ") + .append("LISTAGG(ftpName, ',') WITHIN GROUP (ORDER BY ftp) AS ftpName, ") + .append("LISTAGG(value, ',') WITHIN GROUP (ORDER BY ftp) AS value ") + .append("FROM (") + .append(buildBsmfRFishInnerSql(dataSourceRequest, loadOptions, paramMap)) + .append(") GROUP BY tm ") + .append("ORDER BY tm DESC"); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, FbBsmfRFishSummaryVo.class + ); + + long total = page != null ? page.getTotal() : list.size(); + FbBsmfRFishTableVo tableVo = buildBsmfRFishTableVo(list, total); + DataSourceResult result = new DataSourceResult<>(); + result.setData(Collections.singletonList(tableVo)); + result.setTotal(total); + result.setAggregates(new HashMap<>()); + return result; + } + @Override public DataSourceResult getFbRelatedYrByStcd(String stcd) { DataSourceResult result = new DataSourceResult<>(); @@ -777,6 +808,256 @@ public class FbStationServiceImpl implements FbStationService { } } + private String buildBsmfRFishInnerSql(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions, + Map paramMap) { + String fishCodeExpr = "COALESCE(TO_CHAR(NVL(relRv.ZY_FISH_ID, relRv.FISH_ID)), " + + "TO_CHAR(NVL(relZy.ZY_FISH_ID, relZy.FISH_ID)), TO_CHAR(rec.FTP))"; + String fishNameExpr = buildFishNameExpr("rec.FTP"); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT TO_CHAR(rec.TM, 'YYYY-MM') AS tm, ") + .append(fishCodeExpr).append(" AS ftp, ") + .append("CASE WHEN ").append(fishNameExpr).append(" IS NULL THEN ").append(fishCodeExpr) + .append(" ELSE TO_CHAR(").append(fishNameExpr).append(") END AS ftpName, ") + .append("CASE WHEN SUM(rec.VALUE) IS NULL THEN '-' ELSE TO_CHAR(SUM(rec.VALUE)) END AS value ") + .append("FROM SD_FBBSMF_R rec ") + .append("INNER JOIN SD_FBRD_B_H fb ON fb.STCD = rec.STCD ") + .append(buildFishJoinSql("rec.FTP", "fb.HBRVCD")) + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 "); + + appendBsmfRFishFilterConditions(sql, dataSourceRequest, loadOptions, paramMap); + sql.append("GROUP BY TO_CHAR(rec.TM, 'YYYY-MM'), ") + .append(fishCodeExpr).append(", ") + .append(fishNameExpr).append(" "); + return sql.toString(); + } + + private void appendBsmfRFishFilterConditions(StringBuilder sql, + DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions, + Map paramMap) { + String tm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + if (StrUtil.isNotBlank(tm) && tm.contains(",")) { + String[] parts = tm.split(","); + if (parts.length > 0 && StrUtil.isNotBlank(parts[0])) { + paramMap.put("bsmfFishTmStart", parseDateTimeSafely(parts[0])); + sql.append("AND rec.TM >= #{map.bsmfFishTmStart} "); + } + if (parts.length > 1 && StrUtil.isNotBlank(parts[1])) { + paramMap.put("bsmfFishTmEnd", parseDateTimeSafely(parts[1])); + sql.append("AND rec.TM <= #{map.bsmfFishTmEnd} "); + } + } + + String filterSql = buildBsmfRFishFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + } + + private String buildBsmfRFishFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildBsmfRFishLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildBsmfRFishFilterCondition(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 buildBsmfRFishLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapBsmfRFishFilterColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("tm".equalsIgnoreCase(filter.getField()) + && value instanceof String text + && text.contains(",")) { + return ""; + } + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator)) { + List values = normalizeQgcBsmfRValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "bsmfFishP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String key = "bsmfFishP" + indexHolder[0]++; + Object normalizedValue = normalizeBsmfRFishValue(filter.getField(), value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalizedValue); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalizedValue); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalizedValue); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalizedValue); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalizedValue); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalizedValue); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + normalizedValue + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + normalizedValue); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapBsmfRFishFilterColumn(String field) { + return switch (field) { + case "stcd" -> "rec.STCD"; + case "tm" -> "rec.TM"; + case "ftp" -> "rec.FTP"; + case "bssr" -> "rec.BSSR"; + case "length" -> "rec.LENGTH"; + case "weight" -> "rec.WEIGHT"; + case "age" -> "rec.AGE"; + case "sex" -> "rec.SEX"; + case "signnum" -> "rec.SIGNNUM"; + case "recorder" -> "rec.RECORDER"; + case "value" -> "rec.VALUE"; + case "fid" -> "rec.FID"; + case "rstcd" -> "fb.RSTCD"; + case "baseId" -> "fb.BASE_ID"; + case "hbrvcd" -> "fb.HBRVCD"; + default -> ""; + }; + } + + private Object normalizeBsmfRFishValue(String field, Object value) { + if (value == null) { + return null; + } + if ("tm".equalsIgnoreCase(field) && value instanceof String text) { + return parseDateTimeSafely(text); + } + return value; + } + + private FbBsmfRFishTableVo buildBsmfRFishTableVo(List list, long total) { + List> rows = new ArrayList<>(); + Map fishMap = new LinkedHashMap<>(); + if (CollUtil.isNotEmpty(list)) { + for (FbBsmfRFishSummaryVo item : list) { + Map rowMap = new LinkedHashMap<>(); + rowMap.put("tm", item.getTm()); + List ftpList = splitCsv(item.getFtp()); + List ftpNameList = splitCsv(item.getFtpName()); + List valueList = splitCsv(item.getValue()); + int size = Math.min(ftpList.size(), Math.min(ftpNameList.size(), valueList.size())); + for (int i = 0; i < size; i++) { + String ftp = ftpList.get(i); + String ftpName = ftpNameList.get(i); + String value = valueList.get(i); + rowMap.put(ftp, "-".equals(value) ? null : value); + fishMap.putIfAbsent(ftp, ftpName); + } + rows.add(rowMap); + } + } + return new FbBsmfRFishTableVo() + .setColumns(buildBsmfRFishColumns(fishMap)) + .setDataSource(rows) + .setTotal(total); + } + + private List buildBsmfRFishColumns(Map fishMap) { + List columns = new ArrayList<>(); + columns.add(new FbBsmfRFishHeadColumnVo("tm", "时间", true, "tm", false, new ArrayList<>()) + .setDataType("date") + .setDataFormat("yyyy-MM")); + for (Map.Entry entry : fishMap.entrySet()) { + columns.add(new FbBsmfRFishHeadColumnVo( + entry.getKey(), + entry.getValue() + "(尾)", + true, + entry.getKey(), + false, + new ArrayList<>() + )); + } + return columns; + } + + private List splitCsv(String value) { + if (StrUtil.isBlank(value)) { + return Collections.emptyList(); + } + List result = new ArrayList<>(); + for (String item : value.split(",")) { + String trimmed = StrUtil.trim(item); + if (StrUtil.isNotBlank(trimmed)) { + result.add(trimmed); + } + } + return result; + } + private String buildQgcBsmfRCoreSql(Date startTime, Date endTime, Map paramMap) { String fishCodeExpr = "COALESCE(TO_CHAR(NVL(relRv.ZY_FISH_ID, relRv.FISH_ID)), " + "TO_CHAR(NVL(relZy.ZY_FISH_ID, relZy.FISH_ID)), TO_CHAR(rec.FTP))"; diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java index 6399d079..2fb1bf67 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java @@ -43,4 +43,6 @@ public class FprZyFishDicVo { private String logo; private String inffile; private String spawnMonth; + private String orders; + private String vlsr; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java index 94858b0a..2ab792b0 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java @@ -201,7 +201,20 @@ public class FprMonitorServiceImpl implements FprMonitorService { if (StrUtil.isNotBlank(filterSql)) { sql.append(" AND ").append(filterSql).append(" "); } - + // 增加排序 + if(dataSourceRequest.getSort() !=null && !dataSourceRequest.getSort().isEmpty()){ + List sortDescriptors = dataSourceRequest.getSort(); + StringBuilder orderSql = new StringBuilder(); + orderSql.append(" order by "); + for (DataSourceRequest.SortDescriptor sort:sortDescriptors){ + orderSql.append(sort.getField()).append(" ").append(sort.getDir()).append(","); + } + sql.append(orderSql, 0, orderSql.length()-1); +// String[] beans = SpringContextHolder.getApplicationContext().getBeanDefinitionNames(); + sql.append(" nulls last "); + }else{ + sql.append(" order by rvcd nulls last "); + } List list = microservicDynamicSQLMapper.getAllListWithResultType( sql.toString(), paramMap, @@ -535,6 +548,8 @@ public class FprMonitorServiceImpl implements FprMonitorService { "src.DESCRIPTION AS description, " + "src.LOGO AS logo, " + "src.INFFILE AS inffile, " + + "src.ORDERS, \n" + + "src.VLSR, \n"+ "src.SPAWN_MONTH AS spawnMonth " + "FROM SD_FISHDICTORY_B src " + "LEFT JOIN SD_FISHDICTORY_RLTN_B rel ON src.ID = rel.ZY_FISH_ID " +