#!/usr/bin/env node /** * D41: 模板区剩余硬编码色收编 * * 覆盖三类模板硬编码: * A) 组件属性色值(RadarChart gridColor/labelColor、progress backgroundColor、switch color) * → 绑 data/computed(BrandColors) * B) 模板表达式字符串拼接里的 hex(';color:#fff'、conic-gradient(#F97316 …)) * → 拼接 BrandColors 值(data 属性) * C) placeholder-style / 兜底色字面量 → 绑定 data 字符串 * * 用法: node scripts/d41-template-hex-bind.js [--dry] */ const fs = require('fs'); const path = require('path'); const ROOT = path.resolve(__dirname, '..'); const DRY = process.argv.includes('--dry'); const IMPORT_LINE = "import { BrandColors } from '@/utils/brand-colors.js'"; /** * data: { 属性名: BrandColors 键 } —— 值以 BrandColors.<键> 注入 * raw: { 属性名: JS 表达式字符串 } —— 原样注入(用于拼接字符串) * replace: [[旧文本, 新文本], ...] —— 模板区精确替换(全局) */ const JOBS = [ { file: 'pages/action-detail/index.vue', data: { gridColor: 'emerald100', labelColor: 'emerald800' }, replace: [ ['gridColor="#D1FAE5"', ':gridColor="gridColor"'], ['labelColor="#065F46"', ':labelColor="labelColor"'], ], }, { file: 'pages/body-detail/index.vue', data: { gridColor: 'orange200', labelColor: 'orange800' }, replace: [ ['gridColor="#FED7AA"', ':gridColor="gridColor"'], ['labelColor="#9A3412"', ':labelColor="labelColor"'], ], }, { file: 'pages/member-detail/components/member-detail-sections/body-section.vue', data: { gridColor: 'orange200', labelColor: 'orange800' }, replace: [ ['gridColor="#FED7AA"', ':gridColor="gridColor"'], ['labelColor="#9A3412"', ':labelColor="labelColor"'], ], }, { file: 'pages/mind-detail/index.vue', data: { gridColor: 'pink100', labelColor: 'pink800' }, replace: [ ['gridColor="#FCE7F3"', ':gridColor="gridColor"'], ['labelColor="#9D174D"', ':labelColor="labelColor"'], ], }, { file: 'pages/wisdom-detail/index.vue', data: { gridColor: 'indigo100', labelColor: 'indigo800' }, replace: [ ['gridColor="#E0E7FF"', ':gridColor="gridColor"'], ['labelColor="#3730A3"', ':labelColor="labelColor"'], ], }, { file: 'pages/article-center/article-edit.vue', data: { whiteColor: 'white' }, replace: [["';color:#fff;border-color:'", "';color:' + whiteColor + ';border-color:'"]], }, { file: 'pages/article-center/index.vue', data: { whiteColor: 'white' }, replace: [["';color:#fff;border-color:'", "';color:' + whiteColor + ';border-color:'"]], }, { file: 'pages/mind-detail/articles.vue', data: { whiteColor: 'white' }, replace: [["';color:#fff'", "';color:' + whiteColor"]], }, { file: 'pages/growth/challenge-progress.vue', data: { ringColor: 'primary', ringTrack: 'fill' }, replace: [ ["'conic-gradient(#F97316 ' + progressPercent + '%, #f0f0f0 ' + progressPercent + '%)'", "'conic-gradient(' + ringColor + ' ' + progressPercent + '%, ' + ringTrack + ' ' + progressPercent + '%)'"], ], }, { file: 'pages/activity/create.vue', data: { paleColor: 'primaryPale' }, replace: [["tpl.lightColor || '#FFF7ED'", 'tpl.lightColor || paleColor']], }, { file: 'pages/child/rewards.vue', data: { trackColor: 'hairline2' }, replace: [['backgroundColor="#eee"', ':backgroundColor="trackColor"']], }, { file: 'pages/rewards/rewards.vue', data: { trackColor: 'hairline2' }, replace: [['backgroundColor="#eee"', ':backgroundColor="trackColor"']], }, { file: 'pages/shop/consignee-edit/consignee-edit.vue', data: { switchColor: 'indigoPeriwinkle' }, replace: [['color="#667eea"', ':color="switchColor"']], }, { file: 'pages/shop/address-edit/address-edit.vue', raw: { placeholderStyle: "'color:' + BrandColors.textGhost + '; font-size: 28rpx;'" }, replace: [['placeholder-style="color: #ccc; font-size: 28rpx;"', ':placeholder-style="placeholderStyle"']], }, { file: 'pages/shop/checkout/checkout.vue', raw: { placeholderStyle: "'color:' + BrandColors.textGhost + '; font-size: 26rpx;'" }, replace: [['placeholder-style="color: #ccc; font-size: 26rpx;"', ':placeholder-style="placeholderStyle"']], }, { file: 'pages/diet/index.vue', raw: { placeholderStyle: "'color:' + BrandColors.textHint" }, replace: [['placeholder-style="color:#bbb"', ':placeholder-style="placeholderStyle"']], }, ]; const stats = []; for (const job of JOBS) { const abs = path.join(ROOT, job.file); if (!fs.existsSync(abs)) { console.log('SKIP(not found): ' + job.file); continue; } let src = fs.readFileSync(abs, 'utf8'); const eol = src.includes('\r\n') ? '\r\n' : '\n'; const scriptStart = src.search(/^