Browse Source

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 week ago
parent
commit
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;
 package com.etotem.cfc.common.constant;
 
 
 public class DimensionCodeConstants {
 public class DimensionCodeConstants {
+    // 统一维度体系常量:5 根(body/mind/wisdom/action/wealth)+ 子维构成 body7/wisdom7/mind10/action5/wealth4(共33子维)
     // 5 根维度
     // 5 根维度
     public static final String BODY = "body";
     public static final String BODY = "body";
     public static final String MIND = "mind";
     public static final String MIND = "mind";
@@ -32,4 +33,69 @@ public class DimensionCodeConstants {
     public static final String WUXING_METAL = "金";
     public static final String WUXING_METAL = "金";
     public static final String WUXING_WATER = "水";
     public static final String WUXING_WATER = "水";
     public static final String WUXING_EARTH = "土";
     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();
         migrateUnifiedIndicatorTreeColumns();
         // 迁移447: 统一维度体系(P0-T3)—— 固化 5 根 + 7 body 子维度节点(幂等 seed)
         // 迁移447: 统一维度体系(P0-T3)—— 固化 5 根 + 7 body 子维度节点(幂等 seed)
         seedUnifiedDimensionRegistry();
         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 完成");
         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,不存在则插入。 */
     /** 幂等 upsert 维度种子:按 dimension_code 存在则补 source_system/legacy_alias,不存在则插入。 */
     private void upsertDimensionSeed(String code, String name, String dimensionType, Long parentId,
     private void upsertDimensionSeed(String code, String name, String dimensionType, Long parentId,
                                      int sort, String sourceSystem, String nodeKind,
                                      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'
+  );