fix: 优化AI设备识别数据上报(支持批量)
This commit is contained in:
parent
2dcde94d4b
commit
4bfe058765
@ -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<SdFishDictoryB> list = sdFishDictoryBService.list(new LambdaQueryWrapper<SdFishDictoryB>().eq(SdFishDictoryB::getIsDeleted, "0").select(SdFishDictoryB::getId, SdFishDictoryB::getName));
|
||||
Map<String, String> 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<SdFpssrlR> result = sdFpssrlRService.processAiReportBatch(requests);
|
||||
List<SdFpssrlAiR> result = sdFpssrlRService.processAiReportBatch(requests);
|
||||
// List<String> ids = result.stream().map(SdFpssrlR::getId).collect(Collectors.toList());
|
||||
log.info("AI批量上报成功,共{}条", result.size());
|
||||
return ResponseResult.success();
|
||||
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 过鱼设施AI盒子自动数据表
|
||||
* </p>
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 过鱼设施AI盒子自动数据表 Mapper 接口
|
||||
* </p>
|
||||
*/
|
||||
@Mapper
|
||||
public interface SdFpssrlAiRMapper extends BaseMapper<SdFpssrlAiR> {
|
||||
|
||||
/**
|
||||
* 批量合并过鱼AI自动数据(基于 STCD + TM + FTP 唯一)
|
||||
* 存在则更新,不存在则新增
|
||||
*/
|
||||
int mergeFishRecords(List<SdFpssrlAiR> list);
|
||||
}
|
||||
@ -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<SdFpssrlR> {
|
||||
/**
|
||||
* 批量处理AI设备上报的识别数据
|
||||
*/
|
||||
List<SdFpssrlR> processAiReportBatch(List<SdFpssrlRAiRequest> requests);
|
||||
List<SdFpssrlAiR> processAiReportBatch(List<SdFpssrlRAiRequest> requests);
|
||||
}
|
||||
|
||||
@ -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<SdFpssrlRMapper, SdFpssrlR
|
||||
|
||||
@Resource
|
||||
private IMsOperationLogService msOperationLogService;
|
||||
@Resource
|
||||
private SdFpssrlAiRMapper fpssrlAiRMapper;
|
||||
|
||||
@Override
|
||||
public Page<SdFpssrlR> queryPageList(DataSourceRequest request) {
|
||||
@ -130,12 +134,13 @@ public class SdFpssrlRServiceImpl extends ServiceImpl<SdFpssrlRMapper, SdFpssrlR
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<SdFpssrlR> processAiReportBatch(List<SdFpssrlRAiRequest> requests) {
|
||||
List<SdFpssrlR> entities = new ArrayList<>();
|
||||
public List<SdFpssrlAiR> processAiReportBatch(List<SdFpssrlRAiRequest> requests) {
|
||||
List<SdFpssrlAiR> 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<SdFpssrlRMapper, SdFpssrlR
|
||||
entity.setIsDeleted(0);
|
||||
entities.add(entity);
|
||||
}
|
||||
baseMapper.mergeFishRecords(entities);
|
||||
fpssrlAiRMapper.mergeFishRecords(entities);
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.yfd.platform.qgc_base.mapper.SdFpssrlAiRMapper">
|
||||
|
||||
<!-- 批量合并过鱼AI自动数据(基于 STCD + TM + FTP + AI_BOX_CODE 唯一) -->
|
||||
<insert id="mergeFishRecords" parameterType="java.util.List">
|
||||
MERGE INTO SD_FPSSRL_AI_R T
|
||||
USING (
|
||||
<foreach collection="list" item="obj" index="index" separator="UNION ALL">
|
||||
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
|
||||
</foreach>
|
||||
) 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
|
||||
)
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue
Block a user