feat: 新增自动过鱼数据模块

This commit is contained in:
tangwei 2026-07-22 11:32:37 +08:00
parent 964c1d3a41
commit f7de51f6d2
6 changed files with 614 additions and 0 deletions

View File

@ -0,0 +1,124 @@
package com.yfd.platform.qgc_base.controller;
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.service.ISdFpssrlRService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* <p>
* 过鱼设施自动数据表AI识别 前端控制器
* </p>
*/
@Slf4j
@RestController
@RequestMapping("/base/fpssrlR")
@Tag(name = "过鱼设施自动数据管理")
public class SdFpssrlRController {
@Resource
private ISdFpssrlRService sdFpssrlRService;
@Resource
private ObjectMapper objectMapper;
// ==================== CRUD 方法 ====================
@PostMapping("/queryPageList")
@Operation(summary = "分页查询过鱼自动数据列表(支持动态过滤和排序)")
public ResponseResult queryPageList(@RequestBody DataSourceRequest request) {
Page<SdFpssrlR> page = sdFpssrlRService.queryPageList(request);
return ResponseResult.successData(page);
}
@GetMapping("/getById")
@Operation(summary = "根据ID查询过鱼自动数据")
public ResponseResult getById(@RequestParam String id) {
return ResponseResult.successData(sdFpssrlRService.getById(id));
}
@Log(module = "过鱼设施自动数据管理", value = "新增过鱼自动数据")
@PostMapping("/add")
@Operation(summary = "新增过鱼自动数据")
public ResponseResult add(@RequestBody SdEngInfoBHOperateRequest request) {
SdFpssrlR entity = request == null || request.getEngInfo() == null ? null
: objectMapper.convertValue(request.getEngInfo(), SdFpssrlR.class);
if (entity == null) {
return ResponseResult.error("数据不能为空");
}
boolean result = sdFpssrlRService.add(entity, request.getSource());
return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败");
}
@Log(module = "过鱼设施自动数据管理", value = "修改过鱼自动数据")
@PostMapping("/update")
@Operation(summary = "修改过鱼自动数据")
public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) {
SdFpssrlR entity = request == null || request.getEngInfo() == null ? null
: objectMapper.convertValue(request.getEngInfo(), SdFpssrlR.class);
if (entity == null || entity.getId() == null) {
return ResponseResult.error("数据或ID不能为空");
}
boolean result = sdFpssrlRService.update(entity, request.getSource());
return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败");
}
@Log(module = "过鱼设施自动数据管理", value = "删除过鱼自动数据")
@PostMapping("/delete")
@Operation(summary = "删除过鱼自动数据")
public ResponseResult delete(@RequestBody SdEngInfoBHOperateRequest request) {
List<String> ids = request == null ? null : request.getIds();
if (ids == null || ids.isEmpty()) {
return ResponseResult.error("ID不能为空");
}
boolean result = sdFpssrlRService.delete(ids, request.getSource());
return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
}
// ==================== AI 设备识别数据上报接口 ====================
/**
* AI设备识别数据上报接口
* 接收AI设备自动识别的过鱼数据并入库
*/
@PostMapping("/ai/report")
@Operation(summary = "AI设备识别数据上报")
public ResponseResult aiReport(@RequestBody SdFpssrlRAiRequest request) {
if (request == null) {
return ResponseResult.error("请求数据不能为空");
}
if (request.getStcd() == null || request.getStcd().isEmpty()) {
return ResponseResult.error("过鱼设施编码(stcd)不能为空");
}
if (request.getTm() == null) {
return ResponseResult.error("识别时间(tm)不能为空");
}
if (request.getFtp() == null || request.getFtp().isEmpty()) {
return ResponseResult.error("鱼种类(ftp)不能为空");
}
try {
SdFpssrlR entity = sdFpssrlRService.processAiReport(request);
if (entity != null) {
return ResponseResult.successData(entity.getId());
} else {
return ResponseResult.error("数据保存失败");
}
} catch (Exception e) {
log.error("AI识别数据上报失败", e);
return ResponseResult.error("上报失败: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,180 @@
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_R")
public class SdFpssrlR 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;
/**
* 创建人关联SYS_USER.ID
*/
private String recordUser;
/**
* 创建时间
*/
private Date recordTime;
/**
* 更新人关联SYS_USER.ID
*/
private String modifyUser;
/**
* 更新时间
*/
private Date modifyTime;
/**
* 是否已删除0=未删除 1=已删除
*/
private Integer isDeleted;
/**
* 删除人关联SYS_USER.ID
*/
private String deleteUser;
/**
* 删除时间
*/
private Date deleteTime;
/**
* 附件ID
*/
private String fid;
/**
* 备注
*/
private String remark;
/**
* 过鱼设施名称非表字段用于列表展示
*/
@TableField(exist = false)
private String stnm;
}

View File

@ -0,0 +1,120 @@
package com.yfd.platform.qgc_base.domain;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* <p>
* AI设备识别数据上报请求
* </p>
*/
@Data
public class SdFpssrlRAiRequest {
/**
* 过鱼设施编码必填
*/
private String stcd;
/**
* 识别时间必填格式yyyy-MM-dd HH:mm:ss
*/
private Date tm;
/**
* 鱼种类必填
*/
private String ftp;
/**
* 过鱼数量默认1
*/
private Integer fcnt;
/**
* 鱼尺寸//
*/
private String fsz;
/**
* 鱼长度单位cm
*/
private BigDecimal length;
/**
* 鱼宽度单位cm
*/
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;
/**
* 流量单位m³/s
*/
private BigDecimal q;
/**
* 溶氧单位mg/L
*/
private BigDecimal dox;
/**
* 浊度单位NTU
*/
private Integer tu;
/**
* 过鱼通道默认"主通道"
*/
private String channelno;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,14 @@
package com.yfd.platform.qgc_base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yfd.platform.qgc_base.domain.SdFpssrlR;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 过鱼设施自动数据表 Mapper 接口
* </p>
*/
@Mapper
public interface SdFpssrlRMapper extends BaseMapper<SdFpssrlR> {
}

View File

@ -0,0 +1,47 @@
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.SdFpssrlR;
import com.yfd.platform.qgc_base.domain.SdFpssrlRAiRequest;
import java.util.List;
/**
* <p>
* 过鱼设施自动数据表 服务接口
* </p>
*/
public interface ISdFpssrlRService extends IService<SdFpssrlR> {
/**
* 分页查询Kendo Grid
*/
Page<SdFpssrlR> queryPageList(DataSourceRequest request);
/**
* 新增
*/
boolean add(SdFpssrlR entity, String source);
/**
* 修改
*/
boolean update(SdFpssrlR entity, String source);
/**
* 删除逻辑删除
*/
boolean delete(List<String> ids, String source);
/**
* 根据ID查询排除已删除的
*/
SdFpssrlR getById(String id);
/**
* 处理AI设备上报的识别数据
*/
SdFpssrlR processAiReport(SdFpssrlRAiRequest request);
}

View File

@ -0,0 +1,129 @@
package com.yfd.platform.qgc_base.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.SdFpssrlR;
import com.yfd.platform.qgc_base.domain.SdFpssrlRAiRequest;
import com.yfd.platform.qgc_base.mapper.SdFpssrlRMapper;
import com.yfd.platform.qgc_base.service.IMsOperationLogService;
import com.yfd.platform.qgc_base.service.ISdFpssrlRService;
import com.yfd.platform.utils.DataSourceRequestUtil;
import com.yfd.platform.utils.SecurityUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
* <p>
* 过鱼设施自动数据表 服务实现类
* </p>
*/
@Slf4j
@Service
public class SdFpssrlRServiceImpl extends ServiceImpl<SdFpssrlRMapper, SdFpssrlR> implements ISdFpssrlRService {
private static final String TABLE_NAME = "SD_FPSSRL_R";
@Resource
private IMsOperationLogService msOperationLogService;
@Override
public Page<SdFpssrlR> queryPageList(DataSourceRequest request) {
return DataSourceRequestUtil.executeQuery(request, SdFpssrlR.class, this);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean add(SdFpssrlR entity, String source) {
boolean result = this.save(entity);
// if (result) {
// msOperationLogService.recordAddDetailLog(entity.getId(),TABLE_NAME, entity, source);
// }
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean update(SdFpssrlR entity, String source) {
// SdFpssrlR before = this.getById(entity.getId());
boolean result = this.updateById(entity);
// if (result && before != null) {
// msOperationLogService.recordModifyDetailLog(entity.getId(),TABLE_NAME, before, entity, source);
// }
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean delete(List<String> ids, String source) {
if (ids == null || ids.isEmpty()) return false;
int count = 0;
for (String id : ids) {
// SdFpssrlR entity = getById(id);
LambdaUpdateWrapper<SdFpssrlR> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(SdFpssrlR::getId, id);
wrapper.set(SdFpssrlR::getIsDeleted, 1);
wrapper.set(SdFpssrlR::getDeleteUser, SecurityUtils.getCurrentUsername());
wrapper.set(SdFpssrlR::getDeleteTime, new Date());
if (this.update(wrapper)) {
// msOperationLogService.recordDeleteDetailLog(id,TABLE_NAME, entity, source);
count++;
}
}
return count > 0;
}
@Override
public SdFpssrlR getById(String id) {
LambdaQueryWrapper<SdFpssrlR> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SdFpssrlR::getId, id)
.eq(SdFpssrlR::getIsDeleted, 0);
return getOne(wrapper);
}
@Override
@Transactional(rollbackFor = Exception.class)
public SdFpssrlR processAiReport(SdFpssrlRAiRequest request) {
SdFpssrlR entity = new SdFpssrlR();
entity.setStcd(request.getStcd());
entity.setTm(request.getTm());
entity.setFtp(request.getFtp());
entity.setFcnt(request.getFcnt() != null ? request.getFcnt() : 1);
entity.setFsz(request.getFsz());
entity.setLength(request.getLength());
entity.setWidth(request.getWidth());
entity.setFishspeed(request.getFishspeed());
entity.setDirection(request.getDirection());
entity.setFishposition(request.getFishposition());
entity.setFirstImgUrl(request.getFirstImgUrl());
entity.setSecondImgUrl(request.getSecondImgUrl());
entity.setVideoUrl(request.getVideoUrl());
entity.setTemperature(request.getTemperature());
entity.setWaterlevel(request.getWaterlevel());
entity.setSpeed(request.getSpeed());
entity.setQ(request.getQ());
entity.setDox(request.getDox());
entity.setTu(request.getTu());
entity.setChannelno(StrUtil.isNotBlank(request.getChannelno()) ? request.getChannelno() : "主通道");
entity.setRecordUser("AI_SYSTEM");
entity.setRecordTime(new Date());
entity.setIsDeleted(0);
entity.setRemark(request.getRemark());
boolean result = this.save(entity);
if (result) {
log.info("AI识别数据保存成功, id={}, stcd={}, ftp={}", entity.getId(), entity.getStcd(), entity.getFtp());
} else {
log.error("AI识别数据保存失败, stcd={}, ftp={}", request.getStcd(), request.getFtp());
}
return result ? entity : null;
}
}