|
|
@@ -5387,8 +5387,304 @@ try {
|
|
|
} catch (Exception e) {
|
|
|
log.warn("修改users.role失败(可能已修改): " + e.getMessage());
|
|
|
}
|
|
|
+
|
|
|
+ // 迁移100: assessment_appointments表添加assessor_id(测评师角色分离)
|
|
|
+ ensureColumn("assessment_appointments", "assessor_id",
|
|
|
+ "BIGINT COMMENT '测评师ID(供应商体系), 替代guideId语义'");
|
|
|
+ // 迁移100: dan_assessment_executions表添加appointment_id
|
|
|
+ ensureColumn("dan_assessment_executions", "appointment_id",
|
|
|
+ "BIGINT COMMENT '关联assessment_appointments.id'");
|
|
|
+ log.info("迁移100: 已添加assessor_id和appointment_id字段");
|
|
|
+
|
|
|
+ // 迁移101: 创建 micro_actions 表(12个预定义1秒微行动)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS micro_actions (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "code VARCHAR(32) NOT NULL COMMENT '行动编码: DRINK_WATER, DEEP_BREATH, ...', " +
|
|
|
+ "name VARCHAR(50) NOT NULL COMMENT '行动名称', " +
|
|
|
+ "icon VARCHAR(10) COMMENT '图标emoji', " +
|
|
|
+ "description VARCHAR(200) COMMENT '行动描述', " +
|
|
|
+ "sort_order INT DEFAULT 0 COMMENT '排序号', " +
|
|
|
+ "status TINYINT DEFAULT 1 COMMENT '状态: 1启用 0禁用', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "UNIQUE KEY uk_code (code), " +
|
|
|
+ "INDEX idx_status (status)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微行动定义(12个1秒健康行动)'");
|
|
|
+ log.info("已创建micro_actions表");
|
|
|
+
|
|
|
+ // 插入12个预定义微行动
|
|
|
+ jdbcTemplate.execute("INSERT IGNORE INTO micro_actions (code, name, icon, description, sort_order) VALUES " +
|
|
|
+ "('DRINK_WATER', '喝一杯水', '☕️', '喝一杯温开水,补充水分', 1), " +
|
|
|
+ "('DEEP_BREATH', '深呼吸3次', '🫁', '深吸慢呼3次,放松身心', 2), " +
|
|
|
+ "('STRETCH', '站起来伸懒腰', '🧘', '站起来伸个懒腰,活动筋骨', 3), " +
|
|
|
+ "('LOOK_FAR', '看远处10秒', '🌿', '看远处绿色植物10秒,缓解眼疲劳', 4), " +
|
|
|
+ "('SMILE', '微笑一下', '😊', '对自己微笑,心情会变好', 5), " +
|
|
|
+ "('NECK_ROLL', '转转头颈5圈', '🔄', '缓慢转动头颈5圈,放松颈椎', 6), " +
|
|
|
+ "('FIST_RELAX', '握拳放松3次', '✊', '用力握拳3秒后放松,重复3次', 7), " +
|
|
|
+ "('SIP_WATER', '喝口水润喉', '💧', '小口喝水润润喉咙', 8), " +
|
|
|
+ "('BLINK', '眨眨眼5次', '👁️', '快速眨眼5次,湿润眼球', 9), " +
|
|
|
+ "('ACUPRESSURE', '按揉合谷穴3下', '🖐️', '按揉虎口合谷穴3下,提神醒脑', 10), " +
|
|
|
+ "('TIPTOE', '踮脚尖5次', '⬆️', '踮起脚尖再放下,重复5次', 11), " +
|
|
|
+ "('SHRUG', '耸肩放松3次', '↕️', '耸肩至耳朵再放松,重复3次', 12)");
|
|
|
+ log.info("已初始化12个微行动");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建micro_actions表或初始化数据失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移102: 创建 micro_action_records 表(微行动完成记录)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS micro_action_records (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "user_id BIGINT NOT NULL COMMENT '用户ID', " +
|
|
|
+ "child_id BIGINT NOT NULL COMMENT '家庭成员ID', " +
|
|
|
+ "action_id BIGINT NOT NULL COMMENT '行动ID', " +
|
|
|
+ "completed_date DATETIME NOT NULL COMMENT '完成日期', " +
|
|
|
+ "earned_energy INT DEFAULT 1 COMMENT '获得能量值', " +
|
|
|
+ "note VARCHAR(200) COMMENT '备注', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "INDEX idx_child_date (child_id, completed_date), " +
|
|
|
+ "INDEX idx_user_id (user_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微行动完成记录'");
|
|
|
+ log.info("已创建micro_action_records表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建micro_action_records表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移103: 创建 daily_feedback 表(AI/预设每日健康反馈)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS daily_feedback (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "user_id BIGINT NOT NULL COMMENT '用户ID', " +
|
|
|
+ "child_id BIGINT NOT NULL COMMENT '家庭成员ID', " +
|
|
|
+ "feedback_date DATETIME NOT NULL COMMENT '反馈日期', " +
|
|
|
+ "feedback_type VARCHAR(20) DEFAULT 'daily' COMMENT '反馈类型: daily/weekly/milestone', " +
|
|
|
+ "content VARCHAR(500) NOT NULL COMMENT 'AI生成的反馈文本', " +
|
|
|
+ "milestone_event VARCHAR(100) COMMENT '关联的里程碑事件', " +
|
|
|
+ "is_read TINYINT DEFAULT 0 COMMENT '是否已读: 0未读 1已读', " +
|
|
|
+ "source VARCHAR(20) DEFAULT 'preset' COMMENT '来源: ai_generated / preset', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "INDEX idx_child_date (child_id, feedback_date), " +
|
|
|
+ "INDEX idx_feedback_type (feedback_type)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='每日健康反馈'");
|
|
|
+ log.info("已创建daily_feedback表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建daily_feedback表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移104: 创建 health_alerts 表(健康行为智能预警)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_alerts (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "user_id BIGINT COMMENT '用户ID', " +
|
|
|
+ "child_id BIGINT NOT NULL COMMENT '家庭成员ID', " +
|
|
|
+ "rule_code VARCHAR(10) NOT NULL COMMENT '规则编码: R001-R006', " +
|
|
|
+ "alert_text VARCHAR(200) NOT NULL COMMENT '预警文案', " +
|
|
|
+ "action_suggestion VARCHAR(200) COMMENT '行动建议', " +
|
|
|
+ "severity VARCHAR(10) DEFAULT 'medium' COMMENT '严重程度: high/medium/low', " +
|
|
|
+ "dismissed TINYINT DEFAULT 0 COMMENT '是否已关闭: 0未关闭 1已关闭', " +
|
|
|
+ "dismissed_at DATETIME COMMENT '关闭时间', " +
|
|
|
+ "alert_date DATETIME NOT NULL COMMENT '预警日期', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "INDEX idx_child_date (child_id, alert_date), " +
|
|
|
+ "INDEX idx_rule (rule_code)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康预警记录'");
|
|
|
+ log.info("已创建health_alerts表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建health_alerts表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移105: 创建 health_level 表(身份重塑等级定义)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_level (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "level_num INT NOT NULL COMMENT '等级编号 1-5', " +
|
|
|
+ "title VARCHAR(50) NOT NULL COMMENT '称号', " +
|
|
|
+ "badge_icon VARCHAR(20) COMMENT '徽章图标', " +
|
|
|
+ "min_score INT DEFAULT 0 COMMENT '所需最低健康积分', " +
|
|
|
+ "max_score INT DEFAULT 99999 COMMENT '最高积分上限'" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康等级定义'");
|
|
|
+ log.info("已创建health_level表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建health_level表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移106: 创建 health_timeline_event 表(健康故事时间线)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_timeline_event (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "user_id BIGINT COMMENT '用户ID', " +
|
|
|
+ "child_id BIGINT NOT NULL COMMENT '家庭成员ID', " +
|
|
|
+ "event_type VARCHAR(30) NOT NULL COMMENT '事件类型: streak_7/level_2/first_report', " +
|
|
|
+ "event_text VARCHAR(200) NOT NULL COMMENT '事件描述', " +
|
|
|
+ "ref_id VARCHAR(50) COMMENT '关联ID', " +
|
|
|
+ "event_date DATETIME NOT NULL COMMENT '事件日期', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
|
|
|
+ "INDEX idx_child_date (child_id, event_date), " +
|
|
|
+ "INDEX idx_event_type (event_type)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康时间线事件'");
|
|
|
+ log.info("已创建health_timeline_event表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建health_timeline_event表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移107: 创建 family_challenge 表(P2-2家庭挑战)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS family_challenge (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "family_id BIGINT NOT NULL COMMENT '家庭ID', " +
|
|
|
+ "challenge_type VARCHAR(50) NOT NULL COMMENT 'full_checkin/sports/health_week', " +
|
|
|
+ "title VARCHAR(200) NOT NULL COMMENT '挑战标题', " +
|
|
|
+ "description TEXT COMMENT '挑战描述', " +
|
|
|
+ "duration_days INT DEFAULT 7 COMMENT '持续天数', " +
|
|
|
+ "reward_points INT DEFAULT 0 COMMENT '奖励积分', " +
|
|
|
+ "reward_badge VARCHAR(100) COMMENT '奖励徽章', " +
|
|
|
+ "start_date DATE COMMENT '开始日期', " +
|
|
|
+ "end_date DATE COMMENT '结束日期', " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'active' COMMENT 'active/completed/cancelled', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "INDEX idx_family_id (family_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭挑战'");
|
|
|
+ log.info("已创建family_challenge表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建family_challenge表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移108: 创建 family_challenge_progress 表(P2-2挑战进度)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS family_challenge_progress (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "challenge_id BIGINT NOT NULL COMMENT '挑战ID', " +
|
|
|
+ "child_id BIGINT NOT NULL COMMENT '家庭成员ID', " +
|
|
|
+ "progress_value INT DEFAULT 0 COMMENT '进度值', " +
|
|
|
+ "completed TINYINT(1) DEFAULT 0 COMMENT '是否完成', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', " +
|
|
|
+ "INDEX idx_challenge_id (challenge_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭挑战进度'");
|
|
|
+ log.info("已创建family_challenge_progress表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建family_challenge_progress表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移109: 创建 health_interaction 表(P2-2点赞记录)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_interaction (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "family_id BIGINT NOT NULL COMMENT '家庭ID', " +
|
|
|
+ "from_user_id BIGINT NOT NULL COMMENT '点赞用户ID', " +
|
|
|
+ "to_user_id BIGINT NOT NULL COMMENT '被赞用户ID', " +
|
|
|
+ "action_type VARCHAR(50) NOT NULL COMMENT '行为类型', " +
|
|
|
+ "action_id BIGINT COMMENT '关联行为记录ID', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "INDEX idx_family_action (family_id, action_type, action_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康互动记录(点赞)'");
|
|
|
+ log.info("已创建health_interaction表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建health_interaction表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移110: 创建 health_circle 表(P3 健康圈)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_circle (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "name VARCHAR(100) NOT NULL COMMENT '圈名称', " +
|
|
|
+ "description VARCHAR(500) COMMENT '圈描述', " +
|
|
|
+ "creator_family_id BIGINT COMMENT '创建家庭ID', " +
|
|
|
+ "invite_code VARCHAR(32) COMMENT '邀请码', " +
|
|
|
+ "member_limit INT DEFAULT 50 COMMENT '成员上限', " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'active' COMMENT '状态 active/closed', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "INDEX idx_invite_code (invite_code), " +
|
|
|
+ "INDEX idx_creator (creator_family_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康圈'");
|
|
|
+ log.info("已创建health_circle表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建health_circle表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移111: 创建 health_circle_member 表(P3 健康圈成员)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS health_circle_member (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "circle_id BIGINT NOT NULL COMMENT '圈ID', " +
|
|
|
+ "family_id BIGINT NOT NULL COMMENT '家庭ID', " +
|
|
|
+ "role VARCHAR(20) DEFAULT 'member' COMMENT '角色 member/admin', " +
|
|
|
+ "joined_at DATETIME COMMENT '加入时间', " +
|
|
|
+ "left_at DATETIME COMMENT '退出时间', " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'active' COMMENT '状态 active/inactive', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "INDEX idx_circle_id (circle_id), " +
|
|
|
+ "INDEX idx_family_id (family_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康圈成员'");
|
|
|
+ log.info("已创建health_circle_member表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建health_circle_member表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移112: 创建 circle_challenge 表(P3 圈挑战)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS circle_challenge (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "circle_id BIGINT NOT NULL COMMENT '圈ID', " +
|
|
|
+ "challenge_type VARCHAR(50) NOT NULL COMMENT '挑战类型 checkin/step/meditation', " +
|
|
|
+ "title VARCHAR(200) NOT NULL COMMENT '挑战标题', " +
|
|
|
+ "description VARCHAR(500) COMMENT '挑战描述', " +
|
|
|
+ "duration_days INT DEFAULT 7 COMMENT '持续天数', " +
|
|
|
+ "period VARCHAR(20) DEFAULT 'weekly' COMMENT '周期 weekly/monthly', " +
|
|
|
+ "start_date DATETIME COMMENT '开始日期', " +
|
|
|
+ "end_date DATETIME COMMENT '结束日期', " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'active' COMMENT '状态 active/completed/cancelled', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "INDEX idx_circle_id (circle_id), " +
|
|
|
+ "INDEX idx_status (status)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='圈挑战'");
|
|
|
+ log.info("已创建circle_challenge表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建circle_challenge表失败: {}", e.getMessage());
|
|
|
}
|
|
|
|
|
|
+ // 迁移113: 创建 family_commission 表(P2 推广佣金)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS family_commission (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "promoter_family_id BIGINT NOT NULL COMMENT '推广方家庭ID', " +
|
|
|
+ "buyer_family_id BIGINT NOT NULL COMMENT '购买方家庭ID', " +
|
|
|
+ "order_id BIGINT COMMENT '关联订单ID', " +
|
|
|
+ "amount DECIMAL(10,2) DEFAULT 0.00 COMMENT '订单金额', " +
|
|
|
+ "commission_rate DECIMAL(5,2) DEFAULT 10.00 COMMENT '佣金比例%', " +
|
|
|
+ "commission_amount DECIMAL(10,2) DEFAULT 0.00 COMMENT '佣金金额', " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'pending' COMMENT 'pending/paid/cancelled', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "paid_at DATETIME COMMENT '支付时间', " +
|
|
|
+ "INDEX idx_promoter (promoter_family_id), " +
|
|
|
+ "INDEX idx_buyer (buyer_family_id), " +
|
|
|
+ "INDEX idx_order (order_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭推广佣金记录'");
|
|
|
+ log.info("已创建family_commission表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建family_commission表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 迁移114: 创建 promotion_binding 表(P2 推广绑定)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS promotion_binding (" +
|
|
|
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
|
|
|
+ "promoter_family_id BIGINT NOT NULL COMMENT '推广方家庭ID', " +
|
|
|
+ "invitee_family_id BIGINT NOT NULL COMMENT '被邀请方家庭ID', " +
|
|
|
+ "invite_code VARCHAR(32) COMMENT '使用的邀请码', " +
|
|
|
+ "binding_type VARCHAR(20) DEFAULT 'direct' COMMENT 'direct/indirect', " +
|
|
|
+ "status VARCHAR(20) DEFAULT 'active' COMMENT 'active/inactive', " +
|
|
|
+ "created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', " +
|
|
|
+ "UNIQUE KEY uk_promoter_invitee (promoter_family_id, invitee_family_id), " +
|
|
|
+ "INDEX idx_promoter (promoter_family_id), " +
|
|
|
+ "INDEX idx_invitee (invitee_family_id)" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='推广绑定关系'");
|
|
|
+ log.info("已创建promotion_binding表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("创建promotion_binding表失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
private void runMigration82() {
|
|
|
try {
|
|
|
jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS ai_conversation_summary (" +
|
|
|
@@ -6048,4 +6344,71 @@ try {
|
|
|
log.error("迁移95 Step2 失败: " + e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+private void runMigration97() {
|
|
|
+ // 迁移93: users表添加roles字段
|
|
|
+ ensureColumn("users", "roles", "VARCHAR(100) COMMENT '角色列表'");
|
|
|
+}
|
|
|
+
|
|
|
+private void runMigration96() {
|
|
|
+ // 迁移96: 修复assessment_appointments.status列类型为TINYINT(原库可能为VARCHAR/ENUM导致Data truncated)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("ALTER TABLE assessment_appointments MODIFY COLUMN status TINYINT DEFAULT 0 COMMENT '0=待确认,1=已确认,2=已完成,3=已取消,4=未到'");
|
|
|
+ log.info("已修复assessment_appointments.status列类型为TINYINT");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("Migration 96 skipped: {}", e.getMessage());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+private void runMigration98() {
|
|
|
+ // 迁移98: family_members表新增辈分字段(TASK-P0-001 辈分重构)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("ALTER TABLE family_members ADD COLUMN generation INT COMMENT '辈分值(0=家庭创建者,+n=向上,-n=向下)'");
|
|
|
+ log.info("已添加generation列到family_members表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 列已存在,忽略错误
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("ALTER TABLE family_members ADD COLUMN is_spouse TINYINT(1) DEFAULT 0 COMMENT '是否配偶(同辈中)'");
|
|
|
+ log.info("已添加is_spouse列到family_members表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 列已存在,忽略错误
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+private void runMigration99() {
|
|
|
+ // 迁移99: 旧关系类型数据回填到辈分字段(TASK-P0-001 辈分重构)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("UPDATE family_members SET generation = 0, is_spouse = 1 WHERE relationship_type = 'spouse'");
|
|
|
+ jdbcTemplate.execute("UPDATE family_members SET generation = 1 WHERE relationship_type = 'parent'");
|
|
|
+ jdbcTemplate.execute("UPDATE family_members SET generation = -1 WHERE relationship_type = 'child'");
|
|
|
+ jdbcTemplate.execute("UPDATE family_members SET generation = 0 WHERE relationship_type = 'sibling'");
|
|
|
+ jdbcTemplate.execute("UPDATE family_members SET generation = 0 WHERE relationship_type IS NULL");
|
|
|
+ log.info("迁移99: 已回填generation/is_spouse旧数据");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("迁移99 失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+private void runMigration100() {
|
|
|
+ // 迁移100: 删除废弃列和关系类型配置表(TASK-P0-001 辈分重构)
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("ALTER TABLE family_members DROP COLUMN relationship_type");
|
|
|
+ log.info("已删除family_members.relationship_type列");
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 列已不存在,忽略
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("ALTER TABLE family_members DROP COLUMN role_override");
|
|
|
+ log.info("已删除family_members.role_override列");
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 列已不存在,忽略
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ jdbcTemplate.execute("DROP TABLE IF EXISTS relationship_types");
|
|
|
+ log.info("已删除relationship_types表");
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 表已不存在,忽略
|
|
|
+ }
|
|
|
+}
|
|
|
}
|