Browse Source

unified-dimension: T-D 能量沙盘维度来源切注册中心,五行归属 wuxing_rule_ref/统一 code,语义与回归不变

Agnes Agent 5 ngày trước cách đây
mục cha
commit
b02a949c57

+ 48 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/EnergyService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.etotem.cfc.dto.CfBalanceView;
 import com.etotem.cfc.dto.EnergySandboxDTO;
 import com.etotem.cfc.dto.MemberEnergyDTO;
+import com.etotem.cfc.dto.DimensionNode;
 import com.etotem.cfc.entity.*;
 import com.etotem.cfc.mapper.*;
 import com.alibaba.fastjson.JSON;
@@ -93,6 +94,10 @@ public class EnergyService {
     @Resource
     private FamilyMetricAggConfigMapper familyMetricAggConfigMapper;
 
+    /** 统一维度注册中心:五维根节点五行归属(wuxing_rule_ref)的权威来源 */
+    @Resource
+    private DimensionRegistryService dimensionRegistryService;
+
     /**
      * 计算整个家庭的能量沙盘数据
      *
@@ -2279,10 +2284,53 @@ public class EnergyService {
                     new LambdaQueryWrapper<EnergyDimension>()
                             .orderByAsc(EnergyDimension::getSortOrder)
             );
+            // 统一维度体系:五维五行归属改以注册中心为准(root 节点 wuxing_rule_ref,与旧
+            // energy_dimension.element 同值,迁移448 已对齐)。注册中心未就绪或维度缺失时
+            // 保留旧表值,保证五行回归结果不变、返回结构不变。
+            enrichWuxingElementFromRegistry(dimCache);
         }
         return dimCache;
     }
 
+    /**
+     * 统一维度体系:按注册中心 5 根节点的 wuxing_rule_ref 覆盖五行元素归属(element)。
+     *
+     * <p>维度 code(body/mind/wisdom/action/wealth)与统一 5 根同码,无需 alias 翻译;
+     * id/name/icon/sortOrder/status 仍以 energy_dimension 表为准(energy_log/energy_balance
+     * 以 dimension_id 关联该表 id,切换仅限五行归属来源,保证回归不变)。</p>
+     *
+     * @param dims 已加载的旧表维度列表(就地更新 element)
+     */
+    private void enrichWuxingElementFromRegistry(List<EnergyDimension> dims) {
+        if (dims == null || dims.isEmpty() || dimensionRegistryService == null) {
+            return;
+        }
+        try {
+            List<DimensionNode> roots = dimensionRegistryService.getRoots();
+            if (roots == null || roots.isEmpty()) {
+                return;
+            }
+            Map<String, String> elementByCode = new HashMap<>();
+            for (DimensionNode root : roots) {
+                if (root == null || root.getCode() == null || root.getWuxingRuleRef() == null) {
+                    continue;
+                }
+                elementByCode.put(root.getCode(), root.getWuxingRuleRef());
+            }
+            for (EnergyDimension d : dims) {
+                if (d == null || d.getCode() == null) {
+                    continue;
+                }
+                String element = elementByCode.get(d.getCode());
+                if (element != null) {
+                    d.setElement(element);
+                }
+            }
+        } catch (Exception e) {
+            log.warn("EnergyService.enrichWuxingElementFromRegistry: 注册中心五行归属补齐失败(忽略): {}", e.getMessage());
+        }
+    }
+
     /**
      * 按code查维度
      */

+ 29 - 3
cfc-frontend/components/wuxing-sandbox.vue

@@ -95,6 +95,11 @@ import { renderStar, calcStarVertices } from './wuxing-sandbox-helpers/render.js
 import { FillAnimator } from './wuxing-sandbox-helpers/animation.js'
 import { detectHitArm, armIndexToDomain } from './wuxing-sandbox-helpers/hitdetect.js'
 import { FlowAnimation } from './wuxing-sandbox-helpers/flow-animation.js'
+import {
+  ensureDimensionRegistry,
+  getRegistryRootMeta,
+  isRegistryReady
+} from '../composables/useDimensionRegistry.js'
 import {
   buildMemberOptions,
   findMemberById,
@@ -306,7 +311,9 @@ export default {
       _animator: null,
       _flowAnim: null,
       _flowCanvasReady: false,
-      uiIcons: UI_ICON_URIS
+      uiIcons: UI_ICON_URIS,
+      // 统一维度注册中心是否就绪:就绪后维度名称/五行元素兜底改经注册中心(wuxing_rule_ref/统一 code)
+      registryReady: false
     }
   },
   computed: {
@@ -417,16 +424,27 @@ export default {
         var d = this.dimensions[i]
         if (d && d.code) dimMap[d.code] = d
       }
+      // 统一维度体系:维度名称/五行元素兜底改经注册中心(root name / wuxing_rule_ref),
+      // 未就绪回退组件内 DIM_META(保持既有渲染,五行语义零改动)。
+      var regMeta = {}
+      if (this.registryReady) {
+        var roots = getRegistryRootMeta()
+        for (var r = 0; r < roots.length; r++) {
+          var root = roots[r]
+          if (root && root.code) regMeta[root.code] = root
+        }
+      }
       var all = []
       for (var j = 0; j < order.length; j++) {
         var code = order[j]
         var d = dimMap[code] || {}
+        var reg = regMeta[code] || {}
         var meta = DIM_META[code] || {}
         var score = scoreByCode[code] || 0
         all.push({
           code: code,
-          name: d.name || meta.name || '',
-          element: d.element || meta.element || '',
+          name: d.name || reg.name || meta.name || '',
+          element: d.element || reg.element || meta.element || '',
           energy: score,
           healthIndex: score,
           pointClass: RING_POS[j],
@@ -510,6 +528,14 @@ export default {
   mounted: function() {
     var self = this
 
+    // 统一维度体系:维度名称/五行元素兜底来源切换为注册中心(wuxing_rule_ref/统一 code),
+    // 幂等(模块级缓存单请求);未就绪时保持原有 DIM_META 兜底,五行语义零改动。
+    ensureDimensionRegistry().then(function() {
+      self.registryReady = isRegistryReady()
+    }).catch(function() {
+      self.registryReady = false
+    })
+
     // preview:轻量引导条,不初始化 Canvas、不画完整星图
     if (this.isPreview) return
 

+ 26 - 0
cfc-frontend/composables/useDimensionRegistry.js

@@ -155,9 +155,35 @@ function getRadarConfig(tabCode) {
   return config
 }
 
+/**
+ * 取注册中心 5 根节点元信息(五行归属):[{ code, name, element: wuxingRuleRef }]。
+ *
+ * <p>供五行能量沙盘维度名称 / 五行元素兜底(统一 code + wuxing_rule_ref),
+ * 未就绪返回空数组(调用方回落组件内 DIM_META)。</p>
+ *
+ * @returns {Array<{code:string,name:string,element:string}>}
+ */
+function getRegistryRootMeta() {
+  if (!_cache.tree || !Array.isArray(_cache.tree)) return []
+  var out = []
+  for (var i = 0; i < _cache.tree.length; i++) {
+    var node = _cache.tree[i]
+    if (!node || !node.code) continue
+    // 仅维度根节点(nodeKind=root;旧数据无 nodeKind 的按「无父节点」视为根)
+    if (node.nodeKind && node.nodeKind !== 'root') continue
+    out.push({
+      code: node.code,
+      name: node.name || '',
+      element: node.wuxingRuleRef || ''
+    })
+  }
+  return out
+}
+
 export {
   ensureDimensionRegistry,
   getRadarConfig,
+  getRegistryRootMeta,
   isRegistryReady,
   WEALTH_CHILD_LABEL
 }