Quellcode durchsuchen

Merge branch 'master' of http://222.243.138.146:2000/hmy/hnyz_dcs

HMY vor 7 Monaten
Ursprung
Commit
c80a7456a1

+ 1 - 0
admin/src/main/java/com/dcs/equipment/service/impl/ModbusTcpServiceImpl.java

@@ -156,6 +156,7 @@ public class ModbusTcpServiceImpl implements ProtocolService {
             values = ModbusUtil.getValues(request);
         } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException | DeviceIOException e) {
             logger.error("获取设备数据失败:{}", e.getMessage());
+            logger.error("设备请求:{}", request);
             throw new RuntimeException(e.getMessage());
         }
         return values;

+ 5 - 1
admin/src/main/java/com/dcs/equipment/task/ModbusTcpTask.java

@@ -14,6 +14,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
 
@@ -51,6 +52,9 @@ public class ModbusTcpTask {
     // 保存设备寄存器信息和数据地址
     public static volatile List<EquipmentParam> equipmentParamList;
 
+    @Value("${dcs.influxdb.bucket}")
+    private String influxDBBucket;
+
     @PostConstruct
     private void init() {
         deviceService.updateEquipmentCodes();
@@ -100,7 +104,7 @@ public class ModbusTcpTask {
         CacheCenter.registerNowDataMap= EquipmentParamUtils.paramListToMap(broadCastEquipmentParamFormVOList);
         // 保存数据到influxdb
         CompletableFuture.runAsync(() ->
-                influxDBService.saveDataToInfluxDB("shanghai_dcs_bucket", deepCopyEquipmentParamFormVOList)
+                influxDBService.saveDataToInfluxDB(influxDBBucket, deepCopyEquipmentParamFormVOList)
         , scheduledExecutorService);
     }
 

+ 74 - 45
admin/src/main/java/com/dcs/equipment/utils/ModbusUtil.java

@@ -23,7 +23,9 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.ReentrantLock;
 
 import static com.dcs.equipment.constants.ModbusConstants.*;
 import static com.dcs.equipment.domain.ModbusTcpEnum.DATA_ADDRESS_LENGTH_MAP;
@@ -39,63 +41,84 @@ public class ModbusUtil {
 
     private static final ExecutorService ModbusThreadPoolTaskExecutor = Executors.newFixedThreadPool(10);
 
-    @Value("${dcs.device.reconnectLimit}")
-    private static int reconnectLimit;
+    private static volatile int reconnectLimit = 3;
 
-    private static Map<String, ModbusMaster> masters = new HashMap<>();
-    private static Map<String, AtomicBoolean> reconnectingStatus = new HashMap<>();
+    @Value("${dcs.device.reconnectLimit:3}")
+    public void setReconnectLimit(int limit) { ModbusUtil.reconnectLimit = limit; }
+
+    private static final ConcurrentHashMap<String, ModbusMaster> masters = new ConcurrentHashMap<>();
+    private static final ConcurrentHashMap<String, AtomicBoolean> reconnectingStatus = new ConcurrentHashMap<>();
+    private static final ConcurrentHashMap<String, ReentrantLock> urlLocks = new ConcurrentHashMap<>();
+
+    private static ReentrantLock getUrlLock(String url) {
+        return urlLocks.computeIfAbsent(url, k -> new ReentrantLock());
+    }
 
     public static ModbusMaster connect(String host, Integer port) throws ModbusIOException, UnknownHostException {
         String url = host + ":" + port;
-        logger.info("正在连接到 ModbusTCP {} 服务端", url);
-        TcpParameters tcpParameters = new TcpParameters();
-        InetAddress address = null;
-        try {
-            address = InetAddress.getByName(host);
-        } catch (UnknownHostException e) {
-            logger.error("ModbusTCP {} 地址解析失败: {}", url, e.getMessage());
-            throw new UnknownHostException("ModbusTCP " + url + " 地址解析失败");
+        // fast path: already connected
+        ModbusMaster fastExisting = masters.get(url);
+        if (fastExisting != null && fastExisting.isConnected()) {
+            return fastExisting;
         }
-        tcpParameters.setHost(address);
-        tcpParameters.setPort(port);
-        tcpParameters.setKeepAlive(true);
-        Modbus.setAutoIncrementTransactionId(true);
-        ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
+        ReentrantLock lock = getUrlLock(url);
+        lock.lock();
         try {
-            master.connect();
-            masters.put(url, master);
-            reconnectingStatus.put(url, new AtomicBoolean(false));
-            logger.info("与 ModbusTCP {} 连接成功", url);
-        } catch (ModbusIOException e) {
-            logger.error("与 ModbusTCP {} 连接失败: {}", url, e.getMessage());
-            throw new ModbusIOException("ModbusTCP " + url + " 连接失败");
+            ModbusMaster existing = masters.get(url);
+            if (existing != null && existing.isConnected()) {
+                return existing;
+            }
+
+            logger.info("正在连接到 ModbusTCP {} 服务端", url);
+            TcpParameters tcpParameters = new TcpParameters();
+            InetAddress address;
+            try {
+                address = InetAddress.getByName(host);
+            } catch (UnknownHostException e) {
+                logger.error("ModbusTCP {} 地址解析失败: {}", url, e.getMessage());
+                throw new UnknownHostException("ModbusTCP " + url + " 地址解析失败");
+            }
+            tcpParameters.setHost(address);
+            tcpParameters.setPort(port);
+            tcpParameters.setKeepAlive(true);
+            Modbus.setAutoIncrementTransactionId(true);
+            ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
+            try {
+                master.connect();
+                masters.put(url, master);
+                reconnectingStatus.computeIfAbsent(url, k -> new AtomicBoolean(false));
+                logger.info("与 ModbusTCP {} 连接成功", url);
+            } catch (ModbusIOException e) {
+                logger.error("与 ModbusTCP {} 连接失败: {}", url, e.getMessage());
+                throw new ModbusIOException("ModbusTCP " + url + " 连接失败");
+            }
+            return masters.get(url);
+        } finally {
+            lock.unlock();
         }
-        return master;
     }
 
     private static void reconnect(String host, Integer port) throws DeviceIOException {
         String url = host + ":" + port;
-        AtomicBoolean reconnecting = reconnectingStatus.get(url);
+        AtomicBoolean reconnecting = reconnectingStatus.computeIfAbsent(url, k -> new AtomicBoolean(false));
         if (reconnecting.get()) return;
 
         if (reconnecting.compareAndSet(false, true)) {
             CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                 try {
                     for (int i = 0; i < reconnectLimit; i++) { // 单次重连 最多尝试次数
-                        ModbusMaster master = masters.get(url);
                         logger.warn("ModbusTCP {} 连接断开,开始重连...", url);
                         try {
-                            connect(host, port);
+                            ModbusMaster newMaster = connect(host, port);
+                            if (newMaster != null && newMaster.isConnected()) {
+                                logger.info("ModbusTCP {} 重连成功!", url);
+                                break;
+                            }
                         } catch (UnknownHostException e) {
                             throw new RuntimeException(e);
                         } catch (ModbusIOException e) {
                             if (i == reconnectLimit - 1) throw new RuntimeException(e);
                         }
-                        if (master.isConnected()) {
-                            logger.info("ModbusTCP {} 重连成功!", url);
-                            break;
-                        }
-
                         try {
                             Thread.sleep(1000); // 每次重试间隔 1 秒
                         } catch (InterruptedException e) {
@@ -125,19 +148,23 @@ public class ModbusUtil {
     }
 
     public static void disconnect(String host, Integer port) {
-        String url = host+":"+port;
-        ModbusMaster master= masters.get(url);
+        String url = host + ":" + port;
+        ReentrantLock lock = getUrlLock(url);
+        lock.lock();
         try {
-            master.disconnect();
-            if (masters.containsKey(url)) {
-                masters.remove(url);
-            }
-            if (reconnectingStatus.containsKey(url)) {
-                reconnectingStatus.remove(url);
+            ModbusMaster master = masters.get(url);
+            if (master != null) {
+                try {
+                    master.disconnect();
+                } catch (ModbusIOException e) {
+                    logger.error("与 ModbusTCP {} 断开连接失败: {}", url, e.getMessage());
+                }
             }
+            masters.remove(url);
+            reconnectingStatus.remove(url);
             logger.info("ModbusTCP {} 断开连接", url);
-        } catch (ModbusIOException e) {
-            logger.error("与 ModbusTCP {} 断开连接失败: {}", url, e.getMessage());
+        } finally {
+            lock.unlock();
         }
     }
     @PreDestroy
@@ -311,8 +338,9 @@ public class ModbusUtil {
     }
 
     private static ModbusMaster getMaster(String host, Integer port) throws DeviceIOException {
-        ModbusMaster master = masters.get(host+":"+port);
-        if (master == null){
+        String url = host + ":" + port;
+        ModbusMaster master = masters.get(url);
+        if (master == null) {
             try {
                 return connect(host, port);
             } catch (ModbusIOException | UnknownHostException e) {
@@ -321,6 +349,7 @@ public class ModbusUtil {
         }
         if (!master.isConnected()) {
             reconnect(host, port);
+            master = masters.get(url);
         }
         return master;
     }

+ 190 - 0
admin/src/main/java/com/dcs/equipment/utils/OpcuaUtil.java

@@ -0,0 +1,190 @@
+package com.dcs.equipment.utils;
+
+import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
+import org.eclipse.milo.opcua.stack.core.UaException;
+import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
+import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
+import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+
+import javax.annotation.PreDestroy;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * @author: wangpx
+ * @date: 2025-05-26 14:53
+ */
+public class OpcuaUtil {
+    private static final Logger logger = LoggerFactory.getLogger("OPCUA");
+
+    private static final ExecutorService ModbusThreadPoolTaskExecutor = Executors.newFixedThreadPool(10);
+
+    @Value("${dcs.device.reconnectLimit}")
+    private static int reconnectLimit;
+
+    private static Map<String, OpcUaClient> clients = new HashMap<>();
+    // 检查是否连接并自动重连
+    private static Map<String, AtomicBoolean> reconnectingStatus = new HashMap<>();
+
+    // 创建并连接客户端
+    public static void connect(String host, Integer port) {
+        String URL = "opc.tcp://" + host + ":" + port;
+        try {
+            logger.info("正在连接到 OPC UA {} 服务端", host+":"+port);
+            OpcUaClient client = OpcUaClient.create(URL);
+            client.connect().get();
+            clients.put(host+":"+port, client);
+            reconnectingStatus.put(host+":"+port, new AtomicBoolean(false));
+            logger.info("OPC UA {} 客户端连接成功", host+":"+port);
+        } catch (UaException e) {
+            logger.error("OPC UA 客户端连接失败: {}", e.getMessage());
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            logger.error("连接线程中断: {}", e.getMessage());
+        } catch (ExecutionException e) {
+            logger.error("OPC UA {} 客户端连接失败: {}", host+":"+port, e.getMessage());
+        }
+    }
+
+    private static void reconnect(String host, Integer port) {
+        OpcUaClient client = clients.get(host+":"+port);
+        if (client == null || client.getSession() == null || !client.getSession().isDone()) {
+            logger.warn("检测到 OPC UA 客户端连接中断。");
+            AtomicBoolean reconnecting = reconnectingStatus.get(host+":"+port);
+            if (reconnecting.compareAndSet(false, true)) {
+                try {
+                    logger.info("尝试重新连接 OPC UA 服务器: {}", host);
+                    connect(host, port);
+                    logger.info("重连成功。");
+                } catch (Exception e) {
+                    logger.error("重连 OPC UA 失败: {}", e.getMessage());
+                } finally {
+                    reconnecting.set(false);
+                }
+            } else {
+                logger.debug("已有线程正在重连,当前线程跳过连接尝试。");
+            }
+        }
+    }
+
+    public static void disconnect(String host, Integer port) {
+        OpcUaClient client = clients.get(host+":"+port);
+        try {
+            if (client != null && client.getSession() != null && client.getSession().isDone()) {
+                client.disconnect().get();
+                logger.info("OPC UA 客户端已断开连接");
+            }
+        } catch (Exception e) {
+            logger.error("客户端断开连接失败: {}", e.getMessage());
+        }
+    }
+
+    // 关闭系统时,释放资源
+    @PreDestroy
+    private void destroy() {
+        Set<String> hostList = clients.keySet();
+        for (String key : hostList) {
+            String[] split = key.split(":");
+            String host = split[0];
+            Integer port = Integer.parseInt(split[1]);
+            disconnect(host, port);
+        }
+    }
+
+    private static OpcUaClient getClient(String host, Integer port) {
+        OpcUaClient client = clients.get(host+":"+port);
+
+        if (client == null) {
+            reconnect(host, port);
+        }
+        return client;
+    }
+
+
+    // 批量节点值获取
+    public List<Object> getValues(String host, Integer port, List<NodeId> nodeIds) {
+        OpcUaClient client = getClient(host, port);
+        List<DataValue> dataValueList = new ArrayList<>();
+        try {
+            dataValueList = client.readValues(0, TimestampsToReturn.Both, nodeIds).get();
+        } catch (InterruptedException | ExecutionException e) {
+            logger.error("读取节点 {} 值失败", nodeIds);
+            logger.error("错误信息: {}", e.getMessage());
+        }
+
+        List<Object> values = new ArrayList<>();
+        for (DataValue value : dataValueList) {
+            values.add(value.getValue() != null ? value.getValue().getValue() : null);
+        }
+        return values;
+    }
+
+    // 批量节点值更新
+    public boolean setValues(String host, Integer port, List<NodeId> nodeIds, List<Object> values) {
+        OpcUaClient client = getClient(host, port);
+        List<DataValue> dataValues = new ArrayList<>();
+        for (Object value : values) {
+            dataValues.add(new DataValue(new Variant(value), StatusCode.GOOD, null));
+        }
+        try {
+            List<StatusCode> statusCodes = client.writeValues(nodeIds, dataValues).get();
+            for (StatusCode code : statusCodes) {
+                if (code.isBad()) {
+                    logger.warn("节点写入失败: {}", code);
+                    return false;
+                }
+            }
+            return true;
+        } catch (InterruptedException | ExecutionException e) {
+            logger.error("写入节点值失败: {}", nodeIds, e);
+            return false;
+        }
+    }
+
+    // 单个节点值获取
+    public Object getValue(String host, Integer port, NodeId nodeId) {
+        List<Object> values = getValues(host, port, Collections.singletonList(nodeId));
+        return values.isEmpty() ? null : values.get(0);
+    }
+
+    // 单个节点值更新
+    public boolean setValue(String host, Integer port, NodeId nodeId, Object value) {
+        return setValues(host, port, Collections.singletonList(nodeId), Collections.singletonList(value));
+    }
+
+
+    @Value("${dcs.opcua.url}")
+    private String HOST;
+    @Value("${dcs.opcua.port}")
+    private int PORT;
+
+    private final String URL = "opc.tcp://" + HOST + ":" + PORT;
+    private static String ip = "192.168.0.11";
+    private static Integer port = 4840;
+
+    public static void main(String[] args) {
+        String URL = "opc.tcp://" + ip + ":" + port;
+
+        try {
+            clients.put(ip + ":" + port, OpcUaClient.create(URL));
+        } catch (UaException e) {
+            throw new RuntimeException(e);
+        }
+        try {
+            clients.get(ip + ":" + port).connect().get();
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        } catch (ExecutionException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}

+ 3 - 3
admin/src/main/java/com/dcs/hnyz/domain/EquipmentParam.java

@@ -67,7 +67,7 @@ public class EquipmentParam extends BaseEntity {
     /**
      * 设备数据类型(布尔型,浮点型,整型)
      */
-    @Excel(name = "设备数据类型(布尔型,浮点型,整型)")
+    @Excel(name = "设备数据类型(1布尔型,2浮点型,3整型)")
     @ApiModelProperty(value = "设备数据类型(1布尔型,2浮点型,3整型)")
     private String dataType;
 
@@ -82,8 +82,8 @@ public class EquipmentParam extends BaseEntity {
      * 寄存器类型(只读,保持,线圈)
      * 对应 OPCUA namespaceIndex 命名空间索引
      */
-    @Excel(name = "寄存器类型(只读,保持,线圈)")
-    @ApiModelProperty(value = "寄存器类型(3只读,4保持,1线圈)")
+    @Excel(name = "modbus寄存器类型(3只读,4保持,1线圈) OPCUA namespaceIndex 命名空间索引")
+    @ApiModelProperty(value = "modbus寄存器类型(3只读,4保持,1线圈) OPCUA namespaceIndex 命名空间索引")
     private String registerCode;
 
     /**

+ 0 - 2
admin/src/main/java/com/dcs/hnyz/service/impl/EquipmentServiceImpl.java

@@ -473,8 +473,6 @@ public class EquipmentServiceImpl implements IEquipmentService {
                 Equipment e = equipmentMapper.selectOne(new QueryWrapper<Equipment>().eq("code", equipmentFormVO.getCode()));
                 Equipment equipment = new Equipment();
                 BeanUtils.copyProperties(equipmentFormVO, equipment);
-                // TODO 获取设备类型字符串查询设备类型库 填充相应的设备类型 id
-                // TODO 模糊查询设备流程和页面 填充相应的流程和页面 id 没有命中需返回消息提示无页面
                 // 识别设备的PLC
                 if (equipmentFormVO.getIpAddress() != null && equipmentFormVO.getPort() != null) {
                     Long plcInfoId = plcMap.get(equipmentFormVO.getIpAddress() + ":" + equipmentFormVO.getPort());

+ 1 - 7
admin/src/main/resources/application-hnyz.yml

@@ -18,13 +18,7 @@ dcs:
     url: http://127.0.0.1:8086
     token: gDk4IG7n5riCjACJbY_8TVq37NjrQNz42nI_2bAmxQ9wiOkfb5_3CwqvX3n40nsqZPh2XmJbQp645NeD2li87A==
     org: ygtx
-  # modbus配置
-#  modbus:
-#    host: 200.200.200.10
-#    port: 502
-#  opcua:
-#    host: 192.168.0.1
-#    port: 4840
+    bucket: hnyz_dcs_bucket
 
 # 开发环境配置
 server:

+ 219 - 0
admin/src/main/resources/application-shmfy.yml

@@ -0,0 +1,219 @@
+# 项目相关配置
+dcs:
+  # 名称
+  name: dcs
+  # 版本
+  version: 3.8.9
+  # 版权年份
+  copyrightYear: 2025
+  # 文件路径 示例( Windows配置D:/shanghai_dcs/uploadPath,Linux配置 /home/shanghai_dcs/uploadPath)
+  #  profile: D:/shanghai_dcs/uploadPath
+  profile: D:/hnyz_dcs/uploadPath
+  # 获取ip地址开关
+  addressEnabled: false
+  # 验证码类型 math 数字计算 char 字符验证
+  captchaType: math
+  # influxdb配置
+  influxdb:
+    url: http://127.0.0.1:8086
+    token: kYdrdEfimyHUA0ra_IEiHoYg5m1cpMpaONyET4gRfdMaC3HztXMwdQsrD2-M6w5VLM-3Yo4pYfnxAzFO1mOMXQ==
+    org: ygtx_org
+    bucket: shanghai_dcs_bucket
+
+# 开发环境配置
+server:
+  # 服务器的HTTP端口,默认为8080
+  port: 38080
+  servlet:
+    # 应用的访问路径
+    context-path: /
+  tomcat:
+    # tomcat的URI编码
+    uri-encoding: UTF-8
+    # 连接数满后的排队数,默认为100
+    accept-count: 1000
+    threads:
+      # tomcat最大线程数,默认为200
+      max: 800
+      # Tomcat启动初始化的线程数,默认值10
+      min-spare: 100
+
+# 日志配置
+logging:
+  level:
+    com.ruoyi: debug
+    #    org.springframework: warn
+    org:
+      springframework:
+        web.socket: DEBUG
+
+# 用户配置
+user:
+  password:
+    # 密码最大错误次数
+    maxRetryCount: 5
+    # 密码锁定时间(默认10分钟)
+    lockTime: 10
+
+# Spring配置
+# 数据源配置
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.mysql.cj.jdbc.Driver
+    druid:
+      # 主库数据源
+      master:
+        url: jdbc:mysql://localhost:3306/dcs_hnyz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+        username: root
+        password: sE9r#Xf@2Lp$M7qW
+      # 初始连接数
+      initialSize: 5
+      # 最小连接池数量
+      minIdle: 10
+      # 最大连接池数量
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置连接超时时间
+      connectTimeout: 30000
+      # 配置网络超时时间
+      socketTimeout: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      # 配置一个连接在池中最大生存的时间,单位是毫秒
+      maxEvictableIdleTimeMillis: 900000
+      # 配置检测连接是否有效
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 设置白名单,不填则允许所有访问
+        allow:
+        url-pattern: /druid/*
+        # 控制台管理用户名和密码
+        login-username: ruoyi
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 慢SQL记录
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+  #  时间格式化
+  jackson:
+    time-zone: GMT+8
+    date-format: yyyy-MM-dd HH:mm:ss
+  # 资源信息
+  messages:
+    # 国际化资源文件路径
+    basename: i18n/messages
+  # 文件上传
+  servlet:
+    multipart:
+      # 单个文件大小
+      max-file-size: 10MB
+      # 设置总上传的文件大小
+      max-request-size: 20MB
+  # 服务模块
+  devtools:
+    restart:
+      # 热部署开关
+      enabled: true
+  # redis 配置
+  redis:
+    # 地址
+    #    host: 192.168.110.83
+    host: 127.0.0.1
+    # 端口,默认为6379
+    port: 6379
+    # 数据库索引
+    database: 0
+    # 密码
+    password:
+
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
+
+# token配置
+token:
+  # 令牌自定义标识
+  header: Authorization
+  # 令牌密钥
+  secret: abcdefghijklmnopqrstuvwxyz
+  # 令牌有效期(默认30分钟)
+  expireTime: 300
+
+# MyBatis配置
+#mybatis:
+#  # 搜索指定包别名
+#  typeAliasesPackage: com.dcs.**.domain
+#  # 配置mapper的扫描,找到所有的mapper.xml映射文件
+#  mapperLocations: classpath*:mapper/**/*Mapper.xml
+#  # 加载全局的配置文件
+#  configLocation: classpath:mybatis/mybatis-config.xml
+##  开启驼峰
+#  configuration:
+#    map-underscore-to-camel-case: true
+
+#mybatis-plus配置
+mybatis-plus:
+  # mapper.xml 路径(支持通配)
+  mapper-locations: classpath*:mapper/**/*Mapper.xml
+  # 实体类所在路径(用于别名)
+  type-aliases-package: com.dcs.**.domain
+  global-config:
+    db-config:
+      id-type: auto
+      # 开启逻辑删除
+      logic-delete-field: delFlag  # 全局逻辑删除字段
+      logic-delete-value: '2'
+      logic-not-delete-value: '0'
+      # 配置自动填充
+      fill-strategy: true  # 开启填充策略
+  configuration:
+    map-underscore-to-camel-case: true
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 可选,控制台打印 SQL
+
+
+# PageHelper分页插件
+pagehelper:
+  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+
+# Swagger配置
+swagger:
+  # 是否开启swagger
+  enabled: true
+  # 请求前缀
+  pathMapping: /dev-api
+
+# 防止XSS攻击
+xss:
+  # 过滤开关
+  enabled: true
+  # 排除链接(多个用逗号分隔)
+  excludes: /system/notice
+  # 匹配链接
+  urlPatterns: /system/*,/monitor/*,/tool/*

+ 219 - 0
admin/src/main/resources/application-test.yml

@@ -0,0 +1,219 @@
+# 项目相关配置
+dcs:
+  # 名称
+  name: dcs
+  # 版本
+  version: 3.8.9
+  # 版权年份
+  copyrightYear: 2025
+  # 文件路径 示例( Windows配置D:/shanghai_dcs/uploadPath,Linux配置 /home/shanghai_dcs/uploadPath)
+  #  profile: D:/shanghai_dcs/uploadPath
+  profile: D:/hnyz_dcs/uploadPath
+  # 获取ip地址开关
+  addressEnabled: false
+  # 验证码类型 math 数字计算 char 字符验证
+  captchaType: math
+  # influxdb配置
+  influxdb:
+    url: http://127.0.0.1:8086
+    token: kYdrdEfimyHUA0ra_IEiHoYg5m1cpMpaONyET4gRfdMaC3HztXMwdQsrD2-M6w5VLM-3Yo4pYfnxAzFO1mOMXQ==
+    org: ygtx
+    bucket: hnyz_dcs_test_bucket
+
+# 开发环境配置
+server:
+  # 服务器的HTTP端口,默认为8080
+  port: 38081
+  servlet:
+    # 应用的访问路径
+    context-path: /
+  tomcat:
+    # tomcat的URI编码
+    uri-encoding: UTF-8
+    # 连接数满后的排队数,默认为100
+    accept-count: 1000
+    threads:
+      # tomcat最大线程数,默认为200
+      max: 800
+      # Tomcat启动初始化的线程数,默认值10
+      min-spare: 100
+
+# 日志配置
+logging:
+  level:
+    com.ruoyi: debug
+    #    org.springframework: warn
+    org:
+      springframework:
+        web.socket: DEBUG
+
+# 用户配置
+user:
+  password:
+    # 密码最大错误次数
+    maxRetryCount: 5
+    # 密码锁定时间(默认10分钟)
+    lockTime: 10
+
+# Spring配置
+# 数据源配置
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.mysql.cj.jdbc.Driver
+    druid:
+      # 主库数据源
+      master:
+        url: jdbc:mysql://127.0.0.1:9906/hnyz_dcs_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+        username: root
+        password: 11rrRRvv90)*9&FuuI}{
+      # 初始连接数
+      initialSize: 5
+      # 最小连接池数量
+      minIdle: 10
+      # 最大连接池数量
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置连接超时时间
+      connectTimeout: 30000
+      # 配置网络超时时间
+      socketTimeout: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      # 配置一个连接在池中最大生存的时间,单位是毫秒
+      maxEvictableIdleTimeMillis: 900000
+      # 配置检测连接是否有效
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 设置白名单,不填则允许所有访问
+        allow:
+        url-pattern: /druid/*
+        # 控制台管理用户名和密码
+        login-username: ruoyi
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 慢SQL记录
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+  #  时间格式化
+  jackson:
+    time-zone: GMT+8
+    date-format: yyyy-MM-dd HH:mm:ss
+  # 资源信息
+  messages:
+    # 国际化资源文件路径
+    basename: i18n/messages
+  # 文件上传
+  servlet:
+    multipart:
+      # 单个文件大小
+      max-file-size: 10MB
+      # 设置总上传的文件大小
+      max-request-size: 20MB
+  # 服务模块
+  devtools:
+    restart:
+      # 热部署开关
+      enabled: true
+  # redis 配置
+  redis:
+    # 地址
+    #    host: 192.168.110.83
+    host: 127.0.0.1
+    # 端口,默认为6379
+    port: 6379
+    # 数据库索引
+    database: 0
+    # 密码
+    password:
+
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
+
+# token配置
+token:
+  # 令牌自定义标识
+  header: Authorization
+  # 令牌密钥
+  secret: abcdefghijklmnopqrstuvwxyz
+  # 令牌有效期(默认30分钟)
+  expireTime: 300
+
+# MyBatis配置
+#mybatis:
+#  # 搜索指定包别名
+#  typeAliasesPackage: com.dcs.**.domain
+#  # 配置mapper的扫描,找到所有的mapper.xml映射文件
+#  mapperLocations: classpath*:mapper/**/*Mapper.xml
+#  # 加载全局的配置文件
+#  configLocation: classpath:mybatis/mybatis-config.xml
+##  开启驼峰
+#  configuration:
+#    map-underscore-to-camel-case: true
+
+#mybatis-plus配置
+mybatis-plus:
+  # mapper.xml 路径(支持通配)
+  mapper-locations: classpath*:mapper/**/*Mapper.xml
+  # 实体类所在路径(用于别名)
+  type-aliases-package: com.dcs.**.domain
+  global-config:
+    db-config:
+      id-type: auto
+      # 开启逻辑删除
+      logic-delete-field: delFlag  # 全局逻辑删除字段
+      logic-delete-value: '2'
+      logic-not-delete-value: '0'
+      # 配置自动填充
+      fill-strategy: true  # 开启填充策略
+  configuration:
+    map-underscore-to-camel-case: true
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 可选,控制台打印 SQL
+
+
+# PageHelper分页插件
+pagehelper:
+  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+
+# Swagger配置
+swagger:
+  # 是否开启swagger
+  enabled: true
+  # 请求前缀
+  pathMapping: /dev-api
+
+# 防止XSS攻击
+xss:
+  # 过滤开关
+  enabled: true
+  # 排除链接(多个用逗号分隔)
+  excludes: /system/notice
+  # 匹配链接
+  urlPatterns: /system/*,/monitor/*,/tool/*

+ 1005 - 0
sql/dcs.sql

@@ -0,0 +1,1005 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : 上海崇明正大
+ Source Server Type    : MySQL
+ Source Server Version : 80041 (8.0.41)
+ Source Host           : ab.ranmo.net.cn:3306
+ Source Schema         : dcs_test
+
+ Target Server Type    : MySQL
+ Target Server Version : 80041 (8.0.41)
+ File Encoding         : 65001
+
+ Date: 09/09/2025 18:01:48
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for action_binding
+-- ----------------------------
+DROP TABLE IF EXISTS `action_binding`;
+CREATE TABLE `action_binding`  (
+  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键,自增',
+  `action_id` int NULL DEFAULT NULL COMMENT '动作id(关联动作配置表)',
+  `bind_action_id` int NULL DEFAULT NULL COMMENT '同步触发的动作id',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `fk_action_binding_action`(`action_id` ASC) USING BTREE,
+  INDEX `fk_action_binding_bind_action`(`bind_action_id` ASC) USING BTREE,
+  CONSTRAINT `fk_action_binding_action` FOREIGN KEY (`action_id`) REFERENCES `action_config` (`action_id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
+  CONSTRAINT `fk_action_binding_bind_action` FOREIGN KEY (`bind_action_id`) REFERENCES `action_config` (`action_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '动作关联表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for action_config
+-- ----------------------------
+DROP TABLE IF EXISTS `action_config`;
+CREATE TABLE `action_config`  (
+  `action_id` int NOT NULL AUTO_INCREMENT COMMENT '动作id',
+  `equipment_id` int NULL DEFAULT NULL COMMENT '设备id(关联设备表)',
+  `action_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '动作类型',
+  `value` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '动作值',
+  `unit` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '单位',
+  `trigger_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '触发类型(1定时触发 2条件触发 3事件触发)',
+  `trigger_condition` json NULL COMMENT '触发条件',
+  `trigger_delay` int NULL DEFAULT 0 COMMENT '触发延迟(秒)',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`action_id`) USING BTREE,
+  INDEX `fk_action_equipment`(`equipment_id` ASC) USING BTREE,
+  CONSTRAINT `fk_action_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipment` (`equipment_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '动作配置表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for alarm_config
+-- ----------------------------
+DROP TABLE IF EXISTS `alarm_config`;
+CREATE TABLE `alarm_config`  (
+  `config_id` int NOT NULL AUTO_INCREMENT COMMENT '主键,自增',
+  `equipment_id` int NULL DEFAULT NULL COMMENT '关联设备ID,NULL表示适用于所有设备',
+  `alarm_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '告警代码,唯一标识一个告警类型',
+  `alarm_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '告警名称,便于识别和管理',
+  `alarm_level` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '2' COMMENT '告警等级(1-信息,2-警告,3-严重,4-紧急)',
+  `alarm_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '告警类型,例如:高温、低压、通信异常等',
+  `source` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '告警源(1-PLC,2-DCS)',
+  `threshold_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '>' COMMENT '阈值类型,支持多种比较方式',
+  `threshold_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '阈值设置,单值或范围,例如:75 或 60-80',
+  `unit` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '单位,例如:°C、kPa、ppm 等',
+  `delay_seconds` int NOT NULL DEFAULT 0 COMMENT '延迟触发时间(秒),用于避免瞬时波动引发告警',
+  `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '告警通知',
+  `notification_method` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '告警类型(email, sms, app, none)',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '0' COMMENT '是否启用该告警配置',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `create_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建者',
+  `update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  `update_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新者',
+  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注信息',
+  PRIMARY KEY (`config_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '告警配置表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for alarm_event
+-- ----------------------------
+DROP TABLE IF EXISTS `alarm_event`;
+CREATE TABLE `alarm_event`  (
+  `alarm_id` int NOT NULL AUTO_INCREMENT COMMENT '主键,自增',
+  `equipment_id` int NULL DEFAULT NULL COMMENT '对应设备的 ID(关联设备表)',
+  `alarm_code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '告警代码',
+  `alarm_level` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '告警等级(1-信息,2-警告,3-严重,4-紧急)',
+  `alarm_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '告警类型',
+  `message` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '告警描述',
+  `value` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '当前值',
+  `unit` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '单位',
+  `occur_time` datetime NULL DEFAULT NULL COMMENT '告警发生时间',
+  `recover_time` datetime NULL DEFAULT NULL COMMENT '告警恢复时间',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '告警状态(0-未恢复,1-已恢复)',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`alarm_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 71 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '告警中心表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for communication_protocol
+-- ----------------------------
+DROP TABLE IF EXISTS `communication_protocol`;
+CREATE TABLE `communication_protocol`  (
+  `protocol_id` int NOT NULL AUTO_INCREMENT COMMENT '协议id',
+  `protocol_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '协议名',
+  `code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '协议编码',
+  `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '协议说明',
+  `network_segment` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '网段',
+  `default_port` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '默认端口',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `del_flag` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`protocol_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '通讯协议表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for dcs_equipment
+-- ----------------------------
+DROP TABLE IF EXISTS `dcs_equipment`;
+CREATE TABLE `dcs_equipment`  (
+  `equipment_id` int NOT NULL AUTO_INCREMENT COMMENT '设备id',
+  `address` smallint UNSIGNED NULL DEFAULT NULL COMMENT '寄存器地址',
+  `equipment_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '设备名',
+  `data_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '设备数据类型(浮点型,整型,线圈)',
+  `parents_id` int NULL DEFAULT NULL COMMENT '父设备id',
+  `flow_id` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '流程id',
+  `equipment_code` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '标识码',
+  `register_code` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '寄存器类型',
+  `unit_type` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '单位类型',
+  `equipment_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '设备类型:设备,寄存器',
+  PRIMARY KEY (`equipment_id`) USING BTREE,
+  UNIQUE INDEX `equipment_code`(`equipment_code` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 246 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for dcs_flow
+-- ----------------------------
+DROP TABLE IF EXISTS `dcs_flow`;
+CREATE TABLE `dcs_flow`  (
+  `flow_id` int NOT NULL AUTO_INCREMENT,
+  `flow_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '流程名称',
+  `sort` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '流程顺序',
+  PRIMARY KEY (`flow_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for dcs_group_task
+-- ----------------------------
+DROP TABLE IF EXISTS `dcs_group_task`;
+CREATE TABLE `dcs_group_task`  (
+  `group_id` bigint NOT NULL AUTO_INCREMENT,
+  `group_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '组名称',
+  `group_code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '组号',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `del_flag` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '删除标志(0-存在 2-删除)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`group_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '任务动作组表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for dcs_group_task_line
+-- ----------------------------
+DROP TABLE IF EXISTS `dcs_group_task_line`;
+CREATE TABLE `dcs_group_task_line`  (
+  `line_id` bigint NOT NULL AUTO_INCREMENT,
+  `group_id` bigint NULL DEFAULT NULL COMMENT '组ID',
+  `action_id` bigint NULL DEFAULT NULL COMMENT '动作ID',
+  `action_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '动作名称',
+  `parent_id` bigint NULL DEFAULT NULL COMMENT '上组ID',
+  `action_num` int NULL DEFAULT NULL COMMENT '序号',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态()',
+  `del_flag` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '删除标志(0-存在 2-删除)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`line_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '任务动作组明细' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for dcs_request_task
+-- ----------------------------
+DROP TABLE IF EXISTS `dcs_request_task`;
+CREATE TABLE `dcs_request_task`  (
+  `request_id` bigint NOT NULL AUTO_INCREMENT,
+  `request_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '名称',
+  `request_code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '请求编号',
+  `request_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '请求类型',
+  `line_code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '生产线',
+  `request_param` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '参数',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-待执行,1-执行中,2-完成,3-异常)',
+  `del_flag` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '删除标志(0-存在 2-删除)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`request_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '请求任务表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for equipment
+-- ----------------------------
+DROP TABLE IF EXISTS `equipment`;
+CREATE TABLE `equipment`  (
+  `equipment_id` int NOT NULL AUTO_INCREMENT COMMENT '设备id',
+  `equipment_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '设备名',
+  `title` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '页面显示的title名称',
+  `code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '标识码',
+  `page_ids` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '流程id(用‘,’分隔)',
+  `flow_ids` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '流程id(用‘,’分隔)',
+  `equipment_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '设备种类',
+  `plc_id` int NULL DEFAULT NULL COMMENT '对应plc的id',
+  `ip_address` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '通信地址',
+  `port` int NULL DEFAULT NULL COMMENT '通信端口',
+  `protocol_id` int NULL DEFAULT NULL COMMENT '通讯协议id',
+  `tank_sort` int NULL DEFAULT NULL COMMENT '罐体在流程的顺序(只有罐体设备会用到)',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `del_flag` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '删除标志(0-存在 2-删除)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`equipment_id`) USING BTREE,
+  UNIQUE INDEX `code`(`code` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 591 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for equipment_extension
+-- ----------------------------
+DROP TABLE IF EXISTS `equipment_extension`;
+CREATE TABLE `equipment_extension`  (
+  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `equipment_id` int NULL DEFAULT NULL COMMENT '设备id(为null时,表示测试模型)',
+  `page_id` int NOT NULL COMMENT '页面id',
+  `x` decimal(5, 2) NULL DEFAULT NULL COMMENT 'x坐标',
+  `y` decimal(5, 2) NULL DEFAULT NULL COMMENT 'y坐标',
+  `size` int NULL DEFAULT NULL COMMENT '组态页面显示的尺寸大小',
+  `height` int NULL DEFAULT NULL COMMENT '高',
+  `width` int NULL DEFAULT NULL COMMENT '宽',
+  `rotate` int NULL DEFAULT 0 COMMENT '旋转角度',
+  `model_id` int NULL DEFAULT NULL COMMENT '模型id',
+  `is_reverse` tinyint(1) NULL DEFAULT 0 COMMENT '是否反转(0否,1是)',
+  `special_condition` json NULL COMMENT '特殊条件',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
+  `create_time` datetime NULL DEFAULT NULL,
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
+  `update_time` datetime NULL DEFAULT NULL,
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 571 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for equipment_param
+-- ----------------------------
+DROP TABLE IF EXISTS `equipment_param`;
+CREATE TABLE `equipment_param`  (
+  `register_id` int NOT NULL AUTO_INCREMENT COMMENT '寄存器id',
+  `equipment_code` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '归属设备code(最顶级父设备code)',
+  `relation_code` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '关联code(上一级父设备code)',
+  `unit_id` int NULL DEFAULT NULL COMMENT '从机id(Modbus slaveId / OPC UA session or node short id / MQTT clientId)',
+  `address` smallint NULL DEFAULT NULL COMMENT '寄存器地址',
+  `register_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '寄存器名称',
+  `data_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '设备数据类型(布尔型,浮点型,整型)',
+  `code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '唯一标识码',
+  `register_code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '寄存器类型(只读,保持,线圈)',
+  `unit_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '单位类型(kg,rpm,Mpa等)',
+  `param_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '参数类型(1主数据项,2从数据项,3主设置项,4从设置项,5其他)',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `del_flag` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '删除标志(0-存在,2-删除)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
+  `create_time` datetime NULL DEFAULT NULL,
+  `update_time` datetime NULL DEFAULT NULL,
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
+  PRIMARY KEY (`register_id`) USING BTREE,
+  UNIQUE INDEX `code`(`code` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1874 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for flow
+-- ----------------------------
+DROP TABLE IF EXISTS `flow`;
+CREATE TABLE `flow`  (
+  `flow_id` int NOT NULL AUTO_INCREMENT,
+  `flow_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '流程名称',
+  `sort` int NULL DEFAULT NULL COMMENT '流程顺序',
+  `flow_code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '流程标识',
+  `flow_attribution` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '流程归属',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `del_flag` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '删除标志(0-存在,2-删除)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
+  `create_time` datetime NULL DEFAULT NULL,
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
+  `update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
+  PRIMARY KEY (`flow_id`) USING BTREE,
+  UNIQUE INDEX `uk_flow_code`(`flow_code` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for gen_table
+-- ----------------------------
+DROP TABLE IF EXISTS `gen_table`;
+CREATE TABLE `gen_table`  (
+  `table_id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
+  `table_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '表名称',
+  `table_comment` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '表描述',
+  `sub_table_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '关联子表的表名',
+  `sub_table_fk_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '子表关联的外键名',
+  `class_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '实体类名称',
+  `tpl_category` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'crud' COMMENT '使用的模板(crud单表操作 tree树表操作)',
+  `tpl_web_type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '前端模板类型(element-ui模版 element-plus模版)',
+  `package_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成包路径',
+  `module_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成模块名',
+  `business_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成业务名',
+  `function_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成功能名',
+  `function_author` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成功能作者',
+  `gen_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '生成代码方式(0zip压缩包 1自定义路径)',
+  `gen_path` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '/' COMMENT '生成路径(不填默认项目路径)',
+  `options` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '其它生成选项',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`table_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '代码生成业务表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for gen_table_column
+-- ----------------------------
+DROP TABLE IF EXISTS `gen_table_column`;
+CREATE TABLE `gen_table_column`  (
+  `column_id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
+  `table_id` bigint NULL DEFAULT NULL COMMENT '归属表编号',
+  `column_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '列名称',
+  `column_comment` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '列描述',
+  `column_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '列类型',
+  `java_type` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'JAVA类型',
+  `java_field` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'JAVA字段名',
+  `is_pk` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否主键(1是)',
+  `is_increment` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否自增(1是)',
+  `is_required` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否必填(1是)',
+  `is_insert` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否为插入字段(1是)',
+  `is_edit` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否编辑字段(1是)',
+  `is_list` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否列表字段(1是)',
+  `is_query` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否查询字段(1是)',
+  `query_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'EQ' COMMENT '查询方式(等于、不等于、大于、小于、范围)',
+  `html_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)',
+  `dict_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典类型',
+  `sort` int NULL DEFAULT NULL COMMENT '排序',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`column_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 248 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '代码生成业务表字段' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for model_component
+-- ----------------------------
+DROP TABLE IF EXISTS `model_component`;
+CREATE TABLE `model_component`  (
+  `model_id` int NOT NULL AUTO_INCREMENT COMMENT '模型唯一 ID',
+  `model_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '模型名称(如 储罐A、管道X)',
+  `model_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '模型类型(如 TANKS,VALVES)',
+  `component_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '前端组件名(如 M1Tank)',
+  `component_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'component' COMMENT '组件类型(如 icon、component)',
+  `z_index` int NULL DEFAULT 1 COMMENT '层级',
+  `icon_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'icon 类型模型对应 class 名',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '启用状态(0启用,1禁用)',
+  `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
+  `create_time` datetime NULL DEFAULT NULL,
+  `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
+  `update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
+  PRIMARY KEY (`model_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 39 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '模型组件定义表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for page_control
+-- ----------------------------
+DROP TABLE IF EXISTS `page_control`;
+CREATE TABLE `page_control`  (
+  `page_id` int NOT NULL AUTO_INCREMENT COMMENT '页面id',
+  `page_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '页面名',
+  `page_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '页面编码',
+  `page_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '页面路径',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '删除标志(0-存在,2-删除)',
+  `create_time` datetime NULL DEFAULT NULL,
+  `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
+  `update_time` datetime NULL DEFAULT NULL,
+  `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
+  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
+  PRIMARY KEY (`page_id`) USING BTREE,
+  UNIQUE INDEX `uk_page_code`(`page_code` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for pipeline_instance
+-- ----------------------------
+DROP TABLE IF EXISTS `pipeline_instance`;
+CREATE TABLE `pipeline_instance`  (
+  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `page_id` int NOT NULL COMMENT '页面 ID',
+  `x` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'X 坐标(单位%)',
+  `y` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'Y 坐标',
+  `pipe_width` int NULL DEFAULT 8 COMMENT '管道宽度-px',
+  `pipe_length` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '管道长度-%',
+  `rotate` int NULL DEFAULT 0 COMMENT '旋转角度(0~360)',
+  `model_id` int NOT NULL COMMENT '关联模型 ID',
+  `pipe_class` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '管道种类(如 materials、水、气)',
+  `flow_condition` json NULL COMMENT '流通条件(如:{ \"type\": \"or\", \"valves\": [\"N1\", \"N2\"] })',
+  `dynamic_pipeline_condition` json NULL COMMENT '管道种类切换的触发条件',
+  `reverse_condition` json NULL COMMENT '管道反向流通的触发条件',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '启用状态(0启用,1禁用)',
+  `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
+  `create_time` datetime NULL DEFAULT NULL,
+  `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
+  `update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 813 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '管道组件拓展表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for plc_info
+-- ----------------------------
+DROP TABLE IF EXISTS `plc_info`;
+CREATE TABLE `plc_info`  (
+  `plc_id` int NOT NULL AUTO_INCREMENT COMMENT '主键,自增',
+  `plc_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'PLC名称',
+  `ip_address` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT 'PLC的IP地址',
+  `port` int NULL DEFAULT NULL COMMENT '通信端口',
+  `scan_interval` int NULL DEFAULT NULL COMMENT '采集间隔(单位:毫秒)',
+  `connect_timeout` int NULL DEFAULT NULL COMMENT '连接超时时间(秒)',
+  `protocol_id` int NULL DEFAULT NULL COMMENT '通讯协议id',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `del_flag` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`plc_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = 'PLC信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_blob_triggers
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_blob_triggers`;
+CREATE TABLE `qrtz_blob_triggers`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+  `trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+  `blob_data` blob NULL COMMENT '存放持久化Trigger对象',
+  PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
+  CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'Blob类型的触发器表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_calendars
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_calendars`;
+CREATE TABLE `qrtz_calendars`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `calendar_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '日历名称',
+  `calendar` blob NOT NULL COMMENT '存放持久化calendar对象',
+  PRIMARY KEY (`sched_name`, `calendar_name`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '日历信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_cron_triggers
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_cron_triggers`;
+CREATE TABLE `qrtz_cron_triggers`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+  `trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+  `cron_expression` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'cron表达式',
+  `time_zone_id` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '时区',
+  PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
+  CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'Cron类型的触发器表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_fired_triggers
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_fired_triggers`;
+CREATE TABLE `qrtz_fired_triggers`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `entry_id` varchar(95) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度器实例id',
+  `trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+  `trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+  `instance_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度器实例名',
+  `fired_time` bigint NOT NULL COMMENT '触发的时间',
+  `sched_time` bigint NOT NULL COMMENT '定时器制定的时间',
+  `priority` int NOT NULL COMMENT '优先级',
+  `state` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '状态',
+  `job_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '任务名称',
+  `job_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '任务组名',
+  `is_nonconcurrent` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否并发',
+  `requests_recovery` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否接受恢复执行',
+  PRIMARY KEY (`sched_name`, `entry_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '已触发的触发器表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_job_details
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_job_details`;
+CREATE TABLE `qrtz_job_details`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `job_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务名称',
+  `job_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务组名',
+  `description` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '相关介绍',
+  `job_class_name` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '执行任务类名称',
+  `is_durable` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '是否持久化',
+  `is_nonconcurrent` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '是否并发',
+  `is_update_data` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '是否更新数据',
+  `requests_recovery` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '是否接受恢复执行',
+  `job_data` blob NULL COMMENT '存放持久化job对象',
+  PRIMARY KEY (`sched_name`, `job_name`, `job_group`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '任务详细信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_locks
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_locks`;
+CREATE TABLE `qrtz_locks`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `lock_name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '悲观锁名称',
+  PRIMARY KEY (`sched_name`, `lock_name`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '存储的悲观锁信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_paused_trigger_grps
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`;
+CREATE TABLE `qrtz_paused_trigger_grps`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+  PRIMARY KEY (`sched_name`, `trigger_group`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '暂停的触发器表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_scheduler_state
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_scheduler_state`;
+CREATE TABLE `qrtz_scheduler_state`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `instance_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '实例名称',
+  `last_checkin_time` bigint NOT NULL COMMENT '上次检查时间',
+  `checkin_interval` bigint NOT NULL COMMENT '检查间隔时间',
+  PRIMARY KEY (`sched_name`, `instance_name`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '调度器状态表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_simple_triggers
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_simple_triggers`;
+CREATE TABLE `qrtz_simple_triggers`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+  `trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+  `repeat_count` bigint NOT NULL COMMENT '重复的次数统计',
+  `repeat_interval` bigint NOT NULL COMMENT '重复的间隔时间',
+  `times_triggered` bigint NOT NULL COMMENT '已经触发的次数',
+  PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
+  CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '简单触发器的信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_simprop_triggers
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_simprop_triggers`;
+CREATE TABLE `qrtz_simprop_triggers`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
+  `trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
+  `str_prop_1` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'String类型的trigger的第一个参数',
+  `str_prop_2` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'String类型的trigger的第二个参数',
+  `str_prop_3` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'String类型的trigger的第三个参数',
+  `int_prop_1` int NULL DEFAULT NULL COMMENT 'int类型的trigger的第一个参数',
+  `int_prop_2` int NULL DEFAULT NULL COMMENT 'int类型的trigger的第二个参数',
+  `long_prop_1` bigint NULL DEFAULT NULL COMMENT 'long类型的trigger的第一个参数',
+  `long_prop_2` bigint NULL DEFAULT NULL COMMENT 'long类型的trigger的第二个参数',
+  `dec_prop_1` decimal(13, 4) NULL DEFAULT NULL COMMENT 'decimal类型的trigger的第一个参数',
+  `dec_prop_2` decimal(13, 4) NULL DEFAULT NULL COMMENT 'decimal类型的trigger的第二个参数',
+  `bool_prop_1` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'Boolean类型的trigger的第一个参数',
+  `bool_prop_2` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'Boolean类型的trigger的第二个参数',
+  PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
+  CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '同步机制的行锁表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for qrtz_triggers
+-- ----------------------------
+DROP TABLE IF EXISTS `qrtz_triggers`;
+CREATE TABLE `qrtz_triggers`  (
+  `sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调度名称',
+  `trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '触发器的名字',
+  `trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '触发器所属组的名字',
+  `job_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_job_details表job_name的外键',
+  `job_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'qrtz_job_details表job_group的外键',
+  `description` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '相关介绍',
+  `next_fire_time` bigint NULL DEFAULT NULL COMMENT '上一次触发时间(毫秒)',
+  `prev_fire_time` bigint NULL DEFAULT NULL COMMENT '下一次触发时间(默认为-1表示不触发)',
+  `priority` int NULL DEFAULT NULL COMMENT '优先级',
+  `trigger_state` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '触发器状态',
+  `trigger_type` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '触发器的类型',
+  `start_time` bigint NOT NULL COMMENT '开始时间',
+  `end_time` bigint NULL DEFAULT NULL COMMENT '结束时间',
+  `calendar_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '日程表名称',
+  `misfire_instr` smallint NULL DEFAULT NULL COMMENT '补偿执行的策略',
+  `job_data` blob NULL COMMENT '存放持久化job对象',
+  PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
+  INDEX `sched_name`(`sched_name` ASC, `job_name` ASC, `job_group` ASC) USING BTREE,
+  CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `job_name`, `job_group`) REFERENCES `qrtz_job_details` (`sched_name`, `job_name`, `job_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '触发器详细信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for screen_settings
+-- ----------------------------
+DROP TABLE IF EXISTS `screen_settings`;
+CREATE TABLE `screen_settings`  (
+  `id` int NOT NULL AUTO_INCREMENT COMMENT '自增主键',
+  `screen_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '大屏名称',
+  `code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '标识',
+  `page_id` int NULL DEFAULT NULL COMMENT '模版页id',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `fk_screen_settings_page`(`page_id` ASC) USING BTREE,
+  CONSTRAINT `fk_screen_settings_page` FOREIGN KEY (`page_id`) REFERENCES `template_page` (`page_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '大屏设置表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_config
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_config`;
+CREATE TABLE `sys_config`  (
+  `config_id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键',
+  `config_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '参数名称',
+  `config_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '参数键名',
+  `config_value` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '参数键值',
+  `config_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'N' COMMENT '系统内置(Y是 N否)',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`config_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '参数配置表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_dept
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dept`;
+CREATE TABLE `sys_dept`  (
+  `dept_id` bigint NOT NULL AUTO_INCREMENT COMMENT '部门id',
+  `parent_id` bigint NULL DEFAULT 0 COMMENT '父部门id',
+  `ancestors` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '祖级列表',
+  `dept_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '部门名称',
+  `order_num` int NULL DEFAULT 0 COMMENT '显示顺序',
+  `leader` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '负责人',
+  `phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '联系电话',
+  `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '邮箱',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '部门状态(0正常 1停用)',
+  `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`dept_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 201 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '部门表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_dict_data
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dict_data`;
+CREATE TABLE `sys_dict_data`  (
+  `dict_code` bigint NOT NULL AUTO_INCREMENT COMMENT '字典编码',
+  `dict_sort` int NULL DEFAULT 0 COMMENT '字典排序',
+  `dict_label` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典标签',
+  `dict_value` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典键值',
+  `dict_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典类型',
+  `css_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '样式属性(其他样式扩展)',
+  `list_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '表格回显样式',
+  `is_default` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'N' COMMENT '是否默认(Y是 N否)',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`dict_code`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 181 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '字典数据表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_dict_type
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_dict_type`;
+CREATE TABLE `sys_dict_type`  (
+  `dict_id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典主键',
+  `dict_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典名称',
+  `dict_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典类型',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`dict_id`) USING BTREE,
+  UNIQUE INDEX `dict_type`(`dict_type` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 116 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '字典类型表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_job
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_job`;
+CREATE TABLE `sys_job`  (
+  `job_id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务ID',
+  `job_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '任务名称',
+  `job_group` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'DEFAULT' COMMENT '任务组名',
+  `invoke_target` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调用目标字符串',
+  `cron_expression` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT 'cron执行表达式',
+  `misfire_policy` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '3' COMMENT '计划执行错误策略(1立即执行 2执行一次 3放弃执行)',
+  `concurrent` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '1' COMMENT '是否并发执行(0允许 1禁止)',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '状态(0正常 1暂停)',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '备注信息',
+  `save_log` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '1' COMMENT '是否保存日志(1允许 0禁止)',
+  PRIMARY KEY (`job_id`, `job_name`, `job_group`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 106 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '定时任务调度表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_job_log
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_job_log`;
+CREATE TABLE `sys_job_log`  (
+  `job_log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务日志ID',
+  `job_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务名称',
+  `job_group` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务组名',
+  `invoke_target` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调用目标字符串',
+  `job_message` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '日志信息',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '执行状态(0正常 1失败)',
+  `exception_info` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '异常信息',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  PRIMARY KEY (`job_log_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1596879 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '定时任务调度日志表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_logininfor
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_logininfor`;
+CREATE TABLE `sys_logininfor`  (
+  `info_id` bigint NOT NULL AUTO_INCREMENT COMMENT '访问ID',
+  `user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '用户账号',
+  `ipaddr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '登录IP地址',
+  `login_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '登录地点',
+  `browser` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '浏览器类型',
+  `os` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '操作系统',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '登录状态(0成功 1失败)',
+  `msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '提示消息',
+  `login_time` datetime NULL DEFAULT NULL COMMENT '访问时间',
+  PRIMARY KEY (`info_id`) USING BTREE,
+  INDEX `idx_sys_logininfor_s`(`status` ASC) USING BTREE,
+  INDEX `idx_sys_logininfor_lt`(`login_time` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 448 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '系统访问记录' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_menu
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_menu`;
+CREATE TABLE `sys_menu`  (
+  `menu_id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
+  `menu_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '菜单名称',
+  `parent_id` bigint NULL DEFAULT 0 COMMENT '父菜单ID',
+  `order_num` int NULL DEFAULT 0 COMMENT '显示顺序',
+  `path` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '路由地址',
+  `component` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '组件路径',
+  `query` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '路由参数',
+  `route_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '路由名称',
+  `is_frame` int NULL DEFAULT 1 COMMENT '是否为外链(0是 1否)',
+  `is_cache` int NULL DEFAULT 0 COMMENT '是否缓存(0缓存 1不缓存)',
+  `menu_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '菜单类型(M目录 C菜单 F按钮)',
+  `visible` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '菜单状态(0显示 1隐藏)',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '菜单状态(0正常 1停用)',
+  `perms` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '权限标识',
+  `icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '#' COMMENT '菜单图标',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '备注',
+  PRIMARY KEY (`menu_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2130 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '菜单权限表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_notice
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_notice`;
+CREATE TABLE `sys_notice`  (
+  `notice_id` int NOT NULL AUTO_INCREMENT COMMENT '公告ID',
+  `notice_title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '公告标题',
+  `notice_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '公告类型(1通知 2公告)',
+  `notice_content` longblob NULL COMMENT '公告内容',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '公告状态(0正常 1关闭)',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`notice_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '通知公告表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_oper_log
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_oper_log`;
+CREATE TABLE `sys_oper_log`  (
+  `oper_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志主键',
+  `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '模块标题',
+  `business_type` int NULL DEFAULT 0 COMMENT '业务类型(0其它 1新增 2修改 3删除)',
+  `method` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '方法名称',
+  `request_method` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '请求方式',
+  `operator_type` int NULL DEFAULT 0 COMMENT '操作类别(0其它 1后台用户 2手机端用户)',
+  `oper_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '操作人员',
+  `dept_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '部门名称',
+  `oper_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '请求URL',
+  `oper_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '主机地址',
+  `oper_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '操作地点',
+  `oper_param` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '请求参数',
+  `json_result` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '返回参数',
+  `status` int NULL DEFAULT 0 COMMENT '操作状态(0正常 1异常)',
+  `error_msg` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '错误消息',
+  `oper_time` datetime NULL DEFAULT NULL COMMENT '操作时间',
+  `cost_time` bigint NULL DEFAULT 0 COMMENT '消耗时间',
+  PRIMARY KEY (`oper_id`) USING BTREE,
+  INDEX `idx_sys_oper_log_bt`(`business_type` ASC) USING BTREE,
+  INDEX `idx_sys_oper_log_s`(`status` ASC) USING BTREE,
+  INDEX `idx_sys_oper_log_ot`(`oper_time` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 4391 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '操作日志记录' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_post
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_post`;
+CREATE TABLE `sys_post`  (
+  `post_id` bigint NOT NULL AUTO_INCREMENT COMMENT '岗位ID',
+  `post_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '岗位编码',
+  `post_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '岗位名称',
+  `post_sort` int NOT NULL COMMENT '显示顺序',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '状态(0正常 1停用)',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`post_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '岗位信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_role
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role`;
+CREATE TABLE `sys_role`  (
+  `role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID',
+  `role_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色名称',
+  `role_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色权限字符串',
+  `role_sort` int NOT NULL COMMENT '显示顺序',
+  `data_scope` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '1' COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
+  `menu_check_strictly` tinyint(1) NULL DEFAULT 1 COMMENT '菜单树选择项是否关联显示',
+  `dept_check_strictly` tinyint(1) NULL DEFAULT 1 COMMENT '部门树选择项是否关联显示',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色状态(0正常 1停用)',
+  `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`role_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 101 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '角色信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_role_dept
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role_dept`;
+CREATE TABLE `sys_role_dept`  (
+  `role_id` bigint NOT NULL COMMENT '角色ID',
+  `dept_id` bigint NOT NULL COMMENT '部门ID',
+  PRIMARY KEY (`role_id`, `dept_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '角色和部门关联表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_role_menu
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role_menu`;
+CREATE TABLE `sys_role_menu`  (
+  `role_id` bigint NOT NULL COMMENT '角色ID',
+  `menu_id` bigint NOT NULL COMMENT '菜单ID',
+  PRIMARY KEY (`role_id`, `menu_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '角色和菜单关联表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_user
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user`;
+CREATE TABLE `sys_user`  (
+  `user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+  `dept_id` bigint NULL DEFAULT NULL COMMENT '部门ID',
+  `user_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户账号',
+  `nick_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户昵称',
+  `user_type` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '00' COMMENT '用户类型(00系统用户)',
+  `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '用户邮箱',
+  `phonenumber` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '手机号码',
+  `sex` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
+  `avatar` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '头像地址',
+  `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '密码',
+  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '帐号状态(0正常 1停用)',
+  `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
+  `login_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '最后登录IP',
+  `login_date` datetime NULL DEFAULT NULL COMMENT '最后登录时间',
+  `create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`user_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 101 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户信息表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_user_post
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user_post`;
+CREATE TABLE `sys_user_post`  (
+  `user_id` bigint NOT NULL COMMENT '用户ID',
+  `post_id` bigint NOT NULL COMMENT '岗位ID',
+  PRIMARY KEY (`user_id`, `post_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户与岗位关联表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for sys_user_role
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user_role`;
+CREATE TABLE `sys_user_role`  (
+  `user_id` bigint NOT NULL COMMENT '用户ID',
+  `role_id` bigint NOT NULL COMMENT '角色ID',
+  PRIMARY KEY (`user_id`, `role_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户和角色关联表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Table structure for template_page
+-- ----------------------------
+DROP TABLE IF EXISTS `template_page`;
+CREATE TABLE `template_page`  (
+  `page_id` int NOT NULL AUTO_INCREMENT COMMENT '模版页id',
+  `page_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '模板页名称',
+  `url` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '网页路径',
+  `status` char(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '0' COMMENT '启用状态(0-启用,1-禁用)',
+  `create_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '创建者',
+  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+  `update_by` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '更新者',
+  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+  `remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '备注',
+  PRIMARY KEY (`page_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '模板页表' ROW_FORMAT = DYNAMIC;
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 11 - 3
ui/src/router/index.js

@@ -286,17 +286,25 @@ export const constantRoutes = [
   //   component: () => import('@/views/hnyzConfiguratePage/Na2SO4_G3FJ2/index'),
   //   name: 'Na2SO4_G3FJ2',
   // },
-  { // 页面设计器
+  {
     path: '/deviceState',
     hidden: false,
     component: () => import('@/views/simulator/deviceState/index'),
     name: 'DeviceState',
     meta: { title: '设备模拟页', icon: 'edit' }
   },
+  // 新控制页面(使用 Element Plus 响应式布局)
+  {
+    path: '/newControlPage/reaction',
+    component: () => import('@/views/newControlPage/reaction/index'),
+    name: 'NewReactionControl',
+    hidden: 0,
+    meta: { title: '新控制页面', icon: 'tool' }
+  },
   { // 页面设计器
     path: '/pageDesigner',
-    component: Layout,
-    hidden: true,
+    // component: Layout,
+    // hidden: true,
     name: 'PageDesigner',
     meta: { title: '页面设计器', icon: 'edit' },
     children: [

+ 2 - 1
ui/src/views/dcsForm2/flow/index.vue

@@ -39,7 +39,7 @@
 
     <el-table v-loading="loading" :data="flowList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="流程id" align="center" prop="flowId" />
+      <!-- <el-table-column label="流程id" align="center" prop="flowId" /> -->
       <el-table-column label="流程名称" align="center" prop="flowName" />
       <el-table-column label="流程标识" align="center" prop="flowCode" />
       <el-table-column label="流程顺序" align="center" prop="sort" />
@@ -121,6 +121,7 @@ const data = reactive({
     pageNum: 1,
     pageSize: 10,
     flowName: null,
+    flowAttribution: null,
     status: null,
   },
   rules: {

+ 206 - 0
ui/src/views/newControlPage/components/DeviceConfigItem.vue

@@ -0,0 +1,206 @@
+<template>
+    <div class="device_item">
+        <div class="device_name_code">
+            <div class="device_name">
+                <span v-for="(name, index) in deviceName.split('||')" :key="index">{{ name }}</span>
+            </div>
+            <div class="device_code">{{ deviceCode }}</div>
+        </div>
+        <div class="device_set">
+            <div class="set_item" v-for="(setting, index) in validSettings" :key="index">
+                <div class="set_title">
+                    {{ setting.title }}
+                </div>
+                <component v-if="setting.item.component && componentMap[setting.item.component]"
+                    :is="componentMap[setting.item.component]" v-bind="setting.item.props || {}"
+                    @update:value="handleItemUpdate(setting, $event)"
+                    @click:button="handleItemUpdate(setting, $event)" />
+                <div v-else class="error-message">
+                    组件配置错误: {{ setting.item?.component || '未定义组件' }}
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, computed } from 'vue'
+import { defineAsyncComponent } from 'vue'
+
+// 定义组件映射
+const componentMap = {
+    statusSet: defineAsyncComponent(() => import('./statusSet.vue')),
+    statusView: defineAsyncComponent(() => import('./statusView.vue')),
+    numberInput: defineAsyncComponent(() => import('./numberInput.vue'))
+}
+
+// 定义props
+const props = defineProps({
+    // 设备名称
+    deviceName: {
+        type: String,
+        required: true
+    },
+    deviceCode: {
+        type: String,
+    },
+    // 设置列表
+    settingList: {
+        type: Array,
+        required: true,
+        default: () => []
+        /*
+        格式示例:
+        [
+            {
+                title: "当前模式", // 设置项标题
+                item: {
+                    component: "statusSet", // 组件名称
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '正吹', active: 1 },
+                            { value: 1, type: 'danger', label: '反吹', active: 0 }
+                        ]
+                    }
+                }
+            },
+            {
+                title: "模式设置",
+                item: {
+                    component: "statusSet",
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '开', active: 1 },
+                            { value: 1, type: 'danger', label: '关', active: 0 }
+                        ]
+                    }
+                }
+            },
+            {
+                title: "状态",
+                item: {
+                    component: "statusView",
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: "速度",
+                item: {
+                    component: "numberInput",
+                    props: {
+                        value: 500,
+                        unit: "转",
+                        max: 5000
+                    }
+                }
+            }
+        ]
+        */
+    }
+})
+
+// 过滤有效的设置项
+const validSettings = computed(() => {
+    return props.settingList.filter(setting => setting && setting.item)
+})
+
+// 定义emits
+const emit = defineEmits(['update', 'change'])
+
+// 处理子组件值更新
+const handleItemUpdate = (setting, newValue) => {
+    // console.log('DeviceConfigItem 接收到子组件更新:', {
+    //     deviceName: props.deviceName,
+    //     settingTitle: setting.title,
+    //     newValue: newValue,
+    //     setting: setting
+    // })
+
+    const eventData = {
+        title: setting.title,
+        value: newValue,
+        setting: setting
+    }
+
+    emit('update', eventData)
+    emit('change', eventData)
+}
+</script>
+
+<style lang="scss" scoped>
+.device_item {
+    display: inline-flex;
+    padding: 4px;
+    justify-content: flex-start;
+    align-items: center;
+    gap: 4px;
+    background: #21335F;
+    color: #E2FEFF;
+
+    &:hover {
+        transform: translateY(-2px);
+        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+    }
+
+    .device_name_code {
+        display: flex;
+        max-width: 120px;
+        // max-width: 100px;
+        min-height: 80px;
+        align-self: stretch;
+        padding: 10px;
+        justify-content: center;
+        gap: 10px;
+        flex-direction: column;
+        align-items: center;
+        background: #316297;
+
+        .device_name {
+            display: flex;
+            flex-direction: column;
+            font-family: OPPOSans;
+            font-size: 16px;
+            font-style: normal;
+            font-weight: 400;
+            line-height: normal;
+        }
+    }
+
+    .device_set {
+        display: flex;
+        padding: 4px;
+        flex-direction: column;
+        align-items: flex-start;
+        gap: 5px;
+        font-size: 14px;
+
+        .set_item {
+            display: flex;
+            align-items: center;
+            gap: 10px;
+
+            .set_title {
+                width: 57px;
+                color: #E2FEFF;
+                text-align: right;
+                font-family: OPPOSans;
+                font-size: 14px;
+                font-style: normal;
+                font-weight: 400;
+                line-height: normal;
+            }
+        }
+    }
+
+    .error-message {
+        color: #ff6b6b;
+        font-size: 12px;
+        padding: 4px 8px;
+        background: rgba(255, 107, 107, 0.1);
+        border-radius: 4px;
+        border: 1px solid rgba(255, 107, 107, 0.3);
+    }
+}
+</style>

+ 125 - 0
ui/src/views/newControlPage/components/StatusCard.vue

@@ -0,0 +1,125 @@
+<template>
+    <div class="status_card" shadow="hover">
+        <div class="card_header">
+            <span class="card_title">{{ title }}</span>
+            <span class="card_subtitle">{{ subtitle }}</span>
+        </div>
+        <div class="device_grid">
+            <DeviceConfigItem v-for="(device, index) in deviceList" :key="index" :deviceName="device.deviceName"
+                :deviceCode="device.deviceCode" :settingList="device.settingList" @change="handleDeviceConfigChange" />
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { defineProps, defineEmits } from 'vue'
+import DeviceConfigItem from './DeviceConfigItem.vue'
+
+// 定义props
+const props = defineProps({
+    // 卡片标题
+    title: {
+        type: String,
+        required: true
+    },
+    // 卡片副标题(设备编号)
+    subtitle: {
+        type: String,
+        // required: true
+    },
+    // 设备列表
+    deviceList: {
+        type: Array,
+        required: true,
+        default: () => []
+        /*
+        格式示例:
+        [
+            {
+                deviceName: "工作模式",
+                settingList: [
+                    {
+                        title: "当前模式",
+                        item: {
+                            component: "statusSet",
+                            props: {
+                                buttonInfo: [...]
+                            }
+                        }
+                    }
+                ]
+            }
+        ]
+        */
+    }
+})
+
+// 定义emits
+const emit = defineEmits(['deviceChange'])
+
+// 处理设备配置变化
+const handleDeviceConfigChange = (data) => {
+    // console.log('StatusCard 接收到设备配置变化:', {
+    //     cardTitle: props.title,
+    //     cardSubtitle: props.subtitle,
+    //     ...data
+    // })
+
+    emit('deviceChange', {
+        cardTitle: props.title,
+        cardSubtitle: props.subtitle,
+        ...data
+    })
+}
+</script>
+
+<style lang="scss" scoped>
+.status_card {
+    max-width: 1610px;
+    display: flex;
+    padding: 10px;
+    flex-direction: column;
+    align-items: center;
+    gap: 5px;
+    border-radius: 10px 10px 0 0;
+    border: 2px solid #3B51A2;
+    background: linear-gradient(180deg, rgba(52, 81, 156, 0.89) -6.07%, rgba(52, 139, 201, 0.00) 20.29%);
+
+    .card_header {
+        display: flex;
+        padding: 10px;
+        flex-direction: column;
+        justify-content: flex-end;
+        align-items: center;
+        gap: 10px;
+
+        .card_title {
+            color: #9ED3FF;
+            font-family: OPPOSans;
+            font-size: 24px;
+            font-style: normal;
+            font-weight: 400;
+            line-height: normal;
+        }
+
+        .card_subtitle {
+            color: #9ED3FF;
+            font-family: OPPOSans;
+            font-size: 20px;
+            font-style: normal;
+            font-weight: 400;
+            line-height: normal;
+        }
+    }
+
+    .device_grid {
+        display: flex;
+        max-width: 1590px;
+        row-gap: 5px;
+        column-gap: 5px;
+        flex-wrap: wrap;
+        justify-content: flex-start;
+        align-items: flex-start;
+    }
+}
+</style>

+ 125 - 0
ui/src/views/newControlPage/components/numberInput.vue

@@ -0,0 +1,125 @@
+<template>
+    <div class="set_value">
+        <div class="number_input">
+            <el-input-number v-model="localValue" :min="min" :max="max" :disabled="disable" :step="step"
+                controls-position="right" :controls="false">
+                <!-- <template #decrease-icon>
+                    <el-icon>
+                        <Minus />
+                    </el-icon>
+                </template>
+<template #increase-icon>
+                    <el-icon>
+                        <Plus />
+                    </el-icon>
+                </template> -->
+            </el-input-number>
+            <div class="set_unit">
+                {{ unit }}
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue';
+const props = defineProps({
+    value: {
+        type: Number,
+        default: 0,
+        required: true
+    },
+    unit: {
+        type: String,
+        default: ''
+    },
+    min: {
+        type: Number,
+        default: 0.001
+    },
+    max: {
+        type: Number,
+        default: 9999
+    },
+    step: {
+        type: Number,
+        default: 1
+    },
+    disable: {
+        type: Boolean,
+        default: false
+    }
+})
+
+const emit = defineEmits(['update:value'])
+const localValue = computed({
+    get() {
+        return props.value
+    },
+    set(newValue) {
+        emit('update:value', newValue)
+    }
+})
+</script>
+
+<style lang="scss">
+.set_value {
+    max-width: 84px;
+    max-height: 66px;
+    row-gap: 4px;
+    column-gap: 4px;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+
+    .number_input {
+        // width: 55px;
+        display: flex;
+        align-items: center;
+
+        .el-input-number {
+            width: 40px;
+
+            .el-input-number__decrease,
+            .el-input-number__increase {
+                width: 20px;
+            }
+
+            .el-input__wrapper {
+                border-radius: 5px;
+                background: #0F1E39;
+                padding-left: 5px;
+                // padding-right: 22px;
+                padding-right: 5px;
+
+                border: none !important;
+                box-shadow: none !important;
+
+                .el-input__inner {
+                    width: 30px;
+                    color: #E2FEFF;
+                    font-family: OPPOSans;
+                    font-size: 14px;
+                    font-style: normal;
+                    font-weight: 400;
+                    line-height: normal;
+                }
+            }
+        }
+
+        .el-input.is-disabled .el-input__inner {
+            -webkit-text-fill-color: #E2FEFF;
+            color: #E2FEFF;
+        }
+
+        .set_unit {
+            margin-left: 5px;
+            font-family: OPPOSans;
+            font-size: 10px;
+            font-style: normal;
+            font-weight: 400;
+            line-height: normal;
+        }
+    }
+}
+</style>

+ 48 - 0
ui/src/views/newControlPage/components/statusSet.vue

@@ -0,0 +1,48 @@
+<template>
+    <div class="set_value">
+        <el-button :type="item.active == 1 ? item.type : 'info'" v-for="(item, index) in buttonInfo" :key="index" class="set_button" @click="handleClick(item.value)">{{ item.label }}</el-button>
+    </div>
+</template>
+
+<script setup>
+const props = defineProps({
+    buttonInfo: {
+        type: Array,
+        default: () => [
+            { value: 0, label: '开', type: 'success' }
+        ]
+    },
+    disable: {
+        type: Boolean,
+        default: false
+    }
+})
+const emit = defineEmits(['click:button'])
+const handleClick = (value) => {
+    if (props.disable) return
+    emit('click:button', value)
+}
+</script>
+
+<style lang="scss">
+.set_value {
+    max-width: 100px;
+    max-height: 66px;
+    row-gap: 4px;
+    column-gap: 4px;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+
+    .set_button {
+        display: flex;
+        width: 38px;
+        height: 28px;
+        padding: 5px;
+        justify-content: center;
+        align-items: center;
+        gap: 5px;
+        margin-left: 0;
+    }
+}
+</style>

+ 61 - 0
ui/src/views/newControlPage/components/statusView.vue

@@ -0,0 +1,61 @@
+<template>
+    <div class="set_value">
+        <div class="signal">
+            <div class="square greed" :class="active == 0 ? 'active' : ''"></div>
+            <div class="square red" :class="active == 1 ? 'active' : ''"></div>
+            <div class="square yellow" :class="active == 2 ? 'active' : ''"></div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+
+const props = defineProps({
+    active: {
+        type: Number,
+        default: 0
+    }
+})
+</script>
+
+<style lang="scss">
+.set_value {
+    max-width: 84px;
+    max-height: 66px;
+    row-gap: 4px;
+    column-gap: 4px;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+
+    .signal {
+        display: flex;
+        align-items: center;
+        gap: 5px;
+
+        .square {
+            width: 20px;
+            height: 20px;
+            aspect-ratio: 1/1;
+            opacity: 0.5;
+        }
+
+        .red {
+            background-color: #DF0000;
+        }
+
+        .greed {
+            background-color: #00D35F;
+        }
+
+        .yellow {
+            background-color: #FFC926;
+        }
+
+        .active {
+            opacity: 1;
+        }
+    }
+}
+</style>

+ 588 - 0
ui/src/views/newControlPage/reaction/index.vue

@@ -0,0 +1,588 @@
+<template>
+    <div class="page">
+        <!-- 固定头部 -->
+        <div class="fixed-header" ref="fixedHeader">
+            <HeaderComponent title="硫酸钠-反应控制台" backTo="/controlPage/flowSelect" />
+            <!-- <PageNav :items="navItems" :currentCode="flowCode" /> -->
+        </div>
+        <!-- 主内容区 -->
+        <div class="content_page">
+            <div class="device_status_container">
+                <!-- 1#反应釜 状态卡片 -->
+                <!-- <div class="status_card" shadow="hover">
+                    <div class="card_header">
+                        <span class="card_title">1#反应釜</span>
+                        <span class="card_subtitle">C3001</span>
+                    </div>
+                    <div class="device_grid">
+                        <DeviceConfigItem :deviceName="workModeConfig.deviceName"
+                            :settingList="workModeConfig.settingList" @change="handleDeviceConfigChange" />
+                        <DeviceConfigItem :deviceName="feedConfig.deviceName" :settingList="feedConfig.settingList"
+                            @change="handleDeviceConfigChange" />
+                    </div>
+                </div> -->
+                <StatusCard title="1#反应釜" subtitle="C3001" :deviceList="deviceList"
+                    @deviceChange="handleDeviceConfigChange">
+                </StatusCard>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+const pageCode = 'MGM';
+const flowId = 9;//当前页面流程Id
+import { onMounted, computed, reactive, ref } from 'vue';
+import { useRoute } from 'vue-router';
+const route = useRoute();
+import { useEquipmentLayout } from '@/hooks/useEquipmentLayout'
+import { useValveHelper } from '@/hooks/useValveHelper'
+import { updateZTPageConfig } from '@/api/dcs/configurePage';
+import { getMainSetParam } from '@/api/hnyz/param'
+import { setValues } from '@/api/dcs/flowControl'
+import { stompClient } from '@/utils/ws/stompClient';
+
+import DeviceConfigItem from '../components/DeviceConfigItem.vue';
+import StatusCard from '../components/StatusCard.vue';
+
+import HeaderComponent from '@/components/DCS/HeaderComponent.vue';
+import PageNav from '@/components/GeneralComponents/control/PageNavComponent.vue';
+import { getFlowNav } from '@/api/hnyz/flow';
+const flowCode = computed(() => route.params.flowCode);
+const navItems = ref();
+const fixedHeader = ref(null);
+const headerHeight = ref(0);
+// 计算固定头部高度
+const calculateHeaderHeight = () => { headerHeight.value = fixedHeader.value?.offsetHeight || 0; }
+onMounted(async () => {
+    const res = await getFlowNav('Na2SO4', 'flowSelect');
+    navItems.value = res.data;
+    calculateHeaderHeight();
+    window.addEventListener('resize', calculateHeaderHeight);
+});
+
+onMounted(async () => {
+    // loadInitialData();
+});
+
+const num = ref(1)
+const speedValue = ref(500)
+const weightValue = ref(500)
+const flowValue = ref(100)
+const temperatureValue = ref(25)
+// 工作模式配置
+const workModeConfig = computed(() => ({
+    deviceName: '工作模式',
+    settingList: [
+        {
+            title: '当前模式',
+            item: {
+                component: 'statusSet',
+                props: {
+                    buttonInfo: [
+                        { value: 0, type: 'success', label: '正吹', active: 1 },
+                        { value: 1, type: 'danger', label: '反吹', active: 0 }
+                    ],
+                    disable: true
+                }
+            }
+        },
+        {
+            title: '模式设置',
+            item: {
+                component: 'statusSet',
+                props: {
+                    buttonInfo: [
+                        { value: 0, type: 'success', label: '开', active: 1 },
+                        { value: 1, type: 'danger', label: '关', active: 0 },
+                        { value: 2, type: 'success', label: '正吹', active: 0 },
+                        { value: 3, type: 'success', label: '反吹', active: 0 }
+                    ]
+                }
+            }
+        }
+    ]
+}))
+
+// 原矿进料配置
+const feedConfig = computed(() => ({
+    deviceName: '原矿进料',
+    settingList: [
+        {
+            title: '状态',
+            item: {
+                component: 'statusView',
+                props: {
+                    active: 2
+                }
+            }
+        },
+        {
+            title: '速度',
+            item: {
+                component: 'numberInput',
+                props: {
+                    value: speedValue.value,
+                    unit: '转',
+                    max: 5000
+                }
+            }
+        },
+        {
+            title: '进料量',
+            item: {
+                component: 'numberInput',
+                props: {
+                    value: weightValue.value,
+                    unit: 'T'
+                }
+            }
+        }
+    ]
+}))
+
+const deviceList = computed(() => [
+    {
+        deviceName: '原矿进料',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '启动', active: 1 },
+                            { value: 1, type: 'danger', label: '停止', active: 0 },
+                        ]
+                    }
+                }
+            },
+            {
+                title: '实时转速',
+                code: 'yljksjzs',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: speedValue.value,
+                        unit: '%',
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定转速',
+                code: 'yljksdzs',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: speedValue.value,
+                        unit: '%',
+                        min: 0,
+                        max: 5000
+                    }
+                }
+            },
+            {
+                title: '进料量',
+                code: 'yljkjll',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: weightValue.value,
+                        unit: 'kg',
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#硫酸||进料泵',
+        deviceCode: 'P5003',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '启动', active: 1 },
+                            { value: 1, type: 'danger', label: '停止', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '2#硫酸||进料泵',
+        deviceCode: 'P5004',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '启动', active: 1 },
+                            { value: 1, type: 'danger', label: '停止', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '硫酸流量计',
+        deviceCode: 'FIT3001',
+        settingList: [
+            {
+                title: '实时值',
+                code: 'lslljssz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 100,
+                        unit: 'm³/h',
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定值',
+                code: 'lslljsdz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 100,
+                        unit: 'm³/h',
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#反应釜||温度计',
+        deviceCode: 'TT3001',
+        settingList: [
+            {
+                title: '实时值',
+                code: 'fyfwdjssz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        unit: '°C',
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定值',
+                code: 'fyfwdjsdz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        unit: '°C',
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#反应釜||搅拌电机',
+        deviceCode: 'M3001',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '启动', active: 1 },
+                            { value: 1, type: 'danger', label: '停止', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#反应釜||PH计',
+        deviceCode: 'PH3001',
+        settingList: [
+            {
+                title: '实时值',
+                code: 'fyfphjssz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定值',
+                code: 'fyfphjsdz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '硫酸进料阀',
+        deviceCode: 'QQF5004',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '开', active: 1 },
+                            { value: 1, type: 'danger', label: '关', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '硫酸进料阀',
+        deviceCode: 'QQF5003',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '开', active: 1 },
+                            { value: 1, type: 'danger', label: '关', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#反应釜||液位计',
+        deviceCode: 'LT3101',
+        settingList: [
+            {
+                title: '实时值',
+                code: 'fyfywjssz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定值',
+                code: 'fyfywjsdz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    }
+])
+
+// const {
+//     generatePageParams,
+// } = useEquipmentLayout(pageCode)
+
+// 根据设备类型返回组件
+function getComponentByType(equipmentType) {
+    const type = Number(equipmentType);
+    if ([1, 5].includes(type)) return ValveControlComponent;
+    if (type === 2) return PumpControlComponent;
+    if (type === 4) return SensorControl;
+    return 'div';
+}
+
+// const { getDataArrByCode, getValveStatusArr } = useValveHelper(computed(() => [
+//     ...deviceDataGroup.VALVES,
+//     ...deviceDataGroup.SENSORS
+// ]))
+const handleChange = (value) => {
+    console.log("handleChange", value)
+}
+
+// 处理速度变化
+const handleSpeedChange = (newValue) => {
+    console.log("速度变化:", newValue)
+    // TODO
+}
+
+// 处理进料量变化
+const handleWeightChange = (newValue) => {
+    console.log("进料量变化:", newValue)
+    // TODO
+}
+
+// 处理设备配置变化
+const handleDeviceConfigChange = (data) => {
+    console.log('主页面接收到设备配置变化:', data)
+    const { title, value, setting, cardTitle, cardSubtitle } = data
+
+    // console.log('卡片信息:', { cardTitle, cardSubtitle })
+    // console.log('设置项信息:', { title, value, setting })
+
+    if (title === '设定转速') {
+        console.log('处理速度变化:', value)
+        handleSpeedChange(value)
+        speedValue.value = value
+        // 同步更新配置中的值
+        const speedSetting = feedConfig.value.settingList.find(item => item.title === '速度')
+        if (speedSetting) {
+            speedSetting.item.props.value = value
+        }
+    } else if (title === '进料量') {
+        console.log('处理进料量变化:', value)
+        handleWeightChange(value)
+        weightValue.value = value
+        // 同步更新配置中的值
+        const weightSetting = feedConfig.value.settingList.find(item => item.title === '进料量')
+        if (weightSetting) {
+            weightSetting.item.props.value = value
+        }
+    } else {
+        console.log('处理其他设置项变化:', { title, value })
+    }
+}
+</script>
+
+<style lang="scss">
+@import '@/assets/styles/dcs/hnyzConfiguratePage.scss';
+
+.page {
+    // width: 1920px;
+    // height: 1080px;
+    // background-color: #030709;
+
+    .content_page {
+        position: relative;
+        width: 100%;
+        // min-height: 100vh;
+        padding: 20px;
+        margin-top: 30px;
+        display: flex;
+        justify-content: flex-start;
+        align-items: flex-start;
+
+        .device_status_container {
+            display: inline-flex;
+            padding: 10px;
+            flex-direction: column;
+            align-items: flex-start;
+            gap: 20px;
+            margin: 0 97px 0;
+
+            .light-control-card {
+                background: rgba(255, 255, 255, 0.95);
+                border-radius: 8px;
+
+                .card_header {
+                    display: flex;
+                    justify-content: space-between;
+                    align-items: center;
+
+                    .card_title {
+                        font-size: 18px;
+                        font-weight: 600;
+                        color: #303133;
+                    }
+                }
+
+                .light-button-grid {
+                    display: grid;
+                    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
+                    gap: 12px;
+
+                    .el-button+.el-button {
+                        margin-left: 0;
+                    }
+                }
+
+                .light-button {
+                    width: 100%;
+                    font-size: 12px;
+                    padding: 8px 4px;
+                    line-height: 1.2;
+                }
+            }
+        }
+    }
+}
+</style>