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

refactor(beautify): D21 gut-flora-detail 肠道菌群页清理 (debt 60->0)

- script 9 个指标色收编 BrandColors.*(含 import)
- style 全局令牌:\-danger-tint-2/\-line/\-blue/\-amber-tint/\-green-soft
- 局部 Material Teal 提示色族收编 \-gf-*(6 色)
- uni.scss 新增 \-blue(#1976D2)/\-green-soft(#A5D6A7)/\-line(#FECACA)(均 ≥3 文件复用)
- brand-colors.js 补 infoSky(#0EA5E9)/dangerStrong2(#C62828)
- hex 20->0;P1 3->2
liaoxg 6 дней назад
Родитель
Сommit
7054146ea8

+ 29 - 20
cfc-frontend/pages/health/gut-flora-detail.vue

@@ -356,6 +356,7 @@
 <script>
 <script>
 import { getReportDetail, editHealthReport, queryKnowledgeBase, queryIndicatorKnowledge, getGutFloraAnalysis, confirmReportPreview, discardReportDraft, parseReportDraft, getHealthFoods, getFoodCautionList, getFamilyMemberList, addFamilyMember, getIndicatorChangeRanking } from '../../utils/api.js'
 import { getReportDetail, editHealthReport, queryKnowledgeBase, queryIndicatorKnowledge, getGutFloraAnalysis, confirmReportPreview, discardReportDraft, parseReportDraft, getHealthFoods, getFoodCautionList, getFamilyMemberList, addFamilyMember, getIndicatorChangeRanking } from '../../utils/api.js'
 import HealthKnowledgePopup from '@/pages/health/components/health-knowledge-popup.vue'
 import HealthKnowledgePopup from '@/pages/health/components/health-knowledge-popup.vue'
+import { BrandColors } from '../../utils/brand-colors.js'
 import FeedbackPopup from '@/pages/health/components/feedback-popup.vue'
 import FeedbackPopup from '@/pages/health/components/feedback-popup.vue'
 import { parseDate } from '../../utils/format.js'
 import { parseDate } from '../../utils/format.js'
 import { resolveChangeStyle, formatDelta, colorClassFor } from '../../utils/indicator-change.js'
 import { resolveChangeStyle, formatDelta, colorClassFor } from '../../utils/indicator-change.js'
@@ -791,15 +792,15 @@ applyDraftPayload: function(payload) {
       var s = r.summary || r
       var s = r.summary || r
       var items = []
       var items = []
       var scoreFields = [
       var scoreFields = [
-        { key: 'overallScore',         label: '综合',            color: '#0EA5E9' },
-        { key: 'gutHealthScore',       label: '菌群健康',        color: '#10B981' },
-        { key: 'chronicDiseaseScore',  label: '慢病控制',        color: '#F59E0B' },
-        { key: 'nutritionScore',       label: '营养均衡',        color: '#FF8C42' },
-        { key: 'balanceScore',         label: '平衡',            color: '#6366F1' },
-        { key: 'diversityScore',       label: '多样性',          color: '#FF6B9D' },
-        { key: 'beneficialScore',      label: '有益菌',          color: '#10B981' },
-        { key: 'harmfulScore',         label: '有害菌',          color: '#C62828' },
-        { key: 'coreGenusScore',       label: '核心菌属',        color: '#0EA5E9' }
+        { key: 'overallScore',         label: '综合',            color: BrandColors.infoSky },
+        { key: 'gutHealthScore',       label: '菌群健康',        color: BrandColors.success },
+        { key: 'chronicDiseaseScore',  label: '慢病控制',        color: BrandColors.wealth },
+        { key: 'nutritionScore',       label: '营养均衡',        color: BrandColors.body },
+        { key: 'balanceScore',         label: '平衡',            color: BrandColors.wisdom },
+        { key: 'diversityScore',       label: '多样性',          color: BrandColors.mind },
+        { key: 'beneficialScore',      label: '有益菌',          color: BrandColors.success },
+        { key: 'harmfulScore',         label: '有害菌',          color: BrandColors.dangerStrong2 },
+        { key: 'coreGenusScore',       label: '核心菌属',        color: BrandColors.infoSky }
       ]
       ]
       for (var i = 0; i < scoreFields.length; i++) {
       for (var i = 0; i < scoreFields.length; i++) {
         var f = scoreFields[i]
         var f = scoreFields[i]
@@ -1069,6 +1070,14 @@ applyDraftPayload: function(payload) {
 </script>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">
+// ===== 肠道菌群页专属色阶(Material Teal 提示色族;单页专用,约定见 uni.scss §14)=====
+$c-gf-amber:     #FFB300; // amber-700 提示左边线
+$c-gf-brown:     #795548; // brown-500 提示文字
+$c-gf-teal-bg:   #E0F2F1; // teal-50 浅底
+$c-gf-teal:      #00897B; // teal-600 主色
+$c-gf-teal-deep: #00695C; // teal-800 深档
+$c-gf-teal-ink:  #004D40; // teal-900 深文字
+
 .page { min-height: 100vh; background: $facade-fill-page; }
 .page { min-height: 100vh; background: $facade-fill-page; }
 .content { height: calc(100vh - 100rpx); }
 .content { height: calc(100vh - 100rpx); }
 
 
@@ -1087,9 +1096,9 @@ applyDraftPayload: function(payload) {
 .quick-nav { display: flex; padding: 20rpx; background: $app-surface; margin-bottom: 16rpx; }
 .quick-nav { display: flex; padding: 20rpx; background: $app-surface; margin-bottom: 16rpx; }
 .nav-card { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 16rpx 0; }
 .nav-card { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 16rpx 0; }
 .caution-card {
 .caution-card {
-  background: #FEF2F2;
+  background: $status-danger-tint-2;
   border-radius: 16rpx;
   border-radius: 16rpx;
-  border: 2rpx solid #FECACA;
+  border: 2rpx solid $danger-line;
 }
 }
 .caution-count { color: $status-danger-deep; font-weight: 700; }
 .caution-count { color: $status-danger-deep; font-weight: 700; }
 .nav-icon { font-size: 40rpx; margin-bottom: 6rpx; }
 .nav-icon { font-size: 40rpx; margin-bottom: 6rpx; }
@@ -1158,7 +1167,7 @@ applyDraftPayload: function(payload) {
 .indicator-range { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-ghost-light; display: block; margin-top: 4rpx; }
 .indicator-range { font-size: calc(22rpx * var(--font-scale, 1)); color: $facade-text-ghost-light; display: block; margin-top: 4rpx; }
 
 
 /* 指标知识库 "?" 按钮(与通用报告页一致) */
 /* 指标知识库 "?" 按钮(与通用报告页一致) */
-.ind-help-btn { display: inline-flex; align-items: center; justify-content: center; width: 36rpx; height: 36rpx; border-radius: 50%; background: $mat-blue-tint; color: #1976D2; font-size: 22rpx; font-weight: 600; margin-left: 8rpx; flex-shrink: 0; }
+.ind-help-btn { display: inline-flex; align-items: center; justify-content: center; width: 36rpx; height: 36rpx; border-radius: 50%; background: $mat-blue-tint; color: $mat-blue; font-size: 22rpx; font-weight: 600; margin-left: 8rpx; flex-shrink: 0; }
 
 
 /* 综合评级行 */
 /* 综合评级行 */
 .rating-line { margin: 12rpx 0 0; }
 .rating-line { margin: 12rpx 0 0; }
@@ -1201,32 +1210,32 @@ applyDraftPayload: function(payload) {
 
 
 /* 报告解读 */
 /* 报告解读 */
 .interpretation-box {
 .interpretation-box {
-  background: #FFF8E1;
+  background: $mat-amber-tint;
   border-radius: 12rpx;
   border-radius: 12rpx;
   padding: 16rpx 20rpx;
   padding: 16rpx 20rpx;
   margin: 16rpx 0 0;
   margin: 16rpx 0 0;
-  border-left: 6rpx solid #FFB300;
+  border-left: 6rpx solid $c-gf-amber;
 }
 }
 .interp-text {
 .interp-text {
   font-size: calc(24rpx * var(--font-scale, 1));
   font-size: calc(24rpx * var(--font-scale, 1));
-  color: #795548;
+  color: $c-gf-brown;
   line-height: 1.6;
   line-height: 1.6;
 }
 }
 
 
 /* AI 解读框 */
 /* AI 解读框 */
 .ai-box {
 .ai-box {
-  background: #E0F2F1;
-  border-left-color: #00897B;
+  background: $c-gf-teal-bg;
+  border-left-color: $c-gf-teal;
 }
 }
 .interp-label {
 .interp-label {
   font-size: calc(24rpx * var(--font-scale, 1));
   font-size: calc(24rpx * var(--font-scale, 1));
   font-weight: 600;
   font-weight: 600;
-  color: #00695C;
+  color: $c-gf-teal-deep;
   display: block;
   display: block;
   margin-bottom: 6rpx;
   margin-bottom: 6rpx;
 }
 }
 .ai-box .interp-text {
 .ai-box .interp-text {
-  color: #004D40;
+  color: $c-gf-teal-ink;
 }
 }
 /* 报告总结描述 */
 /* 报告总结描述 */
 .summary-box {
 .summary-box {
@@ -1234,7 +1243,7 @@ applyDraftPayload: function(payload) {
   border-radius: 12rpx;
   border-radius: 12rpx;
   padding: 16rpx 20rpx;
   padding: 16rpx 20rpx;
   margin: 16rpx 0 0;
   margin: 16rpx 0 0;
-  border-left: 6rpx solid #A5D6A7;
+  border-left: 6rpx solid $mat-green-soft;
   display: flex;
   display: flex;
   flex-direction: column;
   flex-direction: column;
   gap: 8rpx;
   gap: 8rpx;

+ 92 - 0
cfc-frontend/scripts/d21-gut-flora.js

@@ -0,0 +1,92 @@
+#!/usr/bin/env node
+/**
+ * D21: gut-flora-detail.vue 肠道菌群详情页清理 (debt 60)
+ * script 9 个指标色收编 BrandColors;style 全局令牌 3 + 局部 Material Teal 色阶 6
+ */
+const fs = require('fs');
+const F = 'pages/health/gut-flora-detail.vue';
+let src = fs.readFileSync(F, 'utf8');
+let replaced = 0;
+
+// ---- 1. import ----
+if (!src.includes('utils/brand-colors.js')) {
+  src = src.replace(
+    "import HealthKnowledgePopup from '@/pages/health/components/health-knowledge-popup.vue'",
+    "import HealthKnowledgePopup from '@/pages/health/components/health-knowledge-popup.vue'\nimport { BrandColors } from '../../utils/brand-colors.js'"
+  );
+}
+
+// ---- 2. script 色值 ----
+const styleIdx = src.indexOf('<style');
+let scriptPart = src.slice(0, styleIdx);
+let stylePart = src.slice(styleIdx);
+
+const SCRIPT_MAP = [
+  ['#0EA5E9', 'BrandColors.infoSky'],
+  ['#10B981', 'BrandColors.success'],
+  ['#F59E0B', 'BrandColors.wealth'],
+  ['#FF8C42', 'BrandColors.body'],
+  ['#6366F1', 'BrandColors.wisdom'],
+  ['#FF6B9D', 'BrandColors.mind'],
+  ['#C62828', 'BrandColors.dangerStrong2'],
+];
+for (const [from, to] of SCRIPT_MAP) {
+  const pat = "'" + from + "'";
+  const cnt = scriptPart.split(pat).length - 1;
+  if (cnt === 0) console.warn('SCRIPT NOT FOUND:', from);
+  scriptPart = scriptPart.split(pat).join(to);
+  replaced += cnt;
+}
+
+// ---- 3. style 全局令牌 ----
+const GLOBAL = [
+  ['#FEF2F2', '$status-danger-tint-2'],
+  ['#FECACA', '$danger-line'],
+  ['#1976D2', '$mat-blue'],
+  ['#FFF8E1', '$mat-amber-tint'],
+  ['#A5D6A7', '$mat-green-soft'],
+];
+for (const [from, to] of GLOBAL) {
+  const re = new RegExp(from + '(?![0-9a-fA-F])', 'gi');
+  replaced += (stylePart.match(re) || []).length;
+  stylePart = stylePart.replace(re, to);
+}
+
+// ---- 4. style 局部 Material Teal 色阶 ----
+const LOCAL = [
+  ['#FFB300', '$c-gf-amber'],       // amber-700 提示条左边线
+  ['#795548', '$c-gf-brown'],       // brown-500 提示文字
+  ['#E0F2F1', '$c-gf-teal-bg'],     // teal-50 浅底
+  ['#00897B', '$c-gf-teal'],        // teal-600 主色
+  ['#00695C', '$c-gf-teal-deep'],   // teal-800 深档
+  ['#004D40', '$c-gf-teal-ink'],    // teal-900 深文字
+];
+for (const [from, to] of LOCAL) {
+  const re = new RegExp(from + '(?![0-9a-fA-F])', 'gi');
+  replaced += (stylePart.match(re) || []).length;
+  stylePart = stylePart.replace(re, to);
+}
+
+const palette = [
+  '// ===== 肠道菌群页专属色阶(Material Teal 提示色族;单页专用,约定见 uni.scss §14)=====',
+  '$c-gf-amber:     #FFB300; // amber-700 提示左边线',
+  '$c-gf-brown:     #795548; // brown-500 提示文字',
+  '$c-gf-teal-bg:   #E0F2F1; // teal-50 浅底',
+  '$c-gf-teal:      #00897B; // teal-600 主色',
+  '$c-gf-teal-deep: #00695C; // teal-800 深档',
+  '$c-gf-teal-ink:  #004D40; // teal-900 深文字',
+  ''
+].join('\n');
+stylePart = stylePart.replace(/(<style[^>]*>\s*\n)/, '$1' + palette + '\n');
+
+fs.writeFileSync(F, scriptPart + stylePart);
+console.log('total replaced:', replaced);
+
+const out = fs.readFileSync(F, 'utf8');
+const lines = out.split('\n');
+let n = 0;
+for (let i = 0; i < lines.length; i++) {
+  const L = lines[i].trim();
+  if (/#[0-9a-fA-F]{3,8}\b/.test(L) && L.charAt(0) !== '$') { console.log('HEX ' + (i + 1) + ': ' + L.slice(0, 100)); n++; }
+}
+console.log('remaining non-palette hex:', n);

+ 3 - 0
cfc-frontend/uni.scss

@@ -56,6 +56,8 @@ $mat-blue-tint:    #E3F2FD; // blue-50 极浅底(29 文件)
 $mat-blue-light:   #BBDEFB; // blue-100 浅档(4 文件)
 $mat-blue-light:   #BBDEFB; // blue-100 浅档(4 文件)
 $mat-blue-light-2: #64B5F6; // blue-300 亮档·副档(1 文件)
 $mat-blue-light-2: #64B5F6; // blue-300 亮档·副档(1 文件)
 $mat-blue-strong:  #1565C0; // blue-800 深文字(17 文件)
 $mat-blue-strong:  #1565C0; // blue-800 深文字(17 文件)
+$mat-blue:         #1976D2; // blue-700 主色(5 文件)
+$mat-green-soft:   #A5D6A7; // green-200 浅边线(3 文件)
 
 
 $uni-warning: #FFB74D;
 $uni-warning: #FFB74D;
 $uni-warning-light: #FFD54F;
 $uni-warning-light: #FFD54F;
@@ -582,6 +584,7 @@ $status-success-tint:  #ECFDF5; // emerald-50(11 文件;vs $status-success-s
 $status-info-tint:     #EFF6FF; // blue-50(3 文件)
 $status-info-tint:     #EFF6FF; // blue-50(3 文件)
 $status-danger-tint-2: #FEF2F2; // tailwind red-50(11 文件;vs $status-danger-tint #FFF5F5 自定义浅档)
 $status-danger-tint-2: #FEF2F2; // tailwind red-50(11 文件;vs $status-danger-tint #FFF5F5 自定义浅档)
 $facade-border-soft:   #DDD;    // 描边灰(46 文件)
 $facade-border-soft:   #DDD;    // 描边灰(46 文件)
+$danger-line:          #FECACA; // red-200 警示描边(5 文件)
 $app-ink-night:        #1A1A2E; // 深夜蓝黑(17 文件)
 $app-ink-night:        #1A1A2E; // 深夜蓝黑(17 文件)
 
 
 // ---- 封面渐变 / 提示条(B 批 articles 收敛时登记)----
 // ---- 封面渐变 / 提示条(B 批 articles 收敛时登记)----

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

@@ -80,6 +80,8 @@ export const BrandColors = {
   weatherSunny: '#FFB347',  // 晴朗心情色(情绪趋势天气板)
   weatherSunny: '#FFB347',  // 晴朗心情色(情绪趋势天气板)
   textGhost: '#CCC',        // $facade-text-ghost
   textGhost: '#CCC',        // $facade-text-ghost
   hairline: '#E0E0E0',      // $facade-hairline
   hairline: '#E0E0E0',      // $facade-hairline
+  infoSky: '#0EA5E9',       // sky-500($uni-info;肠道菌群指标色)
+  dangerStrong2: '#C62828', // red-800($status-danger-strong-2)
   fill: '#F0F0F0',          // $facade-fill
   fill: '#F0F0F0',          // $facade-fill
   fillGray100: '#F3F4F6',   // $facade-fill-gray-100
   fillGray100: '#F3F4F6',   // $facade-fill-gray-100
   goldDeep: '#FFA500',      // $accent-gold-deep(数据图标橙)
   goldDeep: '#FFA500',      // $accent-gold-deep(数据图标橙)