#!/usr/bin/env node /** * D31: script 段维度色批量收编 BrandColors * 只替换「整段字符串就是 hex」的写法('#10B981' / "#10B981"),避免破坏模板字符串/渐变拼接。 * 自动按文件深度计算相对 import 路径;已 import 的文件不重复注入。 * * 用法: node scripts/d31-script-hex-harvest.js [--dry] */ const fs = require('fs'); const path = require('path'); const ROOT = path.resolve(__dirname, '..'); const DRY = process.argv.includes('--dry'); const EXCLUDE_DIRS = new Set(['node_modules', 'dist', 'unpackage', '.git', 'scripts', '.tmp_equiv']); // hex -> BrandColors key(仅登记已存在于 utils/brand-colors.js 的键) const MAP = { '#10B981': 'success', '#F59E0B': 'wealth', '#FF6B9D': 'mind', '#FF8C42': 'body', '#F97316': 'primary', '#6366F1': 'wisdom', '#FFFFFF': 'white', '#3B82F6': 'infoBlue', '#EF4444': 'danger', '#94A3B8': 'appTextSubtle', '#8B5CF6': 'violet', '#EA580C': 'orangeDeep', '#0EA5E9': 'infoSky', '#EC4899': 'pink', '#6B7280': 'textSlate', '#4CAF50': 'matGreen', '#FF6B35': 'mindAccent', '#8D6E63': 'brownWarm', // ---- D40:跨文件重复的 script 色值(≥2 处)---- '#A8A29E': 'stone400', '#64748B': 'slate500', '#444444': 'textDeep', '#444': 'textDeep', '#FFFBEB': 'amber50', '#1E293B': 'slate800', '#78716C': 'stone500', '#E7E5E4': 'stone200', '#999999': 'textMuted', '#999': 'textMuted', '#ECFDF5': 'emerald50', '#06B6D4': 'cyan500', '#1C1917': 'stone900', '#CBD5E1': 'slate300', '#475569': 'slate600', '#F56C6C': 'elementDanger', '#C0C0C0': 'silver', '#FFF0F5': 'mindTint', '#4F46E5': 'indigo600', '#EEF2FF': 'indigo50', '#DB2777': 'pink600', '#FDF2F8': 'pink50', '#F5F5F4': 'stone100', '#000000': 'black', '#4A5568': 'gray700', '#FFB74D': 'orange300', '#E2E8F0': 'slate200', '#EEF2F7': 'slateGhost', '#667EEA': 'indigoPeriwinkle', '#FFF': 'white', '#FFFFFF': 'white', '#F3E5F5': 'tintPurpleSoft', '#FFF3E0': 'tintOrangeSoft', '#E8F5E9': 'tintGreenSoft', '#FCE4EC': 'tintPinkSoft', }; const bcSrc = fs.readFileSync(path.join(ROOT, 'utils/brand-colors.js'), 'utf8'); for (const key of Object.values(MAP)) { if (!new RegExp('^\\s*' + key + ':', 'm').test(bcSrc)) { console.error('缺少 BrandColors 键: ' + key); process.exit(1); } } function walk(dir, out = []) { for (const name of fs.readdirSync(dir)) { if (EXCLUDE_DIRS.has(name)) continue; const p = path.join(dir, name); const st = fs.statSync(p); if (st.isDirectory()) walk(p, out); else if (name.endsWith('.vue')) out.push(p); } return out; } const files = walk(ROOT); let changedFiles = 0; let replacements = 0; const log = []; for (const abs of files) { const src = fs.readFileSync(abs, 'utf8'); const styleIdx = src.search(/