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

style(cfc-web): U5 收敛五维色映射到 colorTokens.js 单一出口,去除 #1677FF 硬编码

- 新建 src/utils/colorTokens.js:DIMENSION_COLORS(身/智/富/行/心)单一出口 +
  adminColor()(getComputedStyle 读 --adm-primary,供 canvas/echarts 使用)+ dimensionColor()
- DimensionWeightPicker / EnergyBehaviorConfig / ProfileManagement 的重复五维映射改引单一出口
- admin/Dashboard、admin/org/Dashboard 的 echarts itemStyle.color 与 color 数组改走 adminColor()/DIMENSION_COLORS
- EnergySandbox el-tag color prop 改 class 绑定 .tag-score-primary 走 var(--adm-primary)
- TeacherTeam 等级头像色、MbtiProfiles 页头图标色改走令牌
- 注释里的色值与 admin-tokens.css 令牌定义均未改动
E2E Test Bot 2 недель назад
Родитель
Сommit
029d4f29b9

+ 7 - 5
cfc-web/src/components/DimensionWeightPicker.vue

@@ -36,6 +36,8 @@
 </template>
 
 <script>
+import { DIMENSION_COLORS } from '@/utils/colorTokens'
+
 export default {
   name: 'DimensionWeightPicker',
   props: {
@@ -53,11 +55,11 @@ export default {
   data() {
     return {
       dimensions: [
-        { code: 'body', name: '身·土', color: '#FF8C42', currentValue: 20 },
-        { code: 'wisdom', name: '智·金', color: '#1677FF', currentValue: 20 },
-        { code: 'action', name: '行·木', color: '#10B981', currentValue: 20 },
-        { code: 'wealth', name: '富·水', color: '#F59E0B', currentValue: 20 },
-        { code: 'mind', name: '心·火', color: '#FF6B9D', currentValue: 20 }
+        { code: 'body', name: '身·土', color: DIMENSION_COLORS.body, currentValue: 20 },
+        { code: 'wisdom', name: '智·金', color: DIMENSION_COLORS.wisdom, currentValue: 20 },
+        { code: 'action', name: '行·木', color: DIMENSION_COLORS.action, currentValue: 20 },
+        { code: 'wealth', name: '富·水', color: DIMENSION_COLORS.wealth, currentValue: 20 },
+        { code: 'mind', name: '心·火', color: DIMENSION_COLORS.mind, currentValue: 20 }
       ],
       presets: [
         { label: '均衡', weights: { body: 20, wisdom: 20, action: 20, wealth: 20, mind: 20 } },

+ 77 - 0
cfc-web/src/utils/colorTokens.js

@@ -0,0 +1,77 @@
+/**
+ * 后台五维色彩映射 —— 品牌色单一出口(U5 批次收敛)
+ *
+ * 品牌色:身 #FF8C42 / 智 #1677FF / 富 #F59E0B / 行 #10B981 / 心 #FF6B9D
+ *
+ * 约定:
+ * 1. 页面不再各自重复定义五维色值,一律从本模块引用;
+ * 2. `--adm-primary` 等令牌的取值在 admin-tokens.css 中定义,本模块只读取不改动;
+ * 3. canvas / echarts 的 itemStyle.color、color 数组不解析 CSS 变量,
+ *    必须经 adminColor() 用 getComputedStyle 读取运行时令牌值;
+ * 4. 普通 DOM 样式仍优先写 `var(--adm-primary)`,不要为了统一样式而多绕一层 JS。
+ */
+
+/** 五维色彩映射(单一出口) */
+export const DIMENSION_COLORS = {
+  body: '#FF8C42', // 身
+  wisdom: '#1677FF', // 智
+  wealth: '#F59E0B', // 富
+  action: '#10B981', // 行
+  mind: '#FF6B9D' // 心
+}
+
+/** 后台语义令牌 → CSS 变量名 */
+const TOKEN_VAR_MAP = {
+  primary: '--adm-primary',
+  success: '--adm-success',
+  warning: '--adm-warning',
+  danger: '--adm-error',
+  error: '--adm-error',
+  info: '--adm-info'
+}
+
+/**
+ * 读取 :root 上的令牌值(canvas/echarts 不解析 CSS var,只能取实际色值)
+ * @param {String} varName CSS 变量名,如 '--adm-primary'
+ * @param {String} fallback 读取失败时的兜底色值
+ * @return {String} 去掉首尾空格后的色值
+ */
+function readCssVar(varName, fallback) {
+  if (typeof window === 'undefined' || typeof document === 'undefined' || !window.getComputedStyle) {
+    return fallback
+  }
+  const value = (window.getComputedStyle(document.documentElement).getPropertyValue(varName) || '').trim()
+  return value || fallback
+}
+
+/**
+ * 取后台令牌色值(品牌主色 / 语义色 / 五维色)
+ * @param {String} key 'primary'|'success'|'warning'|'danger'|'info',或五维 code(body/wisdom/wealth/action/mind)
+ * @return {String} 实际色值,未识别的 key 返回空串
+ */
+export function adminColor(key) {
+  if (!key) return ''
+  if (Object.prototype.hasOwnProperty.call(DIMENSION_COLORS, key)) return DIMENSION_COLORS[key]
+  const varName = TOKEN_VAR_MAP[key]
+  if (!varName) return ''
+  // primary 的兜底值与五维「智」同源(--adm-primary 即 #1677FF)
+  const fallback = key === 'primary' ? DIMENSION_COLORS.wisdom : ''
+  return readCssVar(varName, fallback)
+}
+
+/**
+ * 取五维色值,未命中时用调用方兜底值
+ * @param {String} code 五维 code
+ * @param {String} [fallback] 兜底色值(可传 CSS 变量)
+ * @return {String}
+ */
+export function dimensionColor(code, fallback) {
+  if (code && Object.prototype.hasOwnProperty.call(DIMENSION_COLORS, code)) return DIMENSION_COLORS[code]
+  return fallback || ''
+}
+
+export default {
+  DIMENSION_COLORS: DIMENSION_COLORS,
+  adminColor: adminColor,
+  dimensionColor: dimensionColor
+}

+ 3 - 2
cfc-web/src/views/admin/Dashboard.vue

@@ -149,6 +149,7 @@
 <script>
 import * as echarts from 'echarts'
 import { getDashboardStats, getRevenueStats, getMembershipStats, getTrendStats, getTrafficAnalytics } from '@/api/admin'
+import { adminColor } from '@/utils/colorTokens'
 
 export default {
   name: 'AdminDashboard',
@@ -325,7 +326,7 @@ export default {
         xAxis: { type: 'category', data: this.trafficDates, axisLabel: { rotate: 45, interval: 2, fontSize: 10 } },
         yAxis: { type: 'value' },
         series: [
-          { name: 'PV', type: 'bar', barWidth: '30%', data: this.pvData, itemStyle: { color: '#1677FF', borderRadius: [4, 4, 0, 0] } },
+          { name: 'PV', type: 'bar', barWidth: '30%', data: this.pvData, itemStyle: { color: adminColor('primary'), borderRadius: [4, 4, 0, 0] } },
           { name: 'UV', type: 'line', smooth: true, data: this.uvData, lineStyle: { color: '#52C41A', width: 2 }, itemStyle: { color: '#52C41A' } }
         ]
       })
@@ -346,7 +347,7 @@ export default {
           label: { show: false },
           emphasis: { label: { show: true, fontSize: 13, fontWeight: 'bold' } },
           data: this.sharePieData,
-          color: ['#F97316', '#1677FF', '#52C41A', '#8B5CF6', '#EC4899']
+          color: ['#F97316', adminColor('primary'), '#52C41A', '#8B5CF6', '#EC4899']
         }]
       })
     },

+ 6 - 5
cfc-web/src/views/admin/EnergyBehaviorConfig.vue

@@ -143,13 +143,14 @@
 <script>
 import SortMixin from '@/mixins/SortMixin'
 import { getEnergyBehaviorList, updateEnergyBehavior, toggleEnergyBehavior } from '@/api/energy'
+import { DIMENSION_COLORS } from '@/utils/colorTokens'
 
 const DIMENSION_MAP = {
-  body: { name: '身', color: '#FF8C42' },
-  mind: { name: '心', color: '#FF6B9D' },
-  wisdom: { name: '智', color: '#1677FF' },
-  action: { name: '行', color: '#10B981' },
-  wealth: { name: '富', color: '#F59E0B' }
+  body: { name: '身', color: DIMENSION_COLORS.body },
+  mind: { name: '心', color: DIMENSION_COLORS.mind },
+  wisdom: { name: '智', color: DIMENSION_COLORS.wisdom },
+  action: { name: '行', color: DIMENSION_COLORS.action },
+  wealth: { name: '富', color: DIMENSION_COLORS.wealth }
 }
 
 export default {

+ 9 - 2
cfc-web/src/views/admin/EnergySandbox.vue

@@ -71,7 +71,7 @@
         </el-table-column>
         <el-table-column prop="overallScore" label="综合" width="80" align="center">
           <template slot-scope="scope">
-            <el-tag size="small" color="#1677FF" effect="dark">{{ scope.row.overallScore != null ? scope.row.overallScore : '-' }}</el-tag>
+            <el-tag size="small" class="tag-score-primary" effect="dark">{{ scope.row.overallScore != null ? scope.row.overallScore : '-' }}</el-tag>
           </template>
         </el-table-column>
         <template slot="empty">
@@ -85,6 +85,7 @@
 
 <script>
 import { getFamilyEnergySandbox } from '@/api/energy'
+import { adminColor } from '@/utils/colorTokens'
 
 export default {
   name: 'EnergySandbox',
@@ -107,7 +108,7 @@ export default {
         { key: 'wisdomScore', label: '智', color: '#409EFF' },
         { key: 'wealthScore', label: '富', color: '#F0C929' },
         { key: 'actionScore', label: '行', color: '#E6A23C' },
-        { key: 'overallScore', label: '综合', color: '#1677FF' }
+        { key: 'overallScore', label: '综合', color: adminColor('primary') }
       ]
     }
   },
@@ -183,6 +184,12 @@ export default {
   text-align: center;
 }
 
+/* 综合分标签:走品牌主色 CSS 变量(el-tag color prop 只能收实际色值,故用 class 覆盖) */
+.tag-score-primary {
+  background-color: var(--adm-primary);
+  border-color: var(--adm-primary);
+}
+
 /* == C 批内联清理工具类 == */
 .filter-input-200 { width: 200px; }
 .table-full { width: 100%; }

+ 1 - 1
cfc-web/src/views/admin/MbtiProfiles.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="mbti-profiles admin-page">
     <el-card shadow="never">
-      <PageHeader slot="header" title="<i class=&quot;el-icon-user&quot; style=&quot;color: #1677FF; margin-right: 8px;&quot;></i>
+      <PageHeader slot="header" title="<i class=&quot;el-icon-user&quot; style=&quot;color: var(--adm-primary); margin-right: 8px;&quot;></i>
           MBTI 人格画像库(16型)">
         
         <div class="header-actions">

+ 2 - 2
cfc-web/src/views/admin/ProfileManagement.vue

@@ -118,6 +118,7 @@
 <script>
 import ListStateMixin from '@/mixins/ListStateMixin'
 import { getProfile, getProfileTrend } from '@/api/admin'
+import { dimensionColor } from '@/utils/colorTokens'
 
 export default {
   name: 'ProfileManagement',
@@ -175,8 +176,7 @@ export default {
       return m[dim] || dim
     },
     dimColor(dim) {
-      var m = { body: '#FF8C42', wisdom: '#1677FF', mind: '#FF6B9D', action: '#10B981', wealth: '#F59E0B' }
-      return m[dim] || 'var(--adm-text-45)'
+      return dimensionColor(dim, 'var(--adm-text-45)')
     },
     domainLabel(d) {
       var m = { sleep: '睡眠', attention: '注意力', emotion: '情绪' }

+ 10 - 9
cfc-web/src/views/admin/org/Dashboard.vue

@@ -93,6 +93,7 @@
 <script>
 import * as echarts from 'echarts'
 import { orgMy, orgStatsOverview, orgStatsFamilies, orgStatsActive, orgStatsRevenue, orgStatsTrend } from '@/api/org'
+import { adminColor, DIMENSION_COLORS } from '@/utils/colorTokens'
 
 export default {
   name: 'OrgDashboard',
@@ -206,9 +207,9 @@ export default {
         xAxis: { type: 'category', data: days, axisLabel: { interval: 0, rotate: 30 } },
         yAxis: { type: 'value' },
         series: [
-          { name: '任务完成', type: 'line', smooth: true, data: tasks, itemStyle: { color: '#1677FF' } },
-          { name: '打卡', type: 'line', smooth: true, data: checkins, itemStyle: { color: '#10B981' } },
-          { name: '报告上传', type: 'line', smooth: true, data: reports, itemStyle: { color: '#F59E0B' } }
+          { name: '任务完成', type: 'line', smooth: true, data: tasks, itemStyle: { color: adminColor('primary') } },
+          { name: '打卡', type: 'line', smooth: true, data: checkins, itemStyle: { color: DIMENSION_COLORS.action } },
+          { name: '报告上传', type: 'line', smooth: true, data: reports, itemStyle: { color: DIMENSION_COLORS.wealth } }
         ]
       })
     },
@@ -224,9 +225,9 @@ export default {
         xAxis: { type: 'category', data: days, axisLabel: { interval: 0, rotate: 30 } },
         yAxis: { type: 'value' },
         series: [
-          { name: '订单金额', type: 'bar', stack: 'total', data: orderAmt, itemStyle: { color: '#1677FF' } },
-          { name: '会员订阅', type: 'bar', stack: 'total', data: subAmt, itemStyle: { color: '#10B981' } },
-          { name: '佣金支出', type: 'bar', stack: 'total', data: commission, itemStyle: { color: '#F59E0B' } }
+          { name: '订单金额', type: 'bar', stack: 'total', data: orderAmt, itemStyle: { color: adminColor('primary') } },
+          { name: '会员订阅', type: 'bar', stack: 'total', data: subAmt, itemStyle: { color: DIMENSION_COLORS.action } },
+          { name: '佣金支出', type: 'bar', stack: 'total', data: commission, itemStyle: { color: DIMENSION_COLORS.wealth } }
         ]
       })
     },
@@ -245,9 +246,9 @@ export default {
           { type: 'value', name: '收入(元)', position: 'right' }
         ],
         series: [
-          { name: '活跃成员数', type: 'line', smooth: true, yAxisIndex: 0, data: active, itemStyle: { color: '#1677FF' } },
-          { name: '订单数', type: 'line', smooth: true, yAxisIndex: 0, data: orders, itemStyle: { color: '#10B981' } },
-          { name: '收入(元)', type: 'line', smooth: true, yAxisIndex: 1, data: income, itemStyle: { color: '#F59E0B' } }
+          { name: '活跃成员数', type: 'line', smooth: true, yAxisIndex: 0, data: active, itemStyle: { color: adminColor('primary') } },
+          { name: '订单数', type: 'line', smooth: true, yAxisIndex: 0, data: orders, itemStyle: { color: DIMENSION_COLORS.action } },
+          { name: '收入(元)', type: 'line', smooth: true, yAxisIndex: 1, data: income, itemStyle: { color: DIMENSION_COLORS.wealth } }
         ]
       })
     }

+ 2 - 1
cfc-web/src/views/teacher/TeacherTeam.vue

@@ -196,6 +196,7 @@
 <script>
 import SortMixin from '@/mixins/SortMixin'
 import { getTeamMembers, getTeamStats } from '@/api/guide'
+import { adminColor } from '@/utils/colorTokens'
 
 export default {
   mixins: [SortMixin],
@@ -306,7 +307,7 @@ export default {
     },
     getAvatarColor(level) {
       const colors = {
-        '初级': '#1677FF',
+        '初级': adminColor('primary'),
         '中级': '#52C41A',
         '高级': '#FAAD14'
       }