Просмотр исходного кода

feat: 文章答题记录表迁移与实体字段调整

Sisyphus 16 часов назад
Родитель
Сommit
60a3bf57b1

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

@@ -11104,6 +11104,32 @@ log.info("迁移298: 已为无 openid 的 child 账号补齐 family_members 记
         ensureColumn("shop_categories", "min_visible_level",
                 "VARCHAR(50) DEFAULT NULL COMMENT '最低可见会员级别编码(FREE/FAMILY/PROVIDER/PREMIUM/LIFETIME, NULL=全部可见)'");
         log.info("迁移321: 已完成商品/分类按会员级别可见性改造");
+
+        // 迁移299: 创建 article_quiz_records 表(文章阅读答题记录)
+        try {
+            jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS article_quiz_records (" +
+                    "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+                    "article_id BIGINT DEFAULT NULL, " +
+                    "user_id BIGINT DEFAULT NULL, " +
+                    "member_id BIGINT DEFAULT NULL, " +
+                    "questions TEXT, " +
+                    "answers TEXT, " +
+                    "score INT DEFAULT 0, " +
+                    "total_questions INT DEFAULT 0, " +
+                    "cf_earned INT DEFAULT 0, " +
+                    "energy_earned INT DEFAULT 0, " +
+                    "created_at DATETIME, " +
+                    "updated_at DATETIME, " +
+                    "INDEX idx_member (member_id), " +
+                    "INDEX idx_article (article_id)" +
+                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章答题记录表'");
+            log.info("已创建article_quiz_records表");
+        } catch (Exception e) {
+            log.warn("创建article_quiz_records表可能已存在: {}", e.getMessage());
+        }
+
+        // 迁移300: profile_snapshot 增加 quiz_summary 列(答题认知雷达汇总)
+        ensureColumn("profile_snapshot", "quiz_summary", "JSON DEFAULT NULL COMMENT '答题认知雷达汇总'");
     }
 
     /**

+ 12 - 7
cfc-backend/src/main/java/com/etotem/cfc/entity/ArticleQuizRecord.java

@@ -11,31 +11,36 @@ public class ArticleQuizRecord {
     private Long id;
     private Long articleId;
     private Long userId;
-    private Long childId;
+    private Long memberId;
     private String questions;
     private String answers;
     private Integer score;
-    private Integer pointsEarned;
+    private Integer totalQuestions;
+    private Integer cfEarned;
+    private Integer energyEarned;
     private Date createdAt;
     private Date updatedAt;
 
-    // getters and setters for ALL fields
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public Long getArticleId() { return articleId; }
     public void setArticleId(Long articleId) { this.articleId = articleId; }
     public Long getUserId() { return userId; }
     public void setUserId(Long userId) { this.userId = userId; }
-    public Long getChildId() { return childId; }
-    public void setChildId(Long childId) { this.childId = childId; }
+    public Long getMemberId() { return memberId; }
+    public void setMemberId(Long memberId) { this.memberId = memberId; }
     public String getQuestions() { return questions; }
     public void setQuestions(String questions) { this.questions = questions; }
     public String getAnswers() { return answers; }
     public void setAnswers(String answers) { this.answers = answers; }
     public Integer getScore() { return score; }
     public void setScore(Integer score) { this.score = score; }
-    public Integer getPointsEarned() { return pointsEarned; }
-    public void setPointsEarned(Integer pointsEarned) { this.pointsEarned = pointsEarned; }
+    public Integer getTotalQuestions() { return totalQuestions; }
+    public void setTotalQuestions(Integer totalQuestions) { this.totalQuestions = totalQuestions; }
+    public Integer getCfEarned() { return cfEarned; }
+    public void setCfEarned(Integer cfEarned) { this.cfEarned = cfEarned; }
+    public Integer getEnergyEarned() { return energyEarned; }
+    public void setEnergyEarned(Integer energyEarned) { this.energyEarned = energyEarned; }
     public Date getCreatedAt() { return createdAt; }
     public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; }
     public Date getUpdatedAt() { return updatedAt; }

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/ProfileSnapshot.java

@@ -21,6 +21,7 @@ public class ProfileSnapshot implements Serializable {
     private String actionMetrics;
     private String wealthMetrics;
     private String problemDomains;
+    private String quizSummary;
     private Date computedAt;
     private Date updatedAt;
 }

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/ArticleService.java

@@ -794,11 +794,11 @@ public class ArticleService {
         ArticleQuizRecord record = new ArticleQuizRecord();
         record.setArticleId(articleId);
         record.setUserId(userId);
-        record.setChildId(memberId);
+        record.setMemberId(memberId);
         record.setQuestions(questionsJson);
         record.setAnswers(null);
         record.setScore(0);
-        record.setPointsEarned(0);
+        record.setCfEarned(0);
         record.setCreatedAt(new Date());
         record.setUpdatedAt(new Date());
         articleQuizRecordMapper.insert(record);
@@ -865,7 +865,7 @@ public class ArticleService {
         // 4. 更新记录
         record.setAnswers(answersJson);
         record.setScore(score);
-        record.setPointsEarned(pointsEarned);
+        record.setCfEarned(pointsEarned);
         record.setUpdatedAt(new Date());
         articleQuizRecordMapper.updateById(record);
 

+ 19 - 0
cfc-backend/src/main/resources/schema.sql

@@ -4110,6 +4110,24 @@ CREATE TABLE IF NOT EXISTS article_reading_records (
   INDEX idx_article_child_date (article_id, child_id, read_at)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章阅读记录表';
 
+-- 文章答题记录表
+CREATE TABLE IF NOT EXISTS article_quiz_records (
+  id BIGINT AUTO_INCREMENT PRIMARY KEY,
+  article_id BIGINT DEFAULT NULL COMMENT '文章ID',
+  user_id BIGINT DEFAULT NULL COMMENT '用户ID',
+  member_id BIGINT DEFAULT NULL COMMENT '家庭成员ID(作答人)',
+  questions TEXT COMMENT '题目快照JSON(含正确答案与维度)',
+  answers TEXT COMMENT '用户作答JSON(含每题所选选项),作答前为NULL',
+  score INT DEFAULT 0 COMMENT '答对题数',
+  total_questions INT DEFAULT 0 COMMENT '题目总数',
+  cf_earned INT DEFAULT 0 COMMENT '发放的CF值',
+  energy_earned INT DEFAULT 0 COMMENT '发放的能量值',
+  created_at DATETIME,
+  updated_at DATETIME,
+  INDEX idx_member (member_id),
+  INDEX idx_article (article_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章答题记录表';
+
 -- ============================================================
 -- 统一报告汇总表(report_summary)
 -- ============================================================
@@ -5437,6 +5455,7 @@ CREATE TABLE IF NOT EXISTS profile_snapshot (
     action_metrics JSON DEFAULT NULL COMMENT '近7天行为指标',
     wealth_metrics JSON DEFAULT NULL COMMENT '近30天财商指标',
     problem_domains VARCHAR(500) DEFAULT NULL COMMENT '关注的问题域标签',
+    quiz_summary JSON DEFAULT NULL COMMENT '答题认知雷达汇总',
     computed_at DATETIME DEFAULT NULL COMMENT '最后一次计算时间',
     updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     INDEX idx_member_id (member_id)