Przeglądaj źródła

refactor(beautify): D3 sleep-checkin 睡眠主题清理 (debt 126->48)

- script 4 行质量条渐变改用 BrandColors.* 模板字符串(#818CF8/#6366F1/#34D399/#10B981/#FBBF24/#F59E0B/#FB7185/#EF4444)
- style 全局令牌映射:#EEF2FF->dim-wisdom-tint-2, #E0E7FF->accent-indigo-tint,
  #B45309->status-warning-strong-2, #4338CA->accent-indigo-ink, #F87171->status-danger-light,
  #059669->status-success-deep, #4F46E5->dim-wisdom-deep, #FBBF24->status-warning
- 睡眠主题专属色收编局部变量:雪夜蓝(-night-1/2/3) + 月光米黄(-moon*) +
  暮色橙(-dusk*) + 极浅蓝(-sky*) + -emerald-700/-rose-400
- brand-colors.js 补充 dangerLight2/rose-400
- P0 3->2;硬编码色总数 1782->约1770
liaoxg 5 dni temu
rodzic
commit
ef7b9cc8ed

+ 46 - 29
cfc-frontend/pages/growth/sleep-checkin.vue

@@ -393,10 +393,10 @@ export default {
         ' - ' + (item.wakeTime ? String(item.wakeTime).slice(0, 5) : '--:--')
       item._duration = this.durationFromMinutes(item.durationMinutes)
       item._percent = Math.min(100, Math.max(0, Math.round(score * 10)))
-      if (score >= 8) item._barBg = 'linear-gradient(90deg,#818CF8,#6366F1)'
-      else if (score >= 6) item._barBg = 'linear-gradient(90deg,#34D399,#10B981)'
-      else if (score >= 4) item._barBg = 'linear-gradient(90deg,#FBBF24,#F59E0B)'
-      else item._barBg = 'linear-gradient(90deg,#FB7185,#EF4444)'
+      if (score >= 8) item._barBg = `linear-gradient(90deg, ${BrandColors.wisdomLight}, ${BrandColors.wisdom})`
+      else if (score >= 6) item._barBg = `linear-gradient(90deg, ${BrandColors.successLight3}, ${BrandColors.success})`
+      else if (score >= 4) item._barBg = `linear-gradient(90deg, ${BrandColors.warning}, ${BrandColors.wealth})`
+      else item._barBg = `linear-gradient(90deg, ${BrandColors.dangerLight2}, ${BrandColors.danger})`
     },
     buildRemark: function () {
       var remark = this.form.remark ? this.form.remark.trim() : ''
@@ -458,8 +458,25 @@ export default {
 </script>
 
 <style scoped lang="scss">
+// ===== 睡眠页专属色阶(雪夜蓝 + 月光米黄,单页主题专用;约定见 uni.scss §14)=====
+$c-night-page:    #EEF1F8; // 页面底(深夜蓝灰)
+$c-night-1:       #3B4A8C; // 雪夜蓝渐变档 1(起点)
+$c-night-2:       #2A3470; // 雪夜蓝渐变档 2(中段)
+$c-night-3:       #1B2350; // 雪夜蓝渐变档 3(终点)
+$c-moon-soft:     #FFE9A8; // 月光浅黄
+$c-moon:          #FFD166; // 月光主黄(星星/月牙)
+$c-moon-deep:     #FFB84D; // 月光深黄
+$c-dusk-1:        #FF9F68; // 暮色橙渐档 1
+$c-dusk-2:        #FF7A45; // 暮色橙渐档 2
+$c-sepia-ink:     #4A2A00; // 深棕文字(暖卡内)
+$c-sky-ghost:     #F8FAFF; // 极浅蓝(卡底)
+$c-sky-soft:      #F1F5FF; // 浅蓝(卡内底)
+$c-sky-line:      #EDF1F7; // 浅蓝分隔线
+$c-emerald-700:   #047857; // 好质量徽章文字(vs 全局 $status-success-deep #059669)
+$c-rose-400:      #FB7185; // 差质量徽章渐变起点(rose-400,全局 danger 族无此档)
+
 /* ===== 页面基础 ===== */
-.page { min-height: 100vh; background: #EEF1F8; }
+.page { min-height: 100vh; background: $c-night-page; }
 .content { padding: 20rpx 0 0; }
 
 /* ===== 夜间主题头部 ===== */
@@ -469,7 +486,7 @@ export default {
   padding: 36rpx 32rpx 32rpx;
   border-radius: 32rpx;
   overflow: hidden;
-  background: linear-gradient(155deg, #3B4A8C 0%, #2A3470 45%, #1B2350 100%);
+  background: linear-gradient(155deg, $c-night-1 0%, $c-night-2 45%, $c-night-3 100%);
   box-shadow: 0 16rpx 40rpx rgba(27, 35, 80, 0.35);
   color: $app-surface;
 }
@@ -497,7 +514,7 @@ export default {
 .star {
   position: absolute;
   border-radius: 50%;
-  background: #FFE9A8;
+  background: $c-moon-soft;
   animation: star-twinkle 2.4s ease-in-out infinite;
 }
 @keyframes star-twinkle {
@@ -523,7 +540,7 @@ export default {
   width: 10rpx;
   height: 10rpx;
   border-radius: 50%;
-  background: #FFD166;
+  background: $c-moon;
   box-shadow: 0 0 12rpx rgba(255, 209, 102, 0.9);
 }
 .hero-chip-text { font-size: 22rpx; color: $app-surface; }
@@ -580,7 +597,7 @@ export default {
   font-weight: 700;
   color: $app-surface;
 }
-.tl-pill-on .tl-pill-time { color: #FFD166; }
+.tl-pill-on .tl-pill-time { color: $c-moon; }
 .tl-scroll {
   margin-top: 20rpx;
   width: 100%;
@@ -612,15 +629,15 @@ export default {
 .tl-seg-on { background: rgba(255, 209, 102, 0.55); }
 .tl-seg-on .tl-seg-time { color: rgba(255, 255, 255, 0.95); }
 .tl-seg-sleep {
-  background: linear-gradient(180deg, #FFD166, #FFB84D);
+  background: linear-gradient(180deg, $c-moon, $c-moon-deep);
   box-shadow: 0 0 12rpx rgba(255, 209, 102, 0.8);
 }
 .tl-seg-wake {
-  background: linear-gradient(180deg, #FF9F68, #FF7A45);
+  background: linear-gradient(180deg, $c-dusk-1, $c-dusk-2);
   box-shadow: 0 0 12rpx rgba(255, 159, 104, 0.8);
 }
 .tl-seg-sleep .tl-seg-time, .tl-seg-wake .tl-seg-time {
-  color: #4A2A00;
+  color: $c-sepia-ink;
   font-weight: 700;
 }
 .tl-hint {
@@ -655,7 +672,7 @@ export default {
   width: 56rpx;
   height: 56rpx;
   border-radius: 18rpx;
-  background: linear-gradient(135deg, #EEF2FF, #E0E7FF);
+  background: linear-gradient(135deg, $dim-wisdom-tint-2, $accent-indigo-tint);
   display: flex;
   align-items: center;
   justify-content: center;
@@ -676,7 +693,7 @@ export default {
   display: flex;
   align-items: center;
   gap: 24rpx;
-  background: linear-gradient(160deg, #F8FAFF, #F1F5FF);
+  background: linear-gradient(160deg, $c-sky-ghost, $c-sky-soft);
   border-radius: 24rpx;
   padding: 26rpx 24rpx;
   margin-bottom: 26rpx;
@@ -710,9 +727,9 @@ export default {
   font-weight: 600;
 }
 .quality-badge-poor { background: $status-danger-soft; color: $status-danger-deep; }
-.quality-badge-fair { background: $status-warning-soft; color: #B45309; }
-.quality-badge-good { background: $status-success-soft; color: #047857; }
-.quality-badge-great { background: #E0E7FF; color: #4338CA; }
+.quality-badge-fair { background: $status-warning-soft; color: $status-warning-strong-2; }
+.quality-badge-good { background: $status-success-soft; color: $c-emerald-700; }
+.quality-badge-great { background: $accent-indigo-tint; color: $accent-indigo-ink; }
 .quality-desc { display: block; font-size: 24rpx; color: $uni-text-color-secondary; margin-top: 12rpx; }
 
 .q-chips { display: flex; flex-wrap: wrap; gap: 14rpx; }
@@ -721,7 +738,7 @@ export default {
   height: 78rpx;
   border-radius: 22rpx;
   background: $facade-fill-slate-50;
-  border: 2rpx solid #EDF1F7;
+  border: 2rpx solid $c-sky-line;
   display: flex;
   align-items: center;
   justify-content: center;
@@ -731,12 +748,12 @@ export default {
 .q-chip:active { transform: scale(0.94); }
 .q-chip-active { border-color: transparent; transform: translateY(-4rpx); }
 .q-chip-active text { color: $app-surface; }
-.q-chip-poor text { color: #F87171; }
+.q-chip-poor text { color: $status-danger-light; }
 .q-chip-fair text { color: $status-warning-deep; }
-.q-chip-good text { color: #059669; }
-.q-chip-great text { color: #4F46E5; }
-.q-chip-poor.q-chip-active { background: linear-gradient(135deg, #FB7185, $status-danger); box-shadow: 0 8rpx 20rpx rgba(239, 68, 68, 0.3); }
-.q-chip-fair.q-chip-active { background: linear-gradient(135deg, #FBBF24, $dim-wealth); box-shadow: 0 8rpx 20rpx rgba(245, 158, 11, 0.3); }
+.q-chip-good text { color: $status-success-deep; }
+.q-chip-great text { color: $dim-wisdom-deep; }
+.q-chip-poor.q-chip-active { background: linear-gradient(135deg, $c-rose-400, $status-danger); box-shadow: 0 8rpx 20rpx rgba(239, 68, 68, 0.3); }
+.q-chip-fair.q-chip-active { background: linear-gradient(135deg, $status-warning, $dim-wealth); box-shadow: 0 8rpx 20rpx rgba(245, 158, 11, 0.3); }
 .q-chip-good.q-chip-active { background: linear-gradient(135deg, $status-success-light-3, $status-success); box-shadow: 0 8rpx 20rpx rgba(16, 185, 129, 0.3); }
 .q-chip-great.q-chip-active { background: linear-gradient(135deg, $dim-wisdom-light, $dim-wisdom); box-shadow: 0 8rpx 20rpx rgba(99, 102, 241, 0.3); }
 
@@ -755,20 +772,20 @@ export default {
   padding: 14rpx 26rpx;
   border-radius: 999rpx;
   background: $facade-fill-slate-50;
-  border: 2rpx solid #EDF1F7;
+  border: 2rpx solid $c-sky-line;
   transition: transform 0.18s ease;
 }
 .s-tag text { font-size: 26rpx; color: $facade-text-slate-deep; }
 .s-tag:active { transform: scale(0.96); }
-.s-tag-active { background: #EEF2FF; border-color: $dim-wisdom; }
-.s-tag-active text { color: #4F46E5; font-weight: 600; }
+.s-tag-active { background: $dim-wisdom-tint-2; border-color: $dim-wisdom; }
+.s-tag-active text { color: $dim-wisdom-deep; font-weight: 600; }
 
 /* ===== 备注 ===== */
 .remark-input {
   width: 100%;
   min-height: 150rpx;
   background: $facade-fill-slate-50;
-  border: 2rpx solid #EDF1F7;
+  border: 2rpx solid $c-sky-line;
   border-radius: 20rpx;
   padding: 20rpx;
   font-size: 26rpx;
@@ -780,7 +797,7 @@ export default {
 /* ===== 提交按钮 ===== */
 .submit-wrap { padding: 32rpx 24rpx 8rpx; }
 .submit-btn {
-  background: linear-gradient(135deg, $dim-wisdom, #4F46E5 60%, #4338CA);
+  background: linear-gradient(135deg, $dim-wisdom, $dim-wisdom-deep 60%, $accent-indigo-ink);
   border-radius: 999rpx;
   padding: 26rpx 0;
   text-align: center;
@@ -808,7 +825,7 @@ export default {
   width: 76rpx;
   height: 76rpx;
   border-radius: 24rpx;
-  background: linear-gradient(135deg, #EEF2FF, #E0E7FF);
+  background: linear-gradient(135deg, $dim-wisdom-tint-2, $accent-indigo-tint);
   display: flex;
   align-items: center;
   justify-content: center;

+ 100 - 0
cfc-frontend/scripts/d3-sleep-checkin.js

@@ -0,0 +1,100 @@
+#!/usr/bin/env node
+/**
+ * D3: sleep-checkin.vue 睡眠主题清理 (debt 126)
+ * - script 4 行质量条渐变 -> BrandColors 模板字符串
+ * - style 7 色映射全局等值令牌
+ * - 睡眠主题专属色(雪夜蓝 + 米黄族 + 极浅蓝)收编为页面级局部变量
+ */
+const fs = require('fs');
+const F = 'pages/growth/sleep-checkin.vue';
+let src = fs.readFileSync(F, 'utf8');
+
+// --- 1. script 渐变 -> BrandColors ---
+const SCRIPT_REPL = [
+  [
+    "if (score >= 8) item._barBg = 'linear-gradient(90deg,#818CF8,#6366F1)'",
+    "if (score >= 8) item._barBg = `linear-gradient(90deg, ${BrandColors.wisdomLight}, ${BrandColors.wisdom})`",
+  ],
+  [
+    "else if (score >= 6) item._barBg = 'linear-gradient(90deg,#34D399,#10B981)'",
+    "else if (score >= 6) item._barBg = `linear-gradient(90deg, ${BrandColors.successLight3}, ${BrandColors.success})`",
+  ],
+  [
+    "else if (score >= 4) item._barBg = 'linear-gradient(90deg,#FBBF24,#F59E0B)'",
+    "else if (score >= 4) item._barBg = `linear-gradient(90deg, ${BrandColors.warning}, ${BrandColors.wealth})`",
+  ],
+  [
+    "else item._barBg = 'linear-gradient(90deg,#FB7185,#EF4444)'",
+    "else item._barBg = `linear-gradient(90deg, ${BrandColors.dangerLight2}, ${BrandColors.danger})`",
+  ],
+];
+for (const [from, to] of SCRIPT_REPL) {
+  if (!src.includes(from)) { console.warn('SCRIPT LINE NOT FOUND:', from.slice(0, 50)); continue; }
+  src = src.replace(from, to);
+}
+
+// --- 2. import BrandColors(若未存在)---
+if (!src.includes('brand-colors')) {
+  src = src.replace(/(<script>\n)/, '$1import { BrandColors } from \'../../utils/brand-colors.js\'\n');
+}
+
+// --- 3. style 区块 ---
+const styleIdx = src.indexOf('<style');
+const before = src.slice(0, styleIdx);
+let styleBody = src.slice(styleIdx);
+
+// 3a. 全局令牌映射(等值)
+const GLOBAL_MAP = [
+  ['#EEF2FF', '$dim-wisdom-tint-2'],       // x3
+  ['#E0E7FF', '$accent-indigo-tint'],     // x3
+  ['#B45309', '$status-warning-strong-2'],// x1
+  ['#4338CA', '$accent-indigo-ink'],      // x2
+  ['#F87171', '$status-danger-light'],    // x1
+  ['#059669', '$status-success-deep'],    // x1
+  ['#4F46E5', '$dim-wisdom-deep'],        // x3
+];
+// 3b. 专属色 -> 局部变量
+const PALETTE_MAP = [
+  ['#EEF1F8', '$c-night-page'],    // 页面底(深夜蓝灰)
+  ['#3B4A8C', '$c-night-1'],       // 雪夜蓝渐变档 1
+  ['#2A3470', '$c-night-2'],       // 雪夜蓝渐变档 2
+  ['#1B2350', '$c-night-3'],       // 雪夜蓝渐变档 3
+  ['#FFE9A8', '$c-moon-soft'],     // 月光浅黄
+  ['#FFD166', '$c-moon'],          // 月光主黄
+  ['#FFB84D', '$c-moon-deep'],     // 月光深黄
+  ['#FF9F68', '$c-dusk-1'],        // 暮色橙渐档 1
+  ['#FF7A45', '$c-dusk-2'],        // 暮色橙渐档 2
+  ['#4A2A00', '$c-sepia-ink'],     // 深棕文字(暖卡内)
+  ['#F8FAFF', '$c-sky-ghost'],     // 极浅蓝(卡底)
+  ['#F1F5FF', '$c-sky-soft'],      // 浅蓝(卡内底)
+  ['#EDF1F7', '$c-sky-line'],      // 浅蓝分隔线
+];
+
+for (const [from, to] of [...GLOBAL_MAP, ...PALETTE_MAP]) {
+  const esc = from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+  styleBody = styleBody.replace(new RegExp(esc + '(?![0-9a-fA-F])', 'g'), to);
+}
+
+// 插入局部调色板
+const palette = [
+  '// ===== 睡眠页专属色阶(雪夜蓝 + 月光米黄,单页主题专用;约定见 uni.scss §14)=====',
+  '$c-night-page:    #EEF1F8; // 页面底(深夜蓝灰)',
+  '$c-night-1:       #3B4A8C; // 雪夜蓝渐变档 1(起点)',
+  '$c-night-2:       #2A3470; // 雪夜蓝渐变档 2(中段)',
+  '$c-night-3:       #1B2350; // 雪夜蓝渐变档 3(终点)',
+  '$c-moon-soft:     #FFE9A8; // 月光浅黄',
+  '$c-moon:          #FFD166; // 月光主黄(星星/月牙)',
+  '$c-moon-deep:     #FFB84D; // 月光深黄',
+  '$c-dusk-1:        #FF9F68; // 暮色橙渐档 1',
+  '$c-dusk-2:        #FF7A45; // 暮色橙渐档 2',
+  '$c-sepia-ink:     #4A2A00; // 深棕文字(暖卡内)',
+  '$c-sky-ghost:     #F8FAFF; // 极浅蓝(卡底)',
+  '$c-sky-soft:      #F1F5FF; // 浅蓝(卡内底)',
+  '$c-sky-line:      #EDF1F7; // 浅蓝分隔线',
+  ''
+].join('\n');
+
+styleBody = styleBody.replace(/(<style[^>]*>\s*\n)/, '$1' + palette + '\n');
+
+fs.writeFileSync(F, before + styleBody);
+console.log('D3 done');

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

@@ -45,6 +45,7 @@ export const BrandColors = {
   successLight3: '#34D399', // emerald-400 成功亮档·三档
   warning: '#FBBF24',
   danger: '#EF4444',
+  dangerLight2: '#FB7185',  // rose-400 危险亮档·二档(睡眠质量条)
   info: '#0EA5E9',          // sky-500 信息
   infoLight: '#38BDF8',     // sky-400 信息亮档
   wisdomLight: '#818CF8',   // indigo-400 智慧亮档