- {{ teamMeetingDetail?.compere?.name }}
+ {{ teamMeetingDetail?.compereName }}
{{ item.name }},
- {{ teamMeetingDetail?.team.name }}
- {{ teamMeetingDetail?.contractor.name }}
+ {{ teamMeetingDetail?.teamName }}
+ {{ teamMeetingDetail?.contractorName }}
{{ dayjs(teamMeetingDetail?.meetingDate).format('YYYY 年 MM 月 DD 日') }}
{{ teamMeetingDetail?.createTime }}
{{ teamMeetingDetail?.content }}
-
-
+
+
diff --git a/plus-ui/src/views/safety/teamMeeting/index.vue b/plus-ui/src/views/safety/teamMeeting/index.vue
index 8f31ee4a..e64f1fa1 100644
--- a/plus-ui/src/views/safety/teamMeeting/index.vue
+++ b/plus-ui/src/views/safety/teamMeeting/index.vue
@@ -19,17 +19,17 @@
-
+
- 批量删除
+ 删除
-
+
@@ -37,9 +37,9 @@
-
-
-
+
+
+
{{ scope.row.participantList.length + 1 }}
@@ -50,6 +50,11 @@
{{ parseTime(scope.row.meetingDate, '{y}-{m}-{d}') }}
+
+
+ {{ parseTime(scope.row.createTime, '{y}-{m}-{d} {hh}:{mm}:{ss}') }}
+
+
@@ -57,7 +62,7 @@
详情
- 修改
+
删除
@@ -263,6 +268,20 @@ const handleExport = () => {
);
};
+//监听项目id刷新数据
+const listeningProject = watch(
+ () => currentProject.value.id,
+ (nid, oid) => {
+ queryParams.value.projectId = nid;
+ form.value.projectId = nid;
+ getList();
+ }
+);
+
+onUnmounted(() => {
+ listeningProject();
+});
+
onMounted(() => {
getList();
});
diff --git a/plus-ui/tsconfig.json b/plus-ui/tsconfig.json
index 6315891f..bd21a2d3 100644
--- a/plus-ui/tsconfig.json
+++ b/plus-ui/tsconfig.json
@@ -24,7 +24,9 @@
"removeComments": true,
// 允许默认导入
"allowSyntheticDefaultImports": true,
- "forceConsistentCasingInFileNames": true
+ "forceConsistentCasingInFileNames": true,
+ "outDir": "dist",
+ "rootDir": "."
},
"include": ["src/**/*.ts", "src/**/*.vue", "src/types/**/*.d.ts", "vite.config.ts"],
"exclude": ["node_modules", "dist", "**/*.js", "**/*.md", "src/**/*.md"]
diff --git a/xinnengyuan/ruoyi-admin/src/main/resources/application.yml b/xinnengyuan/ruoyi-admin/src/main/resources/application.yml
index ddf45424..8cd83068 100644
--- a/xinnengyuan/ruoyi-admin/src/main/resources/application.yml
+++ b/xinnengyuan/ruoyi-admin/src/main/resources/application.yml
@@ -121,7 +121,6 @@ security:
- /*/api-docs/**
- /warm-flow-ui/token-name
- /other/ys7Device/webhook
- - /other/ys7Device/test
# 多租户配置
tenant:
diff --git a/xinnengyuan/ruoyi-admin/src/test/java/org/dromara/test/Ys7Test.java b/xinnengyuan/ruoyi-admin/src/test/java/org/dromara/test/Ys7Test.java
index 00a5bc17..688f8eb1 100644
--- a/xinnengyuan/ruoyi-admin/src/test/java/org/dromara/test/Ys7Test.java
+++ b/xinnengyuan/ruoyi-admin/src/test/java/org/dromara/test/Ys7Test.java
@@ -1,6 +1,7 @@
package org.dromara.test;
import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
import org.dromara.manager.ys7manager.Ys7Manager;
import org.dromara.manager.ys7manager.Ys7RequestUtils;
import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo;
@@ -13,6 +14,7 @@ import java.util.List;
* @author lcj
* @date 2025/6/12 17:06
*/
+@Slf4j
@SpringBootTest
public class Ys7Test {
@@ -26,4 +28,10 @@ public class Ys7Test {
System.out.println(ys7QueryDeviceResponseVos);
}
+ @Test
+ void testCaptureDevicePic() {
+ String pic = ys7Manager.getCaptureDevicePic("AE9470016", 1, 1);
+ System.out.println(pic);
+ }
+
}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/controller/FacMatrixController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/controller/FacMatrixController.java
index 19b2c9bd..247248bb 100644
--- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/controller/FacMatrixController.java
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/controller/FacMatrixController.java
@@ -16,8 +16,9 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.facility.domain.dto.matrix.*;
-import org.dromara.facility.domain.vo.matrix.FacMatrixVo;
import org.dromara.facility.domain.vo.matrix.FacMatrixDetailGisVo;
+import org.dromara.facility.domain.vo.matrix.FacMatrixPositionGisVo;
+import org.dromara.facility.domain.vo.matrix.FacMatrixVo;
import org.dromara.facility.service.IFacMatrixService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -79,6 +80,16 @@ public class FacMatrixController extends BaseController {
return R.ok(facMatrixService.getMatrixDetailGis(req));
}
+ /**
+ * 获取设施-方阵大屏位置详情
+ */
+ @SaCheckPermission("facility:matrix:query")
+ @GetMapping("/gis/position/{id}")
+ public R getPositionGis(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(facMatrixService.getPositionGis(id));
+ }
+
/**
* 通过GeoJson新增设施-方阵
*/
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/boxtransformer/FacBoxTransformerPositionGisVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/boxtransformer/FacBoxTransformerPositionGisVo.java
new file mode 100644
index 00000000..4eb5fa1c
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/boxtransformer/FacBoxTransformerPositionGisVo.java
@@ -0,0 +1,54 @@
+package org.dromara.facility.domain.vo.boxtransformer;
+
+import cn.hutool.json.JSONUtil;
+import lombok.Data;
+import org.dromara.facility.domain.FacBoxTransformer;
+import org.springframework.beans.BeanUtils;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 16:22
+ */
+@Data
+public class FacBoxTransformerPositionGisVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = -5381920624456948144L;
+
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 箱变名称
+ */
+ private String name;
+
+ /**
+ * 箱变位置
+ */
+ private List positionList;
+
+ /**
+ * 完成状态(0未开始 1进行中 2完成)
+ */
+ private String status;
+
+ /**
+ * 对象转vo
+ */
+ public static FacBoxTransformerPositionGisVo obj2vo(FacBoxTransformer obj) {
+ FacBoxTransformerPositionGisVo vo = new FacBoxTransformerPositionGisVo();
+ BeanUtils.copyProperties(obj, vo);
+ String positions = obj.getPositions();
+ List positionList = JSONUtil.toList(positions, Double.class);
+ vo.setPositionList(positionList);
+ return vo;
+ }
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/inverter/FacInverterPositionGisVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/inverter/FacInverterPositionGisVo.java
new file mode 100644
index 00000000..a05c46f2
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/inverter/FacInverterPositionGisVo.java
@@ -0,0 +1,54 @@
+package org.dromara.facility.domain.vo.inverter;
+
+import cn.hutool.json.JSONUtil;
+import lombok.Data;
+import org.dromara.facility.domain.FacInverter;
+import org.springframework.beans.BeanUtils;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 16:22
+ */
+@Data
+public class FacInverterPositionGisVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 497930244187026829L;
+
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 逆变器名称
+ */
+ private String name;
+
+ /**
+ * 逆变器位置
+ */
+ private List positionList;
+
+ /**
+ * 完成状态(0未开始 1进行中 2完成)
+ */
+ private String status;
+
+ /**
+ * 对象转vo
+ */
+ public static FacInverterPositionGisVo obj2vo(FacInverter obj) {
+ FacInverterPositionGisVo vo = new FacInverterPositionGisVo();
+ BeanUtils.copyProperties(obj, vo);
+ String positions = obj.getPositions();
+ List positionList = JSONUtil.toList(positions, Double.class);
+ vo.setPositionList(positionList);
+ return vo;
+ }
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/matrix/FacMatrixPositionGisVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/matrix/FacMatrixPositionGisVo.java
new file mode 100644
index 00000000..eb27b849
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/matrix/FacMatrixPositionGisVo.java
@@ -0,0 +1,70 @@
+package org.dromara.facility.domain.vo.matrix;
+
+import lombok.Data;
+import org.dromara.facility.domain.vo.boxtransformer.FacBoxTransformerPositionGisVo;
+import org.dromara.facility.domain.vo.inverter.FacInverterPositionGisVo;
+import org.dromara.facility.domain.vo.photovoltaicpanel.FacPhotovoltaicPanelPositionGisVo;
+import org.dromara.facility.domain.vo.photovoltaicpanelcolumn.FacPhotovoltaicPanelColumnPositionGisVo;
+import org.dromara.facility.domain.vo.photovoltaicpanelpoint.FacPhotovoltaicPanelPointPositionGisVo;
+import org.dromara.facility.domain.vo.photovoltaicpanelsupport.FacPhotovoltaicPanelSupportPositionGisVo;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 16:14
+ */
+@Data
+public class FacMatrixPositionGisVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 7720584094593327756L;
+
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 方阵名称
+ */
+ private String matrixName;
+
+ /**
+ * 方阵位置
+ */
+ private List> positions;
+
+ /**
+ * 逆变器位置
+ */
+ private List inverterPositionList;
+
+ /**
+ * 箱变位置
+ */
+ private List boxTransformerPositionList;
+
+ /**
+ * 光伏板位置
+ */
+ private List photovoltaicPanelPositionList;
+
+ /**
+ * 光伏板立柱位置
+ */
+ private List photovoltaicPanelColumnPositionList;
+
+ /**
+ * 光伏板支架位置
+ */
+ private List photovoltaicPanelSupportPositionList;
+
+ /**
+ * 光伏板桩点位置
+ */
+ private List photovoltaicPanelPointPositionList;
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanel/FacPhotovoltaicPanelPositionGisVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanel/FacPhotovoltaicPanelPositionGisVo.java
new file mode 100644
index 00000000..938f101a
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanel/FacPhotovoltaicPanelPositionGisVo.java
@@ -0,0 +1,59 @@
+package org.dromara.facility.domain.vo.photovoltaicpanel;
+
+import cn.hutool.json.JSONUtil;
+import lombok.Data;
+import org.dromara.facility.domain.FacPhotovoltaicPanel;
+import org.springframework.beans.BeanUtils;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 16:19
+ */
+@Data
+public class FacPhotovoltaicPanelPositionGisVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = -851548161301247186L;
+
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 光伏板名称
+ */
+ private String name;
+
+ /**
+ * 光伏板位置
+ */
+ private List> positionList;
+
+ /**
+ * 完成状态(0未开始 1进行中 2完成)
+ */
+ private String status;
+
+ /**
+ * 对象转VO
+ */
+ public static FacPhotovoltaicPanelPositionGisVo obj2vo(FacPhotovoltaicPanel obj) {
+ FacPhotovoltaicPanelPositionGisVo vo = new FacPhotovoltaicPanelPositionGisVo();
+ BeanUtils.copyProperties(obj, vo);
+ String positions = obj.getPositions();
+ List> positionList = new ArrayList<>();
+ List arr = JSONUtil.toList(positions, String.class);
+ for (String s : arr) {
+ positionList.add(JSONUtil.toList(s, Double.class));
+ }
+ vo.setPositionList(positionList);
+ return vo;
+ }
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanelcolumn/FacPhotovoltaicPanelColumnPositionGisVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanelcolumn/FacPhotovoltaicPanelColumnPositionGisVo.java
new file mode 100644
index 00000000..3f1c587d
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanelcolumn/FacPhotovoltaicPanelColumnPositionGisVo.java
@@ -0,0 +1,54 @@
+package org.dromara.facility.domain.vo.photovoltaicpanelcolumn;
+
+import cn.hutool.json.JSONUtil;
+import lombok.Data;
+import org.dromara.facility.domain.FacPhotovoltaicPanelColumn;
+import org.springframework.beans.BeanUtils;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 16:25
+ */
+@Data
+public class FacPhotovoltaicPanelColumnPositionGisVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 8131058424226441681L;
+
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 光伏板立柱名称
+ */
+ private String name;
+
+ /**
+ * 光伏板立柱位置
+ */
+ private List positionList;
+
+ /**
+ * 完成状态(0未开始 1进行中 2完成)
+ */
+ private String status;
+
+ /**
+ * 对象转vo
+ */
+ public static FacPhotovoltaicPanelColumnPositionGisVo obj2vo(FacPhotovoltaicPanelColumn obj) {
+ FacPhotovoltaicPanelColumnPositionGisVo vo = new FacPhotovoltaicPanelColumnPositionGisVo();
+ BeanUtils.copyProperties(obj, vo);
+ String positions = obj.getPositions();
+ List positionList = JSONUtil.toList(positions, Double.class);
+ vo.setPositionList(positionList);
+ return vo;
+ }
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanelpoint/FacPhotovoltaicPanelPointPositionGisVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanelpoint/FacPhotovoltaicPanelPointPositionGisVo.java
new file mode 100644
index 00000000..eb4249e1
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanelpoint/FacPhotovoltaicPanelPointPositionGisVo.java
@@ -0,0 +1,54 @@
+package org.dromara.facility.domain.vo.photovoltaicpanelpoint;
+
+import cn.hutool.json.JSONUtil;
+import lombok.Data;
+import org.dromara.facility.domain.FacPhotovoltaicPanelPoint;
+import org.springframework.beans.BeanUtils;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 16:25
+ */
+@Data
+public class FacPhotovoltaicPanelPointPositionGisVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = -8626958457981310560L;
+
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 光伏板桩点名称
+ */
+ private String name;
+
+ /**
+ * 光伏板桩点位置
+ */
+ private List positionList;
+
+ /**
+ * 完成状态(0未开始 1进行中 2完成)
+ */
+ private String status;
+
+ /**
+ * 对象转vo
+ */
+ public static FacPhotovoltaicPanelPointPositionGisVo obj2vo(FacPhotovoltaicPanelPoint obj) {
+ FacPhotovoltaicPanelPointPositionGisVo vo = new FacPhotovoltaicPanelPointPositionGisVo();
+ BeanUtils.copyProperties(obj, vo);
+ String positions = obj.getPositions();
+ List positionList = JSONUtil.toList(positions, Double.class);
+ vo.setPositionList(positionList);
+ return vo;
+ }
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanelsupport/FacPhotovoltaicPanelSupportPositionGisVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanelsupport/FacPhotovoltaicPanelSupportPositionGisVo.java
new file mode 100644
index 00000000..e599b2ba
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/vo/photovoltaicpanelsupport/FacPhotovoltaicPanelSupportPositionGisVo.java
@@ -0,0 +1,55 @@
+package org.dromara.facility.domain.vo.photovoltaicpanelsupport;
+
+import cn.hutool.json.JSONUtil;
+import lombok.Data;
+import org.dromara.facility.domain.FacPhotovoltaicPanelSupport;
+import org.springframework.beans.BeanUtils;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 16:25
+ */
+@Data
+public class FacPhotovoltaicPanelSupportPositionGisVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 330832487175547581L;
+
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 光伏板支架名称
+ */
+ private String name;
+
+ /**
+ * 光伏板支架位置
+ */
+ private List positionList;
+
+ /**
+ * 完成状态(0未开始 1进行中 2完成)
+ */
+ private String status;
+
+ /**
+ * 对象转vo
+ */
+ public static FacPhotovoltaicPanelSupportPositionGisVo obj2vo(FacPhotovoltaicPanelSupport obj){
+ FacPhotovoltaicPanelSupportPositionGisVo vo = new FacPhotovoltaicPanelSupportPositionGisVo();
+ BeanUtils.copyProperties(obj, vo);
+ String positions = obj.getPositions();
+ List positionList = JSONUtil.toList(positions, Double.class);
+ vo.setPositionList(positionList);
+ return vo;
+ }
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/IFacMatrixService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/IFacMatrixService.java
index d0a88fc8..4516f632 100644
--- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/IFacMatrixService.java
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/IFacMatrixService.java
@@ -8,6 +8,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.facility.domain.FacMatrix;
import org.dromara.facility.domain.dto.matrix.*;
import org.dromara.facility.domain.vo.matrix.FacMatrixDetailGisVo;
+import org.dromara.facility.domain.vo.matrix.FacMatrixPositionGisVo;
import org.dromara.facility.domain.vo.matrix.FacMatrixVo;
import java.util.Collection;
@@ -129,4 +130,12 @@ public interface IFacMatrixService extends IService {
*/
FacMatrix getMatrixIdBy2Coordinates(List matrixList, List> coordinates);
+ /**
+ * 获取设施-方阵位置信息
+ *
+ * @param id 主键
+ * @return 设施-方阵位置信息
+ */
+ FacMatrixPositionGisVo getPositionGis(Long id);
+
}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacMatrixServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacMatrixServiceImpl.java
index 22ff7581..d6c61c66 100644
--- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacMatrixServiceImpl.java
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacMatrixServiceImpl.java
@@ -18,11 +18,17 @@ import org.dromara.facility.domain.*;
import org.dromara.facility.domain.dto.geojson.*;
import org.dromara.facility.domain.dto.matrix.*;
import org.dromara.facility.domain.enums.FacFinishStatusEnum;
+import org.dromara.facility.domain.vo.boxtransformer.FacBoxTransformerPositionGisVo;
+import org.dromara.facility.domain.vo.inverter.FacInverterPositionGisVo;
import org.dromara.facility.domain.vo.matrix.FacMatrixDetailGisVo;
+import org.dromara.facility.domain.vo.matrix.FacMatrixPositionGisVo;
import org.dromara.facility.domain.vo.matrix.FacMatrixVo;
+import org.dromara.facility.domain.vo.photovoltaicpanel.FacPhotovoltaicPanelPositionGisVo;
+import org.dromara.facility.domain.vo.photovoltaicpanelcolumn.FacPhotovoltaicPanelColumnPositionGisVo;
+import org.dromara.facility.domain.vo.photovoltaicpanelpoint.FacPhotovoltaicPanelPointPositionGisVo;
+import org.dromara.facility.domain.vo.photovoltaicpanelsupport.FacPhotovoltaicPanelSupportPositionGisVo;
import org.dromara.facility.mapper.FacMatrixMapper;
import org.dromara.facility.service.*;
-import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.JSTUtil;
@@ -311,7 +317,7 @@ public class FacMatrixServiceImpl extends ServiceImpl columnList = photovoltaicPanelColumnService.lambdaQuery()
+ .select(
+ FacPhotovoltaicPanelColumn::getId,
+ FacPhotovoltaicPanelColumn::getName,
+ FacPhotovoltaicPanelColumn::getPositions,
+ FacPhotovoltaicPanelColumn::getStatus
+ )
+ .eq(FacPhotovoltaicPanelColumn::getProjectId, projectId)
+ .list();
+ List columnVoList = columnList
+ .stream().map(FacPhotovoltaicPanelColumnPositionGisVo::obj2vo).toList();
+ matrixPositionGisVo.setPhotovoltaicPanelColumnPositionList(columnVoList);
+ // 获取光伏板点信息
+ List pointList = photovoltaicPanelPointService.lambdaQuery()
+ .select(
+ FacPhotovoltaicPanelPoint::getId,
+ FacPhotovoltaicPanelPoint::getName,
+ FacPhotovoltaicPanelPoint::getPositions,
+ FacPhotovoltaicPanelPoint::getStatus
+ )
+ .eq(FacPhotovoltaicPanelPoint::getProjectId, projectId)
+ .list();
+ List pointVoList = pointList
+ .stream().map(FacPhotovoltaicPanelPointPositionGisVo::obj2vo).toList();
+ matrixPositionGisVo.setPhotovoltaicPanelPointPositionList(pointVoList);
+ // 获取光伏板支架信息
+ List supportList = photovoltaicPanelSupportService.lambdaQuery()
+ .select(
+ FacPhotovoltaicPanelSupport::getId,
+ FacPhotovoltaicPanelSupport::getName,
+ FacPhotovoltaicPanelSupport::getPositions,
+ FacPhotovoltaicPanelSupport::getStatus
+ )
+ .eq(FacPhotovoltaicPanelSupport::getProjectId, projectId)
+ .list();
+ List supportVoList = supportList
+ .stream().map(FacPhotovoltaicPanelSupportPositionGisVo::obj2vo).toList();
+ matrixPositionGisVo.setPhotovoltaicPanelSupportPositionList(supportVoList);
+ // 获取光伏板信息
+ List panelList = photovoltaicPanelService.lambdaQuery()
+ .select(
+ FacPhotovoltaicPanel::getId,
+ FacPhotovoltaicPanel::getName,
+ FacPhotovoltaicPanel::getPositions,
+ FacPhotovoltaicPanel::getStatus
+ )
+ .eq(FacPhotovoltaicPanel::getProjectId, projectId)
+ .eq(FacPhotovoltaicPanel::getProgressCategoryName, "光伏板")
+ .list();
+ List panelVoList = panelList
+ .stream().map(FacPhotovoltaicPanelPositionGisVo::obj2vo).toList();
+ matrixPositionGisVo.setPhotovoltaicPanelPositionList(panelVoList);
+ // 获取箱变信息
+ List boxTransformerList = boxTransformerService.lambdaQuery()
+ .select(
+ FacBoxTransformer::getId,
+ FacBoxTransformer::getName,
+ FacBoxTransformer::getPositions,
+ FacBoxTransformer::getStatus
+ )
+ .eq(FacBoxTransformer::getProjectId, projectId)
+ .eq(FacBoxTransformer::getProgressCategoryName, "箱变基础")
+ .list();
+ List boxTransformerVoList = boxTransformerList
+ .stream().map(FacBoxTransformerPositionGisVo::obj2vo).toList();
+ matrixPositionGisVo.setBoxTransformerPositionList(boxTransformerVoList);
+ // 获取逆变器信息
+ List inverterList = inverterService.lambdaQuery()
+ .select(
+ FacInverter::getId,
+ FacInverter::getName,
+ FacInverter::getPositions,
+ FacInverter::getStatus
+ )
+ .eq(FacInverter::getProjectId, projectId)
+ .eq(FacInverter::getProgressCategoryName, "逆变器安装")
+ .list();
+ List inverterVoList = inverterList
+ .stream().map(FacInverterPositionGisVo::obj2vo).toList();
+ matrixPositionGisVo.setInverterPositionList(inverterVoList);
+ // 封装方阵信息
+ matrixPositionGisVo.setMatrixName(matrix.getMatrixName());
+ matrixPositionGisVo.setId(matrix.getId());
+ String positions = matrix.getPositions();
+ List> positionList = new ArrayList<>();
+ List arr = JSONUtil.toList(positions, String.class);
+ for (String s : arr) {
+ positionList.add(JSONUtil.toList(s, Double.class));
+ }
+ matrixPositionGisVo.setPositions(positionList);
+ return matrixPositionGisVo;
+ }
+
}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/job/cycle/IncSyncYs7DeviceCapturePicData.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/job/cycle/IncSyncYs7DeviceCapturePicData.java
new file mode 100644
index 00000000..aedb090d
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/job/cycle/IncSyncYs7DeviceCapturePicData.java
@@ -0,0 +1,140 @@
+package org.dromara.job.cycle;
+
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.manager.ys7manager.Ys7Manager;
+import org.dromara.other.domain.OthDevicePreset;
+import org.dromara.other.domain.OthYs7Device;
+import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgCreateByCapture;
+import org.dromara.other.domain.enums.OthDeviceStatusEnum;
+import org.dromara.other.service.IOthDevicePresetService;
+import org.dromara.other.service.IOthYs7DeviceImgService;
+import org.dromara.other.service.IOthYs7DeviceService;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+/**
+ * 定时同步萤石设备图片数据
+ *
+ * @author lcj
+ * @date 2025/6/18 15:59
+ */
+@Slf4j
+@Component
+public class IncSyncYs7DeviceCapturePicData {
+
+ @Resource
+ private IOthYs7DeviceService ys7DeviceService;
+
+ @Resource
+ private IOthDevicePresetService devicePresetService;
+
+ @Resource
+ private IOthYs7DeviceImgService ys7DeviceImgService;
+
+ @Resource
+ private Ys7Manager ys7Manager;
+
+ private final ExecutorService executorService = Executors.newFixedThreadPool(5);
+
+ // 每 5 分钟执行一次
+ @Scheduled(cron = "0 */5 * * * ?")
+ public void run() {
+ // 查询所有在线的摄像头设备,仅获取必要字段
+ List deviceList = ys7DeviceService.lambdaQuery()
+ .select(OthYs7Device::getId, OthYs7Device::getDeviceSerial, OthYs7Device::getDeviceName)
+ .eq(OthYs7Device::getStatus, OthDeviceStatusEnum.ONLINE.getValue())
+ .list().subList(0, 10);
+ // 提取设备序列号用于后续查询预置位
+ List deviceSerialList = deviceList.stream()
+ .map(OthYs7Device::getDeviceSerial).toList();
+ // 查询所有相关的摄像头预置位信息
+ List presetList = devicePresetService.lambdaQuery()
+ .in(OthDevicePreset::getDeviceSerial, deviceSerialList)
+ .list();
+ // 将预置位按设备序列号分组,便于后续查找
+ Map> presetMap = presetList.stream()
+ .collect(Collectors.groupingBy(OthDevicePreset::getDeviceSerial));
+ // 存储抓拍图片结果,使用线程安全的列表
+ List imgList = Collections.synchronizedList(new ArrayList<>());
+ // 用于等待所有子任务完成的计数器
+ CountDownLatch latch = new CountDownLatch(deviceList.size());
+ // 遍历每个摄像头设备进行处理
+ for (OthYs7Device ys7Device : deviceList) {
+ executorService.submit(() -> {
+ try {
+ String deviceSerial = ys7Device.getDeviceSerial();
+ List presets = presetMap.get(deviceSerial);
+ // 如果存在预置位,则遍历每个预置位进行抓图
+ if (presets != null && !presets.isEmpty()) {
+ for (OthDevicePreset preset : presets) {
+ OthYs7DeviceImgCreateByCapture img = new OthYs7DeviceImgCreateByCapture();
+ img.setDeviceSerial(deviceSerial);
+ img.setDeviceName(ys7Device.getDeviceName());
+ int channelNo = preset.getChannelNo();
+ int index = preset.getPresetIndex();
+ // 调用摄像头移动到预置位
+ boolean result = ys7Manager.moveDevicePreset(deviceSerial, channelNo, index);
+ if (!result) {
+ log.error("调用摄像头预置位失败:{}", deviceSerial);
+ continue;
+ }
+ // 等待摄像头转动到位
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ log.error("线程中断", e);
+ }
+ // 抓取当前画面图片
+ try {
+ String url = ys7Manager.getCaptureDevicePic(deviceSerial, channelNo, 2);
+ img.setUrl(url);
+ imgList.add(img);
+ } catch (Exception e) {
+ log.error("摄像头 {} 通道:{},预置点序号:{},抓图失败:{}", deviceSerial, channelNo, index, e.getMessage());
+ }
+ }
+ } else {
+ // 如果没有预置位,则直接对默认通道抓图
+ OthYs7DeviceImgCreateByCapture img = new OthYs7DeviceImgCreateByCapture();
+ img.setDeviceSerial(deviceSerial);
+ img.setDeviceName(ys7Device.getDeviceName());
+ try {
+ String url = ys7Manager.getCaptureDevicePic(deviceSerial, 1, 2);
+ img.setUrl(url);
+ imgList.add(img);
+ } catch (Exception e) {
+ log.error("摄像头 {} 抓图失败:{}", deviceSerial, e.getMessage());
+ }
+ }
+ } catch (Exception ex) {
+ log.error("设备处理异常:{}", ys7Device.getDeviceSerial(), ex);
+ } finally {
+ // 不论成功与否,都减少计数器
+ latch.countDown();
+ }
+ });
+ }
+ // 等待所有设备处理完成
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ log.error("主线程中断", e);
+ }
+ // 输出抓图结果日志
+ log.info("获取图片完成,共 {} 张:{}", imgList.size(), imgList);
+ ys7DeviceImgService.saveCapturePic(imgList);
+ }
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7Constant.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7Constant.java
index 65548b13..0fd0c1a5 100644
--- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7Constant.java
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7Constant.java
@@ -50,4 +50,10 @@ public interface Ys7Constant {
* 清除设备预置点请求地址 Post
*/
String deleteDevicePresetUrlByPost = "https://open.ys7.com/api/lapp/device/preset/clear";
+
+ /**
+ * 设备抓拍照片请求地址 Post
+ */
+ String captureDeviceUrlByPost = "https://open.ys7.com/api/lapp/device/capture";
+
}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7Manager.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7Manager.java
index 8ad95d51..3c3f3734 100644
--- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7Manager.java
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7Manager.java
@@ -111,4 +111,16 @@ public class Ys7Manager {
public Boolean deleteDevicePreset(String deviceSerial, int channelNo, int index) {
return Ys7RequestUtils.deleteDevicePreset(getToken(), deviceSerial, channelNo, index);
}
+
+ /**
+ * 获取设备图片
+ *
+ * @param deviceSerial 设备序列号
+ * @param channelNo 通道号
+ * @param quality 视频清晰度,0-流畅,1-高清(720P),2-4CIF,3-1080P,4-400w
+ * @return 抓拍后的图片路径
+ */
+ public String getCaptureDevicePic(String deviceSerial, int channelNo, int quality) {
+ return Ys7RequestUtils.getCaptureDevicePic(getToken(), deviceSerial, channelNo, quality);
+ }
}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7RequestUtils.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7RequestUtils.java
index a6015e34..af0dce1c 100644
--- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7RequestUtils.java
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/manager/ys7manager/Ys7RequestUtils.java
@@ -249,4 +249,46 @@ public class Ys7RequestUtils {
}
}
+ /**
+ * 抓拍设备图片
+ *
+ * @param accessToken accessToken
+ * @param deviceSerial 设备序列号
+ * @param channelNo 通道号,IPC设备填写1
+ * @param quality 视频清晰度,0-流畅,1-高清(720P),2-4CIF,3-1080P,4-400w
+ * @return 抓拍后的图片路径,图片保存有效期为2小时
+ */
+ public static String getCaptureDevicePic(String accessToken, String deviceSerial, int channelNo, int quality) {
+ if (StringUtils.isAnyBlank(accessToken, deviceSerial)) {
+ throw new ServiceException("抓拍设备图片参数为空", HttpStatus.BAD_REQUEST);
+ }
+ if (quality < 0 || quality > 4) {
+ quality = 0;
+ }
+ HashMap paramMap = new HashMap<>();
+ paramMap.put("accessToken", accessToken);
+ paramMap.put("deviceSerial", deviceSerial);
+ paramMap.put("channelNo", channelNo);
+ paramMap.put("quality", quality);
+ String errorMsg = "抓拍设备图片请求失败";
+ try (HttpResponse response = HttpRequest.post(Ys7Constant.captureDeviceUrlByPost)
+ .form(paramMap)
+ .execute()) {
+ if (!response.isOk()) {
+ log.error("{}:{}", errorMsg, response.getStatus());
+ throw new ServiceException(errorMsg + response.getStatus());
+ }
+ String body = response.body();
+ Ys7ResponseVo responseVo = JSONUtil.toBean(body, Ys7ResponseVo.class);
+ if (!responseVo.getCode().equals("200")) {
+ log.error("{}:{}", errorMsg, responseVo.getMsg());
+ throw new ServiceException(errorMsg + responseVo.getMsg());
+ }
+ String data = responseVo.getData();
+ String picUrl = JSONUtil.parseObj(data).getStr("picUrl");
+ log.info("抓拍设备图片请求成功,设备[{}]抓拍成功,通道:{},url:{}", deviceSerial, channelNo, picUrl);
+ return picUrl;
+ }
+ }
+
}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/constant/Ys7DeviceImgConstant.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/constant/Ys7DeviceImgConstant.java
new file mode 100644
index 00000000..a7baa4e7
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/constant/Ys7DeviceImgConstant.java
@@ -0,0 +1,32 @@
+package org.dromara.other.constant;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.IdUtil;
+import org.dromara.common.core.utils.DateUtils;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 19:11
+ */
+public interface Ys7DeviceImgConstant {
+
+ /**
+ * 设备图片oss前缀
+ */
+ String DEVICE_IMG_OSS_URL_PREFIX = "ys7/device/img/";
+
+ /**
+ * 获取设备图片oss路径
+ *
+ * @param originalFilename 文件名原始名
+ * @param deviceSerial 设备序列号
+ * @return oss路径
+ */
+ static String getDeviceImgOssPath(String originalFilename, String deviceSerial) {
+ String suffix = FileUtil.getSuffix(originalFilename);
+ String uuid = IdUtil.fastSimpleUUID();
+ String date = DateUtils.getDate();
+ String fileName = String.format("%s_%s.%s", date, uuid, suffix);
+ return DEVICE_IMG_OSS_URL_PREFIX + deviceSerial + "/" + fileName;
+ }
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/controller/OthYs7DeviceImgController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/controller/OthYs7DeviceImgController.java
new file mode 100644
index 00000000..3d0c111e
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/controller/OthYs7DeviceImgController.java
@@ -0,0 +1,68 @@
+package org.dromara.other.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotNull;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgQueryReq;
+import org.dromara.other.domain.vo.ys7deviceimg.OthYs7DeviceImgVo;
+import org.dromara.other.service.IOthYs7DeviceImgService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 萤石摄像头图片
+ *
+ * @author lcj
+ * @date 2025-06-18
+ */
+@Validated
+@RestController
+@RequestMapping("/other/ys7DeviceImg")
+public class OthYs7DeviceImgController extends BaseController {
+
+ @Resource
+ private IOthYs7DeviceImgService othYs7DeviceImgService;
+
+ /**
+ * 查询萤石摄像头图片列表
+ */
+ @SaCheckPermission("other:ys7DeviceImg:list")
+ @GetMapping("/list")
+ public TableDataInfo list(OthYs7DeviceImgQueryReq req, PageQuery pageQuery) {
+ return othYs7DeviceImgService.queryPageList(req, pageQuery);
+ }
+
+ /**
+ * 导出萤石摄像头图片列表
+ */
+ @SaCheckPermission("other:ys7DeviceImg:export")
+ @Log(title = "萤石摄像头图片", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(OthYs7DeviceImgQueryReq req, HttpServletResponse response) {
+ List list = othYs7DeviceImgService.queryList(req);
+ ExcelUtil.exportExcel(list, "萤石摄像头图片", OthYs7DeviceImgVo.class, response);
+ }
+
+ /**
+ * 获取萤石摄像头图片详细信息
+ *
+ * @param id 主键
+ */
+ @SaCheckPermission("other:ys7DeviceImg:query")
+ @GetMapping("/{id}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable Long id) {
+ return R.ok(othYs7DeviceImgService.queryById(id));
+ }
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/OthYs7DeviceImg.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/OthYs7DeviceImg.java
new file mode 100644
index 00000000..f59417ae
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/OthYs7DeviceImg.java
@@ -0,0 +1,60 @@
+package org.dromara.other.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 萤石摄像头图片对象 oth_ys7_device_img
+ *
+ * @author lcj
+ * @date 2025-06-18
+ */
+@Data
+@TableName("oth_ys7_device_img")
+public class OthYs7DeviceImg implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 设备序列号
+ */
+ private String deviceSerial;
+
+ /**
+ * 设备名称
+ */
+ private String deviceName;
+
+ /**
+ * 图片地址
+ */
+ private String url;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/dto/ys7deviceimg/OthYs7DeviceImgCreateByCapture.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/dto/ys7deviceimg/OthYs7DeviceImgCreateByCapture.java
new file mode 100644
index 00000000..76d51e52
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/dto/ys7deviceimg/OthYs7DeviceImgCreateByCapture.java
@@ -0,0 +1,33 @@
+package org.dromara.other.domain.dto.ys7deviceimg;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 18:34
+ */
+@Data
+public class OthYs7DeviceImgCreateByCapture implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 9152300524686055187L;
+
+ /**
+ * 设备序列号
+ */
+ private String deviceSerial;
+
+ /**
+ * 设备名称
+ */
+ private String deviceName;
+
+ /**
+ * 图片地址
+ */
+ private String url;
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/dto/ys7deviceimg/OthYs7DeviceImgQueryReq.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/dto/ys7deviceimg/OthYs7DeviceImgQueryReq.java
new file mode 100644
index 00000000..36c3e97c
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/dto/ys7deviceimg/OthYs7DeviceImgQueryReq.java
@@ -0,0 +1,28 @@
+package org.dromara.other.domain.dto.ys7deviceimg;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @author lcj
+ * @date 2025/6/18 15:06
+ */
+@Data
+public class OthYs7DeviceImgQueryReq implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 5264959525029608917L;
+
+ /**
+ * 设备序列号
+ */
+ private String deviceSerial;
+
+ /**
+ * 设备名称
+ */
+ private String deviceName;
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/vo/ys7deviceimg/OthYs7DeviceImgVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/vo/ys7deviceimg/OthYs7DeviceImgVo.java
new file mode 100644
index 00000000..084f34ac
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/domain/vo/ys7deviceimg/OthYs7DeviceImgVo.java
@@ -0,0 +1,58 @@
+package org.dromara.other.domain.vo.ys7deviceimg;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.other.domain.OthYs7DeviceImg;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * 萤石摄像头图片视图对象 oth_ys7_device_img
+ *
+ * @author lcj
+ * @date 2025-06-18
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = OthYs7DeviceImg.class)
+public class OthYs7DeviceImgVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @ExcelProperty(value = "主键id")
+ private Long id;
+
+ /**
+ * 设备序列号
+ */
+ @ExcelProperty(value = "设备序列号")
+ private String deviceSerial;
+
+ /**
+ * 设备名称
+ */
+ @ExcelProperty(value = "设备名称")
+ private String deviceName;
+
+ /**
+ * 图片地址
+ */
+ @ExcelProperty(value = "图片地址")
+ private String url;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/IOthYs7DeviceImgService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/IOthYs7DeviceImgService.java
new file mode 100644
index 00000000..b90a3b98
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/IOthYs7DeviceImgService.java
@@ -0,0 +1,78 @@
+package org.dromara.other.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.other.domain.OthYs7DeviceImg;
+import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgCreateByCapture;
+import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgQueryReq;
+import org.dromara.other.domain.vo.ys7deviceimg.OthYs7DeviceImgVo;
+
+import java.util.List;
+
+/**
+ * 萤石摄像头图片Service接口
+ *
+ * @author lcj
+ * @date 2025-06-18
+ */
+public interface IOthYs7DeviceImgService extends IService {
+
+ /**
+ * 查询萤石摄像头图片
+ *
+ * @param id 主键
+ * @return 萤石摄像头图片
+ */
+ OthYs7DeviceImgVo queryById(Long id);
+
+ /**
+ * 分页查询萤石摄像头图片列表
+ *
+ * @param req 查询条件
+ * @param pageQuery 分页参数
+ * @return 萤石摄像头图片分页列表
+ */
+ TableDataInfo queryPageList(OthYs7DeviceImgQueryReq req, PageQuery pageQuery);
+
+ /**
+ * 查询符合条件的萤石摄像头图片列表
+ *
+ * @param req 查询条件
+ * @return 萤石摄像头图片列表
+ */
+ List queryList(OthYs7DeviceImgQueryReq req);
+
+ /**
+ * 获取萤石摄像头图片视图
+ *
+ * @param ys7DeviceImg 萤石摄像头图片
+ * @return 萤石摄像头图片视图
+ */
+ OthYs7DeviceImgVo getVo(OthYs7DeviceImg ys7DeviceImg);
+
+ /**
+ * 构建查询条件封装
+ *
+ * @param req 查询条件
+ * @return 查询条件封装
+ */
+ LambdaQueryWrapper buildQueryWrapper(OthYs7DeviceImgQueryReq req);
+
+ /**
+ * 获取萤石摄像头图片分页对象视图
+ *
+ * @param ys7DeviceImgPage 萤石摄像头图片分页对象
+ * @return 萤石摄像头图片分页对象视图
+ */
+ Page getVoPage(Page ys7DeviceImgPage);
+
+ /**
+ * 保存抓拍图片
+ *
+ * @param imgList 抓拍图片列表
+ */
+ void saveCapturePic(List imgList);
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/impl/OthYs7DeviceImgServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/impl/OthYs7DeviceImgServiceImpl.java
new file mode 100644
index 00000000..6bab0781
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/other/service/impl/OthYs7DeviceImgServiceImpl.java
@@ -0,0 +1,186 @@
+package org.dromara.other.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import jakarta.annotation.Resource;
+import org.dromara.common.core.constant.HttpStatus;
+import org.dromara.common.core.exception.ServiceException;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.other.constant.Ys7DeviceImgConstant;
+import org.dromara.other.domain.OthYs7DeviceImg;
+import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgCreateByCapture;
+import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgQueryReq;
+import org.dromara.other.domain.vo.ys7deviceimg.OthYs7DeviceImgVo;
+import org.dromara.other.mapper.OthYs7DeviceImgMapper;
+import org.dromara.other.service.IOthYs7DeviceImgService;
+import org.dromara.system.domain.vo.SysOssUploadVo;
+import org.dromara.system.service.ISysOssService;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 萤石摄像头图片Service业务层处理
+ *
+ * @author lcj
+ * @date 2025-06-18
+ */
+@Service
+public class OthYs7DeviceImgServiceImpl extends ServiceImpl
+ implements IOthYs7DeviceImgService {
+
+ @Resource
+ private ISysOssService ossService;
+
+ /**
+ * 查询萤石摄像头图片
+ *
+ * @param id 主键
+ * @return 萤石摄像头图片
+ */
+ @Override
+ public OthYs7DeviceImgVo queryById(Long id) {
+ OthYs7DeviceImg ys7DeviceImg = this.getById(id);
+ if (ys7DeviceImg == null) {
+ throw new ServiceException("萤石摄像头图片信息不存在", HttpStatus.NOT_FOUND);
+ }
+ return this.getVo(ys7DeviceImg);
+ }
+
+ /**
+ * 分页查询萤石摄像头图片列表
+ *
+ * @param req 查询条件
+ * @param pageQuery 分页参数
+ * @return 萤石摄像头图片分页列表
+ */
+ @Override
+ public TableDataInfo queryPageList(OthYs7DeviceImgQueryReq req, PageQuery pageQuery) {
+ Page result = this.page(pageQuery.build(), this.buildQueryWrapper(req));
+ return TableDataInfo.build(this.getVoPage(result));
+ }
+
+ /**
+ * 查询符合条件的萤石摄像头图片列表
+ *
+ * @param req 查询条件
+ * @return 萤石摄像头图片列表
+ */
+ @Override
+ public List queryList(OthYs7DeviceImgQueryReq req) {
+ LambdaQueryWrapper lqw = this.buildQueryWrapper(req);
+ return this.list(lqw).stream().map(this::getVo).toList();
+ }
+
+ /**
+ * 获取萤石摄像头图片视图
+ *
+ * @param ys7DeviceImg 萤石摄像头图片
+ * @return 萤石摄像头图片视图
+ */
+ @Override
+ public OthYs7DeviceImgVo getVo(OthYs7DeviceImg ys7DeviceImg) {
+ OthYs7DeviceImgVo vo = new OthYs7DeviceImgVo();
+ if (ys7DeviceImg == null) {
+ return vo;
+ }
+ BeanUtils.copyProperties(ys7DeviceImg, vo);
+ return vo;
+ }
+
+ /**
+ * 构建查询条件封装
+ *
+ * @param req 查询条件
+ * @return 查询条件封装
+ */
+ @Override
+ public LambdaQueryWrapper buildQueryWrapper(OthYs7DeviceImgQueryReq req) {
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ if (req == null) {
+ return lqw;
+ }
+ String deviceSerial = req.getDeviceSerial();
+ String deviceName = req.getDeviceName();
+ lqw.like(StringUtils.isNotBlank(deviceSerial), OthYs7DeviceImg::getDeviceSerial, deviceSerial);
+ lqw.like(StringUtils.isNotBlank(deviceName), OthYs7DeviceImg::getDeviceName, deviceName);
+ return lqw;
+ }
+
+ /**
+ * 获取萤石摄像头图片分页对象视图
+ *
+ * @param ys7DeviceImgPage 萤石摄像头图片分页对象
+ * @return 萤石摄像头图片分页对象视图
+ */
+ @Override
+ public Page getVoPage(Page ys7DeviceImgPage) {
+ List ys7DeviceImgList = ys7DeviceImgPage.getRecords();
+ Page ys7DeviceImgVoPage = new Page<>(
+ ys7DeviceImgPage.getCurrent(),
+ ys7DeviceImgPage.getSize(),
+ ys7DeviceImgPage.getTotal()
+ );
+ if (CollUtil.isEmpty(ys7DeviceImgList)) {
+ return ys7DeviceImgVoPage;
+ }
+ List ys7DeviceImgVoList = ys7DeviceImgList.stream().map(this::getVo).toList();
+ ys7DeviceImgVoPage.setRecords(ys7DeviceImgVoList);
+ return ys7DeviceImgVoPage;
+ }
+
+ /**
+ * 保存抓拍图片
+ *
+ * @param imgList 抓拍图片列表
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void saveCapturePic(List imgList) {
+ List saveList = new ArrayList<>();
+ for (OthYs7DeviceImgCreateByCapture img : imgList) {
+ OthYs7DeviceImg othYs7DeviceImg = new OthYs7DeviceImg();
+ String url = img.getUrl();
+ String deviceSerial = img.getDeviceSerial();
+ String originalFilename = extractFilename(url);
+ String deviceImgOssPath = Ys7DeviceImgConstant.getDeviceImgOssPath(originalFilename, deviceSerial);
+ SysOssUploadVo uploadVo = ossService.uploadFileUrlWithNoSave(url, deviceImgOssPath);
+ String ossUrl = uploadVo.getUrl();
+ if (StringUtils.isNotBlank(ossUrl)) {
+ othYs7DeviceImg.setDeviceSerial(deviceSerial);
+ othYs7DeviceImg.setDeviceName(img.getDeviceName());
+ othYs7DeviceImg.setUrl(ossUrl);
+ saveList.add(othYs7DeviceImg);
+ }
+ }
+ if (CollUtil.isNotEmpty(saveList)) {
+ boolean result = saveBatch(saveList);
+ if (!result) {
+ throw new ServiceException("批量新增图片失败,数据库异常", HttpStatus.ERROR);
+ }
+ }
+ }
+
+ /**
+ * 提取文件名
+ *
+ * @param url 文件路径
+ * @return 文件名
+ */
+ public static String extractFilename(String url) {
+ int start = url.lastIndexOf("/") + 1;
+ int end = url.indexOf("?", start);
+ if (start > 0 && end > start) {
+ return url.substring(start, end);
+ }
+ return null;
+ }
+
+}
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java
index e789799e..b776d404 100644
--- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java
@@ -70,6 +70,15 @@ public interface ISysOssService {
*/
SysOssUploadVo uploadWithNoSave(MultipartFile file, String filePath);
+ /**
+ * 通过 url 上传到对象存储服务,不保存文件信息到数据库
+ *
+ * @param fileUrl 要上传的文件url
+ * @param filePath 文件路径
+ * @return 上传成功后的 SysOssVo 对象,包含文件信息
+ */
+ SysOssUploadVo uploadFileUrlWithNoSave(String fileUrl, String filePath);
+
/**
* 上传文件到对象存储服务,并保存文件信息到数据库
*
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java
index bd054508..acb47cd6 100644
--- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java
@@ -2,6 +2,7 @@ package org.dromara.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
+import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -35,8 +36,13 @@ import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
@@ -250,6 +256,41 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
return uploadVo;
}
+ /**
+ * 通过 url 上传到对象存储服务,不保存文件信息到数据库
+ *
+ * @param fileUrl 要上传的文件url
+ * @param filePath 文件路径
+ * @return 上传成功后的 SysOssVo 对象,包含文件信息
+ */
+ @Override
+ public SysOssUploadVo uploadFileUrlWithNoSave(String fileUrl, String filePath) {
+ UploadResult uploadResult;
+ try {
+ // 1. 打开远程连接获取 InputStream
+ URI uri = URI.create(fileUrl);
+ URL url = uri.toURL();
+ URLConnection conn = url.openConnection();
+ InputStream inputStream = conn.getInputStream();
+ // 2. 获取内容长度和类型(部分服务器可能返回为 -1)
+ long length = conn.getContentLengthLong(); // 有些服务可能为 -1,需要兜底处理
+ String contentType = conn.getContentType();
+ if (length <= 0) {
+ byte[] bytes = IoUtil.readBytes(inputStream);
+ length = bytes.length;
+ inputStream = new ByteArrayInputStream(bytes); // 重置为 ByteArrayInputStream
+ }
+ // 3. 上传
+ OssClient storage = OssFactory.instance();
+ uploadResult = storage.upload(inputStream, filePath, length, contentType);
+ } catch (Exception e) {
+ throw new ServiceException(e.getMessage());
+ }
+ SysOssUploadVo uploadVo = new SysOssUploadVo();
+ uploadVo.setUrl(uploadResult.getUrl());
+ return uploadVo;
+ }
+
/**
* 上传文件到对象存储服务,并保存文件信息到数据库
*
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/other/OthDevicePresetMapper.xml b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/other/OthDevicePresetMapper.xml
index 25cffab8..d4f59454 100644
--- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/other/OthDevicePresetMapper.xml
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/other/OthDevicePresetMapper.xml
@@ -1,7 +1,7 @@
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/other/OthYs7DeviceImgMapper.xml b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/other/OthYs7DeviceImgMapper.xml
new file mode 100644
index 00000000..f88a8b30
--- /dev/null
+++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/resources/mapper/other/OthYs7DeviceImgMapper.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/xinnengyuan/script/sql/menuInitValue.sql b/xinnengyuan/script/sql/menuInitValue.sql
index 41b1304f..742e66ea 100644
--- a/xinnengyuan/script/sql/menuInitValue.sql
+++ b/xinnengyuan/script/sql/menuInitValue.sql
@@ -537,3 +537,23 @@ values(1933445976098406405, '摄像头预置位删除', 1933445976098406401, '4'
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(1933445976098406406, '摄像头预置位导出', 1933445976098406401, '5', '#', '', 1, 0, 'F', '0', '0', 'other:devicePreset:export', '#', 103, 1, sysdate(), null, null, '');
+
+-- 菜单 SQL
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
+values(1935231471757307906, '萤石摄像头图片', '1933345067448147969', '1', 'ys7DeviceImg', 'other/ys7DeviceImg/index', 1, 0, 'C', '0', '0', 'other:ys7DeviceImg:list', '#', 103, 1, sysdate(), null, null, '萤石摄像头图片菜单');
+
+-- 按钮 SQL
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
+values(1935231471757307907, '萤石摄像头图片查询', 1935231471757307906, '1', '#', '', 1, 0, 'F', '0', '0', 'other:ys7DeviceImg:query', '#', 103, 1, sysdate(), null, null, '');
+
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
+values(1935231471757307908, '萤石摄像头图片新增', 1935231471757307906, '2', '#', '', 1, 0, 'F', '0', '0', 'other:ys7DeviceImg:add', '#', 103, 1, sysdate(), null, null, '');
+
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
+values(1935231471757307909, '萤石摄像头图片修改', 1935231471757307906, '3', '#', '', 1, 0, 'F', '0', '0', 'other:ys7DeviceImg:edit', '#', 103, 1, sysdate(), null, null, '');
+
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
+values(1935231471757307910, '萤石摄像头图片删除', 1935231471757307906, '4', '#', '', 1, 0, 'F', '0', '0', 'other:ys7DeviceImg:remove', '#', 103, 1, sysdate(), null, null, '');
+
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
+values(1935231471757307911, '萤石摄像头图片导出', 1935231471757307906, '5', '#', '', 1, 0, 'F', '0', '0', 'other:ys7DeviceImg:export', '#', 103, 1, sysdate(), null, null, '');
diff --git a/xinnengyuan/script/sql/xinnengyuan.sql b/xinnengyuan/script/sql/xinnengyuan.sql
index b56ede45..b40a674a 100644
--- a/xinnengyuan/script/sql/xinnengyuan.sql
+++ b/xinnengyuan/script/sql/xinnengyuan.sql
@@ -1102,5 +1102,20 @@ CREATE TABLE `oth_device_preset`
`preset_name` varchar(255) null comment '预置点',
`create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间',
`update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
- primary key (`id`) using btree
+ primary key (`id`) using btree,
+ index `idx_device_serial` (`device_serial` asc) using btree comment '设备序列号'
) comment = '摄像头预置位' collate = utf8mb4_unicode_ci;
+
+DROP TABLE IF EXISTS `oth_ys7_device_img`;
+CREATE TABLE `oth_ys7_device_img`
+(
+ `id` bigint not null auto_increment comment '主键id',
+ `device_serial` varchar(255) not null comment '设备序列号',
+ `device_name` varchar(255) null comment '设备名称',
+ `url` varchar(512) not null comment '图片地址',
+ `remark` varchar(512) null comment '备注',
+ `create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间',
+ `update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
+ primary key (`id`) using btree,
+ index `idx_device_serial` (`device_serial` asc) using btree comment '设备序列号'
+) comment = '萤石摄像头图片' collate = utf8mb4_unicode_ci;