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

fix(frontend+backend): P2/P3 article fixes

- article-edit.vue: fix dimension labels (mind='心', wisdom='智')
  matches SPEC color mapping: mind=#FF6B9D, wisdom=#6366F1
- ArticleService.publishByUser: compute dimensionWeights JSON
  (equal distribution, e.g. 3 dims → {"body":34,"mind":33,"wisdom":33})
  enables dimension-aware query (COALESCE(JSON_EXTRACT)) for user posts
- article-detail.vue: parseDimensions reads real weights from
  article.dimensionWeights JSON, falls back to equal distribution
  Also fixed mind/wisdom color mapping in dimMap to match SPEC
Xiaogang Liao 3 месяцев назад
Родитель
Сommit
8d4e3ac0e2

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

@@ -642,6 +642,8 @@ public class ArticleService {
         // 关联维度
         article.setRelatedDimensions(relatedDimensions);
 
+        article.setDimensionWeights(buildEqualWeights(relatedDimensions));
+
         // 私有(家庭可见)→ 设置 visibleTo
         if ("private".equals(visibility)) {
             User user = userMapper.selectById(userId);
@@ -668,6 +670,29 @@ public class ArticleService {
         return article;
     }
 
+    private String buildEqualWeights(String relatedDimensions) {
+        if (relatedDimensions == null || relatedDimensions.trim().isEmpty()) {
+            return null;
+        }
+        String[] parts = relatedDimensions.split(",");
+        int n = parts.length;
+        if (n == 0) return null;
+        int base = 100 / n;
+        int remainder = 100 - base * n;
+        Map<String, Integer> weights = new LinkedHashMap<>();
+        for (int i = 0; i < n; i++) {
+            String dim = parts[i].trim().toLowerCase();
+            if (dim.isEmpty()) continue;
+            weights.put(dim, i < remainder ? base + 1 : base);
+        }
+        if (weights.isEmpty()) return null;
+        try {
+            return objectMapper.writeValueAsString(weights);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
     /**
      * 获取我的发布列表
      */

+ 39 - 10
cfc-frontend/pages/article-center/article-detail.vue

@@ -34,7 +34,7 @@
         </view>
         <!-- 五维权重彩条 -->
         <view v-if="article.relatedDimensions" class="detail-dimensions">
-          <view v-for="dim in parseDimensions(article.relatedDimensions)" :key="dim.code" class="dim-bar-item">
+          <view v-for="dim in parseDimensions(article)" :key="dim.code" class="dim-bar-item">
             <view class="dim-bar" :style="{ background: dim.color, width: dim.weight + '%' }"></view>
             <text class="dim-label">{{ dim.name }}</text>
           </view>
@@ -191,17 +191,46 @@ export default {
       if (!dateStr) return ''
       return dateStr.slice(0, 10)
     },
-    parseDimensions(str) {
-      if (!str) return []
+    parseDimensions: function(article) {
       var dimMap = {
-        body: { code: 'body', color: '#FF8C42', name: '身', weight: 20 },
-        mind: { code: 'mind', color: '#6366F1', name: '智', weight: 20 },
-        wisdom: { code: 'wisdom', color: '#FF6B9D', name: '心', weight: 20 },
-        action: { code: 'action', color: '#10B981', name: '行', weight: 20 },
-        wealth: { code: 'wealth', color: '#F59E0B', name: '富', weight: 20 }
+        body:   { code: 'body',   color: '#FF8C42', name: '身' },
+        mind:   { code: 'mind',   color: '#FF6B9D', name: '心' },
+        wisdom: { code: 'wisdom', color: '#6366F1', name: '智' },
+        action: { code: 'action', color: '#10B981', name: '行' },
+        wealth: { code: 'wealth', color: '#F59E0B', name: '富' }
       }
-      var codes = str.split(',').map(function(s) { return s.trim().toLowerCase() })
-      return codes.filter(function(c) { return dimMap[c] }).map(function(c) { return dimMap[c] })
+      var raw = article && article.relatedDimensions
+        ? article.relatedDimensions.split(',').map(function(s) { return s.trim().toLowerCase() })
+        : []
+      var weights = null
+      if (article && article.dimensionWeights) {
+        try {
+          var w = JSON.parse(article.dimensionWeights)
+          if (w && typeof w === 'object') weights = w
+        } catch (e) {}
+      }
+      if (!weights) {
+        var n = raw.filter(function(c) { return dimMap[c] }).length
+        if (n > 0) {
+          var base = Math.floor(100 / n)
+          var rem = 100 - base * n
+          weights = {}
+          var i = 0
+          raw.forEach(function(c) {
+            if (!dimMap[c]) return
+            weights[c] = i < rem ? base + 1 : base
+            i++
+          })
+        }
+      }
+      return raw.filter(function(c) { return dimMap[c] }).map(function(c) {
+        return {
+          code: dimMap[c].code,
+          name: dimMap[c].name,
+          color: dimMap[c].color,
+          weight: (weights && weights[c]) ? weights[c] : 20
+        }
+      })
     },
     getOptionLetter(idx) {
       return String.fromCharCode(65 + idx)

+ 2 - 2
cfc-frontend/pages/article-center/article-edit.vue

@@ -110,8 +110,8 @@ export default {
       publishing: false,
       dimensionList: [
         { code: 'body', name: '身', color: '#FF8C42' },
-        { code: 'mind', name: '智', color: '#6366F1' },
-        { code: 'wisdom', name: '心', color: '#FF6B9D' },
+        { code: 'mind', name: '心', color: '#FF6B9D' },
+        { code: 'wisdom', name: '智', color: '#6366F1' },
         { code: 'action', name: '行', color: '#10B981' },
         { code: 'wealth', name: '富', color: '#F59E0B' }
       ]