From 4bfe058765925ad092add81af6e2ba91f285574d Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 30 Jul 2026 18:44:09 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96AI=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E6=95=B0=E6=8D=AE=E4=B8=8A=E6=8A=A5=EF=BC=88?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=89=B9=E9=87=8F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdFpssrlRController.java | 25 +++- .../platform/qgc_base/domain/SdFpssrlAiR.java | 121 ++++++++++++++++++ .../qgc_base/mapper/SdFpssrlAiRMapper.java | 22 ++++ .../qgc_base/service/ISdFpssrlRService.java | 3 +- .../service/impl/SdFpssrlRServiceImpl.java | 15 ++- .../mapper/qgc_base/SdFpssrlAiRMapper.xml | 83 ++++++++++++ 6 files changed, 258 insertions(+), 11 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssrlAiRMapper.java create mode 100644 backend/src/main/resources/mapper/qgc_base/SdFpssrlAiRMapper.xml diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlRController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlRController.java index cb49968c..c48dca22 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlRController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlRController.java @@ -1,13 +1,14 @@ package com.yfd.platform.qgc_base.controller; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fasterxml.jackson.databind.ObjectMapper; import com.yfd.platform.annotation.Log; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; -import com.yfd.platform.qgc_base.domain.SdEngInfoBHOperateRequest; -import com.yfd.platform.qgc_base.domain.SdFpssrlR; -import com.yfd.platform.qgc_base.domain.SdFpssrlRAiRequest; +import com.yfd.platform.qgc_base.domain.*; +import com.yfd.platform.qgc_base.service.ISdFishDictoryBService; import com.yfd.platform.qgc_base.service.ISdFpssrlRService; import com.yfd.platform.qgc_data.service.AttachmentUploadService; import io.swagger.v3.oas.annotations.Operation; @@ -19,6 +20,7 @@ import org.springframework.web.multipart.MultipartFile; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -41,6 +43,9 @@ public class SdFpssrlRController { @Resource private AttachmentUploadService attachmentUploadService; + @Resource + private ISdFishDictoryBService sdFishDictoryBService; + // ==================== CRUD 方法 ==================== @PostMapping("/queryPageList") @@ -131,7 +136,14 @@ public class SdFpssrlRController { if (requests == null || requests.isEmpty()) { return ResponseResult.error("请求数据不能为空"); } - + List list = sdFishDictoryBService.list(new LambdaQueryWrapper().eq(SdFishDictoryB::getIsDeleted, "0").select(SdFishDictoryB::getId, SdFishDictoryB::getName)); + Map idNameMap = list.stream() + .filter(item -> item.getId() != null && item.getName() != null) + .collect(Collectors.toMap( + SdFishDictoryB::getName, + SdFishDictoryB::getId, + (oldValue, newValue) -> oldValue // 如果有重复 key 保留旧值(实际不会重复) + )); // 逐条校验 for (int i = 0; i < requests.size(); i++) { SdFpssrlRAiRequest req = requests.get(i); @@ -150,10 +162,13 @@ public class SdFpssrlRController { if (req.getFtp() == null || req.getFtp().isEmpty()) { return ResponseResult.error("第" + (i + 1) + "条鱼种类(ftp)不能为空"); } + if (StrUtil.isNotBlank(req.getFtp())) { + req.setFtp(idNameMap.getOrDefault(req.getFtp(), req.getFtp())); + } } try { - List result = sdFpssrlRService.processAiReportBatch(requests); + List result = sdFpssrlRService.processAiReportBatch(requests); // List ids = result.stream().map(SdFpssrlR::getId).collect(Collectors.toList()); log.info("AI批量上报成功,共{}条", result.size()); return ResponseResult.success(); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java new file mode 100644 index 00000000..2a85652d --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlAiR.java @@ -0,0 +1,121 @@ +package com.yfd.platform.qgc_base.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 过鱼设施AI盒子自动数据表 + *

+ */ +@Data +@TableName("SD_FPSSRL_AI_R") +public class SdFpssrlAiR implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 主键ID */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 过鱼设施编码 */ + private String stcd; + + /** 时间 */ + private Date tm; + + /** 鱼种类 */ + private String ftp; + + /** 过鱼数量 */ + private Integer fcnt; + + /** 鱼尺寸:大/中/小 */ + private String fsz; + + /** 鱼长度 */ + private BigDecimal length; + + /** 鱼宽度 */ + private BigDecimal width; + + /** 鱼速度 */ + private String fishspeed; + + /** 游向:0=上行 1=下行 */ + private Integer direction; + + /** 鱼位置 */ + private Long fishposition; + + /** 鱼截图主图片url */ + private String firstImgUrl; + + /** 鱼截图副图片url */ + private String secondImgUrl; + + /** 视频url */ + private String videoUrl; + + /** 水温:单位:℃ */ + private BigDecimal temperature; + + /** 水位:单位:m */ + private BigDecimal waterlevel; + + /** 流速:单位:m/s */ + private BigDecimal speed; + + /** 流量:单位:m3/s */ + private BigDecimal q; + + /** 溶氧:单位:mg/L */ + private BigDecimal dox; + + /** 浊度:单位:NTU */ + private Integer tu; + + /** 过鱼通道 */ + private String channelno; + + /** AI盒子编码 */ + private String aiBoxCode; + + /** 创建人 */ + private String recordUser; + + /** 创建时间 */ + private Date recordTime; + + /** 更新人 */ + private String modifyUser; + + /** 更新时间 */ + private Date modifyTime; + + /** 是否已删除:0=未删除 1=已删除 */ + private Integer isDeleted; + + /** 删除人 */ + private String deleteUser; + + /** 删除时间 */ + private Date deleteTime; + + /** 附件ID */ + private String fid; + + /** 备注 */ + private String remark; + + /** 过鱼设施名称(非表字段,用于列表展示) */ + @TableField(exist = false) + private String stnm; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssrlAiRMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssrlAiRMapper.java new file mode 100644 index 00000000..84ffe5d9 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssrlAiRMapper.java @@ -0,0 +1,22 @@ +package com.yfd.platform.qgc_base.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.qgc_base.domain.SdFpssrlAiR; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * 过鱼设施AI盒子自动数据表 Mapper 接口 + *

+ */ +@Mapper +public interface SdFpssrlAiRMapper extends BaseMapper { + + /** + * 批量合并过鱼AI自动数据(基于 STCD + TM + FTP 唯一) + * 存在则更新,不存在则新增 + */ + int mergeFishRecords(List list); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssrlRService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssrlRService.java index 546fb5dc..7044a673 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssrlRService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssrlRService.java @@ -3,6 +3,7 @@ package com.yfd.platform.qgc_base.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.qgc_base.domain.SdFpssrlAiR; import com.yfd.platform.qgc_base.domain.SdFpssrlR; import com.yfd.platform.qgc_base.domain.SdFpssrlRAiRequest; @@ -48,5 +49,5 @@ public interface ISdFpssrlRService extends IService { /** * 批量处理AI设备上报的识别数据 */ - List processAiReportBatch(List requests); + List processAiReportBatch(List requests); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlRServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlRServiceImpl.java index 2b658fb2..1e30499f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlRServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlRServiceImpl.java @@ -6,8 +6,10 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.qgc_base.domain.SdFpssrlAiR; import com.yfd.platform.qgc_base.domain.SdFpssrlR; import com.yfd.platform.qgc_base.domain.SdFpssrlRAiRequest; +import com.yfd.platform.qgc_base.mapper.SdFpssrlAiRMapper; import com.yfd.platform.qgc_base.mapper.SdFpssrlRMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdFpssrlRService; @@ -35,6 +37,8 @@ public class SdFpssrlRServiceImpl extends ServiceImpl queryPageList(DataSourceRequest request) { @@ -130,12 +134,13 @@ public class SdFpssrlRServiceImpl extends ServiceImpl processAiReportBatch(List requests) { - List entities = new ArrayList<>(); + public List processAiReportBatch(List requests) { + List entities = new ArrayList<>(); Date now = new Date(); for (SdFpssrlRAiRequest req : requests) { - SdFpssrlR entity = new SdFpssrlR(); - entity.setStcd(req.getStcd()); + SdFpssrlAiR entity = new SdFpssrlAiR(); + entity.setStcd(req.getFwdx()); + entity.setAiBoxCode(req.getStcd()); entity.setTm(req.getTm()); entity.setFtp(req.getFtp()); entity.setFcnt(req.getFcnt() != null ? req.getFcnt() : 1); @@ -164,7 +169,7 @@ public class SdFpssrlRServiceImpl extends ServiceImpl + + + + + + MERGE INTO SD_FPSSRL_AI_R T + USING ( + + SELECT + #{obj.stcd, jdbcType=VARCHAR} AS STCD, + #{obj.tm, jdbcType=TIMESTAMP} AS TM, + #{obj.ftp, jdbcType=VARCHAR} AS FTP, + #{obj.fcnt, jdbcType=INTEGER} AS FCNT, + #{obj.fsz, jdbcType=VARCHAR} AS FSZ, + #{obj.length, jdbcType=DECIMAL} AS LENGTH, + #{obj.width, jdbcType=DECIMAL} AS WIDTH, + #{obj.fishspeed, jdbcType=VARCHAR} AS FISHSPEED, + #{obj.direction, jdbcType=INTEGER} AS DIRECTION, + #{obj.fishposition, jdbcType=DECIMAL} AS FISHPOSITION, + #{obj.firstImgUrl, jdbcType=VARCHAR} AS FIRSTIMGURL, + #{obj.secondImgUrl, jdbcType=VARCHAR} AS SECONDIMGURL, + #{obj.videoUrl, jdbcType=VARCHAR} AS VIDEOURL, + #{obj.temperature, jdbcType=DECIMAL} AS TEMPERATURE, + #{obj.waterlevel, jdbcType=DECIMAL} AS WATERLEVEL, + #{obj.speed, jdbcType=DECIMAL} AS SPEED, + #{obj.q, jdbcType=DECIMAL} AS Q, + #{obj.dox, jdbcType=DECIMAL} AS DOX, + #{obj.tu, jdbcType=INTEGER} AS TU, + #{obj.channelno, jdbcType=VARCHAR} AS CHANNELNO, + #{obj.aiBoxCode, jdbcType=VARCHAR} AS AI_BOX_CODE, + #{obj.fid, jdbcType=VARCHAR} AS FID, + #{obj.remark, jdbcType=VARCHAR} AS REMARK, + #{obj.recordUser, jdbcType=VARCHAR} AS RECORD_USER, + #{obj.modifyUser, jdbcType=VARCHAR} AS MODIFY_USER + FROM DUAL + + ) S + ON (T.STCD = S.STCD AND T.TM = S.TM AND T.FTP = S.FTP + AND T.AI_BOX_CODE = S.AI_BOX_CODE AND T.IS_DELETED = 0) + WHEN MATCHED THEN + UPDATE SET + T.FCNT = S.FCNT, + T.FSZ = S.FSZ, + T.LENGTH = S.LENGTH, + T.WIDTH = S.WIDTH, + T.FISHSPEED = S.FISHSPEED, + T.DIRECTION = S.DIRECTION, + T.FISHPOSITION = S.FISHPOSITION, + T.FIRSTIMGURL = S.FIRSTIMGURL, + T.SECONDIMGURL = S.SECONDIMGURL, + T.VIDEOURL = S.VIDEOURL, + T.TEMPERATURE = S.TEMPERATURE, + T.WATERLEVEL = S.WATERLEVEL, + T.SPEED = S.SPEED, + T.Q = S.Q, + T.DOX = S.DOX, + T.TU = S.TU, + T.CHANNELNO = S.CHANNELNO, + T.FID = S.FID, + T.REMARK = S.REMARK, + T.MODIFY_USER = S.MODIFY_USER, + T.MODIFY_TIME = SYSDATE + WHEN NOT MATCHED THEN + INSERT ( + ID, STCD, TM, FTP, FCNT, FSZ, LENGTH, WIDTH, FISHSPEED, + DIRECTION, FISHPOSITION, FIRSTIMGURL, SECONDIMGURL, VIDEOURL, + TEMPERATURE, WATERLEVEL, SPEED, Q, DOX, TU, CHANNELNO, AI_BOX_CODE, + FID, REMARK, RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, + IS_DELETED + ) VALUES ( + SYS_GUID(), + S.STCD, S.TM, S.FTP, S.FCNT, S.FSZ, S.LENGTH, S.WIDTH, S.FISHSPEED, + S.DIRECTION, S.FISHPOSITION, S.FIRSTIMGURL, S.SECONDIMGURL, S.VIDEOURL, + S.TEMPERATURE, S.WATERLEVEL, S.SPEED, S.Q, S.DOX, S.TU, S.CHANNELNO, + NVL(S.AI_BOX_CODE, '未知'), + S.FID, S.REMARK, S.RECORD_USER, SYSDATE, S.MODIFY_USER, SYSDATE, + 0 + ) + + +