|
@@ -2934,24 +2934,6 @@ log.info("已添加template_id列到tasks表");
|
|
|
ensureColumn("family_challenge", "target_mode", "VARCHAR(20) DEFAULT 'aggregate' COMMENT '目标模式: aggregate=集体总合/all_members=全员个人目标'");
|
|
ensureColumn("family_challenge", "target_mode", "VARCHAR(20) DEFAULT 'aggregate' COMMENT '目标模式: aggregate=集体总合/all_members=全员个人目标'");
|
|
|
ensureColumn("family_challenge", "target_value", "INT DEFAULT 0 COMMENT '目标值(aggregate=家庭合计值, all_members=每人目标值)'");
|
|
ensureColumn("family_challenge", "target_value", "INT DEFAULT 0 COMMENT '目标值(aggregate=家庭合计值, all_members=每人目标值)'");
|
|
|
|
|
|
|
|
- // 迁移248: 创建 health_report_edit_logs 表(健康报告修改留痕,原迁移222误置于initializeDefaultData中仅测试环境执行)
|
|
|
|
|
- try {
|
|
|
|
|
- jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_report_edit_logs (" +
|
|
|
|
|
- "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
- "report_id BIGINT NOT NULL, " +
|
|
|
|
|
- "user_id BIGINT, " +
|
|
|
|
|
- "report_type VARCHAR(32), " +
|
|
|
|
|
- "action VARCHAR(20) COMMENT 'create/edit', " +
|
|
|
|
|
- "before_payload LONGTEXT, " +
|
|
|
|
|
- "after_payload LONGTEXT, " +
|
|
|
|
|
- "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
|
|
- "INDEX idx_report_id (report_id)" +
|
|
|
|
|
- ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康报告修改留痕'");
|
|
|
|
|
- log.info("已创建health_report_edit_logs表");
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- // 表已存在,忽略错误
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
log.info("数据库迁移完成");
|
|
log.info("数据库迁移完成");
|
|
|
|
|
|
|
|
// ==================== 健康维度 Phase 1: health_dimension_score / health_data_source_record / health_norm_reference ====================
|
|
// ==================== 健康维度 Phase 1: health_dimension_score / health_data_source_record / health_norm_reference ====================
|
|
@@ -4166,6 +4148,21 @@ try {
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
// 列已存在,忽略错误
|
|
// 列已存在,忽略错误
|
|
|
}
|
|
}
|
|
|
|
|
+ try {
|
|
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_report_edit_logs (" +
|
|
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
+ "report_id BIGINT NOT NULL, " +
|
|
|
|
|
+ "user_id BIGINT, " +
|
|
|
|
|
+ "report_type VARCHAR(32), " +
|
|
|
|
|
+ "action VARCHAR(20) COMMENT 'create/edit', " +
|
|
|
|
|
+ "before_payload LONGTEXT, " +
|
|
|
|
|
+ "after_payload LONGTEXT, " +
|
|
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP" +
|
|
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康报告修改留痕'");
|
|
|
|
|
+ log.info("已创建health_report_edit_logs表");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ // 表已存在,忽略错误
|
|
|
|
|
+ }
|
|
|
ensureColumn("product_orders", "supply_system_id", "BIGINT COMMENT '所属供应商体系ID'");
|
|
ensureColumn("product_orders", "supply_system_id", "BIGINT COMMENT '所属供应商体系ID'");
|
|
|
ensureColumn("product_orders", "supplier_id", "BIGINT COMMENT '收款供应商用户ID'");
|
|
ensureColumn("product_orders", "supplier_id", "BIGINT COMMENT '收款供应商用户ID'");
|
|
|
ensureColumn("product_orders", "supply_commission", "INT COMMENT '销售佣金(分)'");
|
|
ensureColumn("product_orders", "supply_commission", "INT COMMENT '销售佣金(分)'");
|
|
@@ -6339,10 +6336,6 @@ try {
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.warn("创建activity_materials表失败: {}", e.getMessage());
|
|
log.warn("创建activity_materials表失败: {}", e.getMessage());
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // 迁移247: user_intents 表添加跳过次数和最近跳过时间(原迁移243误置于seedSysMenus中,菜单非空时永不执行)
|
|
|
|
|
- ensureColumn("user_intents", "skip_count", "INT DEFAULT 0 COMMENT '跳过意图问卷次数'");
|
|
|
|
|
- ensureColumn("user_intents", "last_skip_at", "DATETIME DEFAULT NULL COMMENT '最近一次跳过意图问卷时间'");
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void runMigration82() {
|
|
private void runMigration82() {
|
|
@@ -8968,8 +8961,6 @@ private void runMigration100() {
|
|
|
"survey_template_id BIGINT DEFAULT NULL COMMENT '最近作答问卷模板ID', " +
|
|
"survey_template_id BIGINT DEFAULT NULL COMMENT '最近作答问卷模板ID', " +
|
|
|
"survey_submitted_at DATETIME DEFAULT NULL COMMENT '最近问卷提交时间', " +
|
|
"survey_submitted_at DATETIME DEFAULT NULL COMMENT '最近问卷提交时间', " +
|
|
|
"survey_result_json TEXT COMMENT '问卷答案→推荐结果快照', " +
|
|
"survey_result_json TEXT COMMENT '问卷答案→推荐结果快照', " +
|
|
|
- "skip_count INT DEFAULT 0 COMMENT '跳过意图问卷次数', " +
|
|
|
|
|
- "last_skip_at DATETIME DEFAULT NULL COMMENT '最近一次跳过意图问卷时间', " +
|
|
|
|
|
"created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
"created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
"updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
"updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
|
|
"UNIQUE KEY uk_user (user_id)" +
|
|
"UNIQUE KEY uk_user (user_id)" +
|
|
@@ -9155,7 +9146,7 @@ private void runMigration100() {
|
|
|
if (tplCount == null || tplCount == 0) {
|
|
if (tplCount == null || tplCount == 0) {
|
|
|
jdbcTemplate.execute("INSERT INTO notification_templates (type, title, content, channels) VALUES " +
|
|
jdbcTemplate.execute("INSERT INTO notification_templates (type, title, content, channels) VALUES " +
|
|
|
"('report_ready', '健康报告已完成分析', '您的健康报告已完成解析,可前往查看结果与成长方案。', 'in_app,sms'), " +
|
|
"('report_ready', '健康报告已完成分析', '您的健康报告已完成解析,可前往查看结果与成长方案。', 'in_app,sms'), " +
|
|
|
- "('reward_granted', '问题域完成奖励已到账', '恭喜完成「{domainName}」全部任务,奖励 {reward} CF 已发放至家庭账户。', 'in_app,sms,wechat,gzh'), " +
|
|
|
|
|
|
|
+ "('reward_granted', '问题域完成奖励已到账', '恭喜完成「{domainName}」全部任务,奖励 {reward} CF 已发放至家庭账户。', 'in_app,sms,wechat'), " +
|
|
|
"('system', '系统通知', '您有一条新的系统通知,请前往查看。', 'in_app')");
|
|
"('system', '系统通知', '您有一条新的系统通知,请前往查看。', 'in_app')");
|
|
|
log.info("notification_templates 种子数据已插入");
|
|
log.info("notification_templates 种子数据已插入");
|
|
|
} else {
|
|
} else {
|
|
@@ -9181,65 +9172,9 @@ private void runMigration100() {
|
|
|
log.warn("迁移246失败: {}", e.getMessage());
|
|
log.warn("迁移246失败: {}", e.getMessage());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 迁移246b: 创建 product_bundle_items 表(套餐商品组成明细 BUNDLE-001)
|
|
|
|
|
- try {
|
|
|
|
|
- jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS product_bundle_items (" +
|
|
|
|
|
- "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
|
|
- "bundle_product_id BIGINT NOT NULL COMMENT '套餐商品ID', " +
|
|
|
|
|
- "child_product_id BIGINT NOT NULL COMMENT '子商品ID', " +
|
|
|
|
|
- "child_sku_id BIGINT DEFAULT NULL COMMENT '子SKU ID(为空时直接扣 product.stock)', " +
|
|
|
|
|
- "quantity INT NOT NULL DEFAULT 1 COMMENT '子商品数量', " +
|
|
|
|
|
- "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
|
|
- "INDEX idx_bundle (bundle_product_id), " +
|
|
|
|
|
- "INDEX idx_child (child_product_id)" +
|
|
|
|
|
- ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='套餐商品组成明细'");
|
|
|
|
|
- log.info("已创建product_bundle_items表");
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- // 表已存在,忽略错误
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 迁移247: 已有模板 channels 补充公众号通道(gzh)(五通道:in_app/sms/wechat/gzh/phone,幂等)
|
|
|
|
|
- try {
|
|
|
|
|
- int updated = jdbcTemplate.update("UPDATE notification_templates " +
|
|
|
|
|
- "SET channels = CONCAT(channels, ',gzh') " +
|
|
|
|
|
- "WHERE type IN ('report_ready', 'reward_granted') " +
|
|
|
|
|
- "AND channels IS NOT NULL AND channels NOT LIKE '%gzh%'");
|
|
|
|
|
- if (updated > 0) {
|
|
|
|
|
- log.info("notification_templates 已为 {} 条模板补充公众号通道(gzh)", updated);
|
|
|
|
|
- }
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.warn("补充notification_templates公众号通道失败: " + e.getMessage());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 迁移248: 专项调研内置问卷种子(survey_templates 表为空才插入;problem_domains 未绑定模板才绑定,幂等)
|
|
|
|
|
- // 与 ProblemSurveyController.DEFAULT_QUESTIONS 结构一致(选项带 id/tag 用于 resultTags 聚合)
|
|
|
|
|
- try {
|
|
|
|
|
- Integer tplCount = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM survey_templates", Integer.class);
|
|
|
|
|
- if (tplCount == null || tplCount == 0) {
|
|
|
|
|
- String weightLossQ = "[{\"id\":\"q1\",\"text\":\"目前孩子的体重情况如何?\",\"multi\":false,\"options\":[{\"id\":\"o1\",\"text\":\"偏瘦\",\"tag\":\"体重偏瘦\"},{\"id\":\"o2\",\"text\":\"正常\",\"tag\":\"\"},{\"id\":\"o3\",\"text\":\"偏胖\",\"tag\":\"体重偏胖\"}]},{\"id\":\"q2\",\"text\":\"孩子的饮食结构如何?(可多选)\",\"multi\":true,\"options\":[{\"id\":\"o1\",\"text\":\"零食饮料多\",\"tag\":\"零食饮料\"},{\"id\":\"o2\",\"text\":\"主食过量\",\"tag\":\"主食过量\"},{\"id\":\"o3\",\"text\":\"蔬菜水果少\",\"tag\":\"蔬果不足\"},{\"id\":\"o4\",\"text\":\"三餐规律\",\"tag\":\"\"}]},{\"id\":\"q3\",\"text\":\"孩子每天运动情况如何?\",\"multi\":false,\"options\":[{\"id\":\"o1\",\"text\":\"很少运动\",\"tag\":\"运动不足\"},{\"id\":\"o2\",\"text\":\"每周1-2次\",\"tag\":\"运动不足\"},{\"id\":\"o3\",\"text\":\"每周3次以上\",\"tag\":\"运动良好\"}]},{\"id\":\"q4\",\"text\":\"你最想改善的方面是什么?(可多选)\",\"multi\":true,\"options\":[{\"id\":\"o1\",\"text\":\"控制体重\",\"tag\":\"减重\"},{\"id\":\"o2\",\"text\":\"培养饮食习惯\",\"tag\":\"饮食管理\"},{\"id\":\"o3\",\"text\":\"增加运动\",\"tag\":\"运动习惯\"}]}]";
|
|
|
|
|
- String sleepQ = "[{\"id\":\"q1\",\"text\":\"孩子每晚睡眠时长大约多少?\",\"multi\":false,\"options\":[{\"id\":\"o1\",\"text\":\"不足8小时\",\"tag\":\"睡眠不足\"},{\"id\":\"o2\",\"text\":\"8-10小时\",\"tag\":\"睡眠正常\"},{\"id\":\"o3\",\"text\":\"超过10小时\",\"tag\":\"睡眠过多\"}]},{\"id\":\"q2\",\"text\":\"入睡情况如何?\",\"multi\":false,\"options\":[{\"id\":\"o1\",\"text\":\"入睡困难\",\"tag\":\"入睡困难\"},{\"id\":\"o2\",\"text\":\"容易惊醒\",\"tag\":\"睡眠浅\"},{\"id\":\"o3\",\"text\":\"睡得很沉\",\"tag\":\"\"}]},{\"id\":\"q3\",\"text\":\"睡前习惯有哪些?(可多选)\",\"multi\":true,\"options\":[{\"id\":\"o1\",\"text\":\"看电子产品\",\"tag\":\"屏幕暴露\"},{\"id\":\"o2\",\"text\":\"喝含糖饮料\",\"tag\":\"饮食影响睡眠\"},{\"id\":\"o3\",\"text\":\"睡前剧烈运动\",\"tag\":\"睡前兴奋\"},{\"id\":\"o4\",\"text\":\"规律作息\",\"tag\":\"\"}]},{\"id\":\"q4\",\"text\":\"白天精神状态如何?(可多选)\",\"multi\":true,\"options\":[{\"id\":\"o1\",\"text\":\"白天犯困\",\"tag\":\"白天嗜睡\"},{\"id\":\"o2\",\"text\":\"注意力不集中\",\"tag\":\"注意力不足\"},{\"id\":\"o3\",\"text\":\"情绪烦躁\",\"tag\":\"情绪波动\"},{\"id\":\"o4\",\"text\":\"精力充沛\",\"tag\":\"\"}]}]";
|
|
|
|
|
- String constipationQ = "[{\"id\":\"q1\",\"text\":\"孩子排便频率如何?\",\"multi\":false,\"options\":[{\"id\":\"o1\",\"text\":\"每天1次以上\",\"tag\":\"\"},{\"id\":\"o2\",\"text\":\"2-3天1次\",\"tag\":\"排便频率低\"},{\"id\":\"o3\",\"text\":\"3天以上1次\",\"tag\":\"便秘\"}]},{\"id\":\"q2\",\"text\":\"大便性状如何?\",\"multi\":false,\"options\":[{\"id\":\"o1\",\"text\":\"干硬颗粒状\",\"tag\":\"大便干结\"},{\"id\":\"o2\",\"text\":\"成形但偏干\",\"tag\":\"大便干结\"},{\"id\":\"o3\",\"text\":\"正常软便\",\"tag\":\"\"}]},{\"id\":\"q3\",\"text\":\"饮食习惯如何?(可多选)\",\"multi\":true,\"options\":[{\"id\":\"o1\",\"text\":\"蔬菜水果少\",\"tag\":\"膳食纤维不足\"},{\"id\":\"o2\",\"text\":\"饮水不足\",\"tag\":\"饮水不足\"},{\"id\":\"o3\",\"text\":\"爱吃油炸烧烤\",\"tag\":\"饮食油腻\"},{\"id\":\"o4\",\"text\":\"规律均衡\",\"tag\":\"\"}]},{\"id\":\"q4\",\"text\":\"是否有以下症状?(可多选)\",\"multi\":true,\"options\":[{\"id\":\"o1\",\"text\":\"腹胀\",\"tag\":\"腹胀\"},{\"id\":\"o2\",\"text\":\"腹痛\",\"tag\":\"腹痛\"},{\"id\":\"o3\",\"text\":\"食欲不振\",\"tag\":\"食欲不振\"},{\"id\":\"o4\",\"text\":\"无\",\"tag\":\"\"}]}]";
|
|
|
|
|
- jdbcTemplate.update("INSERT INTO survey_templates (title, dimension, questions_json, cycle_type, ai_generated, enabled) VALUES "
|
|
|
|
|
- + "('减肥专项调研', 'body', '" + weightLossQ + "', 'weekly', 0, 1), "
|
|
|
|
|
- + "('睡眠专项调研', 'body', '" + sleepQ + "', 'weekly', 0, 1), "
|
|
|
|
|
- + "('便秘专项调研', 'body', '" + constipationQ + "', 'weekly', 0, 1)");
|
|
|
|
|
- log.info("迁移248: survey_templates 内置专项调研问卷种子已插入");
|
|
|
|
|
- } else {
|
|
|
|
|
- log.info("迁移248: survey_templates 已有 {} 条数据,跳过内置问卷种子", tplCount);
|
|
|
|
|
- }
|
|
|
|
|
- // 问题域未绑定模板时,按 code 绑定内置问卷(幂等)
|
|
|
|
|
- jdbcTemplate.update("UPDATE problem_domains d SET d.survey_template_id = "
|
|
|
|
|
- + "(SELECT t.id FROM survey_templates t WHERE t.title = '减肥专项调研' LIMIT 1) "
|
|
|
|
|
- + "WHERE d.code = 'weight_loss' AND (d.survey_template_id IS NULL OR d.survey_template_id = 0)");
|
|
|
|
|
- jdbcTemplate.update("UPDATE problem_domains d SET d.survey_template_id = "
|
|
|
|
|
- + "(SELECT t.id FROM survey_templates t WHERE t.title = '睡眠专项调研' LIMIT 1) "
|
|
|
|
|
- + "WHERE d.code = 'sleep' AND (d.survey_template_id IS NULL OR d.survey_template_id = 0)");
|
|
|
|
|
- jdbcTemplate.update("UPDATE problem_domains d SET d.survey_template_id = "
|
|
|
|
|
- + "(SELECT t.id FROM survey_templates t WHERE t.title = '便秘专项调研' LIMIT 1) "
|
|
|
|
|
- + "WHERE d.code = 'constipation' AND (d.survey_template_id IS NULL OR d.survey_template_id = 0)");
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.warn("迁移248初始化专项调研问卷种子失败: " + 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'");
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -9385,5 +9320,12 @@ private void runMigration100() {
|
|
|
Long id = jdbcTemplate.queryForObject("SELECT LAST_INSERT_ID()", Long.class);
|
|
Long id = jdbcTemplate.queryForObject("SELECT LAST_INSERT_ID()", Long.class);
|
|
|
keyToId.put(m[1], id);
|
|
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());
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|