feat: (全过程)增殖站二级页面: 过程图-亲鱼

This commit is contained in:
tangwei 2026-06-17 11:09:21 +08:00
parent caa6e1f8b8
commit 0deb1b2e2f
8 changed files with 413 additions and 1 deletions

View File

@ -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));
}
}

View File

@ -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<FbBsmfRFishHeadColumnVo> 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<FbBsmfRFishHeadColumnVo> children) {
this.title = title;
this.dataIndex = dataIndex;
this.visible = visible;
this.merge = merge;
this.children = children;
this.key = key;
}
}

View File

@ -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;
}

View File

@ -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<FbBsmfRFishHeadColumnVo> columns;
@Schema(description = "表格数据")
private Object dataSource;
@Schema(description = "总数")
private Long total;
}

View File

@ -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<FbBsmfRQgcVo> getQgcBsmfRKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<FbBsmfRFishTableVo> getBsmfRFishKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<FbRelatedYrVo> getFbRelatedYrByStcd(String stcd);
FbStInfoResultVo getStInfoByStcd(String stcd);

View File

@ -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<FbBsmfRFishTableVo> getBsmfRFishKendoListCust(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
Map<String, Object> 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<FbBsmfRFishSummaryVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(
page, sql.toString(), paramMap, FbBsmfRFishSummaryVo.class
);
long total = page != null ? page.getTotal() : list.size();
FbBsmfRFishTableVo tableVo = buildBsmfRFishTableVo(list, total);
DataSourceResult<FbBsmfRFishTableVo> result = new DataSourceResult<>();
result.setData(Collections.singletonList(tableVo));
result.setTotal(total);
result.setAggregates(new HashMap<>());
return result;
}
@Override
public DataSourceResult<FbRelatedYrVo> getFbRelatedYrByStcd(String stcd) {
DataSourceResult<FbRelatedYrVo> result = new DataSourceResult<>();
@ -777,6 +808,256 @@ public class FbStationServiceImpl implements FbStationService {
}
}
private String buildBsmfRFishInnerSql(DataSourceRequest dataSourceRequest,
DataSourceLoadOptionsBase loadOptions,
Map<String, Object> 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<String, Object> 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<String, Object> paramMap,
int[] indexHolder) {
if (filter == null) {
return "";
}
if (StrUtil.isNotBlank(filter.getField())) {
return buildBsmfRFishLeafCondition(filter, paramMap, indexHolder);
}
if (CollUtil.isEmpty(filter.getFilters())) {
return "";
}
List<String> 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<String, Object> 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<Object> values = normalizeQgcBsmfRValues(value);
if (values.isEmpty()) {
return "";
}
List<String> 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<FbBsmfRFishSummaryVo> list, long total) {
List<Map<String, Object>> rows = new ArrayList<>();
Map<String, String> fishMap = new LinkedHashMap<>();
if (CollUtil.isNotEmpty(list)) {
for (FbBsmfRFishSummaryVo item : list) {
Map<String, Object> rowMap = new LinkedHashMap<>();
rowMap.put("tm", item.getTm());
List<String> ftpList = splitCsv(item.getFtp());
List<String> ftpNameList = splitCsv(item.getFtpName());
List<String> 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<FbBsmfRFishHeadColumnVo> buildBsmfRFishColumns(Map<String, String> fishMap) {
List<FbBsmfRFishHeadColumnVo> columns = new ArrayList<>();
columns.add(new FbBsmfRFishHeadColumnVo("tm", "时间", true, "tm", false, new ArrayList<>())
.setDataType("date")
.setDataFormat("yyyy-MM"));
for (Map.Entry<String, String> entry : fishMap.entrySet()) {
columns.add(new FbBsmfRFishHeadColumnVo(
entry.getKey(),
entry.getValue() + "(尾)",
true,
entry.getKey(),
false,
new ArrayList<>()
));
}
return columns;
}
private List<String> splitCsv(String value) {
if (StrUtil.isBlank(value)) {
return Collections.emptyList();
}
List<String> 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<String, Object> 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))";

View File

@ -43,4 +43,6 @@ public class FprZyFishDicVo {
private String logo;
private String inffile;
private String spawnMonth;
private String orders;
private String vlsr;
}

View File

@ -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<DataSourceRequest.SortDescriptor> 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<FprZyFishDicVo> 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 " +