2026-09-09-tianpan-tradition-design.md 16 KB

家庭天盘 · 传统文化 + 五维基础能量分 设计文档

  • 日期: 2026-09-09
  • 状态: 设计待审
  • 需求来源: 用户「完善家庭天盘的展示设计,用姓名、生日通过生辰八字、星座和数字能量进行天盘内容定义。同时也可以对五维有一个基础能量分的计算」

1. 背景与现状

1.1 现有实现(已具备)

能力 位置 说明
八字四柱 family_member_attributes.eight_characters JSON {"year":"甲子","month":"丙寅","day":"戊辰","hour":"壬申"}
五行元素 family_member_attributes.wuxing_elements JSON {"wood":30,"fire":45,"earth":60,"metal":25,"water":40}
生肖 family_member_attributes.zodiac rat/ox/...
出生时间 family_member_attributes.birth_datetime 精确到分钟,用于排盘
生命灵数 NumSoulCalculator + InnatePortraitService.calculateNumSoul() lifePath/天赋数/生日数/命运数,主数 11/22/33 保留
灵数配置 numsoul_detail_config 表 1-9 号人 title/keywords/advice/colorHex
先天分 family_member_attributes.mind_base_score / wisdom_base_score 仅心/智两维已有
天盘聚合 TianpanService.buildDashboard() / buildMemberDetail() 已返回八字/星座/灵数/五行/能量快照

1.2 缺口

  1. 五维基础分仅覆盖 mind/wisdom 两维,缺 body/action/wealth
  2. 天盘主页面 canvas 成员节点未展示传统文化信息
  3. 成员弹窗仅展示生肖/星座/代际/动态能量,无八字/灵数/五维基础分
  4. 无「全家成员传统文化对比」专属页面

1.3 设计决策(用户已确认)

  1. 展示范围:以上都要 —— canvas 节点标注 + 成员弹窗增强 + 新增专属页面
  2. 五维基础分算法:八字五行 + 星座 + 灵数 加权(确定性规则,不走 AI)
  3. 数字能量:9 型人格数字能量学(即生命灵数体系,复用现有 NumSoulCalculator)

2. 五维基础能量分算法

2.1 核心映射(权威,来自 README 五维五行矩阵)

维度 code 五行 颜色
身 body 土 earth #FF8C42
智 wisdom 金 metal #6366F1
富 wealth 水 water #F59E0B
行 action 木 wood #10B981
心 mind 火 fire #FF6B9D

2.2 加权公式

五维基础分[dim] = round( 八字五行[dim] × 0.6  +  星座命中[dim] × 20  +  灵数命中[dim] × 20 )
  • 分数范围:每维度 0-100
  • 八字贡献 0-60 分(主因子,占 60%)
  • 星座贡献 0-20 分(占 20%)
  • 灵数贡献 0-20 分(占 20%)

2.3 八字五行层(权重 60%)

直接取 wuxingElements 中对应五行值(0-100 量纲)乘以 0.6:

五行 映射维度
wood 木 action 行
fire 火 mind 心
earth 土 body 身
metal 金 wisdom 智
water 水 wealth 富

缺数据兜底:某成员无 wuxingElements(或某五行缺失)时,该维度取中性值 50。

2.4 星座层(权重 20%)

西方 12 星座四元素 → 五行 → 五维映射,命中维度 +20 分:

四元素 星座 五行 维度
火象 白羊/狮子/射手 火 心
土象 金牛/处女/摩羯 土 身
风象 双子/天秤/水瓶 木 行
水象 巨蟹/天蝎/双鱼 水 富

边界说明:西方占星无「金」元素,金(智)在星座层恒 0 贡献。智维度由八字金 + 灵数(3/7)覆盖,不影响整体平衡。星座数据来源:TianpanService.enrichMembers() 已通过 zodiacAnnualEnergyService.getWesternSign(month, day) 计算 westernSign。

无星座数据兜底:westernSign 为空时星座层全部 0 贡献。

2.5 生命灵数层(权重 20%)

灵数(生命数 lifePath,1-9)映射主维度,命中维度 +20 分:

灵数 人格特质 主维度
1 开创/独立/领导 行
2 合群/同理/协调 心
3 创意/表达 智
4 务实/规律/稳定 身
5 自由/冒险 行
6 关怀/责任/家庭 心
7 分析/策略/求知 智
8 商业/权力/物质 富
9 博爱/理想 心

灵数来源:现有 NumSoulCalculator.calcLifePath(year, month, day)(主数 11/22/33 保留)。TianpanMemberVO.lifeNumber 来自 behaviorModifier 中存储值,服务内做防御性化简:11→2、22→4、33→6(主数化简),其余 >9 值按 digit sum 递归化简至 1-9,null 则不命中。

无灵数数据兜底:无 birthDatetime 时灵数层全部 0 贡献。

2.6 计算示例

输入:八字五行 {wood:40, fire:60, earth:50, metal:30, water:20}、星座狮子座(火象→心)、灵数 7(→智)

维度 八字×0.6 星座 灵数 基础分
身 body(土) 50×0.6=30 0 0 30
智 wisdom(金) 30×0.6=18 0 20 38
富 wealth(水) 20×0.6=12 0 0 12
行 action(木) 40×0.6=24 0 0 24
心 mind(火) 60×0.6=36 20 0 56

3. 后端设计

3.1 新增服务 FiveDimensionScoreService

文件:cfc-backend/src/main/java/com/etotem/cfc/service/FiveDimensionScoreService.java

@Service
public class FiveDimensionScoreService {

    /**
     * 计算并落库(INSERT ON DUPLICATE KEY UPDATE)
     *
     * @param memberId 成员 ID
     * @param memberType 成员类型
     * @param wuxingElements 五行元素 {"wood":..,"fire":..,"earth":..,"metal":..,"water":..},可为 null
     * @param westernSign    西方星座中文名(如 "狮子座"),可为 null
     * @param lifeNumber     生命灵数(主数 11/22/33 已化简为 1-9),可为 null
     * @param operator       计算来源(system/manual)
     */
    public void calcAndSave(Long memberId, String memberType,
                            Map<String, Integer> wuxingElements,
                            String westernSign, Integer lifeNumber,
                            String operator) {
        Map<String, Integer> scores = calcBaseScores(wuxingElements, westernSign, lifeNumber);
        saveScores(memberId, memberType, scores, operator);
    }

    /**
     * 重算指定成员(覆盖现有记录)
     */
    public void recalibrate(Long memberId, String memberType, String operator) {
        FamilyMemberAttributes attrs = familyMemberAttributeService.getByMember(memberId, memberType);
        if (attrs == null) return;
        String westernSign = calcWesternSignFromAttrs(attrs); // 复用 zodiacAnnualEnergyService 逻辑
        Integer lifeNumber = attrs.getLifeNumber(); // 若未存则从 birthDatetime 重新算
        calcAndSave(memberId, memberType, parseWuxingMap(attrs.getWuxingElements()),
                    westernSign, lifeNumber, operator);
    }

    /**
     * 批量重算全家(用于数据修复/策略调整)
     */
    public int recalibrateFamily(Long familyId, String operator) { ... }

    /**
     * 查询五维基础分(供 dashboard/member 接口读取)
     */
    public Map<String, Integer> getScores(Long memberId) { ... }
}

3.1.1 星座 → 四元素映射(内部常量)

private static final Map<String, String> ZODIAC_ELEMENT = ...;
// 白羊座/狮子座/射手座 -> FIRE
// 金牛座/处女座/摩羯座 -> EARTH
// 双子座/天秤座/水瓶座 -> AIR
// 巨蟹座/天蝎座/双鱼座 -> WATER
// 元素 -> 维度: FIRE->mind, EARTH->body, AIR->action, WATER->wealth

3.1.2 灵数 → 主维度映射(内部常量)

private static final Map<Integer, String> LIFE_NUMBER_DIM = ...;
// 1->action, 2->mind, 3->wisdom, 4->body, 5->action, 6->mind, 7->wisdom, 8->wealth, 9->mind

3.1.3 计算逻辑

// 1. 初始化五维 map,八字层: 各维度 = (wuxing 对应五行值 ?? 50) × 0.6
// 2. 星座命中: elementToDim[westernSign元素] += 20
// 3. 灵数命中: numberToDim[reduceMaster(lifeNumber)] += 20  // 11->2, 22->4, 33->6, >9 digit sum
// 4. round 取整返回

单测:cfc-backend/src/test/java/com/etotem/cfc/unit/FiveDimensionScoreServiceTest.java

  • 全数据用例(对照 2.6 示例断言精确值)
  • 各层缺数据兜底用例(wuxing=null / westernSign=null / lifeNumber=null)
  • 主数化简用例(11→映射2、22→映射4、33→映射6)

3.2 扩展 DTO

TianpanMemberVO 新增字段:

private Map<String, Integer> dimensionBaseScores;  // 五维基础分 {body,mind,wisdom,action,wealth}

3.3 改动点

TianpanService.enrichMembers()(第 174 行附近):

  • 原有 m.getWuxingElements()、vo.getWesternSign()、m.getLifeNumber() 保持不变
  • 改为从新表读取已落库的五维基础分:fiveDimensionScoreService.getScores(m.getMemberId())
  • 若表无数据(首次部署或重算未完成)则 fallback 到内存计算(calcBaseScores(...))并立即落库
  • 新增 zodiacName 填充(见 3.6)

TianpanService.buildMemberDetail():经 enrichMembers 自动填充,无需额外改动。

依赖注入:TianpanService 增加 @Resource private FiveDimensionScoreService fiveDimensionScoreService;

新增 Controller 接口:

  • POST /api/tianpan/recalibrate — 手动触发单个成员重算
    • 请求体:{memberId, memberType, operator: "admin"}
    • 返回:更新后的 dimensionBaseScores
  • POST /api/tianpan/recalibrate-family — 批量重算全家(管理员用)
    • 请求体:{familyId, operator: "admin"}
    • 返回:成功重算的成员数

管理端集成:在 Web 管理端家庭成员详情页新增「重新计算五维基础分」按钮,调用上述接口。

3.4 数据库迁移

新增表 family_member_dimension_base_scores:

CREATE TABLE IF NOT EXISTS family_member_dimension_base_scores (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    member_id BIGINT NOT NULL COMMENT '家庭成员ID',
    member_type VARCHAR(20) NOT NULL COMMENT '成员类型: child/parent',
    dimension_code VARCHAR(20) NOT NULL COMMENT '维度: body/mind/wisdom/action/wealth',
    base_score INT NOT NULL COMMENT '基础能量分(0-100)',
    last_calculated_at DATETIME NOT NULL COMMENT '最后计算时间',
    calculated_by VARCHAR(50) DEFAULT 'system' COMMENT '计算来源(system/manual)',
    UNIQUE KEY uk_member_dimension (member_id, dimension_code),
    INDEX idx_member (member_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='五维基础能量分(落库,支持重算)';

迁移逻辑:DatabaseInitializer.runMigrations() 追加迁移,对已有成员批量回填(若 family_member_attributes 有数据则触发一次性重算写入)。

3.5 显式不做的事

  • ❌ 不引入 AI/LangGraph —— 用户已确认走确定性加权计算

4. 前端设计(三处增强)

4.1 Canvas 成员节点标注(pages/tianpan/index.vue)

drawMemberNodes()(第 375 行附近):

  • 成员节点圆形下方增加一行小字:生肖·灵数(如 兔·7)
  • 数据来源:member.zodiacName(生肖名)+ member.lifeNumber
  • 无生肖/灵数时不显示该行(避免空标注)
  • 颜色:跟随 getMemberColor(member.effectiveRole)
  • 字体:9px,与节点名字体一致

注意:enrichMembers 目前只设置了 vo.setZodiac(m.getZodiac())(生肖代码,如 rat),未设置 zodiacName(生肖中文名)。前端弹窗/节点展示生肖名必须补齐:在 enrichMembers 中通过生肖代码映射中文名(映射表参考 ZodiacConfig/findZodiacName 逻辑,rat→鼠/ox→牛/...)并 vo.setZodiacName(...)。

4.2 成员弹窗增强(pages/tianpan/index.vue member-popup)

弹窗内容重构为两区块:

① 基本信息区(现有 + 扩展):

  • 现有:生肖、星座、代际
  • 新增:生命灵数(member.lifeNumber,显示 灵数 N)、八字四柱(member.eightCharacters:年/月/日/时柱横向四格排布,复用 FamilyTianpanCard 的 pillarLabels 样式)
  • 脱敏:孩子视角查看家长成员时,后端已脱敏为仅年柱(redactEightCharacters),前端直接渲染

② 能量区(双条对比):

  • 现有:动态能量条(selectedMember.energy)
  • 新增:五维基础分条(selectedMember.dimensionBaseScores,用五维标准色,复用现有 .energy-bar 样式)

4.3 新增「命理」专属页面 pages/tianpan/traditional.vue

入口:pages/tianpan/index.vue canvas 下方、tab 栏之前新增「家庭成员命理解读」入口卡片(样式参考现有 fortune-card)

页面结构(全家成员传统文化对比):

  1. 家庭成员列表:mapGetters('tianpan', ['members']) 数据(复用 dashboard 已加载数据,不重复请求)
  2. 每个成员展开卡片:
    • 头部:头像 + 昵称 + 角色
    • 八字四柱:年/月/日/时柱四格
    • 五行条形图:复用 FamilyTianpanCard wuxingData 样式
    • 星座 + 生肖 tag
    • 灵数:定稿为简化版 —— 仅展示生命数(member.lifeNumber)+ 灵数称号(member.lifeNumberTitle)。完整的天赋数/生日数/命运数(NumSoulDetailVO)不随 dashboard 返回,如需完整版走 /api/tianpan/member/{id} 详情扩展(本迭代不做,列入 out of scope)
    • 五维基础分:条形图(五维标准色)+ 总分

页面注册:pages.json 的 pages/tianpan 分包新增 traditional

API 去重规范:本页复用 store tianpan/members(dashboard 已加载),禁止重复请求 /api/tianpan/dashboard;成员展开明细如需更多数据走 /api/tianpan/member/{id}(按需点击加载,遵守规则 4 不 N+1)

4.4 数据依赖核对

前端展示项 后端字段 现状 动作
生肖名 zodiacName ❌ enrichMembers 未设置(仅 zodiac 代码) 补齐:代码→中文名映射 + setZodiacName
星座 westernSign ✅ 已设置 无
灵数 lifeNumber ✅ 已设置 无
八字四柱 eightCharacters ✅ 已设置(含脱敏) 无
五行 wuxingElements ✅ 已设置 无
五维基础分 dimensionBaseScores ❌ 新增 3.3 实现
灵数详情(天赋/生日/命运数) numSoul TianpanMemberVO 未含 传统页简化版仅展示 lifeNumber

5. 测试策略

5.1 后端单测(必须)

FiveDimensionScoreServiceTest:

  • 全数据用例(对照 2.6 示例断言)
  • 兜底用例:wuxing=null、westernSign=null、lifeNumber=null、全部为 null(五维全 50×0.6=30)
  • 主数化简用例
  • 星座边界:12 星座全部覆盖 + 未知星座字符串

5.2 前端校验

  • node --check 提取的 script 块语法校验(按 cfc-frontend/AGENTS.md 规范,Agent 不打包)
  • CI 门禁:node scripts/audit-duplicate-api-calls.js 通过
  • 小程序限制自查:无可选链 ?.、无 CSS Grid、无 :key 表达式、无 new Date(string)

5.3 编译验证

cd cfc-backend && mvn clean compile

6. 范围边界

In scope:

  • 五维基础分算法服务 + 单测
  • family_member_dimension_base_scores 表 + 迁移 + 批量回填
  • TianpanMemberVO 扩展(dimensionBaseScores)+ enrichMembers 填充(含 zodiacName 补齐)
  • 重算接口 POST /api/tianpan/recalibrate / recalibrate-family
  • 天盘首页 canvas 节点标注 + 成员弹窗增强
  • 新增 pages/tianpan/traditional.vue + 入口卡片 + pages.json 注册
  • Web 管理端家庭成员详情「重新计算五维基础分」按钮(可选)

Out of scope:

  • 姓名数理(五格剖象法)—— 需汉字笔画库,单独需求
  • 灵数九宫格连线(147/258/369 连线分析)—— 后续迭代
  • 灵数完整详情(天赋数/生日数/命运数)随 member 详情接口返回 —— 后续迭代
  • AI 天盘解读(LangGraph)—— 未确认前不做
  • 天盘周报 PDF 内容变更
  • 数据库迁移(无新表无新列)