chore(sql): 自有 SQL 脚本统一迁入 sql/ttstd 并更新目录约定

This commit is contained in:
tongtong committed 2026-11-05 10:32:59 +08:00
1 parent 337033f743
commit ee94762905
23 files changed
+4 -2

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
-- ============================================================
-- 应用分类管理 菜单初始化(幂等,可重复执行)
-- ------------------------------------------------------------
-- 说明:
-- 挂在「应用管理」目录(/app-manager)下,新增「分类管理」菜单。
-- 页面路径:app-manager/category/index
-- ============================================================
SET @parent_id = (SELECT id FROM sys_menu WHERE route_path = '/app-manager' AND type = 'C' LIMIT 1);
INSERT INTO sys_menu
(parent_id, tree_path, name, type, route_name, route_path, component,
perm, always_show, keep_alive, visible, sort, icon, redirect,
create_time, update_time, params)
SELECT @parent_id,
CONCAT('0,', @parent_id),
'分类管理', 'M', 'AppCategory', 'category', 'app-manager/category/index',
NULL, NULL, 1, 1, 2, 'menu', NULL,
now(), now(), NULL
FROM DUAL
WHERE @parent_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE component = 'app-manager/category/index');
-- 授权给 ADMIN 角色(role_id=2,如实际不同请修改)
SET @menu_id = (SELECT id FROM sys_menu WHERE component = 'app-manager/category/index' LIMIT 1);
INSERT IGNORE INTO sys_role_menu (role_id, menu_id)
SELECT 2, @menu_id
FROM DUAL
WHERE @menu_id IS NOT NULL;
+54
View File
@@ -0,0 +1,54 @@
-- =============================================================================
-- 应用图标库表(app_icon)
--
-- 设计目标:
-- 1. 全局图标库:同一应用包名(package_name)的所有设备共用图标,按包名维度维护
-- 2. 历史版本:同一包名可保存多个历史图标版本(status 区分当前生效/历史),
-- 支持从历史版本中选取并锁定,规避三方 App 活动期换图标带广告等风险
-- 3. 锁定机制:locked=1 的版本不可被设备端/管理端上传覆盖,需先解锁
-- 4. 内容指纹:icon_md5 用于内容去重(同一图标不同包名复用同一文件)
--
-- 约定:
-- - 同一 package_name 下 status=1(当前生效)的记录有且仅有一条
-- - 历史版本(status=0)仅用于展示与选取锁定,不物理删除
-- - 版本号生成规则(必须严格遵守):
-- version = 该 package_name 下所有记录的 MAX(version) + 1
-- 统计范围必须包含 is_deleted=1 的逻辑删除行,版本号只增不减、永不复用。
-- 原因:uk_package_version 不包含 is_deleted,若用「当前生效版本+1」或从 1 重新开始,
-- 当前生效记录被删除/缺失时会与残留版本号撞唯一键(Duplicate entry '包名-1')。
-- - 图标文件统一存入 storage.type 配置的存储(当前为阿里云 OSS),icon_url 为可直接访问的完整 URL
--
-- 部署规范:不直连库,由 DBA 执行;先 DROP 再 CREATE 确保结构与实体完全一致
-- (DROP 会清空历史图标数据,可由设备端重新上报补齐)。
-- 存量库修复:不重建表的场景,先执行 sql/app_icon_version_repair.sql 清理脏数据。
-- =============================================================================
DROP TABLE IF EXISTS `app_icon`;
CREATE TABLE `app_icon`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`package_name` VARCHAR(255) NOT NULL COMMENT '应用包名(全局唯一维度,同包名多版本共存)',
`app_name` VARCHAR(128) DEFAULT NULL COMMENT '应用名称(上报时的展示名,可为空;新版本上报时刷新)',
`icon_url` VARCHAR(500) NOT NULL COMMENT '图标访问地址(存储服务返回的完整 URL)',
`icon_md5` VARCHAR(64) DEFAULT NULL COMMENT '图标文件MD5(内容指纹,用于去重与换图标检测)',
`icon_sha1` VARCHAR(64) DEFAULT NULL COMMENT '图标文件SHA1',
`icon_sha256` VARCHAR(64) DEFAULT NULL COMMENT '图标文件SHA256',
`version` INT NOT NULL DEFAULT 1 COMMENT '版本号(同包名内自增,取所有记录含逻辑删除的 MAX(version)+1,不复用)',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(1当前生效 0历史版本)',
`locked` TINYINT NOT NULL DEFAULT 0 COMMENT '是否锁定(0未锁定 1已锁定,锁定后不可上传覆盖)',
`source` VARCHAR(20) NOT NULL DEFAULT 'device' COMMENT '图标来源(device设备端上报 admin管理端上传)',
`create_by` BIGINT DEFAULT NULL COMMENT '创建人ID',
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_by` BIGINT DEFAULT NULL COMMENT '更新人ID',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_package_version` (`package_name`, `version`),
KEY `idx_package_status` (`package_name`, `status`),
KEY `idx_md5` (`icon_md5`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '应用图标库(含历史版本)';
+92
View File
@@ -0,0 +1,92 @@
-- =============================================================================
-- app_icon 版本号 / 生效状态 存量数据修复脚本
--
-- 背景:
-- 旧逻辑用「当前生效版本 + 1」生成版本号,无当前生效记录时固定用 1;
-- 而删除是逻辑删除(is_deleted=1),且唯一索引 uk_package_version(package_name, version)
-- 不包含 is_deleted。当前生效记录被删除或缺失时,再次上传就会撞唯一键:
-- Duplicate entry 'com_alibaba_android_rimet-1' for key 'app_icon.uk_package_version'
--
-- 新逻辑:
-- version = 该 package_name 下所有记录(含 is_deleted=1)的 MAX(version) + 1,
-- 版本号只增不减、永不复用;上传 / 锁定已按包名加锁并置于同一事务内。
--
-- 使用说明:
-- 1. 本脚本仅用于「已在运行、不重建表」的库;全新部署执行 app_icon.sql 即可。
-- 2. 由 DBA 在业务低峰期单独执行,执行前请备份 app_icon 表。
-- 3. 诊断语句(第 1 ~ 3 段)先执行确认现状,再执行修复语句(第 4 ~ 5 段)。
-- =============================================================================
-- -----------------------------------------------------------------------------
-- 1. 诊断:同一包名存在多条 status=1(会导致 one() 抛 TooManyResultsException)
-- -----------------------------------------------------------------------------
SELECT package_name, COUNT(*) AS active_cnt
FROM app_icon
WHERE is_deleted = 0
AND status = 1
GROUP BY package_name
HAVING COUNT(*) > 1;
-- -----------------------------------------------------------------------------
-- 2. 诊断:同一包名有未删除记录,但没有任何 status=1(上传会走「无当前版本」分支)
-- -----------------------------------------------------------------------------
SELECT package_name, COUNT(*) AS alive_cnt, MAX(version) AS max_version
FROM app_icon
WHERE is_deleted = 0
GROUP BY package_name
HAVING SUM(status = 1) = 0;
-- -----------------------------------------------------------------------------
-- 3. 诊断:查看具体包名的版本与删除残留
-- -----------------------------------------------------------------------------
SELECT id, package_name, version, status, locked, is_deleted, update_time
FROM app_icon
WHERE package_name = 'com_alibaba_android_rimet'
ORDER BY is_deleted, version;
-- -----------------------------------------------------------------------------
-- 4. 修复多条 status=1:保留 version 最大的一条为当前生效,其余置为历史
-- -----------------------------------------------------------------------------
UPDATE app_icon a
JOIN (SELECT package_name, MAX(version) AS max_version
FROM app_icon
WHERE is_deleted = 0
AND status = 1
GROUP BY package_name) t
ON a.package_name = t.package_name
SET a.status = 0,
a.update_time = NOW()
WHERE a.is_deleted = 0
AND a.status = 1
AND a.version < t.max_version;
-- -----------------------------------------------------------------------------
-- 5. 修复无 status=1:把未删除记录里版本号最大的一条置为当前生效
-- -----------------------------------------------------------------------------
UPDATE app_icon a
JOIN (SELECT package_name, MAX(version) AS max_version
FROM app_icon
WHERE is_deleted = 0
GROUP BY package_name
HAVING SUM(status = 1) = 0) t
ON a.package_name = t.package_name
AND a.version = t.max_version
SET a.status = 1,
a.update_time = NOW()
WHERE a.is_deleted = 0;
-- -----------------------------------------------------------------------------
-- 6. 复核:两条诊断语句均应返回空结果集
-- -----------------------------------------------------------------------------
SELECT package_name, COUNT(*) AS active_cnt
FROM app_icon
WHERE is_deleted = 0
AND status = 1
GROUP BY package_name
HAVING COUNT(*) > 1;
SELECT package_name, COUNT(*) AS alive_cnt
FROM app_icon
WHERE is_deleted = 0
GROUP BY package_name
HAVING SUM(status = 1) = 0;
+56
View File
@@ -0,0 +1,56 @@
-- ============================================================
-- 应用管理 / 应用上传 菜单修复与初始化(幂等,可重复执行)
-- ------------------------------------------------------------
-- 说明:
-- 本项目使用 vue3-element-admin,后端动态菜单约定:
-- - 目录(type='C')的 component 必须是 'Layout'(顶层目录必须有 Layout 壳),
-- 否则 transformRoutes 不会包裹 Layout,点击进入页面会白屏/一直 loading。
-- - 菜单(type='M')的 component 才是页面路径,如 'app-manager/upload-package/index'。
--
-- 本脚本:
-- 1. 修正「应用管理」目录 (route_path=/app-manager) 的 component = 'Layout'(关键修复白屏)。
-- 2. 确保「应用上传」菜单存在且 component 指向正确页面。
-- 3. 授权给 ADMIN 角色 (role_id=2,如不同请改)。
-- ============================================================
-- 1. 修正「应用管理」目录(无论是否已存在,都强制 component='Layout')
INSERT INTO sys_menu
(parent_id, tree_path, name, type, route_name, route_path, component,
perm, always_show, keep_alive, visible, sort, icon, redirect,
create_time, update_time, params)
SELECT 0, '0', '应用管理', 'C', '', '/app-manager', 'Layout',
NULL, 1, NULL, 1, 3, 'box', '/app-manager/upload-package',
now(), now(), NULL
FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE route_path = '/app-manager' AND type = 'C');
-- 把已存在但 component 不是 Layout 的「应用管理」目录修正为 Layout(关键)
UPDATE sys_menu
SET component = 'Layout',
always_show = 1,
redirect = '/app-manager/upload-package',
update_time = now()
WHERE route_path = '/app-manager' AND type = 'C' AND component <> 'Layout';
-- 2. 确保「应用上传」菜单存在(挂在应用管理目录下)
SET @parent_id = (SELECT id FROM sys_menu WHERE route_path = '/app-manager' AND type = 'C' LIMIT 1);
INSERT INTO sys_menu
(parent_id, tree_path, name, type, route_name, route_path, component,
perm, always_show, keep_alive, visible, sort, icon, redirect,
create_time, update_time, params)
SELECT @parent_id,
CONCAT('0,', @parent_id),
'应用上传', 'M', 'UploadPackage', 'upload-package', 'app-manager/upload-package/index',
NULL, NULL, 1, 1, 1, 'upload', NULL,
now(), now(), NULL
FROM DUAL
WHERE @parent_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE component = 'app-manager/upload-package/index');
-- 3. 授权给 ADMIN 角色(role_id=2,如实际不同请修改)
SET @menu_id = (SELECT id FROM sys_menu WHERE component = 'app-manager/upload-package/index' LIMIT 1);
INSERT IGNORE INTO sys_role_menu (role_id, menu_id)
SELECT 2, @menu_id
FROM DUAL
WHERE @menu_id IS NOT NULL;
+55
View File
@@ -0,0 +1,55 @@
-- ============================================================
-- 应用安装包资源库 - 后台菜单与权限初始化脚本(可选)
-- ------------------------------------------------------------
-- 说明:
-- 1. 前端路由已在 constantRoutes 中注册,应用列表页面可直接通过
-- /#/app/package 访问,无需执行本脚本也能使用上传/列表功能。
-- 2. 本脚本仅用于在【后台管理 -> 系统管理 -> 菜单管理】侧边栏中
-- 展示“应用列表”入口,并将权限授予所有角色。
-- 3. 请在执行前确认第 1 步查询出的父目录(通常为“设备”目录)的 ID,
-- 若父目录 route_path 不为 'devices',请修改下面的 @parent_id 取值条件。
-- 4. 本脚本仅 INSERT,可重复执行(已包含存在性判断)。
-- ============================================================
-- 0. 变量:自动定位“设备”目录作为父级(如实际父目录不同请修改条件)
SET @parent_id = (SELECT id FROM sys_menu WHERE type = 'C' AND route_path = 'devices' LIMIT 1);
-- 若未找到设备目录,则挂到根目录(id=0)
SET @parent_id = IFNULL(@parent_id, 0);
-- 1. 插入“应用列表”菜单(作为设备目录下的子菜单)
INSERT INTO sys_menu
(parent_id, name, type, route_name, route_path, component, perm, visible, sort, icon, redirect, tree_path, keep_alive, always_show, create_time, update_time)
SELECT
@parent_id,
'应用列表',
'M',
'AppPackage',
'app/package',
'app/package/index',
'app:package:list',
1,
100,
'box',
NULL,
CONCAT(IF(@parent_id = 0, '', CONCAT(@parent_id, ',')), 'APP_PACKAGE_PLACEHOLDER'),
1,
0,
NOW(),
NOW()
WHERE NOT EXISTS (
SELECT 1 FROM sys_menu WHERE route_name = 'AppPackage' AND route_path = 'app/package'
);
-- 更新 tree_path(去掉占位并写入真实自增 id)
SET @menu_id = (SELECT id FROM sys_menu WHERE route_name = 'AppPackage' AND route_path = 'app/package' LIMIT 1);
UPDATE sys_menu
SET tree_path = IF(@parent_id = 0, CONCAT(@menu_id, ','), CONCAT(@parent_id, ',', @menu_id, ','))
WHERE id = @menu_id;
-- 2. 将“应用列表”菜单权限授予所有角色
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT r.id, @menu_id
FROM sys_role r
WHERE NOT EXISTS (
SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = r.id AND rm.menu_id = @menu_id
);
+72
View File
@@ -0,0 +1,72 @@
-- ============================================================
-- app_user 表结构修复与字段扩展
-- 用途:支持手机号 + 微信小程序登录,补充常用用户字段
-- ============================================================
-- 通用 helper:列不存在时才添加
DROP PROCEDURE IF EXISTS add_app_user_column;
DELIMITER $$
CREATE PROCEDURE add_app_user_column(
IN col_name VARCHAR(64),
IN col_def VARCHAR(256)
)
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'app_user'
AND COLUMN_NAME = col_name
) THEN
SET @sql = CONCAT('ALTER TABLE app_user ADD COLUMN ', col_name, ' ', col_def);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END$$
DELIMITER ;
-- 1. 补充原缺失的 username 列(注册/认证需要)
CALL add_app_user_column('username', 'VARCHAR(64) COMMENT ''用户名'' AFTER id');
-- 2. 补充 BaseEntity 审计/逻辑删除列(MyBatis-Plus 自动填充与逻辑删除依赖)
CALL add_app_user_column('is_deleted', 'TINYINT NOT NULL DEFAULT 0 COMMENT ''逻辑删除(0-否 1-是)'' AFTER status');
CALL add_app_user_column('create_time', 'DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ''创建时间'' AFTER is_deleted');
CALL add_app_user_column('update_time', 'DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ''更新时间'' AFTER create_time');
CALL add_app_user_column('create_by', 'BIGINT DEFAULT NULL COMMENT ''创建人'' AFTER update_time');
CALL add_app_user_column('update_by', 'BIGINT DEFAULT NULL COMMENT ''更新人'' AFTER create_by');
-- 3. 微信小程序登录相关字段
CALL add_app_user_column('unionid', 'VARCHAR(64) DEFAULT NULL COMMENT ''微信unionid'' AFTER wechat_openid');
CALL add_app_user_column('session_key', 'VARCHAR(128) DEFAULT NULL COMMENT ''微信小程序session_key'' AFTER unionid');
CALL add_app_user_column('register_source', 'TINYINT DEFAULT 1 COMMENT ''注册来源(1-手机号 2-微信小程序)'' AFTER session_key');
-- 4. 常用用户字段
CALL add_app_user_column('birthday', 'DATE DEFAULT NULL COMMENT ''生日'' AFTER register_source');
CALL add_app_user_column('last_login_time', 'DATETIME DEFAULT NULL COMMENT ''最后登录时间'' AFTER birthday');
DROP PROCEDURE IF EXISTS add_app_user_column;
-- 5. 删除多余的 user_id 列
-- 实体 ClientUser 主键为 BaseEntity.id(列名 id),代码中 userId 均由 "id AS userId" 映射而来,
-- 表内遗留的 user_id 列(NOT NULL 无默认值)导致 INSERT 未写该列时报 "Field 'user_id' doesn't have a default value"。
-- 该列未被任何代码引用,直接删除以消除冗余。
SET @col_exists = (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'app_user'
AND COLUMN_NAME = 'user_id'
);
SET @sql = IF(
@col_exists > 0,
'ALTER TABLE app_user DROP COLUMN user_id',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 6. 扩大 password 列,BCrypt 加密后固定 60 字符,原 VARCHAR(32) 会触发 Data too long
ALTER TABLE app_user MODIFY COLUMN password VARCHAR(100) NOT NULL COMMENT '密码(加密)';
-- 7. 扩大 sys_log.error_msg,避免长异常信息被截断
ALTER TABLE sys_log MODIFY COLUMN error_msg VARCHAR(2000) COMMENT '错误信息';
+61
View File
@@ -0,0 +1,61 @@
-- ----------------------------------------------------------------------------
-- 应用图标管理 菜单 & 按钮权限初始化脚本(可重复执行 / 幂等)
--
-- 依赖
-- 1. 前端页面 vue3-element-admin-ttstd/src/views/app-manager/app-icon/index.vue
-- 2. 后端接口 com.youlai.boot.device.controller.AppIconController (/api/v1/app-icons)
--
-- 说明
-- - 菜单本身(type=M)不携带权限字符串,权限必须来自按钮行(type=B, perm 非空)
-- - 权限字符串中含冒号,部分客户端会把 :xxx 当成绑定变量,故本脚本用 CONCAT 拼接
-- 且授权改用「菜单下所有按钮」子查询,SQL 文本中避免出现 :token
-- - 权限每次请求实时查库,执行后刷新页面即可,无需重启
-- ----------------------------------------------------------------------------
-- 0. 页面已从 devices/app-icon 迁到 app-manager/app-icon,先迁移存量菜单
UPDATE `sys_menu`
SET `component` = 'app-manager/app-icon/index'
WHERE `component` = 'devices/app-icon/index';
-- 定位「应用图标管理」菜单(按前端组件路径唯一标识)
SET @menu_id = (SELECT `id` FROM `sys_menu` WHERE `component` = 'app-manager/app-icon/index' LIMIT 1);
-- 若菜单不存在则创建(优先挂到应用管理目录下,找不到时回退「设备调试」目录)
SET @parent_id = (SELECT `parent_id` FROM `sys_menu` WHERE `component` = 'app-manager/upload-package/index' LIMIT 1);
SET @parent_id = COALESCE(@parent_id, (SELECT `id` FROM `sys_menu` WHERE `name` = '设备调试' AND `parent_id` = 0 LIMIT 1));
INSERT INTO `sys_menu` (`parent_id`, `tree_path`, `name`, `type`, `route_name`, `route_path`, `component`,
`perm`, `always_show`, `keep_alive`, `visible`, `sort`, `icon`, `redirect`,
`create_time`, `update_time`, `params`)
SELECT @parent_id, CONCAT('0,', @parent_id), '应用图标管理', 'M', 'AppIcon', 'app-icon',
'app-manager/app-icon/index', NULL, NULL, 1, 1, 6, 'picture', NULL, now(), now(), NULL
FROM DUAL
WHERE @parent_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `component` = 'app-manager/app-icon/index');
-- 重新取一次菜单 id(可能刚创建)
SET @menu_id = (SELECT `id` FROM `sys_menu` WHERE `component` = 'app-manager/app-icon/index' LIMIT 1);
-- 计算按钮的 tree_path = 菜单 tree_path + ',' + 菜单 id
SET @tree_path = (SELECT CONCAT(`tree_path`, ',', `id`) FROM `sys_menu` WHERE `id` = @menu_id);
-- 1. 插入 4 个按钮权限(上传 / 锁定 / 解锁 / 删除;不存在才插入)
-- 权限字符串用 CONCAT 拼接,避免 :token 被客户端误判
INSERT INTO `sys_menu` (`parent_id`, `tree_path`, `name`, `type`, `route_name`, `route_path`, `component`,
`perm`, `always_show`, `keep_alive`, `visible`, `sort`, `icon`, `redirect`,
`create_time`, `update_time`, `params`)
SELECT @menu_id, @tree_path, t.`name`, 'B', NULL, NULL, NULL,
t.`perm`, NULL, NULL, 1, t.`sort`, NULL, NULL, now(), now(), NULL
FROM (
SELECT '上传' AS `name`, CONCAT('device', ':', 'app-icon', ':', 'upload') AS `perm`, 1 AS `sort` UNION ALL
SELECT '锁定', CONCAT('device', ':', 'app-icon', ':', 'lock'), 2 UNION ALL
SELECT '解锁', CONCAT('device', ':', 'app-icon', ':', 'unlock'), 3 UNION ALL
SELECT '删除', CONCAT('device', ':', 'app-icon', ':', 'delete'), 4
) t
WHERE @menu_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM `sys_menu` m WHERE m.`perm` = t.`perm`);
-- 2. 授权给 ADMIN 角色(role_id = 2;如实际角色 id 不同请修改)
-- 直接授权该菜单下的全部按钮,避免 SQL 文本中出现带冒号的权限字符串
INSERT IGNORE INTO `sys_role_menu` (`role_id`, `menu_id`)
SELECT 2, `id`
FROM `sys_menu`
WHERE `parent_id` = @menu_id AND `type` = 'B';
+55
View File
@@ -0,0 +1,55 @@
-- ----------------------------------------------------------------------------
-- 设备开发者选项 菜单 & 按钮权限初始化脚本(可重复执行 / 幂等)
--
-- 依赖
-- 1. 前端页面 vue3-element-admin-ttstd/src/views/devices/developer/index.vue
-- 2. 后端接口 com.youlai.boot.device.controller.DeveloperController (/api/v1/developers)
--
-- 说明
-- - 菜单本身(type=M)不携带权限字符串,权限必须来自按钮行(type=B, perm 非空)
-- - 权限字符串中含冒号,部分客户端会把 :xxx 当成绑定变量,故本脚本用 CONCAT 拼接
-- 且授权改用「菜单下所有按钮」子查询,SQL 文本中避免出现 :token
-- - 权限每次请求实时查库,执行后刷新页面即可,无需重启
-- ----------------------------------------------------------------------------
-- 0. 定位「开发者选项」菜单(按前端组件路径唯一标识)
SET @menu_id = (SELECT `id` FROM `sys_menu` WHERE `component` = 'devices/developer/index' LIMIT 1);
-- 若菜单不存在则创建(挂到「设备调试」目录下;如目录 id 不同请自行调整 parent_id)
SET @parent_id = (SELECT `id` FROM `sys_menu` WHERE `name` = '设备调试' AND `parent_id` = 0 LIMIT 1);
INSERT INTO `sys_menu` (`parent_id`, `tree_path`, `name`, `type`, `route_name`, `route_path`, `component`,
`perm`, `always_show`, `keep_alive`, `visible`, `sort`, `icon`, `redirect`,
`create_time`, `update_time`, `params`)
SELECT @parent_id, CONCAT('0,', @parent_id), '开发者选项', 'M', 'DeveloperOptions', 'developer-options',
'devices/developer/index', NULL, NULL, 1, 1, 2, 'developer', NULL, now(), now(), NULL
FROM DUAL
WHERE @parent_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `component` = 'devices/developer/index');
-- 重新取一次菜单 id(可能刚创建)
SET @menu_id = (SELECT `id` FROM `sys_menu` WHERE `component` = 'devices/developer/index' LIMIT 1);
-- 计算按钮的 tree_path = 菜单 tree_path + ',' + 菜单 id
SET @tree_path = (SELECT CONCAT(`tree_path`, ',', `id`) FROM `sys_menu` WHERE `id` = @menu_id);
-- 1. 插入 5 个按钮权限(不存在才插入);权限字符串用 CONCAT 拼接,避免 :token 被客户端误判
INSERT INTO `sys_menu` (`parent_id`, `tree_path`, `name`, `type`, `route_name`, `route_path`, `component`,
`perm`, `always_show`, `keep_alive`, `visible`, `sort`, `icon`, `redirect`,
`create_time`, `update_time`, `params`)
SELECT @menu_id, @tree_path, t.`name`, 'B', NULL, NULL, NULL,
t.`perm`, NULL, NULL, 1, t.`sort`, NULL, NULL, now(), now(), NULL
FROM (
SELECT '查询' AS `name`, CONCAT('device', ':', 'developer', ':', 'list') AS `perm`, 1 AS `sort` UNION ALL
SELECT '新增', CONCAT('device', ':', 'developer', ':', 'create'), 2 UNION ALL
SELECT '编辑', CONCAT('device', ':', 'developer', ':', 'update'), 3 UNION ALL
SELECT '删除', CONCAT('device', ':', 'developer', ':', 'delete'), 4 UNION ALL
SELECT '推送设备', CONCAT('device', ':', 'developer', ':', 'push'), 5
) t
WHERE @menu_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM `sys_menu` m WHERE m.`perm` = t.`perm`);
-- 2. 授权给 ADMIN 角色(role_id = 2;如实际角色 id 不同请修改)
-- 直接授权该菜单下的全部按钮,避免 SQL 文本中出现带冒号的权限字符串
INSERT IGNORE INTO `sys_role_menu` (`role_id`, `menu_id`)
SELECT 2, `id`
FROM `sys_menu`
WHERE `parent_id` = @menu_id AND `type` = 'B';
+61
View File
@@ -0,0 +1,61 @@
-- ----------------------------------------------------------------------------
-- SN管理 菜单 & 按钮权限初始化脚本(可重复执行 / 幂等)
--
-- 依赖
-- 1. 前端页面 vue3-element-admin-ttstd/src/views/devices/sn/index.vue
-- 2. 后端接口 com.youlai.boot.device.controller.DeviceController (/api/v1/device)
--
-- 说明
-- - 菜单本身(type=M)不携带权限字符串,权限必须来自按钮行(type=B, perm 非空)
-- - 权限字符串中含冒号,部分客户端会把 :xxx 当成绑定变量,故本脚本用 CONCAT 拼接
-- 且授权改用「菜单下所有按钮」子查询,SQL 文本中避免出现 :token
-- - 权限每次请求实时查库,执行后刷新页面即可,无需重启
-- ----------------------------------------------------------------------------
-- 0. 定位「SN管理」菜单(按前端组件路径唯一标识)
SET @menu_id = (SELECT `id` FROM `sys_menu` WHERE `component` = 'devices/sn/index' LIMIT 1);
-- 若菜单不存在则创建(挂到「设备调试」目录下;如目录 id 不同请自行调整 parent_id)
SET @parent_id = (SELECT `id` FROM `sys_menu` WHERE `name` = '设备调试' AND `parent_id` = 0 LIMIT 1);
INSERT INTO `sys_menu` (`parent_id`, `tree_path`, `name`, `type`, `route_name`, `route_path`, `component`,
`perm`, `always_show`, `keep_alive`, `visible`, `sort`, `icon`, `redirect`,
`create_time`, `update_time`, `params`)
SELECT @parent_id, CONCAT('0,', @parent_id), 'SN管理', 'M', 'SnManagement', 'sn-management',
'devices/sn/index', NULL, NULL, 1, 1, 1, 'device', NULL, now(), now(), NULL
FROM DUAL
WHERE @parent_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `component` = 'devices/sn/index');
-- 重新取一次菜单 id(可能刚创建)
SET @menu_id = (SELECT `id` FROM `sys_menu` WHERE `component` = 'devices/sn/index' LIMIT 1);
-- 计算按钮的 tree_path = 菜单 tree_path + ',' + 菜单 id
SET @tree_path = (SELECT CONCAT(`tree_path`, ',', `id`) FROM `sys_menu` WHERE `id` = @menu_id);
-- 1. 清理旧命名按钮权限(add/edit → create/update),保证幂等可重跑
-- 旧的 sys:device:add / sys:device:edit 若存在则删除,避免与标准命名并存
DELETE FROM `sys_menu`
WHERE `perm` IN (CONCAT('sys', ':', 'device', ':', 'add'), CONCAT('sys', ':', 'device', ':', 'edit'))
AND `type` = 'B';
-- 2. 插入按钮权限(不存在才插入);权限字符串用 CONCAT 拼接,避免 :token 被客户端误判
-- 命名遵循系统标准(前端 buttonConfig 与后端代码生成器统一):list / create / update / delete
INSERT INTO `sys_menu` (`parent_id`, `tree_path`, `name`, `type`, `route_name`, `route_path`, `component`,
`perm`, `always_show`, `keep_alive`, `visible`, `sort`, `icon`, `redirect`,
`create_time`, `update_time`, `params`)
SELECT @menu_id, @tree_path, t.`name`, 'B', NULL, NULL, NULL,
t.`perm`, NULL, NULL, 1, t.`sort`, NULL, NULL, now(), now(), NULL
FROM (
SELECT '查询' AS `name`, CONCAT('sys', ':', 'device', ':', 'list') AS `perm`, 1 AS `sort` UNION ALL
SELECT '新增', CONCAT('sys', ':', 'device', ':', 'create'), 2 UNION ALL
SELECT '编辑', CONCAT('sys', ':', 'device', ':', 'update'), 3 UNION ALL
SELECT '删除', CONCAT('sys', ':', 'device', ':', 'delete'), 4
) t
WHERE @menu_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM `sys_menu` m WHERE m.`perm` = t.`perm`);
-- 3. 授权给 ADMIN 角色(role_id = 2;如实际角色 id 不同请修改)
-- 直接授权该菜单下的全部按钮,避免 SQL 文本中出现带冒号的权限字符串
INSERT IGNORE INTO `sys_role_menu` (`role_id`, `menu_id`)
SELECT 2, `id`
FROM `sys_menu`
WHERE `parent_id` = @menu_id AND `type` = 'B';
+68
View File
@@ -0,0 +1,68 @@
-- ----------------------------------------------------------------------------
-- 更新管理 菜单初始化脚本(可重复执行 / 幂等)
--
-- 依赖
-- 1. 前端页面 vue3-element-admin-ttstd/src/views/update/{channel,global,gray,save-flow,hot}/index.vue
-- 2. 后端接口 com.youlai.boot.app.update.controller.*(/api/v1/app/update/**)
--
-- 说明
-- - 路由改为后端菜单动态下发,前端 src/router/index.ts 不再保留 /update 静态路由
-- - 目录(type='C')的 component 必须是 'Layout',否则不会套后台布局
-- - 菜单(type='M')的 component 为相对 src/views/ 的页面路径,省略 .vue 后缀
-- - 更新模块后端接口暂未使用 @PreAuthorize 做按钮级鉴权,因此本脚本只建目录和页面菜单;
-- 后续补充接口权限时,再按 menu_device_sn.sql 的方式追加 type='B' 按钮行
-- - 菜单权限每次请求实时查库,执行后重新登录或刷新页面即可生效
-- ----------------------------------------------------------------------------
-- 1. 定位或创建「更新管理」目录(按路由路径唯一标识)
SET @parent_id = (SELECT `id` FROM `sys_menu` WHERE `route_path` = '/update' AND `type` = 'C' LIMIT 1);
INSERT INTO `sys_menu`
(`parent_id`, `tree_path`, `name`, `type`, `route_name`, `route_path`, `component`,
`perm`, `keep_alive`, `visible`, `sort`, `icon`, `redirect`,
`create_time`, `update_time`, `params`)
SELECT 0, '0', '更新管理', 'C', '', '/update', 'Layout',
NULL, NULL, 1, 9, 'el-icon-Refresh', '/update/channel',
now(), now(), NULL
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `sys_menu` WHERE `route_path` = '/update' AND `type` = 'C'
);
SET @parent_id = (SELECT `id` FROM `sys_menu` WHERE `route_path` = '/update' AND `type` = 'C' LIMIT 1);
-- 2. 创建 5 个页面菜单(按 component 唯一标识,已存在则跳过)
INSERT INTO `sys_menu`
(`parent_id`, `tree_path`, `name`, `type`, `route_name`, `route_path`, `component`,
`perm`, `keep_alive`, `visible`, `sort`, `icon`, `redirect`,
`create_time`, `update_time`, `params`)
SELECT @parent_id, CONCAT('0,', @parent_id),
t.`name`, 'M', t.`route_name`, t.`route_path`, t.`component`,
NULL, 1, 1, t.`sort`, t.`icon`, NULL,
now(), now(), NULL
FROM (
SELECT '渠道管理' AS `name`, 'UpdateChannel' AS `route_name`, 'channel' AS `route_path`,
'update/channel/index' AS `component`, 1 AS `sort`, 'el-icon-Connection' AS `icon`
UNION ALL
SELECT '全局更新', 'UpdateGlobal', 'global', 'update/global/index', 2, 'el-icon-Globe'
UNION ALL
SELECT '灰度更新', 'UpdateGray', 'gray', 'update/gray/index', 3, 'el-icon-Picture'
UNION ALL
SELECT '省流更新', 'UpdateSaveFlow', 'save-flow', 'update/save-flow/index', 4, 'el-icon-DataLine'
UNION ALL
SELECT '热更新', 'UpdateHot', 'hot', 'update/hot/index', 5, 'el-icon-Loading'
) t
WHERE @parent_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM `sys_menu` m WHERE m.`component` = t.`component`
);
-- 3. 热更新页目前为占位页,先隐藏菜单;页面补齐后改为 visible = 1
UPDATE `sys_menu` SET `visible` = 0 WHERE `component` = 'update/hot/index';
-- 4. 授权给 ADMIN 角色(role_id = 2;如实际角色 id 不同请修改)
-- 目录与页面菜单一并授权,保证侧边栏可见
INSERT IGNORE INTO `sys_role_menu` (`role_id`, `menu_id`)
SELECT 2, `id`
FROM `sys_menu`
WHERE `id` = @parent_id OR `parent_id` = @parent_id;
+32
View File
@@ -0,0 +1,32 @@
-- =============================================================================
-- 设备闹钟表(sys_sn_alarm)
-- 说明:一设备多行,存放该设备的闹钟列表。家属端(/api/v1/client/sn/alarm)
-- 与设备端(/api/v1/sn/get_alarms|sync_alarms)共用;
-- 任意一端变更后推送 contentType=25,设备拉取整表覆盖本地 Room。
-- =============================================================================
CREATE TABLE IF NOT EXISTS `sys_sn_alarm`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`serialno` VARCHAR(64) NOT NULL COMMENT '设备序列号(关联 sys_sn.serialno)',
`hour` INT NOT NULL DEFAULT 0 COMMENT '时',
`minute` INT NOT NULL DEFAULT 0 COMMENT '分',
`label` VARCHAR(100) DEFAULT NULL COMMENT '标签',
`repeat_type` INT NOT NULL DEFAULT 0 COMMENT '重复类型(0一次 1每天 2工作日 3自定义)',
`custom_days` VARCHAR(50) DEFAULT NULL COMMENT '自定义星期(2,3,6,7,Calendar.MONDAY=2)',
`is_enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '开关(0关 1开)',
`vibration` TINYINT NOT NULL DEFAULT 0 COMMENT '振动(0否 1是)',
`volume` INT NOT NULL DEFAULT 80 COMMENT '音量(0-100)',
`ringtone_uri` VARCHAR(300) DEFAULT NULL COMMENT '铃声URI',
`snooze_interval` INT NOT NULL DEFAULT 5 COMMENT '贪睡间隔(分钟)',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
KEY `idx_serialno` (`serialno`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备闹钟表';
+21
View File
@@ -0,0 +1,21 @@
-- =============================================================================
-- 设备 ECDSA P-256 签名公钥字段(sys_sn 表扩展)
-- 说明:
-- · 设备首次注册时上传 ECDSA P-256 公钥(X.509 SubjectPublicKeyInfo, Base64),
-- 服务端绑定 SN ↔ 公钥,后续 /api/v1/sn/** 请求用该公钥做 SHA256withECDSA 验签。
-- · 封禁/吊销通过 sys_sn.status 字段:1=启用,0=封禁(验签前校验)。
-- =============================================================================
-- 1. 为 sys_sn 表新增设备签名公钥字段(幂等:已存在则跳过)
SET @column_exists := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'sys_sn'
AND COLUMN_NAME = 'public_key'
);
SET @ddl := IF(@column_exists = 0,
'ALTER TABLE sys_sn ADD COLUMN public_key TEXT NULL COMMENT ''设备ECDSA P-256公钥(X.509 Base64)'' AFTER sn_mobile',
'SELECT 1');
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
+28
View File
@@ -0,0 +1,28 @@
-- =============================================================================
-- 设备图片发送记录表(sys_sn_device_picture)
-- 说明:家属端从相册等入口上传图片发送给设备,设备收到推送(contentType=24)
-- 后弹窗显示该图片。本表独立于壁纸配置表,仅记录发送的图片地址。
-- =============================================================================
CREATE TABLE IF NOT EXISTS `sys_sn_device_picture`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`serialno` VARCHAR(64) NOT NULL COMMENT '设备序列号(关联 sys_sn.serialno)',
`image_url` VARCHAR(500) NOT NULL COMMENT '图片完整URL',
`favorite` TINYINT DEFAULT 0 COMMENT '是否收藏(0否 1是)',
`file_size` BIGINT DEFAULT 0 COMMENT '文件大小(字节)',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
KEY `idx_serialno` (`serialno`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备图片发送记录表';
-- 已建库的补充列(若表已存在且无对应列时执行):
-- ALTER TABLE `sys_sn_device_picture` ADD COLUMN `favorite` TINYINT DEFAULT 0 COMMENT '是否收藏(0否 1是)' AFTER `image_url`;
-- ALTER TABLE `sys_sn_device_picture` ADD COLUMN `file_size` BIGINT DEFAULT 0 COMMENT '文件大小(字节)' AFTER `favorite`;
+59
View File
@@ -0,0 +1,59 @@
-- =============================================================================
-- 设备策略信息表(sys_sn_device_policy)
-- 说明:存储设备的策略开关状态,与设备 SN 绑定,每个 SN 唯一一条。
-- 所有开关字段默认值均为 1(开启)。
-- =============================================================================
CREATE TABLE IF NOT EXISTS `sys_sn_device_policy`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`serialno` VARCHAR(64) NOT NULL COMMENT '设备序列号(关联 sys_sn.serialno)',
-- ===================== 策略开关 =====================
`usb_data` TINYINT NOT NULL DEFAULT 1 COMMENT 'USB偏好设置(0关闭 1开启)',
`time_setting` TINYINT NOT NULL DEFAULT 1 COMMENT '时间设置管控(0关闭 1开启)',
`storage_card` TINYINT NOT NULL DEFAULT 1 COMMENT '存储卡(0关闭 1开启)',
`factory_reset` TINYINT NOT NULL DEFAULT 1 COMMENT '恢复出厂(0关闭 1开启)',
`wifi_hotspot` TINYINT NOT NULL DEFAULT 1 COMMENT 'WiFi热点开关(0关闭 1开启)',
`bluetooth` TINYINT NOT NULL DEFAULT 1 COMMENT '蓝牙开关(0关闭 1开启)',
`wallpaper` TINYINT NOT NULL DEFAULT 1 COMMENT '壁纸功能(0关闭 1开启)',
`notification_bar` TINYINT NOT NULL DEFAULT 1 COMMENT '通知栏显示(0关闭 1开启)',
`status_bar_pull_down` TINYINT NOT NULL DEFAULT 1 COMMENT '状态栏下拉开关(0关闭 1开启)',
`system_nav_bar_show` TINYINT NOT NULL DEFAULT 1 COMMENT '系统导航条显示(0关闭 1开启)',
`system_nav_bar_setting` TINYINT NOT NULL DEFAULT 1 COMMENT '系统导航栏设置(0关闭 1开启)',
`nav_bar_options` TINYINT NOT NULL DEFAULT 1 COMMENT '导航条选项(0关闭 1开启)',
`config_bluetooth` TINYINT NOT NULL DEFAULT 1 COMMENT '蓝牙功能开关(0关闭 1开启)',
`ota_upgrade` TINYINT NOT NULL DEFAULT 1 COMMENT 'OTA升级管控(0关闭 1开启)',
`install_apps` TINYINT NOT NULL DEFAULT 1 COMMENT '应用安装开关(0关闭 1开启)',
`auto_rotate` TINYINT NOT NULL DEFAULT 1 COMMENT '自动旋转(0关闭 1开启)',
`auto_brightness` TINYINT NOT NULL DEFAULT 1 COMMENT '自动亮度(0关闭 1开启)',
`eye_protection` TINYINT NOT NULL DEFAULT 1 COMMENT '护眼模式(0关闭 1开启)',
`dark_mode` TINYINT NOT NULL DEFAULT 1 COMMENT '深色模式(0关闭 1开启)',
`safe_boot` TINYINT NOT NULL DEFAULT 1 COMMENT '允许进入安全模式(0关闭 1开启)',
`adb_usb_debug` TINYINT NOT NULL DEFAULT 1 COMMENT '开启ADB/USB调试(0关闭 1开启)',
`mount_physical_storage` TINYINT NOT NULL DEFAULT 1 COMMENT '挂载外部存储(SD卡/U盘)(0关闭 1开启)',
`modify_system_time_zone` TINYINT NOT NULL DEFAULT 1 COMMENT '修改系统时间与时区(0关闭 1开启)',
`toggle_airplane_mode` TINYINT NOT NULL DEFAULT 1 COMMENT '切换飞行模式(0关闭 1开启)',
`modify_mobile_apn` TINYINT NOT NULL DEFAULT 1 COMMENT '修改移动网络/APN(0关闭 1开启)',
`uninstall_apps` TINYINT NOT NULL DEFAULT 1 COMMENT '卸载应用(0关闭 1开启)',
`camera` TINYINT NOT NULL DEFAULT 1 COMMENT '摄像头(0关闭 1开启)',
`usb_file_transfer` TINYINT NOT NULL DEFAULT 1 COMMENT 'USB文件传输(MTP)(0关闭 1开启)',
`modify_location_switch` TINYINT NOT NULL DEFAULT 1 COMMENT '修改定位开关(0关闭 1开启)',
`bluetooth_sharing` TINYINT NOT NULL DEFAULT 1 COMMENT '蓝牙对外分享(0关闭 1开启)',
`reset_network_settings` TINYINT NOT NULL DEFAULT 1 COMMENT '重置网络设置(0关闭 1开启)',
`adjust_global_volume` TINYINT NOT NULL DEFAULT 1 COMMENT '调节全局音量(0关闭 1开启)',
`modify_screen_timeout` TINYINT NOT NULL DEFAULT 1 COMMENT '修改屏幕超时休眠时间(0关闭 1开启)',
`manual_adjust_time_zone` TINYINT NOT NULL DEFAULT 1 COMMENT '手动调整系统时间与时区(0关闭 1开启)',
`modify_system_language` TINYINT NOT NULL DEFAULT 1 COMMENT '修改系统语言与区域设置(0关闭 1开启)',
`manual_adjust_brightness` TINYINT NOT NULL DEFAULT 1 COMMENT '手动调整系统亮度与自动亮度开关(0关闭 1开启)',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_serialno` (`serialno`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备策略信息表';
+31
View File
@@ -0,0 +1,31 @@
-- =============================================================================
-- 设备壁纸图片明细表(sys_sn_wallpaper_item)
-- 说明:设备的壁纸改为「一图一行」的多行存储,支持显式排序(sort_no)。
-- mode 区分壁纸模式:0-单个壁纸(1 行),1-轮换壁纸(最多 7 行)。
-- sort_no 升序即轮换展示顺序;单个壁纸固定为第 0 行。
-- image_url 为可访问的完整图片 URL,如 /static/wallpaper/SN_xxx_1.jpg。
-- 迁移说明:旧表 sys_sn_device_wallpaper(单行 JSON)已被本表取代;
-- 如需清理旧表请手工执行:DROP TABLE IF EXISTS `sys_sn_device_wallpaper`;
-- =============================================================================
CREATE TABLE IF NOT EXISTS `sys_sn_wallpaper_item`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`serialno` VARCHAR(64) NOT NULL COMMENT '设备序列号(关联 sys_sn.serialno)',
`mode` TINYINT NOT NULL DEFAULT 0 COMMENT '壁纸模式:0-单个壁纸 1-轮换壁纸',
`image_url` VARCHAR(500) NOT NULL COMMENT '壁纸图片完整URL',
`sort_no` INT NOT NULL DEFAULT 0 COMMENT '排序号(升序,轮换展示顺序)',
`md5` VARCHAR(64) DEFAULT NULL COMMENT '壁纸图片文件MD5',
`sha1` VARCHAR(64) DEFAULT NULL COMMENT '壁纸图片文件SHA1',
`sha256` VARCHAR(64) DEFAULT NULL COMMENT '壁纸图片文件SHA256',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
KEY `idx_sn_mode` (`serialno`, `mode`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备壁纸图片明细表';
+47
View File
@@ -0,0 +1,47 @@
-- =============================================================================
-- 设备硬件信息表(sys_sn_hardware_info)
-- 说明:设备【硬件信息】面板独立分表,与基本信息表分离存储。
-- =============================================================================
CREATE TABLE IF NOT EXISTS `sys_sn_hardware_info`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`serialno` VARCHAR(64) NOT NULL COMMENT '设备序列号(关联 sys_sn.serialno)',
-- ===================== 硬件信息面板 =====================
`cpu_abi` VARCHAR(128) DEFAULT NULL COMMENT 'CPU ABI 列表(逗号分隔)',
`cpu_abi2` VARCHAR(128) DEFAULT NULL COMMENT 'CPU ABI2',
`cpu_min` VARCHAR(64) DEFAULT NULL COMMENT '最小 CPU ABI',
`cpu_model` VARCHAR(128) DEFAULT NULL COMMENT 'CPU 型号',
`cpu_cores` INT DEFAULT NULL COMMENT 'CPU 核心数',
`cpu_max_freq` VARCHAR(32) DEFAULT NULL COMMENT 'CPU 最大频率',
`cpu_min_freq` VARCHAR(32) DEFAULT NULL COMMENT 'CPU 最小频率',
`total_ram` VARCHAR(32) DEFAULT NULL COMMENT '总内存',
`available_ram` VARCHAR(32) DEFAULT NULL COMMENT '可用内存',
`internal_storage` VARCHAR(32) DEFAULT NULL COMMENT '内部存储',
`available_storage` VARCHAR(32) DEFAULT NULL COMMENT '可用存储',
`external_storage` VARCHAR(32) DEFAULT NULL COMMENT '外部存储(SD卡)',
`battery_capacity` VARCHAR(32) DEFAULT NULL COMMENT '电池容量',
`battery_level` INT DEFAULT NULL COMMENT '电池电量(0-100)',
`battery_status` VARCHAR(32) DEFAULT NULL COMMENT '电池状态',
`battery_health` VARCHAR(32) DEFAULT NULL COMMENT '电池健康度',
`battery_temp` VARCHAR(32) DEFAULT NULL COMMENT '电池温度',
`battery_voltage` VARCHAR(32) DEFAULT NULL COMMENT '电池电压',
`battery_technology` VARCHAR(32) DEFAULT NULL COMMENT '电池技术',
`gpu_renderer` VARCHAR(128) DEFAULT NULL COMMENT 'GPU 渲染器',
`gpu_vendor` VARCHAR(64) DEFAULT NULL COMMENT 'GPU 厂商',
`gpu_version` VARCHAR(64) DEFAULT NULL COMMENT 'GPU 版本',
`sensors` TEXT DEFAULT NULL COMMENT '传感器列表(JSON)',
`support_abi` VARCHAR(128) DEFAULT NULL COMMENT '支持的应用二进制接口',
`support_abi64` VARCHAR(128) DEFAULT NULL COMMENT '支持的 64 位 ABI',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_serialno` (`serialno`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备硬件信息表';
+47
View File
@@ -0,0 +1,47 @@
-- =============================================================================
-- 设备网络信息表(sys_sn_network_info)
-- 说明:设备【网络信息】面板独立分表,与基本信息表分离存储。
-- =============================================================================
CREATE TABLE IF NOT EXISTS `sys_sn_network_info`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`serialno` VARCHAR(64) NOT NULL COMMENT '设备序列号(关联 sys_sn.serialno)',
-- ===================== 网络信息面板 =====================
`network_type` VARCHAR(32) DEFAULT NULL COMMENT '网络类型(WIFI/MOBILE/ETHERNET等)',
`network_subtype` VARCHAR(32) DEFAULT NULL COMMENT '网络子类型',
`is_connected` TINYINT DEFAULT NULL COMMENT '是否联网(0否 1是)',
`wifi_ssid` VARCHAR(128) DEFAULT NULL COMMENT 'WiFi SSID',
`wifi_bssid` VARCHAR(64) DEFAULT NULL COMMENT 'WiFi BSSID',
`wifi_ip` VARCHAR(64) DEFAULT NULL COMMENT 'WiFi IP 地址',
`wifi_mac` VARCHAR(64) DEFAULT NULL COMMENT 'WiFi MAC 地址',
`wifi_gateway` VARCHAR(64) DEFAULT NULL COMMENT 'WiFi 网关',
`wifi_netmask` VARCHAR(64) DEFAULT NULL COMMENT 'WiFi 子网掩码',
`wifi_dns` VARCHAR(128) DEFAULT NULL COMMENT 'WiFi DNS',
`wifi_rssi` INT DEFAULT NULL COMMENT 'WiFi 信号强度',
`wifi_speed` VARCHAR(32) DEFAULT NULL COMMENT 'WiFi 连接速度',
`mobile_ip` VARCHAR(64) DEFAULT NULL COMMENT '移动网络 IP',
`mobile_mac` VARCHAR(64) DEFAULT NULL COMMENT '移动网络 MAC',
`mobile_imei` VARCHAR(64) DEFAULT NULL COMMENT 'IMEI',
`mobile_imsi` VARCHAR(64) DEFAULT NULL COMMENT 'IMSI',
`mobile_operator` VARCHAR(64) DEFAULT NULL COMMENT '运营商名称',
`mobile_sim_serial` VARCHAR(64) DEFAULT NULL COMMENT 'SIM 序列号',
`mobile_network_type` VARCHAR(32) DEFAULT NULL COMMENT '移动网络类型',
`bluetooth_mac` VARCHAR(64) DEFAULT NULL COMMENT '蓝牙 MAC 地址',
`bluetooth_name` VARCHAR(128) DEFAULT NULL COMMENT '蓝牙名称',
`is_vpn` TINYINT DEFAULT NULL COMMENT '是否 VPN(0否 1是)',
`is_proxy` TINYINT DEFAULT NULL COMMENT '是否代理(0否 1是)',
`proxy_host` VARCHAR(64) DEFAULT NULL COMMENT '代理主机',
`proxy_port` VARCHAR(16) DEFAULT NULL COMMENT '代理端口',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_serialno` (`serialno`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备网络信息表';
+45
View File
@@ -0,0 +1,45 @@
-- =============================================================================
-- 设备其他信息表(sys_sn_other_info)
-- 说明:设备【其他信息】面板独立分表,与基本信息表分离存储。
-- =============================================================================
CREATE TABLE IF NOT EXISTS `sys_sn_other_info`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`serialno` VARCHAR(64) NOT NULL COMMENT '设备序列号(关联 sys_sn.serialno)',
-- ===================== 其他信息面板 =====================
`app_version` VARCHAR(32) DEFAULT NULL COMMENT 'App 版本',
`app_version_code` INT DEFAULT NULL COMMENT 'App 版本号',
`install_time` DATETIME DEFAULT NULL COMMENT 'App 安装时间',
`update_time_app` DATETIME DEFAULT NULL COMMENT 'App 更新时间',
`package_name` VARCHAR(128) DEFAULT NULL COMMENT '应用包名',
`channel` VARCHAR(64) DEFAULT NULL COMMENT '渠道',
`device_id` VARCHAR(64) DEFAULT NULL COMMENT '设备 ID(应用层)',
`gaid` VARCHAR(64) DEFAULT NULL COMMENT 'Google Advertising ID',
`oaid` VARCHAR(64) DEFAULT NULL COMMENT 'OAID',
`phone_number` VARCHAR(32) DEFAULT NULL COMMENT '手机号(脱敏)',
`iccid` VARCHAR(32) DEFAULT NULL COMMENT 'ICCID',
`imsi` VARCHAR(64) DEFAULT NULL COMMENT 'IMSI',
`camera_info` TEXT DEFAULT NULL COMMENT '摄像头信息(JSON)',
`sensor_count` INT DEFAULT NULL COMMENT '传感器数量',
`app_list_md5` VARCHAR(64) DEFAULT NULL COMMENT '应用列表 MD5',
`is_charging` TINYINT DEFAULT NULL COMMENT '是否充电中(0否 1是)',
`charging_type` VARCHAR(32) DEFAULT NULL COMMENT '充电类型',
`temperature` VARCHAR(32) DEFAULT NULL COMMENT '设备温度',
`free_storage` VARCHAR(32) DEFAULT NULL COMMENT '剩余存储',
`total_storage` VARCHAR(32) DEFAULT NULL COMMENT '总存储',
`free_ram` VARCHAR(32) DEFAULT NULL COMMENT '剩余内存',
`total_ram` VARCHAR(32) DEFAULT NULL COMMENT '总内存',
`push_id` VARCHAR(128) DEFAULT NULL COMMENT '极光推送注册ID',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_serialno` (`serialno`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备其他信息表';
+32
View File
@@ -0,0 +1,32 @@
-- =============================================================================
-- 设备截图表(sys_sn_screenshot)
-- 说明:设备【截图】记录表,存储设备上报的截图文件信息。
-- =============================================================================
CREATE TABLE IF NOT EXISTS `sys_sn_screenshot`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`sn` VARCHAR(64) NOT NULL COMMENT '设备序列号',
`file_name` VARCHAR(255) DEFAULT NULL COMMENT '文件名称',
`origin_name` VARCHAR(255) DEFAULT NULL COMMENT '原始文件名(上传时的原始文件名)',
`mime_type` VARCHAR(64) DEFAULT NULL COMMENT '文件MIME类型',
`file_extension` VARCHAR(32) DEFAULT NULL COMMENT '文件扩展名',
`file_path` VARCHAR(500) DEFAULT NULL COMMENT '文件路径',
`file_size` BIGINT DEFAULT NULL COMMENT '文件大小(字节)',
`file_md5` VARCHAR(64) DEFAULT NULL COMMENT '文件MD5值',
`file_sha1` VARCHAR(64) DEFAULT NULL COMMENT '文件Sha1值',
`file_sha256` VARCHAR(64) DEFAULT NULL COMMENT '文件Sha256值',
`upload_time` DATETIME DEFAULT NULL COMMENT '上传时间',
`camera` TINYINT DEFAULT NULL COMMENT '摄像头类型:0-后置,1-前置,-1-截屏',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
KEY `idx_sn` (`sn`),
KEY `idx_upload_time` (`upload_time`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备截图表';
+43
View File
@@ -0,0 +1,43 @@
-- =============================================================================
-- 设备安全信息表(sys_sn_security_info)
-- 说明:设备【安全信息】面板独立分表,与基本信息表分离存储。
-- =============================================================================
CREATE TABLE IF NOT EXISTS `sys_sn_security_info`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`serialno` VARCHAR(64) NOT NULL COMMENT '设备序列号(关联 sys_sn.serialno)',
-- ===================== 安全信息面板 =====================
`is_root` TINYINT DEFAULT NULL COMMENT '是否已 Root(0否 1是)',
`is_jailbreak` TINYINT DEFAULT NULL COMMENT '是否已越狱(0否 1是)',
`root_status` TINYINT DEFAULT NULL COMMENT 'Root/越狱状态(0否 1是)',
`has_su_binary` TINYINT DEFAULT NULL COMMENT '是否存在 su 二进制(0否 1是)',
`has_busybox` TINYINT DEFAULT NULL COMMENT '是否存在 BusyBox(0否 1是)',
`is_emulator` TINYINT DEFAULT NULL COMMENT '是否模拟器(0否 1是)',
`is_debuggable` TINYINT DEFAULT NULL COMMENT '是否可调试(0否 1是)',
`is_usb_debug` TINYINT DEFAULT NULL COMMENT '是否开启 USB 调试(0否 1是)',
`is_unknown_sources` TINYINT DEFAULT NULL COMMENT '是否允许未知来源(0否 1是)',
`is_verify_apps` TINYINT DEFAULT NULL COMMENT '是否验证应用(0否 1是)',
`is_encrypted` TINYINT DEFAULT NULL COMMENT '是否加密(0否 1是)',
`lock_screen_type` VARCHAR(32) DEFAULT NULL COMMENT '锁屏类型',
`has_password` TINYINT DEFAULT NULL COMMENT '是否设置密码(0否 1是)',
`password_type` VARCHAR(32) DEFAULT NULL COMMENT '密码类型',
`security_patch` VARCHAR(32) DEFAULT NULL COMMENT '安全补丁级别',
`google_play_protect` TINYINT DEFAULT NULL COMMENT 'Google Play 保护(0否 1是)',
`adb_status` TINYINT DEFAULT NULL COMMENT 'ADB 状态(0关 1开)',
`is_vpn_active` TINYINT DEFAULT NULL COMMENT 'VPN 是否激活(0否 1是)',
`is_device_owner` TINYINT DEFAULT NULL COMMENT '是否设备所有者(0否 1是)',
`android_version` VARCHAR(32) DEFAULT NULL COMMENT 'Android 版本(安全相关)',
`kernel_version` VARCHAR(128) DEFAULT NULL COMMENT '内核版本(安全相关)',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_serialno` (`serialno`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备安全信息表';
+73
View File
@@ -0,0 +1,73 @@
-- =============================================================================
-- 设备基本信息表(sys_sn_system_info)
-- 说明:仅存放设备【基本信息】面板数据;
-- 硬件信息 / 网络信息 / 安全信息 / 其他信息 已拆分至下列独立表。
-- 脚本由实体(SnDeviceSystemInfo / DeviceSystemInfoVO)生成,字段逐一对应。
-- 部署规范:不直连库,由 DBA 执行;先 DROP 再 CREATE 确保结构与实体完全一致
-- (DROP 会清空该表历史数据,设备数据可由端上重新上报补齐)。
-- =============================================================================
DROP TABLE IF EXISTS `sys_sn_system_info`;
CREATE TABLE `sys_sn_system_info`
(
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`serialno` VARCHAR(64) NOT NULL COMMENT '设备序列号(关联 sys_sn.serialno)',
-- ===================== 基本信息面板 =====================
`device_name` VARCHAR(128) DEFAULT NULL COMMENT '设备名称',
`device_brand` VARCHAR(64) DEFAULT NULL COMMENT '设备品牌',
`device_model` VARCHAR(64) DEFAULT NULL COMMENT '设备型号',
`device_board` VARCHAR(64) DEFAULT NULL COMMENT '主板名称',
`device_manufacturer` VARCHAR(64) DEFAULT NULL COMMENT '制造商',
`hardware` VARCHAR(64) DEFAULT NULL COMMENT '硬件信息',
`host` VARCHAR(64) DEFAULT NULL COMMENT '主机名',
`android_version` VARCHAR(32) DEFAULT NULL COMMENT 'Android 版本',
`android_api` INT DEFAULT NULL COMMENT 'Android API 级别',
`android_id` VARCHAR(64) DEFAULT NULL COMMENT 'Android ID',
`build_id` VARCHAR(64) DEFAULT NULL COMMENT 'Build ID',
`build_display_id` VARCHAR(128) DEFAULT NULL COMMENT 'Build Display ID',
`build_fingerprint` VARCHAR(255) DEFAULT NULL COMMENT 'Build 指纹',
`build_type` VARCHAR(32) DEFAULT NULL COMMENT 'Build 类型(user/userdebug/eng)',
`build_user` VARCHAR(64) DEFAULT NULL COMMENT 'Build 用户',
`build_host` VARCHAR(64) DEFAULT NULL COMMENT 'Build 主机',
`build_tags` VARCHAR(64) DEFAULT NULL COMMENT 'Build 标签',
`build_time` DATETIME DEFAULT NULL COMMENT 'Build 时间',
`language` VARCHAR(32) DEFAULT NULL COMMENT '系统语言',
`timezone` VARCHAR(64) DEFAULT NULL COMMENT '时区',
`boot_time` DATETIME DEFAULT NULL COMMENT '开机时间',
`screen_resolution` VARCHAR(32) DEFAULT NULL COMMENT '屏幕分辨率',
`screen_density` INT DEFAULT NULL COMMENT '屏幕密度',
`kernel_version` VARCHAR(128) DEFAULT NULL COMMENT '内核版本',
`rom_version` VARCHAR(128) DEFAULT NULL COMMENT 'ROM 版本',
-- ===================== 补充基本信息字段 =====================
`product_name` VARCHAR(128) DEFAULT NULL COMMENT '产品名称',
`product_model` VARCHAR(64) DEFAULT NULL COMMENT '产品型号',
`product_device` VARCHAR(64) DEFAULT NULL COMMENT '产品设备名',
`board_platform` VARCHAR(64) DEFAULT NULL COMMENT '主板平台',
`device_type` VARCHAR(32) DEFAULT NULL COMMENT '设备类型(phone/tablet/tv等)',
`is_tablet` TINYINT DEFAULT 0 COMMENT '是否平板(0否 1是)',
`release_version` VARCHAR(32) DEFAULT NULL COMMENT 'Android 发布版本号',
`display_version` VARCHAR(256) DEFAULT NULL COMMENT '显示版本号',
`bootloader` VARCHAR(64) DEFAULT NULL COMMENT 'Bootloader 版本',
`baseband_version` VARCHAR(64) DEFAULT NULL COMMENT '基带版本',
`radio_version` VARCHAR(64) DEFAULT NULL COMMENT 'Radio 版本',
`screen_size` VARCHAR(16) DEFAULT NULL COMMENT '屏幕尺寸(英寸,文本)',
`screen_inch` DECIMAL(4,2) DEFAULT NULL COMMENT '屏幕尺寸(数值,英寸)',
`refresh_rate` INT DEFAULT NULL COMMENT '屏幕刷新率(Hz)',
`os_type` VARCHAR(32) DEFAULT NULL COMMENT '操作系统类型',
`os_version` VARCHAR(32) DEFAULT NULL COMMENT '操作系统版本',
`firmware_version` VARCHAR(64) DEFAULT NULL COMMENT '固件版本',
-- ===================== 通用字段 =====================
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除(0未删 1已删)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_serialno` (`serialno`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '设备基本信息表';
@@ -0,0 +1,9 @@
-- 修复 sys_sn_location.map_error 列类型
-- 问题:代码中 map_error 为 String(存 '-' 表示成功,或真实错误信息),
-- 但数据库列当前为 INT,导致写入 '-' 时报错:
-- "Incorrect integer value: '-' for column 'map_error'"
-- 解决:将 map_error 改为 VARCHAR,使其可同时保存成功标记与失败原因。
ALTER TABLE sys_sn_location
MODIFY COLUMN map_error VARCHAR(255) NULL DEFAULT NULL
COMMENT '定位失败原因,成功时为 -';