瀏覽代碼

fix(db): 迁移375 修复 article_quiz_records 缺列导致答题入库报错

旧表(迁移299 IF NOT EXISTS 跳过)缺 member_id/total_questions/cf_earned/energy_earned,
questions/answers 为 VARCHAR(255) 与实体 TEXT 不符。补齐4列并扩为 TEXT,与 schema.sql 对齐。
Xiaogang Liao 1 周之前
父節點
當前提交
e5355fed39
共有 1 個文件被更改,包括 53 次插入 和 0 次删除
  1. 53 0
      cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

+ 53 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -3060,6 +3060,9 @@ insertSysConfigSeed("gift_membership_pay_price", "198000", "送会员商品达
         // 迁移374: 创建 user_content_weights 表(用户内容偏好权重表)
         addUserContentWeightsTable();
 
+        // 迁移375: 修复 article_quiz_records 表结构(旧表缺 member_id/total_questions/cf_earned/energy_earned,questions/answers 需为 TEXT)
+        fixArticleQuizRecordsTable();
+
         // 迁移376: health_status 添加 lifestyle JSON 列(心情/睡眠/排便/抗生素/过敏表现)
         ensureColumn("health_status", "lifestyle", "JSON DEFAULT NULL COMMENT '生活方式与肠道健康 {mood,sleepDuration,bedtime,bowelFrequency,bowelForm,antibioticHistory,allergySymptoms}'");
 
@@ -12637,6 +12640,56 @@ log.info("迁移298: 已为无 openid 的 child 账号补齐 family_members 记
         }
     }
 
+    // 迁移375: 修复 article_quiz_records 表结构(旧表由迁移299创建时已存在导致缺列)
+    private void fixArticleQuizRecordsTable() {
+        try {
+            if (!columnExists("article_quiz_records", "member_id")) {
+                jdbcTemplate.execute("ALTER TABLE article_quiz_records ADD COLUMN member_id BIGINT DEFAULT NULL COMMENT '家庭成员ID(作答人)'");
+                log.info("迁移375: 已添加 member_id 列到 article_quiz_records");
+            }
+            if (!columnExists("article_quiz_records", "total_questions")) {
+                jdbcTemplate.execute("ALTER TABLE article_quiz_records ADD COLUMN total_questions INT DEFAULT 0 COMMENT '题目总数'");
+                log.info("迁移375: 已添加 total_questions 列到 article_quiz_records");
+            }
+            if (!columnExists("article_quiz_records", "cf_earned")) {
+                jdbcTemplate.execute("ALTER TABLE article_quiz_records ADD COLUMN cf_earned INT DEFAULT 0 COMMENT '发放的CF值'");
+                log.info("迁移375: 已添加 cf_earned 列到 article_quiz_records");
+            }
+            if (!columnExists("article_quiz_records", "energy_earned")) {
+                jdbcTemplate.execute("ALTER TABLE article_quiz_records ADD COLUMN energy_earned INT DEFAULT 0 COMMENT '发放的能量值'");
+                log.info("迁移375: 已添加 energy_earned 列到 article_quiz_records");
+            }
+            // questions/answers 旧表为 VARCHAR(255),实体存 JSON 快照会超长,与 schema.sql 对齐为 TEXT
+            if (!columnTypeStartsWith("article_quiz_records", "questions", "text")) {
+                jdbcTemplate.execute("ALTER TABLE article_quiz_records MODIFY COLUMN questions TEXT COMMENT '题目快照JSON(含正确答案与维度)'");
+                log.info("迁移375: questions 列已改为 TEXT");
+            }
+            if (!columnTypeStartsWith("article_quiz_records", "answers", "text")) {
+                jdbcTemplate.execute("ALTER TABLE article_quiz_records MODIFY COLUMN answers TEXT COMMENT '用户作答JSON(含每题所选选项),作答前为NULL'");
+                log.info("迁移375: answers 列已改为 TEXT");
+            }
+            // 补充索引(幂等;重复创建会报 Duplicate key name,捕获忽略)
+            try {
+                jdbcTemplate.execute("ALTER TABLE article_quiz_records ADD INDEX idx_member (member_id)");
+            } catch (Exception ignored) {
+            }
+            log.info("迁移375: article_quiz_records 表结构修复完成");
+        } catch (Exception e) {
+            log.warn("迁移375: 修复 article_quiz_records 表结构失败: {}", e.getMessage());
+        }
+    }
+
+    private boolean columnTypeStartsWith(String table, String column, String typePrefix) {
+        try {
+            String t = jdbcTemplate.queryForObject(
+                    "SELECT DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?",
+                    String.class, table, column);
+            return t != null && t.toLowerCase().startsWith(typePrefix);
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
     // 迁移372: nutrition_product 添加 efficacy_tags 列(成分功效标签)
     private void addNutritionProductEfficacyTags() {
         if (!columnExists("nutrition_product", "efficacy_tags")) {