feat: (全过程)增殖站二级页面: 亲鱼选配与培育->亲鱼信息

This commit is contained in:
tangwei 2026-06-17 10:50:38 +08:00
parent c708daef17
commit caa6e1f8b8
4 changed files with 569 additions and 0 deletions

View File

@ -0,0 +1,29 @@
package com.yfd.platform.qgc_env.fb.controller;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.qgc_env.fb.service.FbStationService;
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("/fb/bsmfr")
@Tag(name = "亲鱼选配与培育-亲鱼信息")
@Validated
public class FbBsmfrController {
@Resource
private FbStationService fbStationService;
@PostMapping("/qgc/GetKendoListCust")
@Operation(summary = "(全过程)增殖站二级页面: 亲鱼选配与培育->亲鱼信息")
public ResponseResult getQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(fbStationService.getQgcBsmfRKendoListCust(dataSourceRequest));
}
}

View File

@ -0,0 +1,72 @@
package com.yfd.platform.qgc_env.fb.entity.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class FbBsmfRQgcVo {
private String id;
private String stcd;
private Date tm;
private String ftp;
private String ftpName;
private String bssr;
private String bssrName;
private BigDecimal length;
private BigDecimal weight;
private BigDecimal age;
private Integer sex;
private String sexName;
private String signnum;
private String recorder;
private Long value;
private String fid;
private String recordUser;
private Date recordTime;
private String modifyUser;
private Date modifyTime;
private Integer isDeleted;
private String deleteUser;
private Date deleteTime;
private String platformId;
private String departmentId;
private String taskId;
private String taskStatus;
private String rstcd;
private String ennm;
private String baseId;
private String baseName;
}

View File

@ -2,6 +2,7 @@ package com.yfd.platform.qgc_env.fb.service;
import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult; 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.FbFlDataVo; 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.FbRelatedYrVo;
import com.yfd.platform.qgc_env.fb.entity.vo.FbStInfoResultVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStInfoResultVo;
@ -19,6 +20,8 @@ public interface FbStationService {
DataSourceResult<FbFlDataVo> getFbFlDataKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult<FbFlDataVo> getFbFlDataKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<FbBsmfRQgcVo> getQgcBsmfRKendoListCust(DataSourceRequest dataSourceRequest);
DataSourceResult<FbRelatedYrVo> getFbRelatedYrByStcd(String stcd); DataSourceResult<FbRelatedYrVo> getFbRelatedYrByStcd(String stcd);
FbStInfoResultVo getStInfoByStcd(String stcd); FbStInfoResultVo getStInfoByStcd(String stcd);

View File

@ -7,9 +7,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceLoadOptionsBase;
import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.common.Group;
import com.yfd.platform.common.GroupHelper; import com.yfd.platform.common.GroupHelper;
import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.GroupingInfo;
import com.yfd.platform.common.MicroservicDynamicSQLMapper; 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.FbFtpStatisticsVo; 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.FbFlDataVo;
import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo;
@ -75,6 +77,16 @@ public class FbStationServiceImpl implements FbStationService {
return queryFbFlDataDetailList(dataSourceRequest, loadOptions); return queryFbFlDataDetailList(dataSourceRequest, loadOptions);
} }
@Override
public DataSourceResult<FbBsmfRQgcVo> getQgcBsmfRKendoListCust(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
GroupingInfo[] groups = loadOptions == null ? null : loadOptions.getGroup();
if (groups != null && groups.length > 0) {
return queryQgcBsmfRGroupList(dataSourceRequest, loadOptions, groups);
}
return queryQgcBsmfRDetailList(dataSourceRequest, loadOptions);
}
@Override @Override
public DataSourceResult<FbRelatedYrVo> getFbRelatedYrByStcd(String stcd) { public DataSourceResult<FbRelatedYrVo> getFbRelatedYrByStcd(String stcd) {
DataSourceResult<FbRelatedYrVo> result = new DataSourceResult<>(); DataSourceResult<FbRelatedYrVo> result = new DataSourceResult<>();
@ -678,6 +690,459 @@ public class FbStationServiceImpl implements FbStationService {
return sql.toString(); return sql.toString();
} }
private DataSourceResult<FbBsmfRQgcVo> queryQgcBsmfRDetailList(DataSourceRequest dataSourceRequest,
DataSourceLoadOptionsBase loadOptions) {
Map<String, Object> paramMap = new HashMap<>();
String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime");
String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime");
StringBuilder sql = new StringBuilder();
sql.append("SELECT ")
.append(buildQgcBsmfRDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect()))
.append(" FROM (")
.append(buildQgcBsmfRCoreSql(parseDateTimeSafely(startTime), parseDateTimeSafely(endTime), paramMap))
.append(") t WHERE 1 = 1 ");
String filterSql = buildQgcBsmfRFilterCondition(
dataSourceRequest == null ? null : dataSourceRequest.getFilter(),
paramMap,
new int[]{0}
);
if (StrUtil.isNotBlank(filterSql)) {
sql.append(" AND ").append(filterSql).append(" ");
}
sql.append(buildQgcBsmfROrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort()));
Page<?> page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
List<FbBsmfRQgcVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(
page, sql.toString(), paramMap, FbBsmfRQgcVo.class
);
postProcessQgcBsmfRList(list);
DataSourceResult<FbBsmfRQgcVo> result = new DataSourceResult<>();
result.setData(list);
result.setTotal(page != null ? page.getTotal() : list.size());
result.setAggregates(new HashMap<>());
return result;
}
@SuppressWarnings({"rawtypes", "unchecked"})
private DataSourceResult<FbBsmfRQgcVo> queryQgcBsmfRGroupList(DataSourceRequest dataSourceRequest,
DataSourceLoadOptionsBase loadOptions,
GroupingInfo[] groupInfos) {
Map<String, Object> paramMap = new HashMap<>();
String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime");
String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime");
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM (")
.append(buildQgcBsmfRCoreSql(parseDateTimeSafely(startTime), parseDateTimeSafely(endTime), paramMap))
.append(") t WHERE 1 = 1 ");
String filterSql = buildQgcBsmfRFilterCondition(
dataSourceRequest == null ? null : dataSourceRequest.getFilter(),
paramMap,
new int[]{0}
);
if (StrUtil.isNotBlank(filterSql)) {
sql.append(" AND ").append(filterSql).append(" ");
}
String groupSql = buildQgcBsmfRGroupSql(sql.toString(), dataSourceRequest == null ? null : dataSourceRequest.getGroup());
List<Map<String, Object>> rows = microservicDynamicSQLMapper.pageAllList(null, groupSql, paramMap);
DataSourceResult<FbBsmfRQgcVo> result = new DataSourceResult<>();
if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) {
result.setData((List<FbBsmfRQgcVo>) (List<?>) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos)));
} else {
List<Group> grouped = new GroupHelper().group(rows, Arrays.asList(groupInfos));
populateQgcBsmfRGroupKeyNames(grouped);
result.setData((List<FbBsmfRQgcVo>) (List<?>) grouped);
}
result.setTotal(0L);
result.setAggregates(new HashMap<>());
return result;
}
private void postProcessQgcBsmfRList(List<FbBsmfRQgcVo> list) {
if (CollUtil.isEmpty(list)) {
return;
}
for (FbBsmfRQgcVo item : list) {
if (item == null) {
continue;
}
if (StrUtil.isBlank(item.getBssrName())) {
item.setBssrName(item.getBssr());
}
if (StrUtil.isBlank(item.getSexName())) {
item.setSexName(resolveFishSexName(item.getSex()));
}
}
}
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))";
String fishNameExpr = buildFishNameExpr("rec.FTP");
StringBuilder sql = new StringBuilder();
sql.append("SELECT rec.ID AS id, ")
.append("rec.STCD AS stcd, ")
.append("rec.TM AS tm, ")
.append(fishCodeExpr).append(" AS ftp, ")
.append(fishNameExpr).append(" AS ftpName, ")
.append("rec.BSSR AS bssr, ")
.append("rec.BSSR AS bssrName, ")
.append("rec.LENGTH AS length, ")
.append("rec.WEIGHT AS weight, ")
.append("rec.AGE AS age, ")
.append("rec.SEX AS sex, ")
.append("CASE WHEN rec.SEX = 1 THEN '雄鱼' WHEN rec.SEX = 2 THEN '雌鱼' ELSE NULL END AS sexName, ")
.append("rec.SIGNNUM AS signnum, ")
.append("rec.RECORDER AS recorder, ")
.append("rec.VALUE AS value, ")
.append("rec.FID AS fid, ")
.append("rec.RECORD_USER AS recordUser, ")
.append("rec.RECORD_TIME AS recordTime, ")
.append("rec.MODIFY_USER AS modifyUser, ")
.append("rec.MODIFY_TIME AS modifyTime, ")
.append("rec.IS_DELETED AS isDeleted, ")
.append("rec.DELETE_USER AS deleteUser, ")
.append("rec.DELETE_TIME AS deleteTime, ")
.append("CAST(NULL AS VARCHAR2(36)) AS platformId, ")
.append("CAST(NULL AS VARCHAR2(36)) AS departmentId, ")
.append("CAST(NULL AS VARCHAR2(36)) AS taskId, ")
.append("CAST(NULL AS VARCHAR2(36)) AS taskStatus, ")
.append("fb.RSTCD AS rstcd, ")
.append("eng.ENNM AS ennm, ")
.append("fb.BASE_ID AS baseId, ")
.append("hb.BASENAME AS baseName ")
.append("FROM SD_FBBSMF_R rec ")
.append("INNER JOIN SD_FBRD_B_H fb ON fb.STCD = rec.STCD ")
.append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD ")
.append(" AND NVL(eng.IS_DELETED, 0) = 0 ")
.append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = fb.BASE_ID ")
.append(" AND NVL(hb.IS_DELETED, 0) = 0 ")
.append(" AND NVL(hb.ENABLED, 1) = 1 ")
.append(buildFishJoinSql("rec.FTP", "fb.HBRVCD"))
.append("WHERE NVL(rec.IS_DELETED, 0) = 0 ");
if (startTime != null) {
paramMap.put("qgcBsmfStartTime", startTime);
sql.append("AND rec.TM >= #{map.qgcBsmfStartTime} ");
}
if (endTime != null) {
paramMap.put("qgcBsmfEndTime", endTime);
sql.append("AND rec.TM <= #{map.qgcBsmfEndTime} ");
}
return sql.toString();
}
private String buildQgcBsmfRDetailSelectSql(List<String> select) {
List<String> fields = CollUtil.isEmpty(select)
? List.of("id", "stcd", "tm", "ftp", "ftpName", "bssr", "bssrName", "length", "weight", "age",
"sex", "sexName", "signnum", "recorder", "value", "fid", "recordUser", "recordTime",
"modifyUser", "modifyTime", "isDeleted", "deleteUser", "deleteTime", "platformId",
"departmentId", "taskId", "taskStatus")
: select;
List<String> selectParts = new ArrayList<>();
for (String field : fields) {
String column = mapQgcBsmfRColumn(field);
if (StrUtil.isNotBlank(column)) {
selectParts.add(column + " AS " + field);
}
}
if (selectParts.isEmpty()) {
selectParts.add("t.id AS id");
}
return String.join(", ", selectParts);
}
private String buildQgcBsmfRFilterCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
if (filter == null) {
return "";
}
if (StrUtil.isNotBlank(filter.getField())) {
return buildQgcBsmfRLeafCondition(filter, paramMap, indexHolder);
}
if (CollUtil.isEmpty(filter.getFilters())) {
return "";
}
List<String> conditions = new ArrayList<>();
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
String childSql = buildQgcBsmfRFilterCondition(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 buildQgcBsmfRLeafCondition(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap,
int[] indexHolder) {
String column = mapQgcBsmfRColumn(filter.getField());
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 ("in".equals(operator)) {
List<Object> values = normalizeQgcBsmfRValues(value);
if (values.isEmpty()) {
return "";
}
List<String> placeholders = new ArrayList<>();
for (Object item : values) {
String key = "qgcBsmfP" + indexHolder[0]++;
paramMap.put(key, normalizeQgcBsmfRValue(filter.getField(), item));
placeholders.add("#{map." + key + "}");
}
return column + " IN (" + String.join(", ", placeholders) + ")";
}
if (value == null) {
return "";
}
String key = "qgcBsmfP" + indexHolder[0]++;
Object normalizedValue = normalizeQgcBsmfRValue(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 buildQgcBsmfROrderBySql(List<DataSourceRequest.SortDescriptor> sortDescriptors) {
if (CollUtil.isEmpty(sortDescriptors)) {
return " ORDER BY t.tm DESC, t.recordTime DESC";
}
List<String> parts = new ArrayList<>();
for (DataSourceRequest.SortDescriptor descriptor : sortDescriptors) {
String column = mapQgcBsmfRColumn(descriptor.getField());
if (StrUtil.isBlank(column)) {
continue;
}
String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC";
parts.add(column + " " + direction);
}
if (parts.isEmpty()) {
return " ORDER BY t.tm DESC, t.recordTime DESC";
}
return " ORDER BY " + String.join(", ", parts);
}
private String buildQgcBsmfRGroupSql(String baseSql, List<DataSourceRequest.GroupDescriptor> groups) {
if (CollUtil.isEmpty(groups)) {
return baseSql;
}
List<DataSourceRequest.GroupDescriptor> validGroups = groups.stream()
.filter(group -> StrUtil.isNotBlank(mapQgcBsmfRColumn(group.getField())))
.toList();
if (validGroups.isEmpty()) {
return baseSql;
}
List<String> fields = validGroups.stream().map(DataSourceRequest.GroupDescriptor::getField).toList();
StringBuilder sql = new StringBuilder("SELECT ");
for (int i = 0; i < fields.size(); i++) {
if (i > 0) {
sql.append(", ");
}
sql.append(fields.get(i));
}
for (String field : fields) {
sql.append(", COUNT(*) AS count_").append(field);
}
sql.append(" FROM (").append(baseSql).append(") t GROUP BY ");
for (int i = 0; i < fields.size(); i++) {
if (i > 0) {
sql.append(", ");
}
sql.append(fields.get(i));
}
List<String> orderByParts = new ArrayList<>();
for (DataSourceRequest.GroupDescriptor descriptor : validGroups) {
if (Boolean.FALSE.equals(descriptor.getNeedSortFlag())) {
continue;
}
String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC";
orderByParts.add(descriptor.getField() + " " + direction);
}
if (!orderByParts.isEmpty()) {
sql.append(" ORDER BY ").append(String.join(", ", orderByParts));
}
return sql.toString();
}
private String mapQgcBsmfRColumn(String field) {
return switch (field) {
case "id" -> "t.id";
case "stcd" -> "t.stcd";
case "tm" -> "t.tm";
case "ftp" -> "t.ftp";
case "ftpName" -> "t.ftpName";
case "bssr" -> "t.bssr";
case "bssrName" -> "t.bssrName";
case "length" -> "t.length";
case "weight" -> "t.weight";
case "age" -> "t.age";
case "sex" -> "t.sex";
case "sexName" -> "t.sexName";
case "signnum" -> "t.signnum";
case "recorder" -> "t.recorder";
case "value" -> "t.value";
case "fid" -> "t.fid";
case "recordUser" -> "t.recordUser";
case "recordTime" -> "t.recordTime";
case "modifyUser" -> "t.modifyUser";
case "modifyTime" -> "t.modifyTime";
case "isDeleted" -> "t.isDeleted";
case "deleteUser" -> "t.deleteUser";
case "deleteTime" -> "t.deleteTime";
case "platformId" -> "t.platformId";
case "departmentId" -> "t.departmentId";
case "taskId" -> "t.taskId";
case "taskStatus" -> "t.taskStatus";
case "rstcd" -> "t.rstcd";
case "ennm" -> "t.ennm";
case "baseId" -> "t.baseId";
case "baseName" -> "t.baseName";
default -> "";
};
}
private List<Object> normalizeQgcBsmfRValues(Object value) {
List<Object> values = new ArrayList<>();
if (value == null) {
return values;
}
if (value instanceof Collection<?> collection) {
values.addAll(collection);
return values;
}
if (value instanceof Object[] array) {
values.addAll(Arrays.asList(array));
return values;
}
String text = String.valueOf(value).trim();
if (text.startsWith("[") && text.endsWith("]")) {
text = text.substring(1, text.length() - 1);
}
if (text.contains(",")) {
for (String item : text.split(",")) {
String trimmed = StrUtil.trim(item);
if (StrUtil.isNotBlank(trimmed)) {
values.add(trimmed);
}
}
return values;
}
values.add(value);
return values;
}
private Object normalizeQgcBsmfRValue(String field, Object value) {
if (value == null) {
return null;
}
if (isQgcBsmfRDateField(field) && value instanceof String text) {
return parseDateTimeSafely(text);
}
return value;
}
private boolean isQgcBsmfRDateField(String field) {
return Set.of("tm", "recordTime", "modifyTime", "deleteTime").contains(field);
}
private Date parseDateTimeSafely(String value) {
if (StrUtil.isBlank(value)) {
return null;
}
String text = value.trim();
if (text.length() == 10) {
return DateUtil.parse(text, "yyyy-MM-dd");
}
if (text.length() == 16) {
return DateUtil.parse(text, "yyyy-MM-dd HH:mm");
}
return parseDateTime(text);
}
private void populateQgcBsmfRGroupKeyNames(List<Group> groups) {
if (CollUtil.isEmpty(groups)) {
return;
}
for (Group group : groups) {
if (group == null) {
continue;
}
if ("sex".equals(group.getField()) || "sexName".equals(group.getField())) {
group.setKeyName(resolveFishSexName(group.getKey()));
}
if (CollUtil.isNotEmpty(group.getItems()) && group.getItems().get(0) instanceof Group) {
populateQgcBsmfRGroupKeyNames((List<Group>) group.getItems());
}
}
}
private String resolveFishSexName(Object sex) {
if (sex == null) {
return null;
}
String text = String.valueOf(sex);
return switch (text) {
case "1" -> "雄鱼";
case "2" -> "雌鱼";
default -> text;
};
}
private String buildFbRelatedYrByStcdSql() { private String buildFbRelatedYrByStcdSql() {
return """ return """
SELECT type, subType, yr SELECT type, subType, yr