Files
drawlogo/_design-test/apply-vue-colors.js
T

136 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 甄房换肤 · WEB 业务层替换器
// 用法: node _design-test/apply-vue-colors.js (预演,报告每条规则的命中数)
// node _design-test/apply-vue-colors.js --write (真写)
//
// 为什么不能只做单色 1:1 替换:
// 1) ECharts 的 10 色分类色板若逐色映射,会与已有的 #3b82f6 / #ef4444 撞色,序列失去区分度
// 2) 同一个渐变串 linear-gradient(135deg,#f08060,#d9481c) 同时用于「房源等级 A」和「客源热度 H」,
// 但 A 现在要改成品牌金、H 仍是红 —— 必须按选择器区分
// 所以规则分两类:先按「选择器/整串」精确处理,再对剩余单色做通用映射。
const fs = require('fs');
const path = require('path');
const WRITE = process.argv.includes('--write');
// 两个前端:WEB(ruoyi-ui)与 H5(zhenfang-uni)
const ROOTS = [
{ root: 'e:/KF_7/ZhenOS-ZF/ruoyi-ui/src', skip: new Set(['assets/styles']) },
{ root: 'e:/KF_7/ZhenOS-ZF/zhenfang-uni/src', skip: new Set() }
];
const EXT = new Set(['.vue', '.js', '.ts', '.html']);
// ── 新的 10 色分类色板(Fiori 官方 Category/Accent 色 + 品牌金,色相拉开 + 明度错位)──
const PALETTE10 = ['#0057D2', '#E76500', '#188918', '#DF1278', '#07838F', '#D27700', '#7858FF', '#D20A0A', '#5B738B', '#C6A15B'];
const OLD10 = ['#ff7a1a', '#2e9e5b', '#ffb31a', '#f08060', '#0F766E', '#756a5e', '#7c3aed', '#14B8A6', '#ef4444', '#3b82f6'];
const OLD6 = ['#ff7a1a', '#2e9e5b', '#ffb31a', '#f08060', '#0F766E', '#756a5e'];
const arr = a => '[' + a.map(c => "'" + c + "'").join(', ') + ']';
// ── 规则(按顺序执行)──
const RULES = [
// 1. 图表 10 色分类色板(4 处)
['图表色板 · 10 色', arr(OLD10).replace(/'/g, "'"), arr(PALETTE10), 'literal'],
// 2. 图表 6 色(1 处)
['图表色板 · 6 色', arr(OLD6).replace(/'/g, "'"), arr(PALETTE10.slice(0, 6)), 'literal'],
// 3. 房源等级 A → 品牌金
['等级 A 渐变 → 品牌金', /(&\.level-A\s*\{[^}]*?linear-gradient\()135deg,\s*#f08060,\s*#d9481c/g,
'$1135deg, #E3CB99, #C6A15B', 'regex'],
// 4. 客源热度 H(热)→ 保留红系
['热度 H 渐变 → 红', /(&\.level-H\s*\{[^}]*?linear-gradient\()135deg,\s*#f08060,\s*#d9481c/g,
'$1135deg, #E06B6B, #AA0808', 'regex'],
// 5. 等级 B → 警告橙
['等级 B 渐变 → 橙', /(&\.level-B\s*\{[^}]*?linear-gradient\()135deg,\s*#FBBF24,\s*#ffb31a/g,
'$1135deg, #D27700, #E76500', 'regex'],
// 6. 等级 C → 中性
['等级 C 渐变 → 中性', /(&\.level-C\s*\{[^}]*?linear-gradient\()135deg,\s*#9a8e80,\s*#756a5e/g,
'$1135deg, #A9B4BE, #788FA6', 'regex'],
// 7. 统计卡 warning 渐变
['warning 渐变', /linear-gradient\((90|135)deg,\s*#ffb31a,\s*#FBBF24\)/g,
'linear-gradient($1deg, #E76500, #D27700)', 'regex'],
// 8. 统计卡 danger 渐变
['danger 渐变', /linear-gradient\((90|135)deg,\s*#f08060,\s*#ef4444\)/g,
'linear-gradient($1deg, #E76500, #D20A0A)', 'regex'],
// 9. el-rate 星级(单一琥珀色 ×3)
['星级 · 单色', "['#ffb31a', '#ffb31a', '#ffb31a']", "['#D27700', '#D27700', '#D27700']", 'literal'],
['星级 · 同色系', "['#2e9e5b', '#2e9e5b', '#2e9e5b']", "['#188918', '#188918', '#188918']", 'literal'],
// 10. el-rate 五档评价(差→极佳)
['评价五档', "['#d9481c', '#ffb31a', '#FBBF24', '#ff7a1a', '#2e9e5b']",
"['#D20A0A', '#E76500', '#D27700', '#C6A15B', '#188918']", 'literal'],
// 11. ThemePicker 预置色
['主题预置色', "['#ff7a1a', '#ff8a3d', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]",
"['#0070F2', '#4D9BF6', '#0C2340','#131E29','#188918', '#07838F', '#7858FF', '#D20A0A', ]", 'literal'],
// 12. rgb()/rgba() 三元组(保留 rgb/rgba 与后面的 alpha)
['rgb 三元组 · 橙', /(rgba?)\(\s*255,\s*122,\s*26\b/g, '$1(0, 112, 242', 'regex'],
['rgb 三元组 · 浅橙', /(rgba?)\(\s*255,\s*138,\s*61\b/g, '$1(77, 155, 246', 'regex'],
['rgb 三元组 · 琥珀', /(rgba?)\(\s*255,\s*179,\s*26\b/g, '$1(231, 101, 0', 'regex'],
['rgb 三元组 · 亮琥珀', /(rgba?)\(\s*251,\s*191,\s*36\b/g, '$1(210, 119, 0', 'regex'],
['rgb 三元组 · 暖墨', /(rgba?)\(\s*42,\s*33,\s*24\b/g, '$1(19, 30, 41', 'regex']
];
// ── 通用单色映射(处理剩余的所有字面量)──
const GENERIC = [
['#ff7a1a', '#0070F2'], ['#e86a0c', '#0064D9'], ['#d96408', '#0057D2'],
['#ff8a3d', '#4D9BF6'], ['#ffc48a', '#A6CFFF'], ['#ffe8d1', '#EBF8FF'], ['#fff6ec', '#F0F6FE'],
['#f6ead8', '#EAECEE'], ['#faf7f2', '#F5F6F7'], ['#fbf5ea', '#F5F6F7'],
['#e9d3b0', '#758CA4'], ['#efe7dc', '#E5E5E5'],
['#2a2118', '#131E29'], ['#3a322a', '#556B82'], ['#756a5e', '#5F7590'],
['#9a8e80', '#5F7590'], ['#8a7f73', '#758CA4'], ['#b8ac9e', '#A9B4BE'], ['#c9beb0', '#BBC1CA'],
['#ffb31a', '#E76500'], ['#fff6e0', '#FDF1E8'],
['#d9481c', '#AA0808'], ['#fdeee8', '#FBF0F0'],
['#2e9e5b', '#256F3A'], ['#ecf7f0', '#F1F7F3'], ['#1f8a5b', '#256F3A'], ['#ea580c', '#B44F00'],
['#f08060', '#D98A8A'], ['#fbbf24', '#D27700'],
['#2f2820', '#0A1D35'], ['#4a4036', '#1E2A36'], ['#d3dce6', '#223040'], ['#99a9bf', '#6B7F94'],
// 图表/其它残留的 Tailwind 色
['#ef4444', '#D20A0A'], ['#3b82f6', '#0057D2'], ['#0f766e', '#07838F'],
['#14b8a6', '#07838F'], ['#7c3aed', '#7858FF'], ['#f5222d', '#D20A0A'],
// H5 专有
['#36cfc9', '#4DA37A'], ['#ff9a3d', '#4D9BF6'], ['#10b981', '#188918']
];
const files = [];
for (const { root, skip } of ROOTS) {
(function walk(d) {
for (const e of fs.readdirSync(d, { withFileTypes: true })) {
const p = path.join(d, e.name);
const rel = path.relative(root, p).replace(/\\/g, '/');
if (e.isDirectory()) { if (!skip.has(rel)) walk(p); continue; }
if (EXT.has(path.extname(e.name).toLowerCase())) files.push(p);
}
})(root);
}
const tally = new Map();
let changedFiles = 0;
for (const f of files) {
let txt = fs.readFileSync(f, 'utf8');
const orig = txt;
for (const [label, pat, rep, kind] of RULES) {
const n = kind === 'literal'
? (txt.split(pat).length - 1)
: (txt.match(pat) || []).length;
if (!n) continue;
txt = kind === 'literal' ? txt.split(pat).join(rep) : txt.replace(pat, rep);
tally.set(label, (tally.get(label) || 0) + n);
}
for (const [from, to] of GENERIC) {
const n = (txt.match(new RegExp(from, 'gi')) || []).length;
if (!n) continue;
txt = txt.replace(new RegExp(from, 'gi'), to);
const k = '单色 ' + from + ' -> ' + to;
tally.set(k, (tally.get(k) || 0) + n);
}
if (txt !== orig) { changedFiles++; if (WRITE) fs.writeFileSync(f, txt); }
}
console.log('=== 规则命中统计 ===');
[...tally.entries()].sort((a, b) => b[1] - a[1]).forEach(([k, v]) => {
console.log(' ' + String(v).padStart(5) + ' ' + k);
});
const total = [...tally.values()].reduce((a, b) => a + b, 0);
console.log('\n涉及文件 ' + changedFiles + ' 个 / 替换合计 ' + total + ' 处');
console.log(WRITE ? '已写入' : '预演,未写入(加 --write 生效)');