Browse Source

项目初始化

tags/1.0
白凤吉 5 months ago
parent
commit
47e430ad8f
  1. 41
      src/main/java/com/qyft/ms/system/config/DeviceTcpConfig.java
  2. 14
      src/main/java/com/qyft/ms/system/config/WebSocketConfig.java
  3. 112
      src/main/java/com/qyft/ms/system/core/client/DeviceTcpClient.java
  4. 31
      src/main/java/com/qyft/ms/system/core/handler/DeviceMessageHandler.java
  5. 34
      src/main/java/com/qyft/ms/system/core/handler/TcpConnectionHandler.java
  6. 79
      src/main/java/com/qyft/ms/system/core/server/WebSocketServer.java
  7. 2
      src/main/java/com/qyft/ms/system/service/RoleService.java
  8. 2
      src/main/java/com/qyft/ms/system/service/UserService.java
  9. 6
      src/main/resources/application.yml
  10. 80
      src/main/resources/logback.xml
  11. 4
      src/main/resources/mapper/system/RoleMapper.xml
  12. 4
      src/main/resources/mapper/system/UserMapper.xml
  13. 232
      src/main/resources/sql/init.sql

41
src/main/java/com/qyft/ms/system/config/DeviceTcpConfig.java

@ -0,0 +1,41 @@
package com.qyft.ms.system.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "tcp")
public class DeviceTcpConfig {
/**
* 是否启用 TCP 连接
*/
private boolean enable;
/**
* 是否开启本地tcp服务器
*/
private boolean serverEnable;
/**
* TCP 链接地址
*/
private String host;
/**
* TCP 端口
*/
private int port;
/**
* 断线重连间隔毫秒
*/
private int reconnect;
/**
* 连接超时时间毫秒
*/
private int timeout;
/**
* 指令反馈超时时间
*/
private int feedbackTimeout;
}

14
src/main/java/com/qyft/ms/system/config/WebSocketConfig.java

@ -0,0 +1,14 @@
package com.qyft.ms.system.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

112
src/main/java/com/qyft/ms/system/core/client/DeviceTcpClient.java

@ -0,0 +1,112 @@
package com.qyft.ms.system.core.client;
import cn.hutool.json.JSONUtil;
import com.qyft.ms.system.config.DeviceTcpConfig;
import com.qyft.ms.system.core.handler.DeviceMessageHandler;
import com.qyft.ms.system.core.handler.TcpConnectionHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.json.JsonObjectDecoder;
import io.netty.util.CharsetUtil;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
@RequiredArgsConstructor
public class DeviceTcpClient {
private final DeviceTcpConfig tcpConfig;
private final EventLoopGroup group = new NioEventLoopGroup();
private Channel channel;
private Bootstrap bootstrap;
@PostConstruct
private void init() {
if (tcpConfig.isEnable()) {
connect();
}
}
// 连接到TCP服务器
public void connect() {
try {
if (bootstrap == null) {
bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, tcpConfig.getTimeout())
.handler(new ChannelInitializer<>() {
@Override
protected void initChannel(Channel ch) {
// 添加JSON解码器
ch.pipeline().addLast(new JsonObjectDecoder());
// 添加设备消息处理器
ch.pipeline().addLast(new DeviceMessageHandler());
// 添加外部定义的TCP连接处理器并传入TcpClient实例
ch.pipeline().addLast(new TcpConnectionHandler(DeviceTcpClient.this));
}
});
}
log.info("尝试连接到TCP服务 {}:{}", tcpConfig.getHost(), tcpConfig.getPort());
ChannelFuture future = bootstrap.connect(new InetSocketAddress(tcpConfig.getHost(), tcpConfig.getPort()));
future.addListener((ChannelFutureListener) f -> {
if (f.isSuccess()) {
channel = f.channel();
log.info("已链接到TCP服务");
} else {
log.error("无法连接到TCP服务. {}ms后重试...", tcpConfig.getReconnect());
f.channel().eventLoop().schedule(this::connect, tcpConfig.getReconnect(), TimeUnit.MILLISECONDS);
}
});
} catch (Exception e) {
log.error("尝试连接到TCP服务发生意外错误: {}", e.getMessage(), e);
}
}
/**
* 定时检查TCP连接
*/
@Scheduled(fixedRateString = "${tcp.reconnect}")
private void checkConnection() {
if (channel == null || !channel.isActive()) {
log.error("TCP服务链接丢失");
connect();
}
}
/**
* 将obj转换成json后发送
*/
public boolean sendToJSON(Object request) {
String msg = JSONUtil.toJsonStr(request);
return this.send(msg);
}
/**
* 发送字符串请求到TCP服务器
*/
public boolean send(String request) {
if (channel != null && channel.isActive()) {
log.info("发送TCP指令:{}", request);
channel.writeAndFlush(Unpooled.copiedBuffer(request, CharsetUtil.UTF_8));
return true;
} else {
log.error("TCP服务未连接,无法发送请求: {}", request);
return false;
}
}
}

31
src/main/java/com/qyft/ms/system/core/handler/DeviceMessageHandler.java

@ -0,0 +1,31 @@
package com.qyft.ms.system.core.handler;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DeviceMessageHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf buf = (ByteBuf) msg;
String serverMsg = buf.toString(CharsetUtil.UTF_8);
log.info("serverMsg:{}", serverMsg);
try {
JSONObject deviceResult = JSONUtil.parseObj(serverMsg);
JSONObject payload = deviceResult.getJSONObject("payload");
String tag = deviceResult.get("tag").toString();
Integer cmdId = payload.getInt("cmdId");
// 根据 tag cmdId 进行处理
} catch (Exception e) {
log.error("TCP服务消息处理错误: {}, error: {}", serverMsg, e.getMessage(), e);
} finally {
buf.release();
}
}
}

34
src/main/java/com/qyft/ms/system/core/handler/TcpConnectionHandler.java

@ -0,0 +1,34 @@
package com.qyft.ms.system.core.handler;
import com.qyft.ms.system.core.client.DeviceTcpClient;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TcpConnectionHandler extends ChannelInboundHandlerAdapter {
private final DeviceTcpClient tcpClient;
// 通过构造方法注入 TcpClient 引用
public TcpConnectionHandler(DeviceTcpClient tcpClient) {
this.tcpClient = tcpClient;
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.error("TCP连接丢失,准备重新连接...");
if (ctx.channel() != null && ctx.channel().isOpen()) {
ctx.channel().close();
}
// 调用 TcpClient 的连接方法
tcpClient.connect();
super.channelInactive(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.error("TCP连接发生异常: {}", cause.getMessage(), cause);
ctx.close();
}
}

79
src/main/java/com/qyft/ms/system/core/server/WebSocketServer.java

@ -0,0 +1,79 @@
package com.qyft.ms.system.core.server;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
@Slf4j
@ServerEndpoint("/ws")
@Component
public class WebSocketServer {
private static final Set<Session> sessions = new CopyOnWriteArraySet<>();
// 消息按顺序发送加锁
private static final Object sendLock = new Object();
/**
* 群发消息给所有客户端
*/
public static void sendMessageToClients(String message) {
synchronized (sendLock) {
for (Session session : sessions) {
if (session.isOpen()) {
try {
session.getBasicRemote().sendText(message);
log.info("发送消息给客户端(sessionId={}):{}", session.getId(), message);
} catch (Exception e) {
log.error("发送消息失败,sessionId={}", session.getId(), e);
}
} else {
log.warn("跳过关闭状态的 session,sessionId={}", session.getId());
}
}
}
}
/**
* 当有新的 WebSocket 连接建立时调用
*/
@OnOpen
private void onOpen(Session session) {
sessions.add(session);
log.info("WebSocket 客户端已连接,sessionId={},当前在线人数={}", session.getId(), sessions.size());
}
/**
* 当接收到来自客户端的消息时调用
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("接收到来自客户端(sessionId={})的消息:{}", session.getId(), message);
// 根据业务需求处理消息此处可添加进一步的处理逻辑
}
/**
* WebSocket 连接关闭时调用
*/
@OnClose
public void onClose(Session session, CloseReason reason) {
sessions.remove(session);
log.info("WebSocket 客户端断开连接,sessionId={},原因={},当前在线人数={}",
session.getId(), reason.getReasonPhrase(), sessions.size());
}
/**
* WebSocket 连接发生错误时调用
*/
@OnError
public void onError(Session session, Throwable error) {
if (session != null) {
log.error("WebSocket 发生错误,sessionId={}", session.getId(), error);
} else {
log.error("WebSocket 发生错误,session 未初始化", error);
}
}
}

2
src/main/java/com/qyft/ms/system/service/RoleService.java

@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
*/
@Service
@RequiredArgsConstructor
public class RoleService extends ServiceImpl<RoleMapper, Role>{
public class RoleService extends ServiceImpl<RoleMapper, Role> {
public Role findByCode(String code) {
return this.baseMapper.findByCode(code);

2
src/main/java/com/qyft/ms/system/service/UserService.java

@ -18,7 +18,7 @@ import java.util.stream.Collectors;
*/
@Service
@RequiredArgsConstructor
public class UserService extends ServiceImpl<UserMapper, User>{
public class UserService extends ServiceImpl<UserMapper, User> {
private final HttpServletRequest request;

6
src/main/resources/application.yml

@ -18,7 +18,7 @@ spring:
mybatis-plus:
configuration:
# 开启 SQL 日志输出(可选)
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 如果需要加载 XML 文件(自定义 SQL),可配置 mapper-locations:
mapper-locations: classpath*:mapper/*.xml
@ -39,8 +39,8 @@ tcp:
enable: false # 是否开启 TCP 连接
server-enable: true # 是否开启 TCP 连接
host: 127.0.0.1
# host: 192.168.1.168
# host: 192.168.1.168
# host: 192.168.1.168
# host: 192.168.1.168
port: 9080
reconnect: 5000 # 断线重连间隔(单位:毫秒)
timeout: 10000 # 连接超时时间(单位:毫秒)

80
src/main/resources/logback.xml

@ -1,31 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志存放路径 -->
<property name="log.path" value="./logs" />
<property name="log.path" value="./logs"/>
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
@ -33,16 +33,16 @@
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
@ -50,26 +50,26 @@
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.qyft" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<!-- 系统模块日志级别控制 -->
<logger name="com.qyft" level="info"/>
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn"/>
<root level="info">
<appender-ref ref="console"/>
</root>
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
<appender-ref ref="file_info"/>
<appender-ref ref="file_error"/>
</root>
</configuration>

4
src/main/resources/mapper/system/RoleMapper.xml

@ -6,6 +6,8 @@
<select id="findByCode" resultType="com.qyft.ms.system.model.entity.Role">
SELECT * FROM sys_role WHERE code = #{code}
SELECT *
FROM sys_role
WHERE code = #{code}
</select>
</mapper>

4
src/main/resources/mapper/system/UserMapper.xml

@ -6,6 +6,8 @@
<select id="findByUsername" resultType="com.qyft.ms.system.model.entity.User">
SELECT * FROM sys_user WHERE username = #{username}
SELECT *
FROM sys_user
WHERE username = #{username}
</select>
</mapper>

232
src/main/resources/sql/init.sql

@ -1,14 +1,35 @@
-- 创建 sys_user 表,用于存储用户信息
CREATE TABLE IF NOT EXISTS sys_user
(
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 用户ID,自增长主键
username TEXT NOT NULL, -- 用户名
nickname TEXT, -- 用户昵称
password TEXT NOT NULL, -- 密码
role_id INTEGER, -- 角色ID,关联sys_role表
is_deleted TINYINT DEFAULT 0, -- 删除标记(0:未删除,1:已删除)
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT, -- 用户ID,自增长主键
username
TEXT
NOT
NULL, -- 用户名
nickname
TEXT, -- 用户昵称
password
TEXT
NOT
NULL, -- 密码
role_id
INTEGER, -- 角色ID,关联sys_role表
is_deleted
TINYINT
DEFAULT
0, -- 删除标记(0:未删除,1:已删除)
create_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP, -- 创建时间
update_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP -- 更新时间
);
-- 插入测试数据到 sys_user 表
@ -20,11 +41,27 @@ VALUES ('admin', 'Admin', '12345', 1, 0),
-- 创建 sys_role 表,用于存储角色信息
CREATE TABLE IF NOT EXISTS sys_role
(
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 角色ID,自增长主键
name TEXT NOT NULL, -- 角色名称
code TEXT NOT NULL, -- 角色代码,如 ADMIN, USER等
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT, -- 角色ID,自增长主键
name
TEXT
NOT
NULL, -- 角色名称
code
TEXT
NOT
NULL, -- 角色代码,如 ADMIN, USER等
create_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP, -- 创建时间
update_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP -- 更新时间
);
-- 插入角色数据到 sys_role 表
@ -37,66 +74,155 @@ VALUES ('管理员', 'ADMIN'),
-- 创建 matrix 表,用于存储基质类型信息
CREATE TABLE IF NOT EXISTS matrix
(
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 基质类型ID,自增长主键
name TEXT NOT NULL, -- 基质名称
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT, -- 基质类型ID,自增长主键
name
TEXT
NOT
NULL, -- 基质名称
create_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP, -- 创建时间
update_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP -- 更新时间
);
-- 创建 matrix_craft 表,用于存储基质工艺信息
CREATE TABLE IF NOT EXISTS matrix_craft
(
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 工艺ID,自增长主键
name TEXT NOT NULL, -- 工艺名称
matrix_id INTEGER NOT NULL, -- 关联的基质类型ID(外键)
matrix_path_type TEXT NOT NULL, -- 基质路径类型
motor_z_height INTEGER, -- 电机Z轴高度
gas_pressure INTEGER, -- 气压
volume INTEGER, -- 容积
matrix_flow_velocity INTEGER, -- 基质流速
high_voltage BOOLEAN, -- 是否采用高压(TRUE 或 FALSE)
high_voltage_value INTEGER, -- 高压值
spacing INTEGER, -- 间距
moving_speed INTEGER, -- 移动速度
times INTEGER, -- 次数
create_user INTEGER, -- 创建用户ID
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT, -- 工艺ID,自增长主键
name
TEXT
NOT
NULL, -- 工艺名称
matrix_id
INTEGER
NOT
NULL, -- 关联的基质类型ID(外键)
matrix_path_type
TEXT
NOT
NULL, -- 基质路径类型
motor_z_height
INTEGER, -- 电机Z轴高度
gas_pressure
INTEGER, -- 气压
volume
INTEGER, -- 容积
matrix_flow_velocity
INTEGER, -- 基质流速
high_voltage
BOOLEAN, -- 是否采用高压(TRUE 或 FALSE)
high_voltage_value
INTEGER, -- 高压值
spacing
INTEGER, -- 间距
moving_speed
INTEGER, -- 移动速度
times
INTEGER, -- 次数
create_user
INTEGER, -- 创建用户ID
create_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP, -- 创建时间
update_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP -- 更新时间
);
-- 创建 operation_log 表,用于存储操作记录信息
CREATE TABLE IF NOT EXISTS operation_log
(
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 日志记录ID,自增长主键
matrix_id INTEGER, -- 关联的基质ID
matrix_info TEXT, -- 基质信息详情
status INTEGER, -- 状态标识(如操作结果状态码)
create_user INTEGER, -- 创建该日志的用户ID
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 日志创建时间
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 日志更新时间
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT, -- 日志记录ID,自增长主键
matrix_id
INTEGER, -- 关联的基质ID
matrix_info
TEXT, -- 基质信息详情
status
INTEGER, -- 状态标识(如操作结果状态码)
create_user
INTEGER, -- 创建该日志的用户ID
create_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP, -- 日志创建时间
update_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP -- 日志更新时间
);
-- 创建 sys_settings 表,用于存储系统配置参数
CREATE TABLE IF NOT EXISTS sys_settings
(
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 配置ID,自增长主键
parent_id INTEGER, -- 父级配置ID(用于层级配置)
name TEXT NOT NULL, -- 配置名称
code TEXT, -- 配置代码
value TEXT -- 配置值
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT, -- 配置ID,自增长主键
parent_id
INTEGER, -- 父级配置ID(用于层级配置)
name
TEXT
NOT
NULL, -- 配置名称
code
TEXT, -- 配置代码
value
TEXT -- 配置值
);
-- 创建 position 表,用于存储设备固定点位信息
CREATE TABLE IF NOT EXISTS position (
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 点位ID,自增长主键
point_name TEXT NOT NULL, -- 点位名称
x REAL NOT NULL, -- X坐标
y REAL NOT NULL, -- Y坐标
z REAL NOT NULL, -- Z坐标
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间
CREATE TABLE IF NOT EXISTS position
(
id
INTEGER
PRIMARY
KEY
AUTOINCREMENT, -- 点位ID,自增长主键
point_name
TEXT
NOT
NULL, -- 点位名称
x
REAL
NOT
NULL, -- X坐标
y
REAL
NOT
NULL, -- Y坐标
z
REAL
NOT
NULL, -- Z坐标
create_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP, -- 创建时间
update_time
TIMESTAMP
DEFAULT
CURRENT_TIMESTAMP -- 更新时间
);
Loading…
Cancel
Save