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

feat(dimension): 统一维度体系增量 - 4根33子维seed(迁移448)+T5历史迁移脚本

- 迁移448: 在主线445-447框架后追加,幂等seed mind10/wisdom7/action5/wealth4 共26子维(权威清单)
- 迁移448: 补5根 wuxing_rule_ref(按 energy_dimension.element 关联木/火/金/水/土)
- DimensionCodeConstants: 新增26子维常量 + 26 legacy_alias 常量,更新数量注释
- 新增 migrate_dimension_unified.sql(T5: 备份+改写7 body+越界扫描,DBA手工)
- 未改动445/446/447,未新建Controller/Service类
Agnes Agent 1 неделя назад
Родитель
Сommit
73751f101d

+ 66 - 0
cfc-backend/src/main/java/com/etotem/cfc/common/constant/DimensionCodeConstants.java

@@ -1,6 +1,7 @@
 package com.etotem.cfc.common.constant;
 
 public class DimensionCodeConstants {
+    // 统一维度体系常量:5 根(body/mind/wisdom/action/wealth)+ 子维构成 body7/wisdom7/mind10/action5/wealth4(共33子维)
     // 5 根维度
     public static final String BODY = "body";
     public static final String MIND = "mind";
@@ -32,4 +33,69 @@ public class DimensionCodeConstants {
     public static final String WUXING_METAL = "金";
     public static final String WUXING_WATER = "水";
     public static final String WUXING_EARTH = "土";
+
+    // ===== 增量子维常量(P0 增量,迁移448 seed;统一 code={root}.{key}) =====
+    // 维度构成:body7 / wisdom7 / mind10 / action5 / wealth4(共 33 子维 + 5 根 = 38 节点)
+
+    // wisdom 智/认知(7,source_system='cognitive')—— DAN 认知报告字段
+    public static final String WISDOM_MEMORY = "wisdom.memory";
+    public static final String WISDOM_ATTENTION = "wisdom.attention";
+    public static final String WISDOM_LOGIC = "wisdom.logic";
+    public static final String WISDOM_SPATIAL = "wisdom.spatial";
+    public static final String WISDOM_PERCEPTION = "wisdom.perception";
+    public static final String WISDOM_FOCUS = "wisdom.focus";
+    public static final String WISDOM_PROCESSING_SPEED = "wisdom.processingSpeed";
+
+    // mind 心/心理(10,source_system='emi')
+    public static final String MIND_OPENNESS = "mind.openness";
+    public static final String MIND_CONSCIENTIOUSNESS = "mind.conscientiousness";
+    public static final String MIND_EXTRAVERSION = "mind.extraversion";
+    public static final String MIND_AGREEABLENESS = "mind.agreeableness";
+    public static final String MIND_NEUROTICISM = "mind.neuroticism";
+    public static final String MIND_DRIVE_AUTONOMY = "mind.driveAutonomy";
+    public static final String MIND_DRIVE_COMPETENCE = "mind.driveCompetence";
+    public static final String MIND_DRIVE_RELATEDNESS = "mind.driveRelatedness";
+    public static final String MIND_EMOTION_STABILITY = "mind.emotionStability";
+    public static final String MIND_SELF_CONCEPT_OVERALL = "mind.selfConceptOverall";
+
+    // action 社会性(5,source_system='relationship')—— RelationshipScoreVO 字段
+    public static final String ACTION_PARENT_TRUST = "action.parentTrust";
+    public static final String ACTION_PARENT_INTIMACY = "action.parentIntimacy";
+    public static final String ACTION_COMMUNICATION = "action.communication";
+    public static final String ACTION_HEALTH_STATUS = "action.healthStatus";
+    public static final String ACTION_LAST_INTERACTION = "action.lastInteraction";
+
+    // wealth 富(4,source_system='energy')—— MemberEnergyDTO 字段
+    public static final String WEALTH_SKILL = "wealth.skill";
+    public static final String WEALTH_ALTRUISM = "wealth.altruism";
+    public static final String WEALTH_INCOME = "wealth.income";
+    public static final String WEALTH_FX = "wealth.fx";
+
+    // 增量 33 子维的 legacy_alias 映射(JSON数组字符串,单元素=后端 API 取数字段名)
+    public static final String LEGACY_MEMORY_SCORE = "memoryScore";
+    public static final String LEGACY_ATTENTION_SCORE = "attentionScore";
+    public static final String LEGACY_LOGIC_SCORE = "logicScore";
+    public static final String LEGACY_SPATIAL_SCORE = "spatialScore";
+    public static final String LEGACY_PERCEPTION_SCORE = "perceptionScore";
+    public static final String LEGACY_FOCUS_SCORE = "focusScore";
+    public static final String LEGACY_PROCESSING_SPEED_SCORE = "processingSpeedScore";
+    public static final String LEGACY_OPENNESS_SCORE = "opennessScore";
+    public static final String LEGACY_CONSCIENTIOUSNESS_SCORE = "conscientiousnessScore";
+    public static final String LEGACY_EXTRAVERSION_SCORE = "extraversionScore";
+    public static final String LEGACY_AGREEABLENESS_SCORE = "agreeablenessScore";
+    public static final String LEGACY_NEUROTICISM_SCORE = "neuroticismScore";
+    public static final String LEGACY_DRIVE_AUTONOMY = "driveAutonomy";
+    public static final String LEGACY_DRIVE_COMPETENCE = "driveCompetence";
+    public static final String LEGACY_DRIVE_RELATEDNESS = "driveRelatedness";
+    public static final String LEGACY_EMOTION_STABILITY = "emotionStability";
+    public static final String LEGACY_SELF_CONCEPT_OVERALL = "selfConceptOverall";
+    public static final String LEGACY_TRUST_SCORE = "trustScore";
+    public static final String LEGACY_INTIMACY_SCORE = "intimacyScore";
+    public static final String LEGACY_COMMUNICATION_SCORE = "communicationScore";
+    public static final String LEGACY_TOTAL_SCORE = "totalScore";
+    public static final String LEGACY_LAST_INTERACTION_AT = "lastInteractionAt";
+    public static final String LEGACY_WEALTH_SKILL = "wealthSkill";
+    public static final String LEGACY_WEALTH_ALTRUISM = "wealthAltruism";
+    public static final String LEGACY_WEALTH_INCOME = "wealthIncome";
+    public static final String LEGACY_WEALTH_FX = "wealthFx";
 }

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

@@ -3443,6 +3443,8 @@ insertSysConfigSeed("gift_membership_pay_price", "198000", "送会员商品达
         migrateUnifiedIndicatorTreeColumns();
         // 迁移447: 统一维度体系(P0-T3)—— 固化 5 根 + 7 body 子维度节点(幂等 seed)
         seedUnifiedDimensionRegistry();
+        // 迁移448: 统一维度体系(增量)—— 另外 4 根 33 子维 + 5 根五行归属(幂等 seed,仅追加,不改动 445-447)
+        seedUnifiedDimensionRegistryExpansion();
     }
 
     /**
@@ -15169,6 +15171,83 @@ log.info("迁移298: 已为无 openid 的 child 账号补齐 family_members 记
         log.info("迁移447: 统一维度注册中心 5 根 + 7 body 子维度 seed 完成");
     }
 
+    /**
+     * 迁移448: 统一维度体系(增量)—— 固化另外 4 根(mind/wisdom/action/wealth)的 33 个子维度节点,
+     * 并补 5 根节点的五行归属(wuxing_rule_ref)。幂等 seed,仅追加,不改动 445-447。
+     * 子维 code = {root}.{key},legacy_alias = 后端 API 取数字段名(供 P1 健康页雷达按配置取数)。
+     */
+    void seedUnifiedDimensionRegistryExpansion() {
+        // 4 根 id(body 的 7 子维已在迁移447 固化;此处覆盖其余 4 根)
+        Long mindId = queryDimensionIdByCode("mind");
+        Long wisdomId = queryDimensionIdByCode("wisdom");
+        Long actionId = queryDimensionIdByCode("action");
+        Long wealthId = queryDimensionIdByCode("wealth");
+
+        // —— mind 心/心理(10,source_system='emi')——
+        if (mindId != null) {
+            upsertDimensionSeed("mind.openness", "开放性", "emi", mindId, 1, "emi", "sub", "[\"opennessScore\"]", null);
+            upsertDimensionSeed("mind.conscientiousness", "尽责性", "emi", mindId, 2, "emi", "sub", "[\"conscientiousnessScore\"]", null);
+            upsertDimensionSeed("mind.extraversion", "外向性", "emi", mindId, 3, "emi", "sub", "[\"extraversionScore\"]", null);
+            upsertDimensionSeed("mind.agreeableness", "宜人性", "emi", mindId, 4, "emi", "sub", "[\"agreeablenessScore\"]", null);
+            upsertDimensionSeed("mind.neuroticism", "神经质", "emi", mindId, 5, "emi", "sub", "[\"neuroticismScore\"]", null);
+            upsertDimensionSeed("mind.driveAutonomy", "自主性", "emi", mindId, 6, "emi", "sub", "[\"driveAutonomy\"]", null);
+            upsertDimensionSeed("mind.driveCompetence", "胜任感", "emi", mindId, 7, "emi", "sub", "[\"driveCompetence\"]", null);
+            upsertDimensionSeed("mind.driveRelatedness", "归属感", "emi", mindId, 8, "emi", "sub", "[\"driveRelatedness\"]", null);
+            upsertDimensionSeed("mind.emotionStability", "情绪稳定性", "emi", mindId, 9, "emi", "sub", "[\"emotionStability\"]", null);
+            upsertDimensionSeed("mind.selfConceptOverall", "自我概念", "emi", mindId, 10, "emi", "sub", "[\"selfConceptOverall\"]", null);
+        } else {
+            log.warn("迁移448: 未找到 mind 根节点 id,跳过 mind 子维度 seed");
+        }
+
+        // —— wisdom 智/认知(7,source_system='cognitive')——
+        if (wisdomId != null) {
+            upsertDimensionSeed("wisdom.memory", "记忆力", "cognitive", wisdomId, 1, "cognitive", "sub", "[\"memoryScore\"]", null);
+            upsertDimensionSeed("wisdom.attention", "注意力", "cognitive", wisdomId, 2, "cognitive", "sub", "[\"attentionScore\"]", null);
+            upsertDimensionSeed("wisdom.logic", "逻辑推理", "cognitive", wisdomId, 3, "cognitive", "sub", "[\"logicScore\"]", null);
+            upsertDimensionSeed("wisdom.spatial", "空间想象", "cognitive", wisdomId, 4, "cognitive", "sub", "[\"spatialScore\"]", null);
+            upsertDimensionSeed("wisdom.perception", "感知能力", "cognitive", wisdomId, 5, "cognitive", "sub", "[\"perceptionScore\"]", null);
+            upsertDimensionSeed("wisdom.focus", "专注力", "cognitive", wisdomId, 6, "cognitive", "sub", "[\"focusScore\"]", null);
+            upsertDimensionSeed("wisdom.processingSpeed", "加工速度", "cognitive", wisdomId, 7, "cognitive", "sub", "[\"processingSpeedScore\"]", null);
+        } else {
+            log.warn("迁移448: 未找到 wisdom 根节点 id,跳过 wisdom 子维度 seed");
+        }
+
+        // —— action 社会性(5,source_system='relationship')——
+        if (actionId != null) {
+            upsertDimensionSeed("action.parentTrust", "亲子信任", "relationship", actionId, 1, "relationship", "sub", "[\"trustScore\"]", null);
+            upsertDimensionSeed("action.parentIntimacy", "亲子亲密度", "relationship", actionId, 2, "relationship", "sub", "[\"intimacyScore\"]", null);
+            upsertDimensionSeed("action.communication", "沟通质量", "relationship", actionId, 3, "relationship", "sub", "[\"communicationScore\"]", null);
+            upsertDimensionSeed("action.healthStatus", "关系健康度", "relationship", actionId, 4, "relationship", "sub", "[\"totalScore\"]", null);
+            upsertDimensionSeed("action.lastInteraction", "最近互动", "relationship", actionId, 5, "relationship", "sub", "[\"lastInteractionAt\"]", null);
+        } else {
+            log.warn("迁移448: 未找到 action 根节点 id,跳过 action 子维度 seed");
+        }
+
+        // —— wealth 富(4,source_system='energy')——
+        if (wealthId != null) {
+            upsertDimensionSeed("wealth.skill", "个人能力", "energy", wealthId, 1, "energy", "sub", "[\"wealthSkill\"]", null);
+            upsertDimensionSeed("wealth.altruism", "利他贡献", "energy", wealthId, 2, "energy", "sub", "[\"wealthAltruism\"]", null);
+            upsertDimensionSeed("wealth.income", "CF值积累", "energy", wealthId, 3, "energy", "sub", "[\"wealthIncome\"]", null);
+            upsertDimensionSeed("wealth.fx", "财务素养", "energy", wealthId, 4, "energy", "sub", "[\"wealthFx\"]", null);
+        } else {
+            log.warn("迁移448: 未找到 wealth 根节点 id,跳过 wealth 子维度 seed");
+        }
+
+        // 补 5 根五行归属:按 energy_dimension.element 填 wuxing_rule_ref(idempotent,仅当为空时填)
+        try {
+            jdbcTemplate.update(
+                    "UPDATE product_dimension_config pdc "
+                            + "JOIN energy_dimension ed ON ed.code = pdc.dimension_code "
+                            + "SET pdc.wuxing_rule_ref = COALESCE(pdc.wuxing_rule_ref, ed.element) "
+                            + "WHERE pdc.dimension_code IN ('body','mind','wisdom','action','wealth') "
+                            + "AND ed.element IS NOT NULL");
+            log.info("迁移448: 5 根五行归属 wuxing_rule_ref 已按 energy_dimension.element 补齐");
+        } catch (Exception e) {
+            log.warn("迁移448: 5 根五行归属补齐失败(忽略): {}", e.getMessage());
+        }
+        log.info("迁移448: 统一维度注册中心增量 seed 完成(mind10/wisdom7/action5/wealth4 共33子维)");
+    }
+
     /** 幂等 upsert 维度种子:按 dimension_code 存在则补 source_system/legacy_alias,不存在则插入。 */
     private void upsertDimensionSeed(String code, String name, String dimensionType, Long parentId,
                                      int sort, String sourceSystem, String nodeKind,

+ 55 - 0
cfc-backend/src/main/resources/db/migrate_dimension_unified.sql

@@ -0,0 +1,55 @@
+-- =====================================================================
+-- T5 历史迁移脚本:health_dimension_scores 维度编码统一(统一维度体系)
+-- ---------------------------------------------------------------------
+-- 性质:DBA 手工执行脚本,非应用自启(不进入 DatabaseInitializer 调用链)。
+-- 目的:将旧健康评分表里的裸维度名(growth/sleep/...)改写为统一点分编码
+--       (body.growth/...),与 product_dimension_config 注册中心对齐。
+-- 幂等性:所有语句均幂等,可重复执行;备份表 IF NOT EXISTS + INSERT 去重。
+-- 执行前请先在测试库演练并核对 affected rows。
+-- 日期戳:20261105(按执行日替换 YYYYMMDD 亦可,保持全脚本一致)
+-- =====================================================================
+
+-- ---------------------------------------------------------------------
+-- 步骤1:备份 health_dimension_scores(幂等:表已存在则跳过)
+-- ---------------------------------------------------------------------
+CREATE TABLE IF NOT EXISTS health_dimension_scores_bak_20261105
+    LIKE health_dimension_scores;
+
+-- 仅当备份表为空时首次全量同步;重复执行不会重复插入(按主键去重)
+INSERT INTO health_dimension_scores_bak_20261105
+SELECT * FROM health_dimension_scores
+WHERE NOT EXISTS (
+    SELECT 1 FROM health_dimension_scores_bak_20261105
+);
+
+-- ---------------------------------------------------------------------
+-- 步骤2:改写 7 个 body 子维编码(幂等:已带 'body.' 前缀的行不会被二次改写)
+--   旧维度名 -> 统一点分编码 body.{sub}
+-- ---------------------------------------------------------------------
+UPDATE health_dimension_scores
+SET dimension = CONCAT('body.', dimension)
+WHERE dimension IN ('growth','sleep','vision','immunity','nutrition','gut','exercise');
+
+-- ---------------------------------------------------------------------
+-- 步骤3:越界扫描(仅报告,不修改)——供 P1-T3 收敛
+--   列出 indicator_definitions 中 dimension_code 不属于
+--   [5 根 + 33 子维] 白名单的越界记录,人工确认后应收敛。
+-- ---------------------------------------------------------------------
+SELECT id, code, name, dimension_code
+FROM indicator_definitions
+WHERE dimension_code IS NOT NULL
+  AND dimension_code NOT IN (
+    -- 5 根
+    'body','mind','wisdom','action','wealth',
+    -- 7 body 子维(P0-T3 已 seed)
+    'body.growth','body.sleep','body.vision','body.immunity','body.nutrition','body.gut','body.exercise',
+    -- 7 wisdom 子维(P0 增量 迁移448)
+    'wisdom.memory','wisdom.attention','wisdom.logic','wisdom.spatial','wisdom.perception','wisdom.focus','wisdom.processingSpeed',
+    -- 10 mind 子维(P0 增量 迁移448)
+    'mind.openness','mind.conscientiousness','mind.extraversion','mind.agreeableness','mind.neuroticism',
+    'mind.driveAutonomy','mind.driveCompetence','mind.driveRelatedness','mind.emotionStability','mind.selfConceptOverall',
+    -- 5 action 子维(P0 增量 迁移448)
+    'action.parentTrust','action.parentIntimacy','action.communication','action.healthStatus','action.lastInteraction',
+    -- 4 wealth 子维(P0 增量 迁移448)
+    'wealth.skill','wealth.altruism','wealth.income','wealth.fx'
+  );