diff --git a/pom.xml b/pom.xml
index bf8dc982..064270e0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -127,11 +127,6 @@
spring-boot-starter-websocket
-
- org.springframework.boot
- spring-boot-starter-websocket
-
-
org.springframework.boot
spring-boot-starter-test
diff --git a/sql/menu_app_icon.sql b/sql/menu_app_icon.sql
index ed99c873..d9f95031 100644
--- a/sql/menu_app_icon.sql
+++ b/sql/menu_app_icon.sql
@@ -2,7 +2,7 @@
-- 应用图标管理 菜单 & 按钮权限初始化脚本(可重复执行 / 幂等)
--
-- 依赖
--- 1. 前端页面 vue3-element-admin-ttstd/src/views/devices/app-icon/index.vue
+-- 1. 前端页面 vue3-element-admin-ttstd/src/views/app-manager/app-icon/index.vue
-- 2. 后端接口 com.youlai.boot.device.controller.AppIconController (/api/v1/app-icons)
--
-- 说明
@@ -12,22 +12,28 @@
-- - 权限每次请求实时查库,执行后刷新页面即可,无需重启
-- ----------------------------------------------------------------------------
--- 0. 定位「应用图标管理」菜单(按前端组件路径唯一标识)
-SET @menu_id = (SELECT `id` FROM `sys_menu` WHERE `component` = 'devices/app-icon/index' LIMIT 1);
+-- 0. 页面已从 devices/app-icon 迁到 app-manager/app-icon,先迁移存量菜单
+UPDATE `sys_menu`
+SET `component` = 'app-manager/app-icon/index'
+WHERE `component` = 'devices/app-icon/index';
--- 若菜单不存在则创建(挂到「设备调试」目录下;如目录 id 不同请自行调整 parent_id)
-SET @parent_id = (SELECT `id` FROM `sys_menu` WHERE `name` = '设备调试' AND `parent_id` = 0 LIMIT 1);
+-- 定位「应用图标管理」菜单(按前端组件路径唯一标识)
+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',
- 'devices/app-icon/index', NULL, NULL, 1, 1, 6, 'picture', NULL, now(), now(), NULL
+ '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` = 'devices/app-icon/index');
+ 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` = 'devices/app-icon/index' LIMIT 1);
+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);
diff --git a/sql/menu_update_manager.sql b/sql/menu_update_manager.sql
new file mode 100644
index 00000000..0ffe5bc8
--- /dev/null
+++ b/sql/menu_update_manager.sql
@@ -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;