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
new file mode 100644
index 00000000..4883f43f
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssrlRController.java
@@ -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;
+
+/**
+ *
+ * 过鱼设施自动数据表(AI识别) 前端控制器
+ *
+ */
+@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 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 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());
+ }
+ }
+}
diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlR.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlR.java
new file mode 100644
index 00000000..a768db6f
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlR.java
@@ -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;
+
+/**
+ *
+ * 过鱼设施自动数据表(AI识别)
+ *
+ */
+@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;
+}
diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlRAiRequest.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlRAiRequest.java
new file mode 100644
index 00000000..37b9c3e4
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssrlRAiRequest.java
@@ -0,0 +1,120 @@
+package com.yfd.platform.qgc_base.domain;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ *
+ * AI设备识别数据上报请求
+ *
+ */
+@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;
+}
diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssrlRMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssrlRMapper.java
new file mode 100644
index 00000000..6998c983
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssrlRMapper.java
@@ -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;
+
+/**
+ *
+ * 过鱼设施自动数据表 Mapper 接口
+ *
+ */
+@Mapper
+public interface SdFpssrlRMapper extends BaseMapper {
+}
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
new file mode 100644
index 00000000..4c129542
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssrlRService.java
@@ -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;
+
+/**
+ *
+ * 过鱼设施自动数据表 服务接口
+ *
+ */
+public interface ISdFpssrlRService extends IService {
+
+ /**
+ * 分页查询(Kendo Grid)
+ */
+ Page queryPageList(DataSourceRequest request);
+
+ /**
+ * 新增
+ */
+ boolean add(SdFpssrlR entity, String source);
+
+ /**
+ * 修改
+ */
+ boolean update(SdFpssrlR entity, String source);
+
+ /**
+ * 删除(逻辑删除)
+ */
+ boolean delete(List ids, String source);
+
+ /**
+ * 根据ID查询(排除已删除的)
+ */
+ SdFpssrlR getById(String id);
+
+ /**
+ * 处理AI设备上报的识别数据
+ */
+ SdFpssrlR processAiReport(SdFpssrlRAiRequest request);
+}
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
new file mode 100644
index 00000000..04eb0406
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssrlRServiceImpl.java
@@ -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;
+
+/**
+ *
+ * 过鱼设施自动数据表 服务实现类
+ *
+ */
+@Slf4j
+@Service
+public class SdFpssrlRServiceImpl extends ServiceImpl implements ISdFpssrlRService {
+
+ private static final String TABLE_NAME = "SD_FPSSRL_R";
+
+ @Resource
+ private IMsOperationLogService msOperationLogService;
+
+ @Override
+ public Page 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 ids, String source) {
+ if (ids == null || ids.isEmpty()) return false;
+ int count = 0;
+ for (String id : ids) {
+// SdFpssrlR entity = getById(id);
+ LambdaUpdateWrapper 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 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;
+ }
+}