diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 626a813..9da7e97 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -92,6 +92,12 @@
ruoyi-fishery
${revision}
+
+
+ org.dromara
+ ruoyi-tdengine
+ ${revision}
+
org.dromara
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 00efc2b..5a0531d 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -51,17 +51,17 @@ spring:
# username: root
# password: root
driverClassName: org.postgresql.Driver
- url: jdbc:postgresql://117.72.197.29:15432/ruoyi-plus?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
+ url: jdbc:postgresql://154.8.147.51:15432/fishery_dev?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
username: postgres
password: intc@123987
# # 从库数据源
# slave:
# lazy: true
# type: ${spring.datasource.type}
-# driverClassName: com.mysql.cj.jdbc.Driver
-# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
-# username:
-# password:
+# driverClassName: com.taosdata.jdbc.rs.RestfulDriver
+# url: jdbc:TAOS-RS://117.72.197.29:6041/log?timezone=Shanghai&charset=UTF-8&locale=en_US.UTF-8
+# username: root
+# password: taosdata
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml
index b315613..5735bcc 100644
--- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml
+++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml
@@ -2,7 +2,7 @@ spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driverClassName: org.postgresql.Driver
- url: jdbc:postgresql://117.72.197.29:15432/ruoyi-plus?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
+ url: jdbc:postgresql://154.8.147.51:15432/fishery_dev?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
username: postgres
password: intc@123987
hikari:
diff --git a/ruoyi-modules/pom.xml b/ruoyi-modules/pom.xml
index 757fcf4..c42af1b 100644
--- a/ruoyi-modules/pom.xml
+++ b/ruoyi-modules/pom.xml
@@ -16,6 +16,7 @@
ruoyi-system
ruoyi-workflow
ruoyi-fishery
+ ruoyi-tdengine
ruoyi-modules
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/DeviceCorrectRecordController.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/DeviceCorrectRecordController.java
new file mode 100644
index 0000000..8599b1c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/DeviceCorrectRecordController.java
@@ -0,0 +1,105 @@
+package org.dromara.fishery.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.fishery.domain.vo.DeviceCorrectRecordVo;
+import org.dromara.fishery.domain.bo.DeviceCorrectRecordBo;
+import org.dromara.fishery.service.IDeviceCorrectRecordService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 设备校准记录
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/fishery/deviceCorrectRecord")
+public class DeviceCorrectRecordController extends BaseController {
+
+ private final IDeviceCorrectRecordService deviceCorrectRecordService;
+
+ /**
+ * 查询设备校准记录列表
+ */
+ @SaCheckPermission("fishery:deviceCorrectRecord:list")
+ @GetMapping("/list")
+ public TableDataInfo list(DeviceCorrectRecordBo bo, PageQuery pageQuery) {
+ return deviceCorrectRecordService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出设备校准记录列表
+ */
+ @SaCheckPermission("fishery:deviceCorrectRecord:export")
+ @Log(title = "设备校准记录", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(DeviceCorrectRecordBo bo, HttpServletResponse response) {
+ List list = deviceCorrectRecordService.queryList(bo);
+ ExcelUtil.exportExcel(list, "设备校准记录", DeviceCorrectRecordVo.class, response);
+ }
+
+ /**
+ * 获取设备校准记录详细信息
+ *
+ * @param id 主键
+ */
+ @SaCheckPermission("fishery:deviceCorrectRecord:query")
+ @GetMapping("/{id}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(deviceCorrectRecordService.queryById(id));
+ }
+
+ /**
+ * 新增设备校准记录
+ */
+ @SaCheckPermission("fishery:deviceCorrectRecord:add")
+ @Log(title = "设备校准记录", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody DeviceCorrectRecordBo bo) {
+ return toAjax(deviceCorrectRecordService.insertByBo(bo));
+ }
+
+ /**
+ * 修改设备校准记录
+ */
+ @SaCheckPermission("fishery:deviceCorrectRecord:edit")
+ @Log(title = "设备校准记录", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody DeviceCorrectRecordBo bo) {
+ return toAjax(deviceCorrectRecordService.updateByBo(bo));
+ }
+
+ /**
+ * 删除设备校准记录
+ *
+ * @param ids 主键串
+ */
+ @SaCheckPermission("fishery:deviceCorrectRecord:remove")
+ @Log(title = "设备校准记录", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(deviceCorrectRecordService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/DeviceErrorCodeController.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/DeviceErrorCodeController.java
new file mode 100644
index 0000000..8a74d2b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/DeviceErrorCodeController.java
@@ -0,0 +1,105 @@
+package org.dromara.fishery.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.fishery.domain.vo.DeviceErrorCodeVo;
+import org.dromara.fishery.domain.bo.DeviceErrorCodeBo;
+import org.dromara.fishery.service.IDeviceErrorCodeService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 设备故障码
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/fishery/deviceErrorCode")
+public class DeviceErrorCodeController extends BaseController {
+
+ private final IDeviceErrorCodeService deviceErrorCodeService;
+
+ /**
+ * 查询设备故障码列表
+ */
+ @SaCheckPermission("fishery:deviceErrorCode:list")
+ @GetMapping("/list")
+ public TableDataInfo list(DeviceErrorCodeBo bo, PageQuery pageQuery) {
+ return deviceErrorCodeService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出设备故障码列表
+ */
+ @SaCheckPermission("fishery:deviceErrorCode:export")
+ @Log(title = "设备故障码", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(DeviceErrorCodeBo bo, HttpServletResponse response) {
+ List list = deviceErrorCodeService.queryList(bo);
+ ExcelUtil.exportExcel(list, "设备故障码", DeviceErrorCodeVo.class, response);
+ }
+
+ /**
+ * 获取设备故障码详细信息
+ *
+ * @param id 主键
+ */
+ @SaCheckPermission("fishery:deviceErrorCode:query")
+ @GetMapping("/{id}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(deviceErrorCodeService.queryById(id));
+ }
+
+ /**
+ * 新增设备故障码
+ */
+ @SaCheckPermission("fishery:deviceErrorCode:add")
+ @Log(title = "设备故障码", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody DeviceErrorCodeBo bo) {
+ return toAjax(deviceErrorCodeService.insertByBo(bo));
+ }
+
+ /**
+ * 修改设备故障码
+ */
+ @SaCheckPermission("fishery:deviceErrorCode:edit")
+ @Log(title = "设备故障码", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody DeviceErrorCodeBo bo) {
+ return toAjax(deviceErrorCodeService.updateByBo(bo));
+ }
+
+ /**
+ * 删除设备故障码
+ *
+ * @param ids 主键串
+ */
+ @SaCheckPermission("fishery:deviceErrorCode:remove")
+ @Log(title = "设备故障码", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(deviceErrorCodeService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/DeviceSwitchController.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/DeviceSwitchController.java
new file mode 100644
index 0000000..3a2fdee
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/DeviceSwitchController.java
@@ -0,0 +1,105 @@
+package org.dromara.fishery.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.fishery.domain.vo.DeviceSwitchVo;
+import org.dromara.fishery.domain.bo.DeviceSwitchBo;
+import org.dromara.fishery.service.IDeviceSwitchService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 测控一体机开关
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/fishery/deviceSwitch")
+public class DeviceSwitchController extends BaseController {
+
+ private final IDeviceSwitchService deviceSwitchService;
+
+ /**
+ * 查询测控一体机开关列表
+ */
+ @SaCheckPermission("fishery:deviceSwitch:list")
+ @GetMapping("/list")
+ public TableDataInfo list(DeviceSwitchBo bo, PageQuery pageQuery) {
+ return deviceSwitchService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出测控一体机开关列表
+ */
+ @SaCheckPermission("fishery:deviceSwitch:export")
+ @Log(title = "测控一体机开关", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(DeviceSwitchBo bo, HttpServletResponse response) {
+ List list = deviceSwitchService.queryList(bo);
+ ExcelUtil.exportExcel(list, "测控一体机开关", DeviceSwitchVo.class, response);
+ }
+
+ /**
+ * 获取测控一体机开关详细信息
+ *
+ * @param id 主键
+ */
+ @SaCheckPermission("fishery:deviceSwitch:query")
+ @GetMapping("/{id}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(deviceSwitchService.queryById(id));
+ }
+
+ /**
+ * 新增测控一体机开关
+ */
+ @SaCheckPermission("fishery:deviceSwitch:add")
+ @Log(title = "测控一体机开关", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody DeviceSwitchBo bo) {
+ return toAjax(deviceSwitchService.insertByBo(bo));
+ }
+
+ /**
+ * 修改测控一体机开关
+ */
+ @SaCheckPermission("fishery:deviceSwitch:edit")
+ @Log(title = "测控一体机开关", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody DeviceSwitchBo bo) {
+ return toAjax(deviceSwitchService.updateByBo(bo));
+ }
+
+ /**
+ * 删除测控一体机开关
+ *
+ * @param ids 主键串
+ */
+ @SaCheckPermission("fishery:deviceSwitch:remove")
+ @Log(title = "测控一体机开关", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(deviceSwitchService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/PayDeviceController.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/PayDeviceController.java
new file mode 100644
index 0000000..27df701
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/PayDeviceController.java
@@ -0,0 +1,105 @@
+package org.dromara.fishery.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.fishery.domain.vo.PayDeviceVo;
+import org.dromara.fishery.domain.bo.PayDeviceBo;
+import org.dromara.fishery.service.IPayDeviceService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 设备充值记录
+ *
+ * @author intc
+ * @date 2025-10-16
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/fishery/payDevice")
+public class PayDeviceController extends BaseController {
+
+ private final IPayDeviceService payDeviceService;
+
+ /**
+ * 查询设备充值记录列表
+ */
+ @SaCheckPermission("fishery:payDevice:list")
+ @GetMapping("/list")
+ public TableDataInfo list(PayDeviceBo bo, PageQuery pageQuery) {
+ return payDeviceService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出设备充值记录列表
+ */
+ @SaCheckPermission("fishery:payDevice:export")
+ @Log(title = "设备充值记录", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(PayDeviceBo bo, HttpServletResponse response) {
+ List list = payDeviceService.queryList(bo);
+ ExcelUtil.exportExcel(list, "设备充值记录", PayDeviceVo.class, response);
+ }
+
+ /**
+ * 获取设备充值记录详细信息
+ *
+ * @param id 主键
+ */
+ @SaCheckPermission("fishery:payDevice:query")
+ @GetMapping("/{id}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(payDeviceService.queryById(id));
+ }
+
+ /**
+ * 新增设备充值记录
+ */
+ @SaCheckPermission("fishery:payDevice:add")
+ @Log(title = "设备充值记录", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody PayDeviceBo bo) {
+ return toAjax(payDeviceService.insertByBo(bo));
+ }
+
+ /**
+ * 修改设备充值记录
+ */
+ @SaCheckPermission("fishery:payDevice:edit")
+ @Log(title = "设备充值记录", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody PayDeviceBo bo) {
+ return toAjax(payDeviceService.updateByBo(bo));
+ }
+
+ /**
+ * 删除设备充值记录
+ *
+ * @param ids 主键串
+ */
+ @SaCheckPermission("fishery:payDevice:remove")
+ @Log(title = "设备充值记录", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(payDeviceService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/PayOrderController.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/PayOrderController.java
new file mode 100644
index 0000000..bfe6d03
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/PayOrderController.java
@@ -0,0 +1,105 @@
+package org.dromara.fishery.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.fishery.domain.vo.PayOrderVo;
+import org.dromara.fishery.domain.bo.PayOrderBo;
+import org.dromara.fishery.service.IPayOrderService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 充值订单
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/fishery/payOrder")
+public class PayOrderController extends BaseController {
+
+ private final IPayOrderService payOrderService;
+
+ /**
+ * 查询充值订单列表
+ */
+ @SaCheckPermission("fishery:payOrder:list")
+ @GetMapping("/list")
+ public TableDataInfo list(PayOrderBo bo, PageQuery pageQuery) {
+ return payOrderService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出充值订单列表
+ */
+ @SaCheckPermission("fishery:payOrder:export")
+ @Log(title = "充值订单", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(PayOrderBo bo, HttpServletResponse response) {
+ List list = payOrderService.queryList(bo);
+ ExcelUtil.exportExcel(list, "充值订单", PayOrderVo.class, response);
+ }
+
+ /**
+ * 获取充值订单详细信息
+ *
+ * @param id 主键
+ */
+ @SaCheckPermission("fishery:payOrder:query")
+ @GetMapping("/{id}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(payOrderService.queryById(id));
+ }
+
+ /**
+ * 新增充值订单
+ */
+ @SaCheckPermission("fishery:payOrder:add")
+ @Log(title = "充值订单", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody PayOrderBo bo) {
+ return toAjax(payOrderService.insertByBo(bo));
+ }
+
+ /**
+ * 修改充值订单
+ */
+ @SaCheckPermission("fishery:payOrder:edit")
+ @Log(title = "充值订单", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody PayOrderBo bo) {
+ return toAjax(payOrderService.updateByBo(bo));
+ }
+
+ /**
+ * 删除充值订单
+ *
+ * @param ids 主键串
+ */
+ @SaCheckPermission("fishery:payOrder:remove")
+ @Log(title = "充值订单", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(payOrderService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/UserRelationController.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/UserRelationController.java
new file mode 100644
index 0000000..d9b55d0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/controller/UserRelationController.java
@@ -0,0 +1,105 @@
+package org.dromara.fishery.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.fishery.domain.vo.UserRelationVo;
+import org.dromara.fishery.domain.bo.UserRelationBo;
+import org.dromara.fishery.service.IUserRelationService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 养殖用户子账号
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/fishery/userRelation")
+public class UserRelationController extends BaseController {
+
+ private final IUserRelationService userRelationService;
+
+ /**
+ * 查询养殖用户子账号列表
+ */
+ @SaCheckPermission("fishery:userRelation:list")
+ @GetMapping("/list")
+ public TableDataInfo list(UserRelationBo bo, PageQuery pageQuery) {
+ return userRelationService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出养殖用户子账号列表
+ */
+ @SaCheckPermission("fishery:userRelation:export")
+ @Log(title = "养殖用户子账号", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(UserRelationBo bo, HttpServletResponse response) {
+ List list = userRelationService.queryList(bo);
+ ExcelUtil.exportExcel(list, "养殖用户子账号", UserRelationVo.class, response);
+ }
+
+ /**
+ * 获取养殖用户子账号详细信息
+ *
+ * @param id 主键
+ */
+ @SaCheckPermission("fishery:userRelation:query")
+ @GetMapping("/{id}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(userRelationService.queryById(id));
+ }
+
+ /**
+ * 新增养殖用户子账号
+ */
+ @SaCheckPermission("fishery:userRelation:add")
+ @Log(title = "养殖用户子账号", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody UserRelationBo bo) {
+ return toAjax(userRelationService.insertByBo(bo));
+ }
+
+ /**
+ * 修改养殖用户子账号
+ */
+ @SaCheckPermission("fishery:userRelation:edit")
+ @Log(title = "养殖用户子账号", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody UserRelationBo bo) {
+ return toAjax(userRelationService.updateByBo(bo));
+ }
+
+ /**
+ * 删除养殖用户子账号
+ *
+ * @param ids 主键串
+ */
+ @SaCheckPermission("fishery:userRelation:remove")
+ @Log(title = "养殖用户子账号", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(userRelationService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/DeviceCorrectRecord.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/DeviceCorrectRecord.java
new file mode 100644
index 0000000..74ed9b4
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/DeviceCorrectRecord.java
@@ -0,0 +1,71 @@
+package org.dromara.fishery.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 设备校准记录对象 aqu_device_correct_record
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("aqu_device_correct_record")
+public class DeviceCorrectRecord extends TenantEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 设备id
+ */
+ private Long deviceId;
+
+ /**
+ * 用户id
+ */
+ private Long userId;
+
+ /**
+ * 设备序列号
+ */
+ private String serialNum;
+
+ /**
+ * 设备类型
+ */
+ private Integer deviceType;
+
+ /**
+ * 溶解氧
+ */
+ private Double valueDissolvedOxygen;
+
+ /**
+ * 水温
+ */
+ private Double valueTemperature;
+
+ /**
+ * 饱和度
+ */
+ private Double valueSaturability;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/DeviceErrorCode.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/DeviceErrorCode.java
new file mode 100644
index 0000000..94a5d28
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/DeviceErrorCode.java
@@ -0,0 +1,51 @@
+package org.dromara.fishery.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 设备故障码对象 aqu_device_error_code
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("aqu_device_error_code")
+public class DeviceErrorCode extends TenantEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 设备id
+ */
+ private Long deviceId;
+
+ /**
+ * 开关序号
+ */
+ private Integer switchIndex;
+
+ /**
+ * 故障码
+ */
+ private Integer errorCode;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/DeviceSwitch.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/DeviceSwitch.java
new file mode 100644
index 0000000..1d264ec
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/DeviceSwitch.java
@@ -0,0 +1,98 @@
+package org.dromara.fishery.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 测控一体机开关对象 aqu_device_switch
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("aqu_device_switch")
+public class DeviceSwitch extends TenantEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 设备id
+ */
+ private Long deviceId;
+
+ /**
+ * 序号
+ */
+ private Integer index;
+
+ /**
+ * 名称
+ */
+ private String switchName;
+
+ /**
+ * 当前测定电流
+ */
+ private Double detectElectricValue;
+
+ /**
+ * 当前测定电压
+ */
+ private Double detectVoltageValue;
+
+ /**
+ * 接线方式
+ */
+ private Integer connectVoltageType;
+
+ /**
+ * 塘口id
+ */
+ private Long pondId;
+
+ /**
+ * 额定电流设置
+ */
+ private Double rateElectricValue;
+
+ /**
+ * 当前开关状态
+ */
+ private Integer isOpen;
+
+ /**
+ * 联动控制id
+ */
+ private Long linkedCtrlId;
+
+ /**
+ * 电流告警开关
+ */
+ private Integer electricWarnOpen;
+
+ /**
+ * 上次操作开关时间
+ */
+ private Date lastTurnTime;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/PayDevice.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/PayDevice.java
new file mode 100644
index 0000000..a2a426a
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/PayDevice.java
@@ -0,0 +1,83 @@
+package org.dromara.fishery.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 设备充值记录对象 aqu_pay_device
+ *
+ * @author intc
+ * @date 2025-10-16
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("aqu_pay_device")
+public class PayDevice extends TenantEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 用户Id
+ */
+ private Long userId;
+
+ /**
+ * 设备编号
+ */
+ private String serialNum;
+
+ /**
+ * 设备类型
+ */
+ private Integer deviceType;
+
+ /**
+ * 续费时长(月)
+ */
+ private Integer addMonth;
+
+ /**
+ * 最新到期时间
+ */
+ private Date deadTime;
+
+ /**
+ * 续费金额(分)
+ */
+ private Integer payAmount;
+
+ /**
+ * 订单id
+ */
+ private Long orderId;
+
+ /**
+ * 续费方式
+ */
+ private Integer payType;
+
+ /**
+ * 分润状态
+ */
+ private Integer profitStatus;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/PayOrder.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/PayOrder.java
new file mode 100644
index 0000000..9d836d5
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/PayOrder.java
@@ -0,0 +1,148 @@
+package org.dromara.fishery.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 充值订单对象 aqu_pay_order
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("aqu_pay_order")
+public class PayOrder extends TenantEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 用户id
+ */
+ private Long userId;
+
+ /**
+ * 充值总金额(分)
+ */
+ private Integer totalAmount;
+
+ /**
+ * 有效期增加月数
+ */
+ private Integer addMonth;
+
+ /**
+ * 附加数据
+ */
+ private String attachment;
+
+ /**
+ * 付款银行类型
+ */
+ private String bankType;
+
+ /**
+ * 币种
+ */
+ private String currency;
+
+ /**
+ * 订单描述
+ */
+ private String description;
+
+ /**
+ * 设备数量
+ */
+ private Long deviceCount;
+
+ /**
+ * 支付的设备编号,json格式
+ */
+ private String isonDeviceSerialNum;
+
+ /**
+ * 支付回调通知URL
+ */
+ private String notifyUrl;
+
+ /**
+ * 商户系统内部订单号
+ */
+ private String outTradeNumber;
+
+ /**
+ * 用户支付币种
+ */
+ private String payerCurrency;
+
+ /**
+ * 用户支付金额(分)
+ */
+ private Integer payerTotal;
+
+ /**
+ * 微信预交易订单号
+ */
+ private String prepayId;
+
+ /**
+ * 支付完成时间
+ */
+ private Date successTime;
+
+ /**
+ * 交易状态
+ */
+ private String tradeState;
+
+ /**
+ * 交易状态描述
+ */
+ private String tradeStateDescription;
+
+ /**
+ * 交易类型
+ */
+ private String tradeType;
+
+ /**
+ * 微信支付订单号
+ */
+ private String transactionId;
+
+ /**
+ * 用户开放id
+ */
+ private String wxOpenId;
+
+ /**
+ * 订单状态
+ */
+ private Integer orderStatus;
+
+ /**
+ * 分润状态
+ */
+ private Integer profitStatus;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/UserRelation.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/UserRelation.java
new file mode 100644
index 0000000..bd47c3c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/UserRelation.java
@@ -0,0 +1,46 @@
+package org.dromara.fishery.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 养殖用户子账号对象 aqu_user_relation
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("aqu_user_relation")
+public class UserRelation extends TenantEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 父级账号id
+ */
+ private Long parentUserId;
+
+ /**
+ * 子账号id
+ */
+ private Long childUserId;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/DeviceCorrectRecordBo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/DeviceCorrectRecordBo.java
new file mode 100644
index 0000000..2cd9147
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/DeviceCorrectRecordBo.java
@@ -0,0 +1,75 @@
+package org.dromara.fishery.domain.bo;
+
+import org.dromara.fishery.domain.DeviceCorrectRecord;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 设备校准记录业务对象 aqu_device_correct_record
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceCorrectRecord.class, reverseConvertGenerate = false)
+public class DeviceCorrectRecordBo extends BaseEntity {
+
+ /**
+ * 主键id
+ */
+ @NotNull(message = "主键id不能为空", groups = { EditGroup.class })
+ private Long id;
+
+ /**
+ * 设备id
+ */
+ private Long deviceId;
+
+ /**
+ * 用户id
+ */
+ private Long userId;
+
+ /**
+ * 设备序列号
+ */
+ @NotBlank(message = "设备序列号不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String serialNum;
+
+ /**
+ * 设备类型
+ */
+ @NotNull(message = "设备类型不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer deviceType;
+
+ /**
+ * 溶解氧
+ */
+ @NotNull(message = "溶解氧不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Double valueDissolvedOxygen;
+
+ /**
+ * 水温
+ */
+ @NotNull(message = "水温不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Double valueTemperature;
+
+ /**
+ * 饱和度
+ */
+ @NotNull(message = "饱和度不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Double valueSaturability;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/DeviceErrorCodeBo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/DeviceErrorCodeBo.java
new file mode 100644
index 0000000..9e83811
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/DeviceErrorCodeBo.java
@@ -0,0 +1,53 @@
+package org.dromara.fishery.domain.bo;
+
+import org.dromara.fishery.domain.DeviceErrorCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 设备故障码业务对象 aqu_device_error_code
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceErrorCode.class, reverseConvertGenerate = false)
+public class DeviceErrorCodeBo extends BaseEntity {
+
+ /**
+ * 主键id
+ */
+ @NotNull(message = "主键id不能为空", groups = { EditGroup.class })
+ private Long id;
+
+ /**
+ * 设备id
+ */
+ @NotNull(message = "设备id不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Long deviceId;
+
+ /**
+ * 开关序号
+ */
+ @NotNull(message = "开关序号不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer switchIndex;
+
+ /**
+ * 故障码
+ */
+ @NotNull(message = "故障码不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer errorCode;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/DeviceSwitchBo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/DeviceSwitchBo.java
new file mode 100644
index 0000000..d978d35
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/DeviceSwitchBo.java
@@ -0,0 +1,107 @@
+package org.dromara.fishery.domain.bo;
+
+import org.dromara.fishery.domain.DeviceSwitch;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 测控一体机开关业务对象 aqu_device_switch
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = DeviceSwitch.class, reverseConvertGenerate = false)
+public class DeviceSwitchBo extends BaseEntity {
+
+ /**
+ * 主键id
+ */
+ @NotNull(message = "主键id不能为空", groups = { EditGroup.class })
+ private Long id;
+
+ /**
+ * 设备id
+ */
+ @NotNull(message = "设备id不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Long deviceId;
+
+ /**
+ * 序号
+ */
+ @NotNull(message = "序号不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer index;
+
+ /**
+ * 名称
+ */
+ @NotBlank(message = "名称不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String switchName;
+
+ /**
+ * 当前测定电流
+ */
+ @NotNull(message = "当前测定电流不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Double detectElectricValue;
+
+ /**
+ * 当前测定电压
+ */
+ @NotNull(message = "当前测定电压不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Double detectVoltageValue;
+
+ /**
+ * 接线方式
+ */
+ @NotNull(message = "接线方式不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer connectVoltageType;
+
+ /**
+ * 塘口id
+ */
+ private Long pondId;
+
+ /**
+ * 额定电流设置
+ */
+ @NotNull(message = "额定电流设置不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Double rateElectricValue;
+
+ /**
+ * 当前开关状态
+ */
+ @NotNull(message = "当前开关状态不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer isOpen;
+
+ /**
+ * 联动控制id
+ */
+ private Long linkedCtrlId;
+
+ /**
+ * 电流告警开关
+ */
+ @NotNull(message = "电流告警开关不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer electricWarnOpen;
+
+ /**
+ * 上次操作开关时间
+ */
+ @NotNull(message = "上次操作开关时间不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Date lastTurnTime;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/PayDeviceBo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/PayDeviceBo.java
new file mode 100644
index 0000000..c94c317
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/PayDeviceBo.java
@@ -0,0 +1,89 @@
+package org.dromara.fishery.domain.bo;
+
+import org.dromara.fishery.domain.PayDevice;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 设备充值记录业务对象 aqu_pay_device
+ *
+ * @author intc
+ * @date 2025-10-16
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = PayDevice.class, reverseConvertGenerate = false)
+public class PayDeviceBo extends BaseEntity {
+
+ /**
+ * 主键id
+ */
+// @NotNull(message = "主键id不能为空", groups = { EditGroup.class })
+ private Long id;
+
+ /**
+ * 用户Id
+ */
+// @NotNull(message = "用户Id不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Long userId;
+
+ /**
+ * 设备编号
+ */
+ @NotBlank(message = "设备编号不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String serialNum;
+
+ /**
+ * 设备类型
+ */
+ @NotNull(message = "设备类型不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer deviceType;
+
+ /**
+ * 续费时长(月)
+ */
+// @NotNull(message = "续费时长(月)不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer addMonth;
+
+ /**
+ * 最新到期时间
+ */
+ @NotNull(message = "最新到期时间不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Date deadTime;
+
+ /**
+ * 续费金额(分)
+ */
+// @NotNull(message = "续费金额(分)不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer payAmount;
+
+ /**
+ * 订单id
+ */
+ private Long orderId;
+
+ /**
+ * 续费方式
+ */
+// @NotNull(message = "续费方式不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer payType;
+
+ /**
+ * 分润状态
+ */
+ private Integer profitStatus;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/PayOrderBo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/PayOrderBo.java
new file mode 100644
index 0000000..79b9e18
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/PayOrderBo.java
@@ -0,0 +1,156 @@
+package org.dromara.fishery.domain.bo;
+
+import org.dromara.fishery.domain.PayOrder;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 充值订单业务对象 aqu_pay_order
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = PayOrder.class, reverseConvertGenerate = false)
+public class PayOrderBo extends BaseEntity {
+
+ /**
+ * 主键id
+ */
+ @NotNull(message = "主键id不能为空", groups = { EditGroup.class })
+ private Long id;
+
+ /**
+ * 用户id
+ */
+ @NotNull(message = "用户id不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Long userId;
+
+ /**
+ * 充值总金额(分)
+ */
+ @NotNull(message = "充值总金额(分)不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer totalAmount;
+
+ /**
+ * 有效期增加月数
+ */
+ @NotNull(message = "有效期增加月数不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Integer addMonth;
+
+ /**
+ * 附加数据
+ */
+ private String attachment;
+
+ /**
+ * 付款银行类型
+ */
+ private String bankType;
+
+ /**
+ * 币种
+ */
+ private String currency;
+
+ /**
+ * 订单描述
+ */
+ @NotBlank(message = "订单描述不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String description;
+
+ /**
+ * 设备数量
+ */
+ @NotNull(message = "设备数量不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Long deviceCount;
+
+ /**
+ * 支付的设备编号,json格式
+ */
+ @NotBlank(message = "支付的设备编号,json格式不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String isonDeviceSerialNum;
+
+ /**
+ * 支付回调通知URL
+ */
+ @NotBlank(message = "支付回调通知URL不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String notifyUrl;
+
+ /**
+ * 商户系统内部订单号
+ */
+ @NotBlank(message = "商户系统内部订单号不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String outTradeNumber;
+
+ /**
+ * 用户支付币种
+ */
+ private String payerCurrency;
+
+ /**
+ * 用户支付金额(分)
+ */
+ private Integer payerTotal;
+
+ /**
+ * 微信预交易订单号
+ */
+ @NotBlank(message = "微信预交易订单号不能为空", groups = { AddGroup.class, EditGroup.class })
+ private String prepayId;
+
+ /**
+ * 支付完成时间
+ */
+ private Date successTime;
+
+ /**
+ * 交易状态
+ */
+ private String tradeState;
+
+ /**
+ * 交易状态描述
+ */
+ private String tradeStateDescription;
+
+ /**
+ * 交易类型
+ */
+ private String tradeType;
+
+ /**
+ * 微信支付订单号
+ */
+ private String transactionId;
+
+ /**
+ * 用户开放id
+ */
+ private String wxOpenId;
+
+ /**
+ * 订单状态
+ */
+ private Integer orderStatus;
+
+ /**
+ * 分润状态
+ */
+ private Integer profitStatus;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/UserRelationBo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/UserRelationBo.java
new file mode 100644
index 0000000..730199e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/bo/UserRelationBo.java
@@ -0,0 +1,47 @@
+package org.dromara.fishery.domain.bo;
+
+import org.dromara.fishery.domain.UserRelation;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 养殖用户子账号业务对象 aqu_user_relation
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = UserRelation.class, reverseConvertGenerate = false)
+public class UserRelationBo extends BaseEntity {
+
+ /**
+ * 主键id
+ */
+ @NotNull(message = "主键id不能为空", groups = { EditGroup.class })
+ private Long id;
+
+ /**
+ * 父级账号id
+ */
+ @NotNull(message = "父级账号id不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Long parentUserId;
+
+ /**
+ * 子账号id
+ */
+ @NotNull(message = "子账号id不能为空", groups = { AddGroup.class, EditGroup.class })
+ private Long childUserId;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/DeviceCorrectRecordVo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/DeviceCorrectRecordVo.java
new file mode 100644
index 0000000..09ff73b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/DeviceCorrectRecordVo.java
@@ -0,0 +1,116 @@
+package org.dromara.fishery.domain.vo;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.common.json.handler.DoubleSerializer;
+import org.dromara.fishery.domain.DeviceCorrectRecord;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+
+
+/**
+ * 设备校准记录视图对象 aqu_device_correct_record
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = DeviceCorrectRecord.class)
+public class DeviceCorrectRecordVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @ExcelProperty(value = "主键id")
+ private Long id;
+
+ /**
+ * 设备id
+ */
+ @ExcelProperty(value = "设备id")
+ private Long deviceId;
+
+ /**
+ * 用户id
+ */
+ @ExcelProperty(value = "用户id")
+ private Long userId;
+
+ /**
+ * 设备序列号
+ */
+ @ExcelProperty(value = "设备序列号")
+ private String serialNum;
+
+ /**
+ * 设备类型
+ */
+ @ExcelProperty(value = "设备类型", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "aqu_device_type")
+ private Integer deviceType;
+
+ /**
+ * 溶解氧
+ */
+ @ExcelProperty(value = "溶解氧")
+ @JsonSerialize(using = DoubleSerializer.class)
+ private Double valueDissolvedOxygen;
+
+ /**
+ * 水温
+ */
+ @ExcelProperty(value = "水温")
+ @JsonSerialize(using = DoubleSerializer.class)
+ private Double valueTemperature;
+
+ /**
+ * 饱和度
+ */
+ @ExcelProperty(value = "饱和度")
+ @JsonSerialize(using = DoubleSerializer.class)
+ private Double valueSaturability;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+ /**
+ * 用户名
+ */
+ @ExcelProperty(value = "用户名")
+ private String userName;
+
+ /**
+ * 手机号
+ */
+ @ExcelProperty(value = "手机号")
+ private String mobilePhone;
+
+ /**
+ * 设备名称
+ */
+ @ExcelProperty(value = "设备名称")
+ private String deviceName;
+
+
+ private Date createTime;
+
+ private Date updateTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/DeviceErrorCodeVo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/DeviceErrorCodeVo.java
new file mode 100644
index 0000000..19b1a93
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/DeviceErrorCodeVo.java
@@ -0,0 +1,96 @@
+package org.dromara.fishery.domain.vo;
+
+import org.dromara.fishery.domain.DeviceErrorCode;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 设备故障码视图对象 aqu_device_error_code
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = DeviceErrorCode.class)
+public class DeviceErrorCodeVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @ExcelProperty(value = "主键id")
+ private Long id;
+
+ /**
+ * 设备id
+ */
+ @ExcelProperty(value = "设备id")
+ private Long deviceId;
+
+ /**
+ * 开关序号
+ */
+ @ExcelProperty(value = "开关序号")
+ private Integer switchIndex;
+
+ /**
+ * 开关名称
+ */
+ @ExcelProperty(value = "开关名称")
+ private String switchName;
+
+ /**
+ * 故障码
+ */
+ @ExcelProperty(value = "故障码")
+ private Integer errorCode;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+ /**
+ * 设备名称
+ */
+ @ExcelProperty(value = "设备名称")
+ private String deviceName;
+
+ /**
+ * 设备编号
+ */
+ @ExcelProperty(value = "设备编号")
+ private String serialNum;
+
+ /**
+ * 用户名
+ */
+ @ExcelProperty(value = "用户名")
+ private String userName;
+
+ /**
+ * 手机号
+ */
+ @ExcelProperty(value = "手机号")
+ private String mobilePhone;
+
+ private Date createTime;
+
+ private Date updateTime;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/DeviceSwitchVo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/DeviceSwitchVo.java
new file mode 100644
index 0000000..dfc55f0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/DeviceSwitchVo.java
@@ -0,0 +1,143 @@
+package org.dromara.fishery.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.dromara.common.json.handler.DoubleSerializer;
+import org.dromara.fishery.domain.DeviceSwitch;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 测控一体机开关视图对象 aqu_device_switch
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = DeviceSwitch.class)
+public class DeviceSwitchVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @ExcelProperty(value = "主键id")
+ private Long id;
+
+ /**
+ * 设备id
+ */
+ @ExcelProperty(value = "设备id")
+ private Long deviceId;
+
+ /**
+ * 序号
+ */
+ @ExcelProperty(value = "序号")
+ private Integer index;
+
+ /**
+ * 名称
+ */
+ @ExcelProperty(value = "名称")
+ private String switchName;
+
+ /**
+ * 当前测定电流
+ */
+ @ExcelProperty(value = "当前测定电流")
+ @JsonSerialize(using = DoubleSerializer.class)
+ private Double detectElectricValue;
+
+ /**
+ * 当前测定电压
+ */
+ @ExcelProperty(value = "当前测定电压")
+ @JsonSerialize(using = DoubleSerializer.class)
+ private Double detectVoltageValue;
+
+ /**
+ * 接线方式
+ */
+ @ExcelProperty(value = "接线方式")
+ private Integer connectVoltageType;
+
+ /**
+ * 塘口id
+ */
+ @ExcelProperty(value = "塘口id")
+ private Long pondId;
+
+ /**
+ * 额定电流设置
+ */
+ @ExcelProperty(value = "额定电流设置")
+ private Double rateElectricValue;
+
+ /**
+ * 当前开关状态
+ */
+ @ExcelProperty(value = "当前开关状态")
+ private Integer isOpen;
+
+ /**
+ * 电流告警开关
+ */
+ @ExcelProperty(value = "电流告警开关")
+ private Integer electricWarnOpen;
+
+ /**
+ * 上次操作开关时间
+ */
+ @ExcelProperty(value = "上次操作开关时间")
+ private Date lastTurnTime;
+
+ /**
+ * 联动控制id
+ */
+ private Long linkedCtrlId;
+
+ /**
+ * 设备名称
+ */
+ @ExcelProperty(value = "设备名称")
+ private String deviceName;
+
+ /**
+ * 设备编号
+ */
+ @ExcelProperty(value = "设备编号")
+ private String serialNum;
+
+ /**
+ * 塘口名称
+ */
+ @ExcelProperty(value = "塘口名称")
+ private String pondName;
+
+ /**
+ * 是否有联动控制(0-否,1-是)
+ */
+ @ExcelProperty(value = "是否联动控制")
+ private Integer isLinkedCtrl;
+
+
+ private Date createTime;
+
+ private Date updateTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/PayDeviceVo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/PayDeviceVo.java
new file mode 100644
index 0000000..1418216
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/PayDeviceVo.java
@@ -0,0 +1,111 @@
+package org.dromara.fishery.domain.vo;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.fishery.domain.PayDevice;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+
+
+/**
+ * 设备充值记录视图对象 aqu_pay_device
+ *
+ * @author intc
+ * @date 2025-10-16
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = PayDevice.class)
+public class PayDeviceVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 用户Id
+ */
+ @ExcelProperty(value = "用户Id")
+ private Long userId;
+
+ /**
+ * 设备编号
+ */
+ @ExcelProperty(value = "设备编号")
+ private String serialNum;
+
+ /**
+ * 设备类型
+ */
+ @ExcelProperty(value = "设备类型", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "aqu_device_type")
+ private Integer deviceType;
+
+ /**
+ * 续费时长(月)
+ */
+ @ExcelProperty(value = "续费时长", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "月=")
+ private Integer addMonth;
+
+ /**
+ * 最新到期时间
+ */
+ @ExcelProperty(value = "最新到期时间")
+ private Date deadTime;
+
+ /**
+ * 续费金额(分)
+ */
+ @ExcelProperty(value = "续费金额", converter = ExcelDictConvert.class)
+ private Integer payAmount;
+
+ /**
+ * 续费金额(元)
+ */
+ @ExcelProperty(value = "续费金额(元)")
+ private Double payAmountYuan;
+
+ /**
+ * 续费方式
+ */
+ @ExcelProperty(value = "续费方式", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "pay_type")
+ private Integer payType;
+
+ /**
+ * 分润状态
+ */
+ @ExcelProperty(value = "分润状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "profit_status")
+ private Integer profitStatus;
+
+ /**
+ * 用户名
+ */
+ @ExcelProperty(value = "用户名")
+ private String userName;
+
+ /**
+ * 手机号
+ */
+ @ExcelProperty(value = "手机号")
+ private String mobilePhone;
+
+ /**
+ * 订单id
+ */
+ private Long orderId;
+
+ private Date createTime;
+
+ private Date updateTime;
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/PayOrderVo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/PayOrderVo.java
new file mode 100644
index 0000000..5adcb43
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/PayOrderVo.java
@@ -0,0 +1,119 @@
+package org.dromara.fishery.domain.vo;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.fishery.domain.PayOrder;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+
+
+/**
+ * 充值订单视图对象 aqu_pay_order
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = PayOrder.class)
+public class PayOrderVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+// @ExcelProperty(value = "主键id")
+ private Long id;
+
+ /**
+ * 用户id
+ */
+// @ExcelProperty(value = "用户id")
+ private Long userId;
+
+ /**
+ * 充值总金额(分)
+ */
+// @ExcelProperty(value = "充值总金额", converter = ExcelDictConvert.class)
+ private Integer totalAmount;
+
+ /**
+ * 用户名
+ */
+ @ExcelProperty(value = "用户名")
+ private String userName;
+
+ /**
+ * 手机号
+ */
+ @ExcelProperty(value = "手机号")
+ private String mobilePhone;
+
+ /**
+ * 充值总金额(元)
+ */
+ @ExcelProperty(value = "充值总金额(元)")
+ private Double totalAmountYuan;
+
+ /**
+ * 有效期增加月数
+ */
+ @ExcelProperty(value = "有效期增加月数")
+ private Integer addMonth;
+
+ /**
+ * 设备数量
+ */
+ @ExcelProperty(value = "设备数量")
+ private Long deviceCount;
+
+ /**
+ * 用户支付金额(分)
+ */
+// @ExcelProperty(value = "用户支付金额", converter = ExcelDictConvert.class)
+ private Integer payerTotal;
+
+ /**
+ * 用户支付金额(元)
+ */
+ @ExcelProperty(value = "用户支付金额(元)")
+ private Double payerTotalYuan;
+
+ /**
+ * 支付完成时间
+ */
+ @ExcelProperty(value = "支付完成时间")
+ private Date successTime;
+
+ /**
+ * 订单状态
+ */
+ @ExcelProperty(value = "订单状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "order_status")
+ private Integer orderStatus;
+
+ /**
+ * 分润状态
+ */
+ @ExcelProperty(value = "分润状态", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(dictType = "profit_status")
+ private Integer profitStatus;
+
+
+ @ExcelProperty(value = "创建时间")
+ private Date createTime;
+
+ private Date updateTime;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/UserRelationVo.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/UserRelationVo.java
new file mode 100644
index 0000000..38c8d46
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/domain/vo/UserRelationVo.java
@@ -0,0 +1,56 @@
+package org.dromara.fishery.domain.vo;
+
+import org.dromara.fishery.domain.UserRelation;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 养殖用户子账号视图对象 aqu_user_relation
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = UserRelation.class)
+public class UserRelationVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @ExcelProperty(value = "主键id")
+ private Long id;
+
+ /**
+ * 父级账号id
+ */
+ @ExcelProperty(value = "父级账号id")
+ private Long parentUserId;
+
+ /**
+ * 子账号id
+ */
+ @ExcelProperty(value = "子账号id")
+ private Long childUserId;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/DeviceCorrectRecordMapper.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/DeviceCorrectRecordMapper.java
new file mode 100644
index 0000000..748d29b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/DeviceCorrectRecordMapper.java
@@ -0,0 +1,15 @@
+package org.dromara.fishery.mapper;
+
+import org.dromara.fishery.domain.DeviceCorrectRecord;
+import org.dromara.fishery.domain.vo.DeviceCorrectRecordVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlusJoin;
+
+/**
+ * 设备校准记录Mapper接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface DeviceCorrectRecordMapper extends BaseMapperPlusJoin {
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/DeviceErrorCodeMapper.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/DeviceErrorCodeMapper.java
new file mode 100644
index 0000000..3362c9d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/DeviceErrorCodeMapper.java
@@ -0,0 +1,15 @@
+package org.dromara.fishery.mapper;
+
+import org.dromara.fishery.domain.DeviceErrorCode;
+import org.dromara.fishery.domain.vo.DeviceErrorCodeVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlusJoin;
+
+/**
+ * 设备故障码Mapper接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface DeviceErrorCodeMapper extends BaseMapperPlusJoin {
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/DeviceSwitchMapper.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/DeviceSwitchMapper.java
new file mode 100644
index 0000000..1289936
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/DeviceSwitchMapper.java
@@ -0,0 +1,15 @@
+package org.dromara.fishery.mapper;
+
+import org.dromara.fishery.domain.DeviceSwitch;
+import org.dromara.fishery.domain.vo.DeviceSwitchVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlusJoin;
+
+/**
+ * 测控一体机开关Mapper接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface DeviceSwitchMapper extends BaseMapperPlusJoin {
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/FishMapper.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/FishMapper.java
index 41455de..2ebebe7 100644
--- a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/FishMapper.java
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/FishMapper.java
@@ -1,5 +1,6 @@
package org.dromara.fishery.mapper;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlusJoin;
import org.dromara.fishery.domain.Fish;
import org.dromara.fishery.domain.vo.FishVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/PayDeviceMapper.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/PayDeviceMapper.java
new file mode 100644
index 0000000..8020dca
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/PayDeviceMapper.java
@@ -0,0 +1,16 @@
+package org.dromara.fishery.mapper;
+
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlusJoin;
+import org.dromara.fishery.domain.PayDevice;
+import org.dromara.fishery.domain.vo.PayDeviceVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 设备充值记录Mapper接口
+ *
+ * @author intc
+ * @date 2025-10-16
+ */
+public interface PayDeviceMapper extends BaseMapperPlusJoin {
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/PayOrderMapper.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/PayOrderMapper.java
new file mode 100644
index 0000000..2e7437a
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/PayOrderMapper.java
@@ -0,0 +1,16 @@
+package org.dromara.fishery.mapper;
+
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlusJoin;
+import org.dromara.fishery.domain.PayOrder;
+import org.dromara.fishery.domain.vo.PayOrderVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 充值订单Mapper接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface PayOrderMapper extends BaseMapperPlusJoin {
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/UserRelationMapper.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/UserRelationMapper.java
new file mode 100644
index 0000000..248ffd5
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/mapper/UserRelationMapper.java
@@ -0,0 +1,15 @@
+package org.dromara.fishery.mapper;
+
+import org.dromara.fishery.domain.UserRelation;
+import org.dromara.fishery.domain.vo.UserRelationVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 养殖用户子账号Mapper接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface UserRelationMapper extends BaseMapperPlus {
+
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IDeviceCorrectRecordService.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IDeviceCorrectRecordService.java
new file mode 100644
index 0000000..3fc34eb
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IDeviceCorrectRecordService.java
@@ -0,0 +1,68 @@
+package org.dromara.fishery.service;
+
+import org.dromara.fishery.domain.vo.DeviceCorrectRecordVo;
+import org.dromara.fishery.domain.bo.DeviceCorrectRecordBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 设备校准记录Service接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface IDeviceCorrectRecordService {
+
+ /**
+ * 查询设备校准记录
+ *
+ * @param id 主键
+ * @return 设备校准记录
+ */
+ DeviceCorrectRecordVo queryById(Long id);
+
+ /**
+ * 分页查询设备校准记录列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 设备校准记录分页列表
+ */
+ TableDataInfo queryPageList(DeviceCorrectRecordBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询符合条件的设备校准记录列表
+ *
+ * @param bo 查询条件
+ * @return 设备校准记录列表
+ */
+ List queryList(DeviceCorrectRecordBo bo);
+
+ /**
+ * 新增设备校准记录
+ *
+ * @param bo 设备校准记录
+ * @return 是否新增成功
+ */
+ Boolean insertByBo(DeviceCorrectRecordBo bo);
+
+ /**
+ * 修改设备校准记录
+ *
+ * @param bo 设备校准记录
+ * @return 是否修改成功
+ */
+ Boolean updateByBo(DeviceCorrectRecordBo bo);
+
+ /**
+ * 校验并批量删除设备校准记录信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IDeviceErrorCodeService.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IDeviceErrorCodeService.java
new file mode 100644
index 0000000..e7d02ce
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IDeviceErrorCodeService.java
@@ -0,0 +1,68 @@
+package org.dromara.fishery.service;
+
+import org.dromara.fishery.domain.vo.DeviceErrorCodeVo;
+import org.dromara.fishery.domain.bo.DeviceErrorCodeBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 设备故障码Service接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface IDeviceErrorCodeService {
+
+ /**
+ * 查询设备故障码
+ *
+ * @param id 主键
+ * @return 设备故障码
+ */
+ DeviceErrorCodeVo queryById(Long id);
+
+ /**
+ * 分页查询设备故障码列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 设备故障码分页列表
+ */
+ TableDataInfo queryPageList(DeviceErrorCodeBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询符合条件的设备故障码列表
+ *
+ * @param bo 查询条件
+ * @return 设备故障码列表
+ */
+ List queryList(DeviceErrorCodeBo bo);
+
+ /**
+ * 新增设备故障码
+ *
+ * @param bo 设备故障码
+ * @return 是否新增成功
+ */
+ Boolean insertByBo(DeviceErrorCodeBo bo);
+
+ /**
+ * 修改设备故障码
+ *
+ * @param bo 设备故障码
+ * @return 是否修改成功
+ */
+ Boolean updateByBo(DeviceErrorCodeBo bo);
+
+ /**
+ * 校验并批量删除设备故障码信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IDeviceSwitchService.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IDeviceSwitchService.java
new file mode 100644
index 0000000..1767e8f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IDeviceSwitchService.java
@@ -0,0 +1,68 @@
+package org.dromara.fishery.service;
+
+import org.dromara.fishery.domain.vo.DeviceSwitchVo;
+import org.dromara.fishery.domain.bo.DeviceSwitchBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 测控一体机开关Service接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface IDeviceSwitchService {
+
+ /**
+ * 查询测控一体机开关
+ *
+ * @param id 主键
+ * @return 测控一体机开关
+ */
+ DeviceSwitchVo queryById(Long id);
+
+ /**
+ * 分页查询测控一体机开关列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 测控一体机开关分页列表
+ */
+ TableDataInfo queryPageList(DeviceSwitchBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询符合条件的测控一体机开关列表
+ *
+ * @param bo 查询条件
+ * @return 测控一体机开关列表
+ */
+ List queryList(DeviceSwitchBo bo);
+
+ /**
+ * 新增测控一体机开关
+ *
+ * @param bo 测控一体机开关
+ * @return 是否新增成功
+ */
+ Boolean insertByBo(DeviceSwitchBo bo);
+
+ /**
+ * 修改测控一体机开关
+ *
+ * @param bo 测控一体机开关
+ * @return 是否修改成功
+ */
+ Boolean updateByBo(DeviceSwitchBo bo);
+
+ /**
+ * 校验并批量删除测控一体机开关信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IPayDeviceService.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IPayDeviceService.java
new file mode 100644
index 0000000..5258e8b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IPayDeviceService.java
@@ -0,0 +1,68 @@
+package org.dromara.fishery.service;
+
+import org.dromara.fishery.domain.vo.PayDeviceVo;
+import org.dromara.fishery.domain.bo.PayDeviceBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 设备充值记录Service接口
+ *
+ * @author intc
+ * @date 2025-10-16
+ */
+public interface IPayDeviceService {
+
+ /**
+ * 查询设备充值记录
+ *
+ * @param id 主键
+ * @return 设备充值记录
+ */
+ PayDeviceVo queryById(Long id);
+
+ /**
+ * 分页查询设备充值记录列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 设备充值记录分页列表
+ */
+ TableDataInfo queryPageList(PayDeviceBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询符合条件的设备充值记录列表
+ *
+ * @param bo 查询条件
+ * @return 设备充值记录列表
+ */
+ List queryList(PayDeviceBo bo);
+
+ /**
+ * 新增设备充值记录
+ *
+ * @param bo 设备充值记录
+ * @return 是否新增成功
+ */
+ Boolean insertByBo(PayDeviceBo bo);
+
+ /**
+ * 修改设备充值记录
+ *
+ * @param bo 设备充值记录
+ * @return 是否修改成功
+ */
+ Boolean updateByBo(PayDeviceBo bo);
+
+ /**
+ * 校验并批量删除设备充值记录信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IPayOrderService.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IPayOrderService.java
new file mode 100644
index 0000000..786422f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IPayOrderService.java
@@ -0,0 +1,68 @@
+package org.dromara.fishery.service;
+
+import org.dromara.fishery.domain.vo.PayOrderVo;
+import org.dromara.fishery.domain.bo.PayOrderBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 充值订单Service接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface IPayOrderService {
+
+ /**
+ * 查询充值订单
+ *
+ * @param id 主键
+ * @return 充值订单
+ */
+ PayOrderVo queryById(Long id);
+
+ /**
+ * 分页查询充值订单列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 充值订单分页列表
+ */
+ TableDataInfo queryPageList(PayOrderBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询符合条件的充值订单列表
+ *
+ * @param bo 查询条件
+ * @return 充值订单列表
+ */
+ List queryList(PayOrderBo bo);
+
+ /**
+ * 新增充值订单
+ *
+ * @param bo 充值订单
+ * @return 是否新增成功
+ */
+ Boolean insertByBo(PayOrderBo bo);
+
+ /**
+ * 修改充值订单
+ *
+ * @param bo 充值订单
+ * @return 是否修改成功
+ */
+ Boolean updateByBo(PayOrderBo bo);
+
+ /**
+ * 校验并批量删除充值订单信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IUserRelationService.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IUserRelationService.java
new file mode 100644
index 0000000..f96cb2e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/IUserRelationService.java
@@ -0,0 +1,68 @@
+package org.dromara.fishery.service;
+
+import org.dromara.fishery.domain.vo.UserRelationVo;
+import org.dromara.fishery.domain.bo.UserRelationBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 养殖用户子账号Service接口
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+public interface IUserRelationService {
+
+ /**
+ * 查询养殖用户子账号
+ *
+ * @param id 主键
+ * @return 养殖用户子账号
+ */
+ UserRelationVo queryById(Long id);
+
+ /**
+ * 分页查询养殖用户子账号列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 养殖用户子账号分页列表
+ */
+ TableDataInfo queryPageList(UserRelationBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询符合条件的养殖用户子账号列表
+ *
+ * @param bo 查询条件
+ * @return 养殖用户子账号列表
+ */
+ List queryList(UserRelationBo bo);
+
+ /**
+ * 新增养殖用户子账号
+ *
+ * @param bo 养殖用户子账号
+ * @return 是否新增成功
+ */
+ Boolean insertByBo(UserRelationBo bo);
+
+ /**
+ * 修改养殖用户子账号
+ *
+ * @param bo 养殖用户子账号
+ * @return 是否修改成功
+ */
+ Boolean updateByBo(UserRelationBo bo);
+
+ /**
+ * 校验并批量删除养殖用户子账号信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/DeviceCorrectRecordServiceImpl.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/DeviceCorrectRecordServiceImpl.java
new file mode 100644
index 0000000..48751fe
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/DeviceCorrectRecordServiceImpl.java
@@ -0,0 +1,181 @@
+package org.dromara.fishery.service.impl;
+
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.fishery.domain.bo.DeviceCorrectRecordBo;
+import org.dromara.fishery.domain.vo.DeviceCorrectRecordVo;
+import org.dromara.fishery.domain.DeviceCorrectRecord;
+import org.dromara.fishery.domain.AquUser;
+import org.dromara.fishery.domain.Device;
+import org.dromara.fishery.mapper.DeviceCorrectRecordMapper;
+import org.dromara.fishery.service.IDeviceCorrectRecordService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 设备校准记录Service业务层处理
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class DeviceCorrectRecordServiceImpl implements IDeviceCorrectRecordService {
+
+ private final DeviceCorrectRecordMapper baseMapper;
+
+ /**
+ * 查询设备校准记录
+ *
+ * @param id 主键
+ * @return 设备校准记录
+ */
+ @Override
+ public DeviceCorrectRecordVo queryById(Long id){
+ return baseMapper.selectVoById(id);
+ }
+
+ /**
+ * 分页查询设备校准记录列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 设备校准记录分页列表
+ */
+ @Override
+ public TableDataInfo queryPageList(DeviceCorrectRecordBo bo, PageQuery pageQuery) {
+ MPJLambdaWrapper wrapper = buildQueryWrapper(bo);
+ Page result = baseMapper.selectJoinPage(pageQuery.build(), DeviceCorrectRecordVo.class, wrapper);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询符合条件的设备校准记录列表
+ *
+ * @param bo 查询条件
+ * @return 设备校准记录列表
+ */
+ @Override
+ public List queryList(DeviceCorrectRecordBo bo) {
+ MPJLambdaWrapper wrapper = buildQueryWrapper(bo);
+ return baseMapper.selectJoinList(DeviceCorrectRecordVo.class, wrapper);
+ }
+
+ private MPJLambdaWrapper buildQueryWrapper(DeviceCorrectRecordBo bo) {
+ Map params = bo.getParams();
+ MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>();
+
+ // 选择主表所有字段
+ wrapper.selectAll(DeviceCorrectRecord.class);
+
+ // 选择用户表字段
+ wrapper.selectAs(AquUser::getUserName, DeviceCorrectRecordVo::getUserName)
+ .selectAs(AquUser::getMobilePhone, DeviceCorrectRecordVo::getMobilePhone);
+
+ // 选择设备表字段
+ wrapper.selectAs(Device::getDeviceName, DeviceCorrectRecordVo::getDeviceName);
+
+ // 左连接用户表
+ wrapper.leftJoin(AquUser.class, AquUser::getId, DeviceCorrectRecord::getUserId);
+
+ // 左连接设备表
+ wrapper.leftJoin(Device.class, Device::getId, DeviceCorrectRecord::getDeviceId);
+
+ // 查询条件
+ wrapper.eq(bo.getDeviceId() != null, DeviceCorrectRecord::getDeviceId, bo.getDeviceId())
+ .eq(bo.getUserId() != null, DeviceCorrectRecord::getUserId, bo.getUserId())
+ .eq(StringUtils.isNotBlank(bo.getSerialNum()), DeviceCorrectRecord::getSerialNum, bo.getSerialNum())
+ .eq(bo.getDeviceType() != null, DeviceCorrectRecord::getDeviceType, bo.getDeviceType())
+ .eq(bo.getValueDissolvedOxygen() != null, DeviceCorrectRecord::getValueDissolvedOxygen, bo.getValueDissolvedOxygen())
+ .eq(bo.getValueTemperature() != null, DeviceCorrectRecord::getValueTemperature, bo.getValueTemperature())
+ .eq(bo.getValueSaturability() != null, DeviceCorrectRecord::getValueSaturability, bo.getValueSaturability());
+
+ // 处理额外的查询参数
+ if (params != null && !params.isEmpty()) {
+ handleExtraParams(wrapper, params);
+ }
+
+ // 默认按id升序排列
+ wrapper.orderByDesc(DeviceCorrectRecord::getCreateTime);
+
+ return wrapper;
+ }
+
+ /**
+ * 处理额外的查询参数
+ *
+ * @param wrapper 查询包装器
+ * @param params 额外参数
+ */
+ private void handleExtraParams(MPJLambdaWrapper wrapper, Map params) {
+ // 处理用户搜索关键词 - 直接在SQL中进行JOIN查询
+ String userKeyword = (String) params.get("userKeyword");
+ if (StringUtils.isNotBlank(userKeyword)) {
+ wrapper.and(w -> w.like(AquUser::getUserName, userKeyword)
+ .or()
+ .like(AquUser::getMobilePhone, userKeyword));
+ }
+ }
+
+ /**
+ * 新增设备校准记录
+ *
+ * @param bo 设备校准记录
+ * @return 是否新增成功
+ */
+ @Override
+ public Boolean insertByBo(DeviceCorrectRecordBo bo) {
+ DeviceCorrectRecord add = MapstructUtils.convert(bo, DeviceCorrectRecord.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setId(add.getId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改设备校准记录
+ *
+ * @param bo 设备校准记录
+ * @return 是否修改成功
+ */
+ @Override
+ public Boolean updateByBo(DeviceCorrectRecordBo bo) {
+ DeviceCorrectRecord update = MapstructUtils.convert(bo, DeviceCorrectRecord.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(DeviceCorrectRecord entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 校验并批量删除设备校准记录信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteByIds(ids) > 0;
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/DeviceErrorCodeServiceImpl.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/DeviceErrorCodeServiceImpl.java
new file mode 100644
index 0000000..d43adf4
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/DeviceErrorCodeServiceImpl.java
@@ -0,0 +1,215 @@
+package org.dromara.fishery.service.impl;
+
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.fishery.domain.bo.DeviceErrorCodeBo;
+import org.dromara.fishery.domain.vo.DeviceErrorCodeVo;
+import org.dromara.fishery.domain.DeviceErrorCode;
+import org.dromara.fishery.domain.Device;
+import org.dromara.fishery.domain.AquUser;
+import org.dromara.fishery.domain.DeviceSwitch;
+import org.dromara.fishery.mapper.DeviceErrorCodeMapper;
+import org.dromara.fishery.service.IDeviceErrorCodeService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 设备故障码Service业务层处理
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class DeviceErrorCodeServiceImpl implements IDeviceErrorCodeService {
+
+ private final DeviceErrorCodeMapper baseMapper;
+
+ /**
+ * 查询设备故障码
+ *
+ * @param id 主键
+ * @return 设备故障码
+ */
+ @Override
+ public DeviceErrorCodeVo queryById(Long id){
+ return baseMapper.selectVoById(id);
+ }
+
+ /**
+ * 分页查询设备故障码列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 设备故障码分页列表
+ */
+ @Override
+ public TableDataInfo queryPageList(DeviceErrorCodeBo bo, PageQuery pageQuery) {
+ MPJLambdaWrapper wrapper = buildQueryWrapper(bo);
+ Page result = baseMapper.selectJoinPage(pageQuery.build(), DeviceErrorCodeVo.class, wrapper);
+ // 处理 switchIndex 为 0 的记录
+ processSwitchName(result.getRecords());
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询符合条件的设备故障码列表
+ *
+ * @param bo 查询条件
+ * @return 设备故障码列表
+ */
+ @Override
+ public List queryList(DeviceErrorCodeBo bo) {
+ MPJLambdaWrapper wrapper = buildQueryWrapper(bo);
+ List list = baseMapper.selectJoinList(DeviceErrorCodeVo.class, wrapper);
+ // 处理 switchIndex 为 0 的记录
+ processSwitchName(list);
+ return list;
+ }
+
+ private MPJLambdaWrapper buildQueryWrapper(DeviceErrorCodeBo bo) {
+ Map params = bo.getParams();
+ MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>();
+
+ // 选择主表所有字段
+ wrapper.selectAll(DeviceErrorCode.class);
+
+ // 选择设备表字段
+ wrapper.selectAs(Device::getDeviceName, DeviceErrorCodeVo::getDeviceName)
+ .selectAs(Device::getSerialNum, DeviceErrorCodeVo::getSerialNum);
+
+ // 选择用户表字段
+ wrapper.selectAs(AquUser::getUserName, DeviceErrorCodeVo::getUserName)
+ .selectAs(AquUser::getMobilePhone, DeviceErrorCodeVo::getMobilePhone);
+
+ // 选择开关表字段(条件查询:switchIndex 不为 0 时才关联)
+ wrapper.selectAs(DeviceSwitch::getSwitchName, DeviceErrorCodeVo::getSwitchName);
+
+ // 左连接设备表
+ wrapper.leftJoin(Device.class, Device::getId, DeviceErrorCode::getDeviceId);
+
+ // 左连接用户表 (通过设备表的userId)
+ wrapper.leftJoin(AquUser.class, AquUser::getId, Device::getUserId);
+
+ // 条件左连接开关表:只在 switchIndex 为 1-4 时关联
+ wrapper.leftJoin(DeviceSwitch.class, on -> on
+ .eq(DeviceSwitch::getDeviceId, DeviceErrorCode::getDeviceId)
+ .eq(DeviceSwitch::getIndex, DeviceErrorCode::getSwitchIndex)
+ .in(DeviceErrorCode::getSwitchIndex, 1, 2, 3, 4));
+
+ // 查询条件
+ wrapper.eq(bo.getDeviceId() != null, DeviceErrorCode::getDeviceId, bo.getDeviceId())
+ .eq(bo.getSwitchIndex() != null, DeviceErrorCode::getSwitchIndex, bo.getSwitchIndex())
+ .like(bo.getErrorCode() != null, DeviceErrorCode::getErrorCode, bo.getErrorCode());
+
+ // 处理额外的查询参数
+ if (params != null && !params.isEmpty()) {
+ handleExtraParams(wrapper, params);
+ }
+
+ // 默认按id升序排列
+ wrapper.orderByDesc(DeviceErrorCode::getCreateTime);
+
+ return wrapper;
+ }
+
+ /**
+ * 处理额外的查询参数
+ *
+ * @param wrapper 查询包装器
+ * @param params 额外参数
+ */
+ private void handleExtraParams(MPJLambdaWrapper wrapper, Map params) {
+ // 处理用户搜索关键词 - 直接在SQL中进行JOIN查询
+ String userKeyword = (String) params.get("userKeyword");
+ if (StringUtils.isNotBlank(userKeyword)) {
+ wrapper.and(w -> w.like(AquUser::getUserName, userKeyword)
+ .or()
+ .like(AquUser::getMobilePhone, userKeyword));
+ }
+
+ // 处理设备编号搜索关键词 - 直接在SQL中进行JOIN查询
+ String deviceKeyword = (String) params.get("deviceKeyword");
+ if (StringUtils.isNotBlank(deviceKeyword)) {
+ wrapper.and(w -> w.like(Device::getSerialNum, deviceKeyword));
+ }
+ }
+
+ /**
+ * 处理 switchIndex 为 0 的记录,将 switchName 设置为 "--"
+ *
+ * @param list 设备故障码列表
+ */
+ private void processSwitchName(List list) {
+ if (list == null || list.isEmpty()) {
+ return;
+ }
+ for (DeviceErrorCodeVo vo : list) {
+ if (vo.getSwitchIndex() != null && vo.getSwitchIndex() == 0) {
+ vo.setSwitchName("--");
+ }
+ }
+ }
+
+ /**
+ * 新增设备故障码
+ *
+ * @param bo 设备故障码
+ * @return 是否新增成功
+ */
+ @Override
+ public Boolean insertByBo(DeviceErrorCodeBo bo) {
+ DeviceErrorCode add = MapstructUtils.convert(bo, DeviceErrorCode.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setId(add.getId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改设备故障码
+ *
+ * @param bo 设备故障码
+ * @return 是否修改成功
+ */
+ @Override
+ public Boolean updateByBo(DeviceErrorCodeBo bo) {
+ DeviceErrorCode update = MapstructUtils.convert(bo, DeviceErrorCode.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(DeviceErrorCode entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 校验并批量删除设备故障码信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteByIds(ids) > 0;
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/DeviceSwitchServiceImpl.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/DeviceSwitchServiceImpl.java
new file mode 100644
index 0000000..b378823
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/DeviceSwitchServiceImpl.java
@@ -0,0 +1,223 @@
+package org.dromara.fishery.service.impl;
+
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.fishery.domain.bo.DeviceSwitchBo;
+import org.dromara.fishery.domain.vo.DeviceSwitchVo;
+import org.dromara.fishery.domain.DeviceSwitch;
+import org.dromara.fishery.domain.Device;
+import org.dromara.fishery.domain.Pond;
+import org.dromara.fishery.mapper.DeviceSwitchMapper;
+import org.dromara.fishery.service.IDeviceSwitchService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 测控一体机开关Service业务层处理
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class DeviceSwitchServiceImpl implements IDeviceSwitchService {
+
+ private final DeviceSwitchMapper baseMapper;
+
+ /**
+ * 查询测控一体机开关
+ *
+ * @param id 主键
+ * @return 测控一体机开关
+ */
+ @Override
+ public DeviceSwitchVo queryById(Long id){
+ return baseMapper.selectVoById(id);
+ }
+
+ /**
+ * 分页查询测控一体机开关列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 测控一体机开关分页列表
+ */
+ @Override
+ public TableDataInfo queryPageList(DeviceSwitchBo bo, PageQuery pageQuery) {
+ MPJLambdaWrapper wrapper = buildJoinQueryWrapper(bo);
+ Page result = baseMapper.selectJoinPage(pageQuery.build(), DeviceSwitchVo.class, wrapper);
+ // 填充isLinkedCtrl字段
+ fillIsLinkedCtrl(result.getRecords());
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询符合条件的测控一体机开关列表
+ *
+ * @param bo 查询条件
+ * @return 测控一体机开关列表
+ */
+ @Override
+ public List queryList(DeviceSwitchBo bo) {
+ MPJLambdaWrapper wrapper = buildJoinQueryWrapper(bo);
+ List list = baseMapper.selectJoinList(DeviceSwitchVo.class, wrapper);
+ // 填充isLinkedCtrl字段
+ fillIsLinkedCtrl(list);
+ return list;
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(DeviceSwitchBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.orderByAsc(DeviceSwitch::getId);
+ lqw.eq(bo.getDeviceId() != null, DeviceSwitch::getDeviceId, bo.getDeviceId());
+ lqw.eq(bo.getIndex() != null, DeviceSwitch::getIndex, bo.getIndex());
+ lqw.like(StringUtils.isNotBlank(bo.getSwitchName()), DeviceSwitch::getSwitchName, bo.getSwitchName());
+ lqw.eq(bo.getConnectVoltageType() != null, DeviceSwitch::getConnectVoltageType, bo.getConnectVoltageType());
+ lqw.eq(bo.getPondId() != null, DeviceSwitch::getPondId, bo.getPondId());
+ lqw.eq(bo.getIsOpen() != null, DeviceSwitch::getIsOpen, bo.getIsOpen());
+ lqw.eq(bo.getLinkedCtrlId() != null, DeviceSwitch::getLinkedCtrlId, bo.getLinkedCtrlId());
+ lqw.eq(bo.getLastTurnTime() != null, DeviceSwitch::getLastTurnTime, bo.getLastTurnTime());
+ return lqw;
+ }
+
+ /**
+ * 构建关联查询条件
+ *
+ * @param bo 查询条件
+ * @return 关联查询Wrapper
+ */
+ private MPJLambdaWrapper buildJoinQueryWrapper(DeviceSwitchBo bo) {
+ Map params = bo.getParams();
+ MPJLambdaWrapper wrapper = new MPJLambdaWrapper()
+ .selectAll(DeviceSwitch.class)
+ .selectAs(Device::getDeviceName, DeviceSwitchVo::getDeviceName)
+ .selectAs(Device::getSerialNum, DeviceSwitchVo::getSerialNum)
+ .selectAs(Pond::getPondName, DeviceSwitchVo::getPondName)
+ .leftJoin(Device.class, Device::getId, DeviceSwitch::getDeviceId)
+ .leftJoin(Pond.class, Pond::getId, DeviceSwitch::getPondId)
+ .eq(bo.getDeviceId() != null, DeviceSwitch::getDeviceId, bo.getDeviceId())
+ .eq(bo.getIndex() != null, DeviceSwitch::getIndex, bo.getIndex())
+ .like(StringUtils.isNotBlank(bo.getSwitchName()), DeviceSwitch::getSwitchName, bo.getSwitchName())
+ .eq(bo.getConnectVoltageType() != null, DeviceSwitch::getConnectVoltageType, bo.getConnectVoltageType())
+ .eq(bo.getPondId() != null, DeviceSwitch::getPondId, bo.getPondId())
+ .eq(bo.getIsOpen() != null, DeviceSwitch::getIsOpen, bo.getIsOpen())
+ .eq(bo.getLinkedCtrlId() != null, DeviceSwitch::getLinkedCtrlId, bo.getLinkedCtrlId())
+ .eq(bo.getLastTurnTime() != null, DeviceSwitch::getLastTurnTime, bo.getLastTurnTime())
+ .orderByAsc(DeviceSwitch::getId);
+
+ // 处理额外的查询参数
+ if (params != null && !params.isEmpty()) {
+ handleExtraParams(wrapper, params);
+ }
+
+ return wrapper;
+ }
+
+ /**
+ * 填充isLinkedCtrl字段
+ * 如果linkedCtrlId不为空,isLinkedCtrl设置为1,否则设置为0
+ *
+ * @param list 测控一体机开关列表
+ */
+ private void fillIsLinkedCtrl(List list) {
+ if (list == null || list.isEmpty()) {
+ return;
+ }
+ for (DeviceSwitchVo vo : list) {
+ vo.setIsLinkedCtrl(vo.getLinkedCtrlId() != null ? 1 : 0);
+ }
+ }
+
+ /**
+ * 处理额外的查询参数
+ *
+ * @param wrapper 查询包装器
+ * @param params 额外参数
+ */
+ private void handleExtraParams(MPJLambdaWrapper wrapper, Map params) {
+ // 处理设备名称或设备编号模糊查询
+ String deviceKeyword = (String) params.get("deviceKeyword");
+ if (StringUtils.isNotBlank(deviceKeyword)) {
+ wrapper.and(w -> w.like(Device::getDeviceName, deviceKeyword)
+ .or()
+ .like(Device::getSerialNum, deviceKeyword));
+ }
+
+ // 处理设备名称模糊查询
+ String deviceName = (String) params.get("deviceName");
+ if (StringUtils.isNotBlank(deviceName)) {
+ wrapper.like(Device::getDeviceName, deviceName);
+ }
+
+ // 处理设备编号模糊查询
+ String serialNum = (String) params.get("serialNum");
+ if (StringUtils.isNotBlank(serialNum)) {
+ wrapper.like(Device::getSerialNum, serialNum);
+ }
+ }
+
+ /**
+ * 新增测控一体机开关
+ *
+ * @param bo 测控一体机开关
+ * @return 是否新增成功
+ */
+ @Override
+ public Boolean insertByBo(DeviceSwitchBo bo) {
+ DeviceSwitch add = MapstructUtils.convert(bo, DeviceSwitch.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setId(add.getId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改测控一体机开关
+ *
+ * @param bo 测控一体机开关
+ * @return 是否修改成功
+ */
+ @Override
+ public Boolean updateByBo(DeviceSwitchBo bo) {
+ DeviceSwitch update = MapstructUtils.convert(bo, DeviceSwitch.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(DeviceSwitch entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 校验并批量删除测控一体机开关信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteByIds(ids) > 0;
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/PayDeviceServiceImpl.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/PayDeviceServiceImpl.java
new file mode 100644
index 0000000..f7f162f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/PayDeviceServiceImpl.java
@@ -0,0 +1,245 @@
+package org.dromara.fishery.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.fishery.domain.bo.PayDeviceBo;
+import org.dromara.fishery.domain.vo.PayDeviceVo;
+import org.dromara.fishery.domain.PayDevice;
+import org.dromara.fishery.domain.Device;
+import org.dromara.fishery.domain.AquUser;
+import org.dromara.fishery.mapper.PayDeviceMapper;
+import org.dromara.fishery.mapper.DeviceMapper;
+import org.dromara.fishery.service.IPayDeviceService;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 设备充值记录Service业务层处理
+ *
+ * @author intc
+ * @date 2025-10-16
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class PayDeviceServiceImpl implements IPayDeviceService {
+
+ private final PayDeviceMapper baseMapper;
+ private final DeviceMapper deviceMapper;
+
+ /**
+ * 查询设备充值记录
+ *
+ * @param id 主键
+ * @return 设备充值记录
+ */
+ @Override
+ public PayDeviceVo queryById(Long id){
+ MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>();
+ wrapper.selectAll(PayDevice.class)
+ .selectAs(AquUser::getUserName, PayDeviceVo::getUserName)
+ .selectAs(AquUser::getMobilePhone, PayDeviceVo::getMobilePhone)
+ .leftJoin(AquUser.class, AquUser::getId, PayDevice::getUserId)
+ .eq(PayDevice::getId, id);
+ PayDeviceVo vo = baseMapper.selectJoinOne(PayDeviceVo.class, wrapper);
+ if (vo != null) {
+ convertPayAmountToYuan(vo);
+ }
+ return vo;
+ }
+
+ /**
+ * 分页查询设备充值记录列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 设备充值记录分页列表
+ */
+ @Override
+ public TableDataInfo queryPageList(PayDeviceBo bo, PageQuery pageQuery) {
+ MPJLambdaWrapper wrapper = buildJoinQueryWrapper(bo);
+ Page result = baseMapper.selectJoinPage(pageQuery.build(), PayDeviceVo.class, wrapper);
+ // 转换金额从分到元
+ result.getRecords().forEach(this::convertPayAmountToYuan);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询符合条件的设备充值记录列表
+ *
+ * @param bo 查询条件
+ * @return 设备充值记录列表
+ */
+ @Override
+ public List queryList(PayDeviceBo bo) {
+ MPJLambdaWrapper wrapper = buildJoinQueryWrapper(bo);
+ List list = baseMapper.selectJoinList(PayDeviceVo.class, wrapper);
+ // 转换金额从分到元
+ list.forEach(this::convertPayAmountToYuan);
+ return list;
+ }
+
+ private MPJLambdaWrapper buildJoinQueryWrapper(PayDeviceBo bo) {
+ Map params = bo.getParams();
+ MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>();
+
+ // Select all fields from main table
+ wrapper.selectAll(PayDevice.class);
+ // Select joined fields from AquUser table
+ wrapper.selectAs(AquUser::getUserName, PayDeviceVo::getUserName)
+ .selectAs(AquUser::getMobilePhone, PayDeviceVo::getMobilePhone);
+
+ // Left join with AquUser table
+ wrapper.leftJoin(AquUser.class, AquUser::getId, PayDevice::getUserId);
+
+ // Build query conditions
+ wrapper.orderByDesc(PayDevice::getCreateTime);
+ wrapper.eq(bo.getUserId() != null, PayDevice::getUserId, bo.getUserId());
+ wrapper.like(StringUtils.isNotBlank(bo.getSerialNum()), PayDevice::getSerialNum, bo.getSerialNum());
+ wrapper.eq(bo.getDeviceType() != null, PayDevice::getDeviceType, bo.getDeviceType());
+ wrapper.eq(bo.getOrderId() != null, PayDevice::getOrderId, bo.getOrderId());
+ wrapper.eq(bo.getPayType() != null, PayDevice::getPayType, bo.getPayType());
+ wrapper.eq(bo.getProfitStatus() != null, PayDevice::getProfitStatus, bo.getProfitStatus());
+
+ // 处理扩展查询参数:用户关键词搜索(用户名或手机号模糊查询)
+ if (params != null && !params.isEmpty()) {
+ String userKeyword = (String) params.get("userKeyword");
+ if (StringUtils.isNotBlank(userKeyword)) {
+ wrapper.and(w -> w.like(AquUser::getUserName, userKeyword)
+ .or()
+ .like(AquUser::getMobilePhone, userKeyword));
+ }
+ }
+
+ return wrapper;
+ }
+
+ /**
+ * 将续费金额从分转换为元
+ *
+ * @param vo 设备充值记录VO
+ */
+ private void convertPayAmountToYuan(PayDeviceVo vo) {
+ if (vo != null && vo.getPayAmount() != null) {
+ // 分转元:除以100,保畚2位小数
+ double yuan = vo.getPayAmount() / 100.0;
+ vo.setPayAmountYuan(Math.round(yuan * 100.0) / 100.0);
+ }
+ }
+
+ /**
+ * 新增设备充值记录
+ *
+ * @param bo 设备充值记录
+ * @return 是否新增成功
+ */
+ @Override
+ public Boolean insertByBo(PayDeviceBo bo) {
+ PayDevice add = MapstructUtils.convert(bo, PayDevice.class);
+
+ // 1. 根据设备编号查询设备信息
+ LambdaQueryWrapper deviceQuery = new LambdaQueryWrapper<>();
+ deviceQuery.eq(Device::getSerialNum, bo.getSerialNum());
+ Device device = deviceMapper.selectOne(deviceQuery);
+
+ if (device == null) {
+ log.error("设备不存在,设备编号: {}", bo.getSerialNum());
+ throw new RuntimeException("设备不存在");
+ }
+
+ // 2. 计算续费时长(月)- 使用设备原到期时间与新到期时间比较
+ Integer addMonth = calculateAddMonth(device.getDeadTime(), bo.getDeadTime());
+ add.setAddMonth(addMonth);
+
+ // 3. 保存充值记录
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+
+ if (flag) {
+ bo.setId(add.getId());
+
+ // 4. 直接更新设备的到期时间为前端传来的新到期时间
+ device.setDeadTime(bo.getDeadTime());
+ deviceMapper.updateById(device);
+ }
+
+ return flag;
+ }
+
+ /**
+ * 计算续费时长(月)
+ *
+ * @param oldDeadTime 原到期时间
+ * @param newDeadTime 新到期时间
+ * @return 续费月数
+ */
+ private Integer calculateAddMonth(Date oldDeadTime, Date newDeadTime) {
+ if (newDeadTime == null) {
+ log.warn("新到期时间为空,无法计算续费时长");
+ return 0;
+ }
+
+ // 如果设备原来没有到期时间,使用当前时间作为基准
+ Date baseTime = (oldDeadTime != null) ? oldDeadTime : new Date();
+
+ // 转换为LocalDate进行月份计算
+ LocalDate baseDate = baseTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+ LocalDate newDate = newDeadTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+
+ // 计算月份差
+ long months = ChronoUnit.MONTHS.between(baseDate, newDate);
+
+ log.debug("计算续费时长 - 基准时间: {}, 新到期时间: {}, 续费月数: {}", baseDate, newDate, months);
+
+ return Math.max(0, (int) months);
+ }
+
+ /**
+ * 修改设备充值记录
+ *
+ * @param bo 设备充值记录
+ * @return 是否修改成功
+ */
+ @Override
+ public Boolean updateByBo(PayDeviceBo bo) {
+ PayDevice update = MapstructUtils.convert(bo, PayDevice.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(PayDevice entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 校验并批量删除设备充值记录信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteByIds(ids) > 0;
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/PayOrderServiceImpl.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/PayOrderServiceImpl.java
new file mode 100644
index 0000000..5eae000
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/PayOrderServiceImpl.java
@@ -0,0 +1,199 @@
+package org.dromara.fishery.service.impl;
+
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.fishery.domain.bo.PayOrderBo;
+import org.dromara.fishery.domain.vo.PayOrderVo;
+import org.dromara.fishery.domain.PayOrder;
+import org.dromara.fishery.domain.AquUser;
+import org.dromara.fishery.mapper.PayOrderMapper;
+import org.dromara.fishery.service.IPayOrderService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 充值订单Service业务层处理
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class PayOrderServiceImpl implements IPayOrderService {
+
+ private final PayOrderMapper baseMapper;
+
+ /**
+ * 查询充值订单
+ *
+ * @param id 主键
+ * @return 充值订单
+ */
+ @Override
+ public PayOrderVo queryById(Long id){
+ MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>();
+ wrapper.selectAll(PayOrder.class)
+ .selectAs(AquUser::getUserName, PayOrderVo::getUserName)
+ .selectAs(AquUser::getMobilePhone, PayOrderVo::getMobilePhone)
+ .leftJoin(AquUser.class, AquUser::getId, PayOrder::getUserId)
+ .eq(PayOrder::getId, id);
+ PayOrderVo vo = baseMapper.selectJoinOne(PayOrderVo.class, wrapper);
+ if (vo != null) {
+ convertAmountToYuan(vo);
+ }
+ return vo;
+ }
+
+ /**
+ * 分页查询充值订单列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 充值订单分页列表
+ */
+ @Override
+ public TableDataInfo queryPageList(PayOrderBo bo, PageQuery pageQuery) {
+ MPJLambdaWrapper wrapper = buildJoinQueryWrapper(bo);
+ Page result = baseMapper.selectJoinPage(pageQuery.build(), PayOrderVo.class, wrapper);
+ // 转换金额从分到元
+ result.getRecords().forEach(this::convertAmountToYuan);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询符合条件的充值订单列表
+ *
+ * @param bo 查询条件
+ * @return 充值订单列表
+ */
+ @Override
+ public List queryList(PayOrderBo bo) {
+ MPJLambdaWrapper wrapper = buildJoinQueryWrapper(bo);
+ List list = baseMapper.selectJoinList(PayOrderVo.class, wrapper);
+ // 转换金额从分到元
+ list.forEach(this::convertAmountToYuan);
+ return list;
+ }
+
+ private MPJLambdaWrapper buildJoinQueryWrapper(PayOrderBo bo) {
+ Map params = bo.getParams();
+ MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>();
+
+ // Select all fields from main table
+ wrapper.selectAll(PayOrder.class);
+ // Select joined fields from AquUser table
+ wrapper.selectAs(AquUser::getUserName, PayOrderVo::getUserName)
+ .selectAs(AquUser::getMobilePhone, PayOrderVo::getMobilePhone);
+
+ // Left join with AquUser table
+ wrapper.leftJoin(AquUser.class, AquUser::getId, PayOrder::getUserId);
+
+ // Build query conditions
+ wrapper.orderByDesc(PayOrder::getCreateTime);
+ wrapper.eq(bo.getUserId() != null, PayOrder::getUserId, bo.getUserId());
+ wrapper.eq(StringUtils.isNotBlank(bo.getBankType()), PayOrder::getBankType, bo.getBankType());
+ wrapper.eq(bo.getSuccessTime() != null, PayOrder::getSuccessTime, bo.getSuccessTime());
+ wrapper.eq(StringUtils.isNotBlank(bo.getTradeState()), PayOrder::getTradeState, bo.getTradeState());
+ wrapper.eq(StringUtils.isNotBlank(bo.getTradeType()), PayOrder::getTradeType, bo.getTradeType());
+ wrapper.eq(StringUtils.isNotBlank(bo.getTransactionId()), PayOrder::getTransactionId, bo.getTransactionId());
+ wrapper.eq(bo.getOrderStatus() != null, PayOrder::getOrderStatus, bo.getOrderStatus());
+ wrapper.eq(bo.getProfitStatus() != null, PayOrder::getProfitStatus, bo.getProfitStatus());
+
+ // 处理扩展查询参数:用户关键词搜索(用户名或手机号模糊查询)
+ if (params != null && !params.isEmpty()) {
+ String userKeyword = (String) params.get("userKeyword");
+ if (StringUtils.isNotBlank(userKeyword)) {
+ wrapper.and(w -> w.like(AquUser::getUserName, userKeyword)
+ .or()
+ .like(AquUser::getMobilePhone, userKeyword));
+ }
+ }
+
+ return wrapper;
+ }
+
+ /**
+ * 将金额从分转换为元
+ *
+ * @param vo 充值订单VO
+ */
+ private void convertAmountToYuan(PayOrderVo vo) {
+ if (vo == null) {
+ return;
+ }
+
+ // 转换充值总金额
+ if (vo.getTotalAmount() != null) {
+ double yuan = vo.getTotalAmount() / 100.0;
+ vo.setTotalAmountYuan(Math.round(yuan * 100.0) / 100.0);
+ }
+
+ // 转换用户支付金额
+ if (vo.getPayerTotal() != null) {
+ double yuan = vo.getPayerTotal() / 100.0;
+ vo.setPayerTotalYuan(Math.round(yuan * 100.0) / 100.0);
+ }
+ }
+
+ /**
+ * 新增充值订单
+ *
+ * @param bo 充值订单
+ * @return 是否新增成功
+ */
+ @Override
+ public Boolean insertByBo(PayOrderBo bo) {
+ PayOrder add = MapstructUtils.convert(bo, PayOrder.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setId(add.getId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改充值订单
+ *
+ * @param bo 充值订单
+ * @return 是否修改成功
+ */
+ @Override
+ public Boolean updateByBo(PayOrderBo bo) {
+ PayOrder update = MapstructUtils.convert(bo, PayOrder.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(PayOrder entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 校验并批量删除充值订单信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteByIds(ids) > 0;
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/UserRelationServiceImpl.java b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/UserRelationServiceImpl.java
new file mode 100644
index 0000000..97bfe72
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/java/org/dromara/fishery/service/impl/UserRelationServiceImpl.java
@@ -0,0 +1,133 @@
+package org.dromara.fishery.service.impl;
+
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.fishery.domain.bo.UserRelationBo;
+import org.dromara.fishery.domain.vo.UserRelationVo;
+import org.dromara.fishery.domain.UserRelation;
+import org.dromara.fishery.mapper.UserRelationMapper;
+import org.dromara.fishery.service.IUserRelationService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 养殖用户子账号Service业务层处理
+ *
+ * @author intc
+ * @date 2025-10-17
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class UserRelationServiceImpl implements IUserRelationService {
+
+ private final UserRelationMapper baseMapper;
+
+ /**
+ * 查询养殖用户子账号
+ *
+ * @param id 主键
+ * @return 养殖用户子账号
+ */
+ @Override
+ public UserRelationVo queryById(Long id){
+ return baseMapper.selectVoById(id);
+ }
+
+ /**
+ * 分页查询养殖用户子账号列表
+ *
+ * @param bo 查询条件
+ * @param pageQuery 分页参数
+ * @return 养殖用户子账号分页列表
+ */
+ @Override
+ public TableDataInfo queryPageList(UserRelationBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询符合条件的养殖用户子账号列表
+ *
+ * @param bo 查询条件
+ * @return 养殖用户子账号列表
+ */
+ @Override
+ public List queryList(UserRelationBo bo) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(UserRelationBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.orderByAsc(UserRelation::getId);
+ lqw.eq(bo.getParentUserId() != null, UserRelation::getParentUserId, bo.getParentUserId());
+ lqw.eq(bo.getChildUserId() != null, UserRelation::getChildUserId, bo.getChildUserId());
+ return lqw;
+ }
+
+ /**
+ * 新增养殖用户子账号
+ *
+ * @param bo 养殖用户子账号
+ * @return 是否新增成功
+ */
+ @Override
+ public Boolean insertByBo(UserRelationBo bo) {
+ UserRelation add = MapstructUtils.convert(bo, UserRelation.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setId(add.getId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改养殖用户子账号
+ *
+ * @param bo 养殖用户子账号
+ * @return 是否修改成功
+ */
+ @Override
+ public Boolean updateByBo(UserRelationBo bo) {
+ UserRelation update = MapstructUtils.convert(bo, UserRelation.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(UserRelation entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 校验并批量删除养殖用户子账号信息
+ *
+ * @param ids 待删除的主键集合
+ * @param isValid 是否进行有效性校验
+ * @return 是否删除成功
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteByIds(ids) > 0;
+ }
+}
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/DeviceCorrectRecordMapper.xml b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/DeviceCorrectRecordMapper.xml
new file mode 100644
index 0000000..a89c6e6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/DeviceCorrectRecordMapper.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/DeviceErrorCodeMapper.xml b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/DeviceErrorCodeMapper.xml
new file mode 100644
index 0000000..68a770b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/DeviceErrorCodeMapper.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/DeviceSwitchMapper.xml b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/DeviceSwitchMapper.xml
new file mode 100644
index 0000000..14ab5af
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/DeviceSwitchMapper.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/PayDeviceMapper.xml b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/PayDeviceMapper.xml
new file mode 100644
index 0000000..91bfbbf
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/PayDeviceMapper.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/PayOrderMapper.xml b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/PayOrderMapper.xml
new file mode 100644
index 0000000..be21ffb
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/PayOrderMapper.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/UserRelationMapper.xml b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/UserRelationMapper.xml
new file mode 100644
index 0000000..e94ef19
--- /dev/null
+++ b/ruoyi-modules/ruoyi-fishery/src/main/resources/mapper/fishery/UserRelationMapper.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/ruoyi-modules/ruoyi-tdengine/pom.xml b/ruoyi-modules/ruoyi-tdengine/pom.xml
new file mode 100644
index 0000000..ff4cf65
--- /dev/null
+++ b/ruoyi-modules/ruoyi-tdengine/pom.xml
@@ -0,0 +1,112 @@
+
+
+
+ org.dromara
+ ruoyi-modules
+ ${revision}
+
+ 4.0.0
+
+ ruoyi-tdengine
+
+
+ TD数据模块
+
+
+
+
+
+
+ org.dromara
+ ruoyi-common-core
+
+
+
+ org.dromara
+ ruoyi-common-doc
+
+
+
+ org.dromara
+ ruoyi-common-sms
+
+
+
+ org.dromara
+ ruoyi-common-mail
+
+
+
+ org.dromara
+ ruoyi-common-redis
+
+
+
+ org.dromara
+ ruoyi-common-idempotent
+
+
+
+ org.dromara
+ ruoyi-common-mybatis
+
+
+
+ org.dromara
+ ruoyi-common-log
+
+
+
+ org.dromara
+ ruoyi-common-excel
+
+
+
+ org.dromara
+ ruoyi-common-security
+
+
+
+ org.dromara
+ ruoyi-common-web
+
+
+
+ org.dromara
+ ruoyi-common-ratelimiter
+
+
+
+ org.dromara
+ ruoyi-common-translation
+
+
+
+ org.dromara
+ ruoyi-common-sensitive
+
+
+
+ org.dromara
+ ruoyi-common-encrypt
+
+
+
+ org.dromara
+ ruoyi-common-tenant
+
+
+
+ org.dromara
+ ruoyi-common-websocket
+
+
+ com.taosdata.jdbc
+ taos-jdbcdriver
+ 2.0.40
+
+
+
+
diff --git a/ruoyi-modules/ruoyi-tdengine/src/main/resources/mapper/package-info.md b/ruoyi-modules/ruoyi-tdengine/src/main/resources/mapper/package-info.md
new file mode 100644
index 0000000..c938b1e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-tdengine/src/main/resources/mapper/package-info.md
@@ -0,0 +1,3 @@
+java包使用 `.` 分割 resource 目录使用 `/` 分割
+
+此文件目的 防止文件夹粘连找不到 `xml` 文件
\ No newline at end of file