d18-emotion-trend.js 5.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env node
  2. /**
  3. * D18: emotion-trend.vue 情绪趋势页清理 (debt 69)
  4. *
  5. * 1) template 5 个 legend-step 内联 background -> class(SCSS 变量)
  6. * 2) script 天气色板/canvas 色收编 BrandColors + 补 key
  7. * 3) style 局部变量/全局映射
  8. */
  9. const fs = require('fs');
  10. const F = 'pages/mind-detail/emotion-trend.vue';
  11. let src = fs.readFileSync(F, 'utf8');
  12. let replaced = 0;
  13. function repl(from, to) {
  14. const cnt = src.split(from).length - 1;
  15. if (cnt === 0) { console.warn('NOT FOUND:', from.slice(0, 90)); return; }
  16. src = src.split(from).join(to);
  17. replaced += cnt;
  18. }
  19. // ---- 1. template legend-step 内联 -> 语义 class ----
  20. repl('<view class="legend-step" style="background:#FFE0E0"></view>', '<view class="legend-step legend-step-1"></view>');
  21. repl('<view class="legend-step" style="background:#FFB0B0"></view>', '<view class="legend-step legend-step-2"></view>');
  22. repl('<view class="legend-step" style="background:#FFD9A0"></view>', '<view class="legend-step legend-step-3"></view>');
  23. repl('<view class="legend-step" style="background:#C8E6C9"></view>', '<view class="legend-step legend-step-4"></view>');
  24. repl('<view class="legend-step" style="background:#81C784"></view>', '<view class="legend-step legend-step-5"></view>');
  25. // ---- 2. script 天气色板 / canvas ----
  26. repl("sunny: { icon: '\\u2600\\uFE0F', label: '心情很好', color: '#FFB347' }", "sunny: { icon: '\\u2600\\uFE0F', label: '心情很好', color: BrandColors.weatherSunny }");
  27. repl("cloudy: { icon: '\\u26C5', label: '一般般', color: '#A0A0A0' }", "cloudy: { icon: '\\u26C5', label: '一般般', color: BrandColors.emotionDisgust }");
  28. repl("rainy: { icon: '\\uD83C\\uDF27\\uFE0F', label: '有点难过', color: '#6B9BD2' }", "rainy: { icon: '\\uD83C\\uDF27\\uFE0F', label: '有点难过', color: BrandColors.emotionSadness }");
  29. repl("stormy: { icon: '\\u26A1', label: '很烦躁', color: '#8B5CF6' }", "stormy: { icon: '\\u26A1', label: '很烦躁', color: BrandColors.violet }");
  30. repl("rainbow: { icon: '\\uD83C\\uDF08', label: '特别开心', color: '#FF6B9D' }", "rainbow: { icon: '\\uD83C\\uDF08', label: '特别开心', color: BrandColors.mind }");
  31. repl("color: '#ccc' }", "color: BrandColors.textGhost }");
  32. repl("ctx.setStrokeStyle('#E0E0E0')", "ctx.setStrokeStyle(BrandColors.hairline)");
  33. repl("ctx.setFillStyle('#999')", "ctx.setFillStyle(BrandColors.textMuted)");
  34. repl("ctx.setStrokeStyle('#F0F0F0')", "ctx.setStrokeStyle(BrandColors.fill)");
  35. repl("var lineColor = avg >= 5 ? '#10B981' : '#FF6B9D'", "var lineColor = avg >= 5 ? BrandColors.success : BrandColors.mind");
  36. repl("color = '#10B981'", "color = BrandColors.success");
  37. repl("color = '#FFD93D'", "color = BrandColors.emotionJoy");
  38. repl("color = '#FF6B9D'", "color = BrandColors.mind");
  39. // ---- 3. import ----
  40. const hasImport = src.includes('utils/brand-colors.js');
  41. if (!hasImport) {
  42. const m = src.match(/<script>\r?\n/);
  43. if (m) src = src.replace(m[0], m[0] + "import { BrandColors } from '../../utils/brand-colors.js'\r\n");
  44. else console.warn('script tag not found');
  45. }
  46. // ---- 4. style ----
  47. const styleIdx = src.indexOf('<style');
  48. const before = src.slice(0, styleIdx);
  49. let styleBody = src.slice(styleIdx);
  50. styleBody = styleBody.replace(/#FF6B9D(?![0-9a-fA-F])/gi, '$dim-mind');
  51. styleBody = styleBody.replace(/#81C784(?![0-9a-fA-F])/gi, '$mat-green-light');
  52. const palette = [
  53. '// ===== 情绪趋势页专属色阶(热力图绿阶 + 画布近白;单页专用,约定见 uni.scss §14)=====',
  54. '$c-et-heat-1: #FFE0E0; // 热力档 1(最浅红)',
  55. '$c-et-heat-2: #FFB0B0; // 热力档 2(浅红)',
  56. '$c-et-heat-3: #FFD9A0; // 热力档 3(浅橙)',
  57. '$c-et-heat-4: #C8E6C9; // 热力档 4(浅绿)',
  58. '$c-et-heat-5: #81C784; // 热力档 5(中绿)',
  59. '$c-canvas-bg: #FCFCFC; // 画布近白',
  60. ''
  61. ].join('\n');
  62. styleBody = styleBody.replace(/(<style[^>]*>\s*\n)/, '$1' + palette + '\n');
  63. // legend-step 类(追加在局部调色板后)
  64. styleBody = styleBody.replace(
  65. /(<style[^>]*>\s*\n[^]*?<style[^>]*>)/,
  66. '$1'
  67. );
  68. // 直接在 style 开头 palette 后插入 legend-step 类
  69. styleBody = styleBody.replace(
  70. /(\$c-canvas-bg: #FCFCFC; \/\/ 画布近白\r?\n)/,
  71. '$1\n.legend-step-1 { background: $c-et-heat-1; }\n.legend-step-2 { background: $c-et-heat-2; }\n.legend-step-3 { background: $c-et-heat-3; }\n.legend-step-4 { background: $c-et-heat-4; }\n.legend-step-5 { background: $c-et-heat-5; }\n'
  72. );
  73. // style 内残留:$c-canvas-bg 声明本身保留;替换 style 里的 #FCFCFC
  74. styleBody = styleBody.replace(/#FCFCFC(?![0-9a-fA-F])/gi, '$c-canvas-bg');
  75. // 恢复声明行(避免变成 $c-canvas-bg: $c-canvas-bg)
  76. styleBody = styleBody.replace('$c-canvas-bg: $c-canvas-bg;', '$c-canvas-bg: #FCFCFC;');
  77. src = before + styleBody;
  78. fs.writeFileSync(F, src);
  79. console.log('total replaced:', replaced);
  80. const out = fs.readFileSync(F, 'utf8');
  81. const lines = out.split('\n');
  82. let n = 0;
  83. for (let i = 0; i < lines.length; i++) {
  84. const L = lines[i].trim();
  85. if (/#[0-9a-fA-F]{3,8}\b/.test(L) && L.charAt(0) !== '$') { console.log('HEX ' + (i + 1) + ': ' + L); n++; }
  86. }
  87. console.log('remaining non-palette hex:', n);