fix: 优化生态调查模块

This commit is contained in:
tangwei 2026-09-07 17:15:28 +08:00
parent 8a97706ab7
commit 750445cbdd
8 changed files with 601 additions and 14 deletions

View File

@ -48,4 +48,10 @@ public class EngStBaseInfoVo {
@Schema(description = "所属流域名称") @Schema(description = "所属流域名称")
private String rvcdName; private String rvcdName;
@Schema(description = "监测方式")
private Integer mway;
@Schema(description = "监测方式名称")
private String mwayName;
} }

View File

@ -19,6 +19,8 @@ public class EngVmsstbprptVo implements Serializable {
private String id; private String id;
private String sttp; private String sttp;
private String sttpCode; private String sttpCode;
private Integer mway;
private String mwayName;
private String sttpMap; private String sttpMap;
private String logo; private String logo;
private String sttpName; private String sttpName;

View File

@ -1027,20 +1027,15 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
Map<String, Object> paramMap = new HashMap<>(); Map<String, Object> paramMap = new HashMap<>();
paramMap.put("stcd", stcd); 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, " + "STTP_FULL_PATH AS sttpFullPath, STTP_TREE_LEVEL AS sttpTreeLevel, " +
"BASE_ID AS baseId, BASE_NAME AS baseName, HBRVCD AS hbrvcd, " + "BASE_ID AS baseId, BASE_NAME AS baseName, HBRVCD AS hbrvcd, " +
"HBRVCD_NAME AS hbrvcdName, RVCD AS rvcd, RVCD_NAME AS rvcdName "; "HBRVCD_NAME AS hbrvcdName, RVCD AS rvcd, RVCD_NAME AS rvcdName ";
//
EngStInfoResultVo vo = new EngStInfoResultVo(); // EngStInfoResultVo vo = new EngStInfoResultVo();
//
// 主站点基础信息 // // 主站点基础信息
vo.setStBaseInfo(microservicDynamicSQLMapper.getOneBySqlWithResultType( // vo.setStBaseInfo(oneBySqlWithResultType);
"SELECT " + selectCols +
"FROM V_MS_STBPRP_T " +
"WHERE STCD = #{map.stcd} AND NVL(IS_DELETED, 0) = 0",
paramMap,
EngStBaseInfoVo.class));
// 关联站点列表站类全路径包含当前站点的其他站点 // 关联站点列表站类全路径包含当前站点的其他站点
List<EngStBaseInfoVo> relList = microservicDynamicSQLMapper.getAllListWithResultType( List<EngStBaseInfoVo> relList = microservicDynamicSQLMapper.getAllListWithResultType(
@ -1050,12 +1045,21 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
"AND ST_FULL_PATH LIKE CONCAT(CONCAT('%', #{map.stcd}), '%')", "AND ST_FULL_PATH LIKE CONCAT(CONCAT('%', #{map.stcd}), '%')",
paramMap, paramMap,
EngStBaseInfoVo.class); EngStBaseInfoVo.class);
if (relList != null) { // if (relList != null) {
vo.setRelList(relList); // vo.setRelList(relList);
} // }
// EngStBaseInfoVo oneBySqlWithResultType = microservicDynamicSQLMapper.getOneBySqlWithResultType(
// "SELECT " + selectCols +
// "FROM V_MS_STBPRP_T " +
// "WHERE STCD = #{map.stcd} AND NVL(IS_DELETED, 0) = 0",
// paramMap,
// EngStBaseInfoVo.class);
// ENG直接从 V_MS_STBPRP_T 视图返回 // ENG直接从 V_MS_STBPRP_T 视图返回
String viewSql = "SELECT *,SWDT STSTDT FROM V_MS_STBPRP_T WHERE STCD = #{map.stcd} AND IS_DELETED = 0"; String viewSql = "SELECT *,SWDT STSTDT FROM V_MS_STBPRP_T WHERE STCD = #{map.stcd} AND IS_DELETED = 0";
EngVmsstbprptVo engVmsstbprptVo= microservicDynamicSQLMapper.getOneBySqlWithResultType(viewSql, Collections.singletonMap("stcd", stcd), EngVmsstbprptVo.class); EngVmsstbprptVo engVmsstbprptVo= microservicDynamicSQLMapper.getOneBySqlWithResultType(viewSql, Collections.singletonMap("stcd", stcd), EngVmsstbprptVo.class);
dictCodeToNameConverter.convertCodeToName(engVmsstbprptVo,CODE_TO_NAME_META_LIST);
engVmsstbprptVo.setRelList(relList); engVmsstbprptVo.setRelList(relList);
return engVmsstbprptVo; return engVmsstbprptVo;
} }

View File

@ -162,6 +162,18 @@ public class WeFishController {
return ResponseResult.successData(weFishService.getQgcWeAnimalList(dataSourceRequest)); return ResponseResult.successData(weFishService.getQgcWeAnimalList(dataSourceRequest));
} }
@PostMapping("/anml/dict/GetKendoListCust")
@Operation(summary = "动物识别监测-按动物ID查询动物字典信息(SD_ANIMALDICTORY_B)")
public ResponseResult getQgcWeAnmlDictByAnimalId(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeAnmlDictByAnimalId(dataSourceRequest));
}
@PostMapping("/anml/run/GetKendoListCust")
@Operation(summary = "动物识别监测-根据STCD+ANIMAL_ID+年份查询监测数据(SD_ANML_R)")
public ResponseResult getQgcWeAnmlRunList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(weFishService.getQgcWeAnmlRunList(dataSourceRequest));
}
@PostMapping("/we/point/qgc/GetKendoListCust") @PostMapping("/we/point/qgc/GetKendoListCust")
@Operation(summary = "环保部-水生生态调查-地图锚点") @Operation(summary = "环保部-水生生态调查-地图锚点")
public ResponseResult getQgcWePoint(@RequestBody DataSourceRequest dataSourceRequest) { public ResponseResult getQgcWePoint(@RequestBody DataSourceRequest dataSourceRequest) {

View File

@ -0,0 +1,101 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@Data
@Schema(description = "动物字典信息(SD_ANIMALDICTORY_B)")
public class WeAnmlDictVo {
@Schema(description = "主键")
private String id;
@Schema(description = "编码")
private String code;
@Schema(description = "名称")
private String name;
@Schema(description = "英文名称")
private String nameEn;
@Schema(description = "俗名")
private String alias;
@Schema(description = "动物类群:1=哺乳 2=鸟类 3=两栖 4=爬行 5=节肢 6=其他")
private Integer category;
@Schema(description = "生境类型:1=陆生 2=水生 3=两栖")
private Integer type;
@Schema(description = "是否珍稀:0=否 1=是")
private Integer rare;
@Schema(description = "物种来源:1=本土 2=外来")
private Integer specOrigin;
@Schema(description = "保护级别")
private Integer ptype;
@Schema(description = "保护/灭绝等级:1=极危 2=濒危 3=易危 4=近危 5=低危")
private Integer situation;
@Schema(description = "主要生活环境")
private String habitat;
@Schema(description = "")
private String filum;
@Schema(description = "")
private String classis;
@Schema(description = "")
private String orders;
@Schema(description = "")
private String family;
@Schema(description = "")
private String genus;
@Schema(description = "")
private String species;
@Schema(description = "体型大小")
private String fsz;
@Schema(description = "食性:1=肉食 2=草食 3=杂食")
private String feedingHabit;
@Schema(description = "活动时律:1=昼行 2=夜行 3=晨昏")
private String activityTime;
@Schema(description = "分布区域")
private String distribution;
@Schema(description = "形态特征/识别特征")
private String symbol;
@Schema(description = "栖息习性")
private String habitation;
@Schema(description = "LOGO")
private String logo;
@Schema(description = "介绍")
private String introduce;
@Schema(description = "介绍弹窗图片")
private String inffile;
@Schema(description = "附件")
private String fid;
@Schema(description = "描述")
private String description;
@Schema(description = "排序")
private Integer orderIndex;
}

View File

@ -0,0 +1,56 @@
package com.yfd.platform.qgc_env.wte.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@Data
@Schema(description = "动物鸟类智能识别监测数据(SD_ANML_R)")
public class WeAnmlRunVo {
@Schema(description = "主键")
private String id;
@Schema(description = "监测站/设备编码: 关联SD_AIMONITOR_B_H.STCD")
private String stcd;
@Schema(description = "监测站/设备名称: 关联SD_AIMONITOR_B_H.STNM")
private String stnm;
@Schema(description = "动物ID: 关联SD_ANIMALDICTORY_B.ID")
private String animalId;
@Schema(description = "动物名称")
private String animalName;
@Schema(description = "动物编码")
private String animalCode;
@Schema(description = "记录入库时间")
private Date tm;
@Schema(description = "拍摄时间")
private Date shootTime;
@Schema(description = "识别时间")
private Date recognizeTime;
@Schema(description = "识别行为描述")
private String behavior;
@Schema(description = "视频显示名称")
private String flnm;
@Schema(description = "图片路径或者图片ID")
private String imgPath;
@Schema(description = "视频路径或者视频ID")
private String flpth;
@Schema(description = "附件ID")
private String fid;
@Schema(description = "备注")
private String description;
}

View File

@ -61,6 +61,16 @@ public interface WeFishService {
DataSourceResult<WeTeSpecialAnimalVo> getTeSpecialAnimalList(DataSourceRequest dataSourceRequest); DataSourceResult<WeTeSpecialAnimalVo> getTeSpecialAnimalList(DataSourceRequest dataSourceRequest);
/**
* 按动物ID查询动物字典信息(SD_ANIMALDICTORY_B)
*/
DataSourceResult<WeAnmlDictVo> getQgcWeAnmlDictByAnimalId(DataSourceRequest dataSourceRequest);
/**
* 根据 STCD + ANIMAL_ID + 年份查询动物监测数据(SD_ANML_R)
*/
DataSourceResult<WeAnmlRunVo> getQgcWeAnmlRunList(DataSourceRequest dataSourceRequest);
List<WeDefaultDataVo> getWeDefaultData(String stcd); List<WeDefaultDataVo> getWeDefaultData(String stcd);
DataSourceResult getWeYr(String stcd); DataSourceResult getWeYr(String stcd);

View File

@ -1437,6 +1437,402 @@ public class WeFishServiceImpl implements WeFishService {
return result; return result;
} }
@Override
public DataSourceResult<WeAnmlDictVo> getQgcWeAnmlDictByAnimalId(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
Map<String, Object> 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<WeAnmlDictVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(
page, sql.toString(), paramMap, WeAnmlDictVo.class
);
DataSourceResult<WeAnmlDictVo> result = new DataSourceResult<>();
result.setData(list);
result.setTotal(page != null ? page.getTotal() : list.size());
result.setAggregates(new HashMap<>());
return result;
}
@Override
public DataSourceResult<WeAnmlRunVo> getQgcWeAnmlRunList(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
Map<String, Object> 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<WeAnmlRunVo> 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<Map<String, Object>> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap);
if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) {
result.setData((List<WeAnmlRunVo>) (List<?>) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos)));
} else {
result.setData((List<WeAnmlRunVo>) (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<WeAnmlRunVo> 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<String, Object> paramMap,
int[] indexHolder) {
if (filter == null) {
return "";
}
if (StrUtil.isNotBlank(filter.getField())) {
return buildWeAnmlDictLeafCondition(filter, paramMap, indexHolder);
}
if (CollUtil.isEmpty(filter.getFilters())) {
return "";
}
List<String> 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<String, Object> 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<String> 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<DataSourceRequest.SortDescriptor> sorts) {
if (CollUtil.isEmpty(sorts)) {
return " ORDER BY a.ORDER_INDEX ASC";
}
List<String> 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<String, Object> paramMap,
int[] indexHolder) {
if (filter == null) {
return "";
}
if (StrUtil.isNotBlank(filter.getField())) {
return buildWeAnmlRunLeafCondition(filter, paramMap, indexHolder);
}
if (CollUtil.isEmpty(filter.getFilters())) {
return "";
}
List<String> 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<String, Object> 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<String> 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<String> groupFields = new ArrayList<>();
List<String> 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<DataSourceRequest.SortDescriptor> sorts) {
if (CollUtil.isEmpty(sorts)) {
return " ORDER BY r.TM DESC";
}
List<String> 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() { private String buildWeAnimalListDetailSql() {
return "SELECT " + return "SELECT " +
"a.ID AS id, a.NAME AS name, a.CODE AS code, " + "a.ID AS id, a.NAME AS name, a.CODE AS code, " +