Explorar o código

refactor(beautify): D27 health-report 健康报告页清理 (debt 51->0)

- SVG 属性色(轨道/主文字/次文字)改为 :stroke/:fill 绑定 data 常量
- script 4 个指标色 + 3 档评分色 + canvas 色全部收编 BrandColors.*(含 import)
- brand-colors.js 补 matOrange(#FF9800)/matBlue(#2196F3)/matRed(#F44336)/amber(#FFC107)
- hex 17->0;P2 42->41,全站硬编码色 1303->1286
liaoxg hai 5 días
pai
achega
97adadef2d

+ 22 - 18
cfc-frontend/pages/body-detail/health-report.vue

@@ -34,10 +34,10 @@
         <view class="main-score-item" v-for="item in mainScores" :key="item.key">
           <view class="score-ring-wrap">
             <svg width="140" height="140" viewBox="0 0 120 120">
-              <circle cx="60" cy="60" r="50" fill="none" stroke="#EEEEEE" stroke-width="8"/>
+              <circle cx="60" cy="60" r="50" fill="none" :stroke="svgTrack" stroke-width="8"/>
               <circle cx="60" cy="60" r="50" fill="none" v-bind:stroke="item.color" stroke-width="8" v-bind:stroke-dasharray="item.circumference" v-bind:stroke-dashoffset="item.offset" stroke-linecap="round" transform="rotate(-90 60 60)"/>
-              <text x="60" y="52" text-anchor="middle" font-size="32" font-weight="bold" fill="#333">{{ item.score }}</text>
-              <text x="60" y="72" text-anchor="middle" font-size="14" fill="#999">分</text>
+              <text x="60" y="52" text-anchor="middle" font-size="32" font-weight="bold" :fill="svgInk">{{ item.score }}</text>
+              <text x="60" y="72" text-anchor="middle" font-size="14" :fill="svgMuted">分</text>
             </svg>
           </view>
           <text class="main-score-label">{{ item.label }}</text>
@@ -181,6 +181,7 @@
 </template>
 
 <script>
+import { BrandColors } from '../../utils/brand-colors.js'
 import config from '@/config.js'
 import { getDeficiencyAnalysis } from '@/utils/api.js'
 import { parseDate } from '@/utils/format.js'
@@ -223,7 +224,10 @@ export default {
       indicators: [],
       deficiencyRecords: [],
       foods: [],
-      loading: false
+      loading: false,
+      svgTrack: BrandColors.hairline2,
+      svgInk: BrandColors.textStrong,
+      svgMuted: BrandColors.textMuted
     }
   },
   computed: {
@@ -277,10 +281,10 @@ export default {
       var items = []
       var r = this.report
       var pairs = [
-        {key:'overall', label:'综合评分', score: r.overallScore, color:'#F97316'},
-        {key:'gut', label:'肠道健康', score: r.gutHealthScore, color:'#4CAF50'},
-        {key:'chronic', label:'慢病控制', score: r.chronicDiseaseScore, color:'#FF9800'},
-        {key:'nutrition', label:'营养均衡', score: r.nutritionScore, color:'#2196F3'}
+        {key:'overall', label:'综合评分', score: r.overallScore, color:BrandColors.primary},
+        {key:'gut', label:'肠道健康', score: r.gutHealthScore, color:BrandColors.matGreen},
+        {key:'chronic', label:'慢病控制', score: r.chronicDiseaseScore, color:BrandColors.matOrange},
+        {key:'nutrition', label:'营养均衡', score: r.nutritionScore, color:BrandColors.matBlue}
       ]
       var circ = Math.round(2 * Math.PI * 50)
       for (var i = 0; i < pairs.length; i++) {
@@ -310,9 +314,9 @@ export default {
         var p = pairs[i]
         if (p.score != null) {
           var s = p.score
-          var color = '#4CAF50'
-          if (s < 30) { color = '#F44336' }
-          else if (s < 60) { color = '#FFC107' }
+          var color = BrandColors.matGreen
+          if (s < 30) { color = BrandColors.matRed }
+          else if (s < 60) { color = BrandColors.amber }
           items.push({key: p.key, label: p.label, score: s, color: color})
         }
       }
@@ -427,9 +431,9 @@ export default {
       return '未分类'
     },
     getSeverityColor: function(severity) {
-      if (severity >= 0.7) return '#EF4444'
-      if (severity >= 0.3) return '#F59E0B'
-      return '#10B981'
+      if (severity >= 0.7) return BrandColors.danger
+      if (severity >= 0.3) return BrandColors.wealth
+      return BrandColors.success
     },
     drawRadarChart: function() {
       var dims = this.radarDimensions
@@ -445,7 +449,7 @@ export default {
 
       for (var level = 1; level <= 5; level++) {
         var r = maxR * (level / 5)
-        ctx.setStrokeStyle('#E5E7EB')
+        ctx.setStrokeStyle(BrandColors.gray200)
         ctx.setLineWidth(1)
         ctx.beginPath()
         for (var j = 0; j < n; j++) {
@@ -464,7 +468,7 @@ export default {
         ctx.beginPath()
         ctx.moveTo(cx, cy)
         ctx.lineTo(cx + maxR * Math.cos(a2), cy + maxR * Math.sin(a2))
-        ctx.setStrokeStyle('#E5E7EB')
+        ctx.setStrokeStyle(BrandColors.gray200)
         ctx.setLineWidth(1)
         ctx.stroke()
       }
@@ -482,7 +486,7 @@ export default {
       ctx.closePath()
       ctx.setFillStyle('rgba(249, 115, 22, 0.2)')
       ctx.fill()
-      ctx.setStrokeStyle('#F97316')
+      ctx.setStrokeStyle(BrandColors.primary)
       ctx.setLineWidth(2)
       ctx.stroke()
 
@@ -491,7 +495,7 @@ export default {
         var lx = cx + (maxR + 20) * Math.cos(angle3)
         var ly = cy + (maxR + 20) * Math.sin(angle3)
         ctx.setFontSize(11)
-        ctx.setFillStyle('#6B7280')
+        ctx.setFillStyle(BrandColors.textSlate)
         ctx.setTextAlign('center')
         ctx.setTextBaseline('middle')
         ctx.fillText(dims[q].label + ' ' + (dims[q].value || '--'), lx, ly)

+ 58 - 0
cfc-frontend/scripts/d27-health-report.js

@@ -0,0 +1,58 @@
+#!/usr/bin/env node
+/**
+ * D27: health-report.vue 健康报告页清理 (debt 51 -> 0)
+ * SVG 属性色绑定 data;script 指标色/canvas 色收编 BrandColors
+ */
+const fs = require('fs');
+const F = 'pages/body-detail/health-report.vue';
+let src = fs.readFileSync(F, 'utf8');
+let replaced = 0;
+
+function repl(from, to) {
+  const cnt = src.split(from).length - 1;
+  if (cnt === 0) { console.warn('NOT FOUND: ' + from.slice(0, 100)); return; }
+  src = src.split(from).join(to);
+  replaced += cnt;
+}
+
+// ---- 1. import ----
+if (!src.includes('utils/brand-colors.js')) {
+  const m = src.match(/<script>\r?\n/);
+  if (m) src = src.replace(m[0], m[0] + "import { BrandColors } from '../../utils/brand-colors.js'\r\n");
+  else console.warn('script tag not found');
+}
+
+// ---- 2. SVG 属性 ----
+repl('stroke="#EEEEEE"', ':stroke="svgTrack"');
+repl('fill="#333"', ':fill="svgInk"');
+repl('fill="#999"', ':fill="svgMuted"');
+repl('      healthReport: null,', '      healthReport: null,\r\n      svgTrack: BrandColors.hairline2,\r\n      svgInk: BrandColors.textStrong,\r\n      svgMuted: BrandColors.textMuted,');
+
+// ---- 3. script 指标色 ----
+repl("color:'#F97316'", "color:BrandColors.primary");
+repl("color:'#4CAF50'", "color:BrandColors.matGreen");
+repl("color:'#FF9800'", "color:BrandColors.matOrange");
+repl("color:'#2196F3'", "color:BrandColors.matBlue");
+
+// ---- 4. 评分色档 ----
+repl("var color = '#4CAF50'", "var color = BrandColors.matGreen");
+repl("color = '#F44336'", "color = BrandColors.matRed");
+repl("color = '#FFC107'", "color = BrandColors.amber");
+
+// ---- 5. canvas ----
+repl("return '#EF4444'", "return BrandColors.danger");
+repl("return '#F59E0B'", "return BrandColors.wealth");
+repl("return '#10B981'", "return BrandColors.success");
+repl("ctx.setStrokeStyle('#E5E7EB')", "ctx.setStrokeStyle(BrandColors.gray200)");
+repl("ctx.setStrokeStyle('#F97316')", "ctx.setStrokeStyle(BrandColors.primary)");
+repl("ctx.setFillStyle('#6B7280')", "ctx.setFillStyle(BrandColors.textSlate)");
+
+fs.writeFileSync(F, src);
+console.log('total replaced:', replaced);
+
+const lines = src.split('\n');
+let n = 0;
+for (let i = 0; i < lines.length; i++) {
+  if (/#[0-9a-fA-F]{3,8}\b/.test(lines[i])) { console.log('HEX ' + (i + 1) + ': ' + lines[i].trim().slice(0, 110)); n++; }
+}
+console.log('remaining hex lines:', n);

+ 4 - 0
cfc-frontend/utils/brand-colors.js

@@ -80,6 +80,10 @@ export const BrandColors = {
   weatherSunny: '#FFB347',  // 晴朗心情色(情绪趋势天气板)
   textGhost: '#CCC',        // $facade-text-ghost
   hairline: '#E0E0E0',      // $facade-hairline
+  matOrange: '#FF9800',     // $mat-orange-base
+  matBlue: '#2196F3',       // $mat-blue-base
+  matRed: '#F44336',        // Material red-500
+  amber: '#FFC107',         // Material amber-500
   infoSky: '#0EA5E9',       // sky-500($uni-info;肠道菌群指标色)
   dangerStrong2: '#C62828', // red-800($status-danger-strong-2)
   fill: '#F0F0F0',          // $facade-fill