|
|
@@ -12,7 +12,9 @@ import org.springframework.util.StreamUtils;
|
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
import java.util.regex.Matcher;
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
@@ -8861,54 +8863,6 @@ private void runMigration100() {
|
|
|
log.warn("插入GROWTH_COACH权益种子数据失败: {}", ex.getMessage());
|
|
|
}
|
|
|
|
|
|
- // 迁移230: 创建 admin_menu 表(后台菜单管理)
|
|
|
- try {
|
|
|
- jdbcTemplate.execute(
|
|
|
- "CREATE TABLE IF NOT EXISTS admin_menu (" +
|
|
|
- "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
- "parent_id BIGINT DEFAULT 0 COMMENT '父菜单ID,0=顶级', " +
|
|
|
- "name VARCHAR(50) NOT NULL COMMENT '菜单名称', " +
|
|
|
- "path VARCHAR(200) DEFAULT NULL COMMENT '路由路径', " +
|
|
|
- "icon VARCHAR(50) DEFAULT NULL COMMENT '图标类名', " +
|
|
|
- "sort_order INT DEFAULT 0 COMMENT '排序号', " +
|
|
|
- "perm VARCHAR(100) DEFAULT NULL COMMENT '权限标识', " +
|
|
|
- "component VARCHAR(200) DEFAULT NULL COMMENT '前端组件路径', " +
|
|
|
- "visible TINYINT DEFAULT 1 COMMENT '是否显示:0隐藏1显示', " +
|
|
|
- "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
- "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
- "INDEX idx_parent (parent_id)" +
|
|
|
- ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='后台管理菜单'"
|
|
|
- );
|
|
|
- log.info("已创建admin_menu表");
|
|
|
- } catch (Exception ex) {
|
|
|
- log.warn("创建admin_menu表失败: {}", ex.getMessage());
|
|
|
- }
|
|
|
- try {
|
|
|
- jdbcTemplate.execute("INSERT IGNORE INTO admin_menu (parent_id, name, path, icon, sort_order, perm, component, visible) VALUES " +
|
|
|
- "(0, '首页', '/dashboard', 'el-icon-house', 0, 'dashboard', 'admin/Dashboard', 1), " +
|
|
|
- "(0, '家庭管理', NULL, 'el-icon-user', 10, 'family:list', NULL, 1), " +
|
|
|
- "(1, '家庭列表', '/families', 'el-icon-office-building', 1, 'family:list', 'Families', 1), " +
|
|
|
- "(1, '孩子管理', '/children', 'el-icon-child', 2, 'family:children', 'Children', 1), " +
|
|
|
- "(0, '积分管理', NULL, 'el-icon-ticket', 20, 'family:points', NULL, 1), " +
|
|
|
- "(3, '积分记录', '/points-log', 'el-icon-document', 1, 'family:points', 'admin/PointsLog', 1), " +
|
|
|
- "(0, '会员管理', NULL, 'el-icon-v-ip', 30, 'system:config', NULL, 1), " +
|
|
|
- "(4, '会员中心', '/membership-center', 'el-icon-setting', 1, 'system:config', 'admin/MembershipCenter', 1), " +
|
|
|
- "(0, '订单管理', NULL, 'el-icon-shopping-cart-2', 40, 'product:list', NULL, 1), " +
|
|
|
- "(6, '商品订单', '/product-orders', 'el-icon-s-order', 1, 'product:list', 'admin/ProductManage', 1), " +
|
|
|
- "(0, '内容管理', NULL, 'el-icon-document-checked', 50, 'article:list', NULL, 1), " +
|
|
|
- "(8, '文章管理', '/article-manage', 'el-icon-edit', 1, 'article:list', 'admin/ArticleManage', 1), " +
|
|
|
- "(8, '分类管理', '/article-category', 'el-icon-folder', 2, 'article:list', 'admin/ArticleCategory', 1), " +
|
|
|
- "(0, '测评管理', NULL, 'el-icon-reading', 60, 'assessment:list', NULL, 1), " +
|
|
|
- "(10, '测评订单', '/assessment-orders', 'el-icon-tickets', 1, 'assessment:list', 'admin/AssessmentOrders', 1), " +
|
|
|
- "(10, '测评产品', '/assessment-products', 'el-icon-price-tag', 2, 'assessment:product', 'admin/AssessmentProducts', 1), " +
|
|
|
- "(0, '系统配置', NULL, 'el-icon-setting', 90, 'system:config', NULL, 1), " +
|
|
|
- "(14, '菜单管理', '/menu-manage', 'el-icon-menu', 1, 'system:menu', 'admin/MenuManage', 1), " +
|
|
|
- "(14, '系统配置', '/sys-config', 'el-icon-setting', 2, 'system:config', 'admin/SysConfig', 1)");
|
|
|
- log.info("已插入admin_menu种子数据");
|
|
|
- } catch (Exception ex) {
|
|
|
- log.warn("插入admin_menu种子数据失败: {}", ex.getMessage());
|
|
|
- }
|
|
|
-
|
|
|
// 迁移231: 画像驱动推荐 - member_profile_dimension 表
|
|
|
try {
|
|
|
jdbcTemplate.execute(
|
|
|
@@ -9043,12 +8997,340 @@ private void runMigration100() {
|
|
|
log.warn("创建user_notifications表失败: " + e.getMessage());
|
|
|
}
|
|
|
|
|
|
- // 迁移237: task 表添加 member_only 字段(1=会员任务,仅方案/套餐生成)
|
|
|
- ensureColumn("task", "member_only", "TINYINT DEFAULT 0 COMMENT '1=会员任务(方案/套餐生成),执行需会员; 0=普通任务可免费执行'");
|
|
|
+ // 迁移237: tasks 表添加 member_only 字段(1=会员任务,仅方案/套餐生成)
|
|
|
+ ensureColumn("tasks", "member_only", "TINYINT DEFAULT 0 COMMENT '1=会员任务(方案/套餐生成),执行需会员; 0=普通任务可免费执行'");
|
|
|
|
|
|
// 迁移238: package_orders 表添加物流状态字段(试剂盒寄送/样本寄回)
|
|
|
ensureColumn("package_orders", "logistics_status", "VARCHAR(20) DEFAULT 'none' COMMENT 'none/kit_shipped/kit_received/sample_shipped/sample_received'");
|
|
|
ensureColumn("package_orders", "tracking_no", "VARCHAR(100) DEFAULT '' COMMENT '快递单号'");
|
|
|
log.info("已添加package_orders物流字段");
|
|
|
+
|
|
|
+ // 迁移239: 创建 health_status 表(当前状态调研-健康现状档案,SS-2026-08-13)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute(
|
|
|
+ "CREATE TABLE IF NOT EXISTS health_status (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "user_id BIGINT NOT NULL COMMENT '所属账号(一个账号一份)', " +
|
|
|
+ "height_cm DECIMAL(5,1) DEFAULT NULL COMMENT '身高(cm)', " +
|
|
|
+ "weight_kg DECIMAL(5,1) DEFAULT NULL COMMENT '体重(kg)', " +
|
|
|
+ "blood_pressure VARCHAR(20) DEFAULT NULL COMMENT '血压,如 120/80', " +
|
|
|
+ "blood_glucose DECIMAL(4,1) DEFAULT NULL COMMENT '空腹血糖(mmol/L)', " +
|
|
|
+ "blood_lipids JSON DEFAULT NULL COMMENT '血脂 [{name,value,unit,note}]', " +
|
|
|
+ "disease_history JSON DEFAULT NULL COMMENT '疾病史 [{name,note}]', " +
|
|
|
+ "medications JSON DEFAULT NULL COMMENT '在服药物/治疗 [{name,note}]', " +
|
|
|
+ "notes VARCHAR(500) DEFAULT NULL COMMENT '其他补充说明', " +
|
|
|
+ "filled_at DATETIME DEFAULT NULL COMMENT '首次填写时间', " +
|
|
|
+ "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', " +
|
|
|
+ "UNIQUE KEY uk_user (user_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='当前状态调研-健康现状档案'"
|
|
|
+ );
|
|
|
+ log.info("已创建health_status表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建health_status表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移240: 创建 system_prompts 表(系统提示词统一管理,cfc-web后台可维护)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute(
|
|
|
+ "CREATE TABLE IF NOT EXISTS system_prompts (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "prompt_key VARCHAR(64) NOT NULL COMMENT '提示词键(如 health_coach/analysis/chat)', " +
|
|
|
+ "title VARCHAR(100) NOT NULL COMMENT '提示词标题', " +
|
|
|
+ "content TEXT NOT NULL COMMENT '提示词内容', " +
|
|
|
+ "default_content TEXT COMMENT '出厂默认内容(重置时恢复)', " +
|
|
|
+ "version INT NOT NULL DEFAULT 1 COMMENT '版本号', " +
|
|
|
+ "status TINYINT NOT NULL DEFAULT 1 COMMENT '1=启用 0=禁用', " +
|
|
|
+ "remark VARCHAR(255) COMMENT '备注', " +
|
|
|
+ "updated_by VARCHAR(64) COMMENT '更新人', " +
|
|
|
+ "created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
+ "UNIQUE KEY uk_prompt_key (prompt_key)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统提示词管理'"
|
|
|
+ );
|
|
|
+ log.info("已创建system_prompts表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建system_prompts表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移240b: 插入默认系统提示词(仅当表为空时)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute(
|
|
|
+ "INSERT IGNORE INTO system_prompts (prompt_key, title, content, default_content, version, remark) VALUES " +
|
|
|
+ "('health_butler', '家庭健康管家', " +
|
|
|
+ "'你是一个家庭AI健康管家, 为用户提供专业、温暖的个性化健康建议。\\n你的能力:\\n1. 基于健康知识库(菌属功能、指标解读、营养素、食物)提供科学建议\\n2. 解读健康报告数据, 结合知识库给出改善方案\\n3. 根据菌群检测结果推荐精准营养方案\\n4. 提供可执行的健康微行动\\n回答原则:\\n1. 用中文, 像家庭医生一样亲切但专业\\n2. 引用知识库中的菌属/指标/食物信息作为证据\\n3. 优先使用知识库数据, 其次使用通用健康知识\\n4. 需要产品推荐时使用搜索工具\\n5. 生成 [TASK: {\"title\": \"任务名\", \"dimension\": \"身\", \"points\": 10, \"frequency\": \"每天\"}] 标记创建健康行动任务\\n6. 超出知识库范围的慢性病/急症问题, 建议咨询专业医生\\n7. 不要编造医学建议, 不夸大效果', " +
|
|
|
+ "'你是一个家庭AI健康管家, 为用户提供专业、温暖的个性化健康建议。\\n你的能力:\\n1. 基于健康知识库(菌属功能、指标解读、营养素、食物)提供科学建议\\n2. 解读健康报告数据, 结合知识库给出改善方案\\n3. 根据菌群检测结果推荐精准营养方案\\n4. 提供可执行的健康微行动\\n回答原则:\\n1. 用中文, 像家庭医生一样亲切但专业\\n2. 引用知识库中的菌属/指标/食物信息作为证据\\n3. 优先使用知识库数据, 其次使用通用健康知识\\n4. 需要产品推荐时使用搜索工具\\n5. 生成 [TASK: {\"title\": \"任务名\", \"dimension\": \"身\", \"points\": 10, \"frequency\": \"每天\"}] 标记创建健康行动任务\\n6. 超出知识库范围的慢性病/急症问题, 建议咨询专业医生\\n7. 不要编造医学建议, 不夸大效果', " +
|
|
|
+ "1, 'AI健康管家对话', " +
|
|
|
+ "'init'), " +
|
|
|
+ "('health_coach', '儿童健康教练', " +
|
|
|
+ "'你是一个儿童健康教练,喜欢用提问的方式引导家长发现问题和解决方案。\\n核心原则:\\n1. 先问后答:不要直接给答案,用问题引导家长思考\\n2. 用开放式问题了解情况,再给针对性建议\\n3. 语气温暖,像一个耐心的教练在陪伴家长成长\\n你的职责:\\n1. 儿童体质调理(如挑食、瘦弱、易疲劳、反复生病)—— 用提问了解情况\\n2. 科学喂养和营养建议 —— 先问饮食现状再给建议\\n3. 日常保健(睡眠、运动、季节防护)—— 引导家长发现生活中的问题\\n4. 体质辨识基础咨询 —— 通过提问帮助家长理解孩子体质特点\\n5. 健康问题判断 —— 先收集症状信息再建议是否就医\\n回答结构: 提问-分析-建议-跟进', " +
|
|
|
+ "'你是一个儿童健康教练,喜欢用提问的方式引导家长发现问题和解决方案。\\n核心原则:\\n1. 先问后答:不要直接给答案,用问题引导家长思考\\n2. 用开放式问题了解情况,再给针对性建议\\n3. 语气温暖,像一个耐心的教练在陪伴家长成长\\n你的职责:\\n1. 儿童体质调理(如挑食、瘦弱、易疲劳、反复生病)—— 用提问了解情况\\n2. 科学喂养和营养建议 —— 先问饮食现状再给建议\\n3. 日常保健(睡眠、运动、季节防护)—— 引导家长发现生活中的问题\\n4. 体质辨识基础咨询 —— 通过提问帮助家长理解孩子体质特点\\n5. 健康问题判断 —— 先收集症状信息再建议是否就医\\n回答结构: 提问-分析-建议-跟进', " +
|
|
|
+ "1, '儿童健康咨询对话', " +
|
|
|
+ "'init'), " +
|
|
|
+ "('chat_assistant', '儿童成长助手', " +
|
|
|
+ "'你是一个儿童成长家庭助手, 回答关于孩子成长、健康、教育的各种问题。', " +
|
|
|
+ "'你是一个儿童成长家庭助手, 回答关于孩子成长、健康、教育的各种问题。', " +
|
|
|
+ "1, '通用对话助手', " +
|
|
|
+ "'init')"
|
|
|
+ );
|
|
|
+ log.info("已插入默认系统提示词");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("插入默认系统提示词失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ // 迁移242: 创建 sys_menu 表(管理后台侧边栏菜单,数据库驱动 + 角色授权)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute(
|
|
|
+ "CREATE TABLE IF NOT EXISTS sys_menu (" +
|
|
|
+ " id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ " parent_id BIGINT NOT NULL DEFAULT 0 COMMENT '父菜单ID,0=顶级', " +
|
|
|
+ " title VARCHAR(50) COMMENT '目录标题(有子菜单时用,对应 el-submenu)', " +
|
|
|
+ " label VARCHAR(50) COMMENT '叶子菜单显示名(对应 el-menu-item)', " +
|
|
|
+ " path VARCHAR(200) COMMENT '路由路径(叶子菜单必填,如 /families)', " +
|
|
|
+ " icon VARCHAR(100) COMMENT 'Element UI 图标类名,如 el-icon-s-custom', " +
|
|
|
+ " perm VARCHAR(100) COMMENT '权限标识,如 family:list / task:* / system:config', " +
|
|
|
+ " sort INT DEFAULT 0 COMMENT '排序号,小的在前', " +
|
|
|
+ " visible TINYINT DEFAULT 1 COMMENT '是否显示 1=显示 0=隐藏', " +
|
|
|
+ " created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ " updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
+ " INDEX idx_parent (parent_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='后台侧边栏菜单表'"
|
|
|
+ );
|
|
|
+ log.info("已创建sys_menu表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建sys_menu表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移243: 创建 sys_role_menu 表(角色-菜单授权)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute(
|
|
|
+ "CREATE TABLE IF NOT EXISTS sys_role_menu (" +
|
|
|
+ " id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ " role VARCHAR(50) NOT NULL COMMENT '角色标识: admin/teacher/nutritionist/article_manager/activity_manager/supplier_admin', " +
|
|
|
+ " menu_id BIGINT NOT NULL COMMENT 'sys_menu.id', " +
|
|
|
+ " created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ " UNIQUE KEY uk_role_menu (role, menu_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色-菜单授权表'"
|
|
|
+ );
|
|
|
+ log.info("已创建sys_role_menu表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建sys_role_menu表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移244: sys_menu 菜单种子数据(对应 Layout.vue 硬编码 menuItems,表为空才插入,幂等)
|
|
|
+ try {
|
|
|
+ Integer menuCount = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM sys_menu", Integer.class);
|
|
|
+ if (menuCount == null || menuCount == 0) {
|
|
|
+ seedSysMenus();
|
|
|
+ log.info("sys_menu 种子数据已插入");
|
|
|
+ } else {
|
|
|
+ log.info("sys_menu 已有 {} 条数据,跳过种子插入", menuCount);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("初始化sys_menu种子数据失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+// 迁移245: 创建 notification_templates 表(通知模板管理 W3)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS notification_templates (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "type VARCHAR(30) NOT NULL COMMENT '通知类型: report_ready/reward_granted/system', " +
|
|
|
+ "title VARCHAR(200) NOT NULL COMMENT '默认标题(支持占位符)', " +
|
|
|
+ "content VARCHAR(1000) NOT NULL COMMENT '默认内容模板(支持占位符)', " +
|
|
|
+ "channels VARCHAR(100) DEFAULT 'in_app' COMMENT '推送通道: in_app,sms,wechat,phone 逗号分隔', " +
|
|
|
+ "status TINYINT DEFAULT 1 COMMENT '1启用 0停用', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
+ "UNIQUE KEY uk_type (type)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='通知模板(改版v1 W3)'");
|
|
|
+ log.info("已创建notification_templates表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建notification_templates表可能已存在: {}", e.getMessage());
|
|
|
+ }
|
|
|
+ // 迁移245b: notification_templates 种子数据(表为空才插入,幂等)
|
|
|
+ try {
|
|
|
+ Integer tplCount = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM notification_templates", Integer.class);
|
|
|
+ if (tplCount == null || tplCount == 0) {
|
|
|
+ jdbcTemplate.execute("INSERT INTO notification_templates (type, title, content, channels) VALUES " +
|
|
|
+ "('report_ready', '健康报告已完成分析', '您的健康报告已完成解析,可前往查看结果与成长方案。', 'in_app,sms'), " +
|
|
|
+ "('reward_granted', '问题域完成奖励已到账', '恭喜完成「{domainName}」全部任务,奖励 {reward} CF 已发放至家庭账户。', 'in_app,sms,wechat'), " +
|
|
|
+ "('system', '系统通知', '您有一条新的系统通知,请前往查看。', 'in_app')");
|
|
|
+ log.info("notification_templates 种子数据已插入");
|
|
|
+ } else {
|
|
|
+ log.info("notification_templates 已有 {} 条数据,跳过种子插入", tplCount);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("初始化notification_templates种子数据失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移246: product_skus 存量价格 ×100(元→分),sys_config 幂等标记
|
|
|
+ try {
|
|
|
+ Integer migrated = jdbcTemplate.queryForObject(
|
|
|
+ "SELECT COUNT(*) FROM sys_config WHERE config_key = 'sku_price_to_cents_done'",
|
|
|
+ Integer.class);
|
|
|
+ if (migrated == null || migrated == 0) {
|
|
|
+ jdbcTemplate.update("UPDATE product_skus SET price = IFNULL(price, 0) * 100, original_price = IFNULL(original_price, 0) * 100");
|
|
|
+ jdbcTemplate.update("INSERT INTO sys_config (config_key, config_value, description) VALUES ('sku_price_to_cents_done', '1', 'SKU价格已迁移为分单位')");
|
|
|
+ log.info("迁移246: product_skus 价格已×100(元→分)");
|
|
|
+ } else {
|
|
|
+ log.info("迁移246: product_skus 价格已迁移过,跳过");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("迁移246失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移247: product_skus 添加 linked_product_id 和 label 列(SKU关联商品选择器)
|
|
|
+ ensureColumn("product_skus", "linked_product_id", "BIGINT COMMENT '关联商品ID,null=Legacy SKU'");
|
|
|
+ ensureColumn("product_skus", "label", "VARCHAR(100) COMMENT '自定义显示标签,null=使用linked_product.name'");
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 迁移244辅助方法: 插入 sys_menu 种子数据
|
|
|
+ * 结构与 cfc-web/src/views/Layout.vue 的 menuItems 硬编码一致
|
|
|
+ * 数组格式: {parentKey(空=顶级), key, title(目录), label(叶子), path, icon, perm, sort}
|
|
|
+ */
|
|
|
+ private void seedSysMenus() {
|
|
|
+ Map<String, Long> keyToId = new HashMap<>();
|
|
|
+ String[][] menus = {
|
|
|
+ // 顶级叶子
|
|
|
+ {"", "home", "", "首页", "/dashboard", "el-icon-s-home", "dashboard", "0"},
|
|
|
+ // 家庭运营
|
|
|
+ {"", "operation", "家庭运营", "", "", "el-icon-s-custom", "operation", "1"},
|
|
|
+ {"operation", "families", "", "家庭列表", "/families", "el-icon-s-custom", "family:list", "0"},
|
|
|
+ {"operation", "children", "", "孩子管理", "/children", "el-icon-user-solid", "family:children", "1"},
|
|
|
+ {"operation", "points", "", "积分管理", "/points", "el-icon-s-finance", "family:points", "2"},
|
|
|
+ {"operation", "pointsLog", "", "积分记录", "/points-log", "el-icon-document", "family:points", "3"},
|
|
|
+ {"operation", "wishes", "", "心愿管理", "/wishes", "el-icon-star-off", "family:wishes", "4"},
|
|
|
+ {"operation", "rewards", "", "奖励管理", "/rewards", "el-icon-s-goods", "reward:list", "5"},
|
|
|
+ // 任务中心
|
|
|
+ {"", "taskCenter", "任务中心", "", "", "el-icon-s-order", "task:*", "2"},
|
|
|
+ {"taskCenter", "tasks", "", "任务列表", "/tasks", "el-icon-s-order", "task:list", "0"},
|
|
|
+ {"taskCenter", "taskTemplates", "", "任务模板", "/task-templates", "el-icon-document", "task:templates", "1"},
|
|
|
+ {"taskCenter", "growthTask", "", "成长任务管理", "/growth-task", "el-icon-s-management", "task:list", "2"},
|
|
|
+ // 审核中心
|
|
|
+ {"", "reviewCenter", "", "审核中心", "/review-center", "el-icon-s-check", "audit", "3"},
|
|
|
+ {"", "serviceRoleApp", "", "服务角色申请审核", "/service-role-applications", "el-icon-s-check", "audit", "4"},
|
|
|
+ // 商城营销
|
|
|
+ {"", "commerce", "商城营销", "", "", "el-icon-s-goods", "commerce", "5"},
|
|
|
+ {"commerce", "productManage", "", "商品管理", "/product-manage", "el-icon-s-goods", "commerce:products", "0"},
|
|
|
+ {"commerce", "inventory", "", "库存管理", "/inventory", "el-icon-document", "commerce:products", "1"},
|
|
|
+ {"commerce", "ecomSupplier", "", "供应商管理", "/ecom-supplier", "el-icon-s-shop", "commerce:products", "2"},
|
|
|
+ {"commerce", "orderManage", "", "订单管理", "/order-manage", "el-icon-s-order", "commerce:orders", "3"},
|
|
|
+ {"commerce", "pendingRefund", "", "待退款管理", "/pending-refund", "el-icon-warning", "commerce:orders", "4"},
|
|
|
+ {"commerce", "productProfitRate", "", "产品利润率", "/product-profit-rate", "el-icon-data-line", "commerce:profit", "5"},
|
|
|
+ {"commerce", "coupon", "", "优惠券管理", "/coupon", "el-icon-ticket", "marketing:coupon", "6"},
|
|
|
+ {"commerce", "couponGrantLog", "", "发券记录", "/coupon-grant-log", "el-icon-document", "marketing:coupon", "7"},
|
|
|
+ {"commerce", "promotion", "", "推广管理", "/promotion", "el-icon-s-marketing", "marketing:promotion", "8"},
|
|
|
+ {"commerce", "familyEarnings", "", "家庭收益", "/family-earnings", "el-icon-s-money", "marketing:promotion", "9"},
|
|
|
+ {"commerce", "earningWithdraw", "", "收益提现审核", "/family-earnings-withdraw", "el-icon-document-checked", "audit:withdraw", "10"},
|
|
|
+ // 知识中心
|
|
|
+ {"", "knowledge", "知识中心", "", "", "el-icon-document", "content", "6"},
|
|
|
+ {"knowledge", "articleCategories", "", "知识分类", "/article-categories", "el-icon-folder", "articles:categories", "0"},
|
|
|
+ {"knowledge", "articleManage", "", "知识管理", "/article-manage", "el-icon-document", "articles:manage", "1"},
|
|
|
+ {"knowledge", "commentReview", "", "评论审核", "/comment-review", "el-icon-chat-dot-round", "articles:manage", "2"},
|
|
|
+ {"knowledge", "knowledgeTags", "", "知识标签", "/knowledge-tags", "el-icon-price-tag", "articles:categories", "3"},
|
|
|
+ {"knowledge", "knowledgeBase", "", "知识库", "/knowledge-base", "el-icon-reading", "system:config", "4"},
|
|
|
+ {"knowledge", "healthKnowledge", "", "健康知识库", "/health-knowledge", "el-icon-first-aid-kit", "system:config", "5"},
|
|
|
+ // 活动管理
|
|
|
+ {"", "activity", "活动管理", "", "", "el-icon-date", "activity:*", "7"},
|
|
|
+ {"activity", "activities", "", "活动列表", "/activities", "el-icon-date", "activity:list", "0"},
|
|
|
+ {"activity", "activityReview", "", "活动审核", "/activity-review", "el-icon-document-checked", "activity:review", "1"},
|
|
|
+ {"activity", "activityRegReview", "", "活动报名审核", "/activity-registration-review", "el-icon-document-checked", "activity:review", "2"},
|
|
|
+ // 健康饮食
|
|
|
+ {"", "health", "健康饮食", "", "", "el-icon-first-aid-kit", "health", "8"},
|
|
|
+ {"health", "healthReports", "", "健康报告", "/health-reports", "el-icon-document", "health:reports", "0"},
|
|
|
+ {"health", "healthIndicators", "", "健康指标", "/health-indicators", "el-icon-data-line", "health:indicators", "1"},
|
|
|
+ {"health", "healthCheckins", "", "健康打卡", "/health-checkins", "el-icon-s-order", "health:checkins", "2"},
|
|
|
+ {"health", "emotionAlert", "", "情绪告警", "/emotion-alert", "el-icon-warning", "health:checkins", "3"},
|
|
|
+ {"health", "nutritionMappings", "", "营养素映射", "/nutrition-mappings", "el-icon-connection", "health:mappings", "4"},
|
|
|
+ {"health", "energySandbox", "", "五维能量", "/energy-sandbox", "el-icon-data-line", "energy", "5"},
|
|
|
+ {"health", "energyRule", "", "能量规则管理", "/energy-rule", "el-icon-setting", "energy", "6"},
|
|
|
+ {"health", "energyBehaviorConfig", "", "能量行为配置", "/energy-behavior-config", "el-icon-edit-outline", "energy", "7"},
|
|
|
+ {"health", "periodicServiceConfig", "", "周期性服务配置", "/periodic-service-config", "el-icon-refresh", "energy", "8"},
|
|
|
+ {"health", "foods", "", "食材管理", "/foods", "el-icon-apple", "diet:foods", "9"},
|
|
|
+ {"health", "recipes", "", "食谱管理", "/recipes", "el-icon-dish", "diet:recipes", "10"},
|
|
|
+ {"health", "langgraphAdmin", "", "LangGraph 管理", "/langgraph-admin", "el-icon-cpu", "system:config", "11"},
|
|
|
+ {"health", "nutritionProducts", "", "营养产品", "/nutrition-products", "el-icon-first-aid-kit", "health:*", "12"},
|
|
|
+ // 报告解析系统
|
|
|
+ {"", "reportParser", "报告解析系统", "", "", "el-icon-cpu", "system:config", "9"},
|
|
|
+ {"reportParser", "reportTypes", "", "报告类型管理", "/report-types", "el-icon-collection", "system:config", "0"},
|
|
|
+ {"reportParser", "reportParserImport", "", "解析器导入", "/report-parser-import", "el-icon-upload2", "system:config", "1"},
|
|
|
+ {"reportParser", "reportUnknownClusters", "", "未知报告审核", "/report-unknown-clusters", "el-icon-question", "system:config", "2"},
|
|
|
+ {"reportParser", "reportAutoLearn", "", "报告自学习", "/report-auto-learn", "el-icon-magic-stick", "system:config", "3"},
|
|
|
+ // 家庭服务(规划师)
|
|
|
+ {"", "familyService", "家庭服务", "", "", "el-icon-s-custom", "service:*", "10"},
|
|
|
+ {"familyService", "myFamilies", "", "我的家庭", "/my-families", "el-icon-s-custom", "service:family", "0"},
|
|
|
+ {"familyService", "teacherTeam", "", "我的团队", "/teacher-team", "el-icon-s-custom", "service:team", "1"},
|
|
|
+ // 业务管理(规划师)
|
|
|
+ {"", "biz", "业务管理", "", "", "el-icon-s-marketing", "biz:*", "11"},
|
|
|
+ {"biz", "teacherPackages", "", "任务模板管理", "/teacher-packages", "el-icon-s-goods", "biz:packages", "0"},
|
|
|
+ {"biz", "teacherOrders", "", "订单佣金", "/teacher-orders", "el-icon-s-order", "biz:orders", "1"},
|
|
|
+ // 测评咨询(规划师)
|
|
|
+ {"", "assessment", "测评咨询", "", "", "el-icon-edit", "assessment:*", "12"},
|
|
|
+ {"assessment", "teacherAssessment", "", "DAN测评", "/teacher-assessment", "el-icon-edit", "assessment:dan", "0"},
|
|
|
+ {"assessment", "teacherConsult", "", "家长咨询", "/teacher-consult", "el-icon-chat-dot-round", "assessment:consult", "1"},
|
|
|
+ {"assessment", "growthRecords", "", "成长记录", "/growth-records", "el-icon-document", "growth:records", "2"},
|
|
|
+ {"assessment", "growthPlans", "", "成长计划", "/growth-plans", "el-icon-document", "growth:plans", "3"},
|
|
|
+ // 系统配置(三级)
|
|
|
+ {"", "system", "系统配置", "", "", "el-icon-s-tools", "system:*", "13"},
|
|
|
+ {"system", "baseManage", "基础管理", "", "", "el-icon-s-tools", "system:config", "0"},
|
|
|
+ {"baseManage", "sysConfig", "", "系统配置", "/sys-config", "el-icon-s-tools", "system:config", "0"},
|
|
|
+ {"baseManage", "users", "", "用户管理", "/users", "el-icon-user", "system:users", "1"},
|
|
|
+ {"baseManage", "operationLogs", "", "操作日志", "/operation-logs", "el-icon-s-order", "system:logs", "2"},
|
|
|
+ {"baseManage", "membershipCenter", "", "会员中心", "/membership-center", "el-icon-s-custom", "system:config", "3"},
|
|
|
+ {"baseManage", "badgeManage", "", "勋章管理", "/badge-manage", "el-icon-medal", "system:config", "4"},
|
|
|
+ {"baseManage", "virtualGoodsConfig", "", "虚拟支付道具", "/virtual-goods-config", "el-icon-goods", "system:config", "5"},
|
|
|
+ {"baseManage", "gates", "", "关卡配置", "/gates", "el-icon-key", "system:config", "6"},
|
|
|
+ {"baseManage", "menuManage", "", "菜单管理", "/menu-manage", "el-icon-menu", "system:menu", "7"},
|
|
|
+ {"system", "configCenter", "配置中心", "", "", "el-icon-setting", "system:config", "1"},
|
|
|
+ {"configCenter", "dimensionConfig", "", "维度配置", "/dimension-config", "el-icon-data-line", "system:config", "0"},
|
|
|
+ {"system", "supplyHierarchy", "供应商体系", "", "", "el-icon-s-management", "system:supply", "2"},
|
|
|
+ {"supplyHierarchy", "supplySystem", "", "供应商体系", "/supply-system", "el-icon-s-management", "system:supply", "0"},
|
|
|
+ {"system", "supplierManage", "供应商管理", "", "", "el-icon-s-shop", "supply:manage", "3"},
|
|
|
+ {"supplierManage", "supplyManage", "", "供应商管理", "/supply-manage", "el-icon-s-shop", "supply:manage", "0"},
|
|
|
+ {"supplierManage", "supplierProducts", "", "商品管理", "/supplier-products", "el-icon-s-goods", "commerce:product", "1"},
|
|
|
+ {"system", "healthConfig", "健康配置", "", "", "el-icon-first-aid-kit", "system:config", "4"},
|
|
|
+ {"healthConfig", "healthNormConfig", "", "健康常模", "/health-norm-config", "el-icon-data-line", "system:config", "0"},
|
|
|
+ {"healthConfig", "healthDataSource", "", "健康数据源", "/health-data-source", "el-icon-data-line", "system:config", "1"},
|
|
|
+ {"healthConfig", "healthEnergyConfig", "", "七维能量配置", "/health-energy-config", "el-icon-data-line", "system:config", "2"},
|
|
|
+ {"system", "lifeDimension", "人生维度", "", "", "el-icon-s-custom", "system:config", "5"},
|
|
|
+ {"lifeDimension", "zodiacConfigs", "", "星座配置", "/zodiac-configs", "el-icon-s-management", "system:config", "0"},
|
|
|
+ {"lifeDimension", "baziConfigs", "", "八字配置", "/bazi-configs", "el-icon-s-management", "system:config", "1"},
|
|
|
+ {"lifeDimension", "bloodTypeConfigs", "", "血型配置", "/blood-type-configs", "el-icon-s-management", "system:config", "2"},
|
|
|
+ {"system", "assessmentManage", "测评管理", "", "", "el-icon-edit", "assessment:dan", "6"},
|
|
|
+ {"assessmentManage", "assessmentAdmin", "", "测评管理", "/assessment-admin", "el-icon-edit", "assessment:dan", "0"},
|
|
|
+ {"assessmentManage", "assessmentOrders", "", "测评订单", "/assessment-orders", "el-icon-s-order", "assessment:dan", "1"},
|
|
|
+ {"assessmentManage", "assessmentAssign", "", "待分配规划师", "/assessment-assign", "el-icon-user", "assessment:dan", "2"},
|
|
|
+ {"system", "virtualTeam", "虚拟团队", "", "", "el-icon-s-custom", "system:config", "7"},
|
|
|
+ {"virtualTeam", "virtualTeams", "", "虚拟团队", "/virtual-teams", "el-icon-s-custom", "system:config", "0"},
|
|
|
+ };
|
|
|
+
|
|
|
+ for (String[] m : menus) {
|
|
|
+ Long parentId = 0L;
|
|
|
+ if (m[0] != null && !m[0].isEmpty()) {
|
|
|
+ parentId = keyToId.get(m[0]);
|
|
|
+ if (parentId == null) {
|
|
|
+ parentId = 0L;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String title = m[2] != null && !m[2].isEmpty() ? m[2] : null;
|
|
|
+ String label = m[3] != null && !m[3].isEmpty() ? m[3] : null;
|
|
|
+ String path = m[4] != null && !m[4].isEmpty() ? m[4] : null;
|
|
|
+ String icon = m[5] != null && !m[5].isEmpty() ? m[5] : null;
|
|
|
+ String perm = m[6] != null && !m[6].isEmpty() ? m[6] : null;
|
|
|
+ int sort = Integer.parseInt(m[7]);
|
|
|
+ jdbcTemplate.update(
|
|
|
+ "INSERT INTO sys_menu (parent_id, title, label, path, icon, perm, sort, visible) VALUES (?, ?, ?, ?, ?, ?, ?, 1)",
|
|
|
+ parentId, title, label, path, icon, perm, sort
|
|
|
+ );
|
|
|
+ Long id = jdbcTemplate.queryForObject("SELECT LAST_INSERT_ID()", Long.class);
|
|
|
+ keyToId.put(m[1], id);
|
|
|
+ }
|
|
|
+ // 迁移242: health_reports 表添加 payload_json 字段(报告完整载荷快照)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("ALTER TABLE health_reports ADD COLUMN payload_json LONGTEXT DEFAULT NULL COMMENT '报告完整载荷快照'");
|
|
|
+ log.info("已添加payload_json列到health_reports表");
|
|
|
+ } catch (Exception ex) {
|
|
|
+ log.warn("添加payload_json列失败: {}", ex.getMessage());
|
|
|
+ }
|
|
|
}
|
|
|
}
|