Просмотр исходного кода

fix(profile): 修复 ProfileMenu 纯 CSS style 块中的 // 行注释导致构建失败

外部提交 722ef3a86(字号缩放)在 <style scoped>(无 lang="scss",按纯 CSS
编译)中写入 // 字体大小弹窗,CSS 不支持 // 行注释 → webpack style 编译
报错。改为 /* */ 块注释。全仓扫描确认此为唯一实例(其余 style 块均已
带 lang="scss",// 合法)。

新增 scripts/audit-beautify-debt.js:全站页面样式债务量化审计
(硬编码色/旧品牌蓝/transition:all/px/内联样式 + 债务分层),
为全站美化方案提供数据底座。
liaoxg 1 неделя назад
Родитель
Сommit
342d78f3de

+ 1 - 1
cfc-frontend/pages/profile/components/ProfileMenu.vue

@@ -452,7 +452,7 @@ var res = await getReferralCode()
   text-decoration: underline;
 }
 
-// 字体大小弹窗
+/* 字体大小弹窗 */
 .font-scale-current {
   margin-right: 16rpx;
   color: #999;

+ 128 - 0
cfc-frontend/scripts/audit-beautify-debt.js

@@ -0,0 +1,128 @@
+#!/usr/bin/env node
+/* 全站页面美化审计 v2(2026-10-17)
+ * 对齐 UniForge UI 取证阶段:量化每个页面的样式债务
+ * 维度:硬编码色 / 旧品牌蓝 / transition:all / getSystemInfoSync / 内联样式 / px 单位 / 页面体量
+ */
+const fs = require('fs')
+const path = require('path')
+
+const ROOT = path.resolve(__dirname, '..')
+const EXCLUDE_DIRS = new Set(['node_modules', 'dist', 'unpackage', '.git', 'dist_bak_1792213156'])
+
+// 已重制完成的页面(阶段一~四 + 成员标签),不纳入待美化清单
+const DONE_PAGES = new Set([
+  'pages/body-detail/index.vue',
+  'pages/mind-detail/index.vue',
+  'pages/wisdom-detail/index.vue',
+  'pages/wealth/index.vue',
+  'pages/action-detail/index.vue',
+])
+
+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)
+const HEX = /#[0-9a-fA-F]{3,8}\b/g
+const OLD_BLUE = /#5[Bb]9[Bb][Dd]5/g
+const TRANS_ALL = /transition\s*:\s*all/g
+const SYSINFO = /getSystemInfoSync/g
+const INLINE_STYLE = /style="/g
+const PX_UNIT = /(?<![\w-])\d+px(?![\w-])/g
+
+const rows = []
+for (const abs of files) {
+  const rel = path.relative(ROOT, abs).split(path.sep).join('/')
+  if (rel.startsWith('components/')) continue // 组件单独一轮
+  const src = fs.readFileSync(abs, 'utf8')
+  const styleStart = src.search(/<style/)
+  const styleBlock = styleStart === -1 ? '' : src.slice(styleStart)
+  const hexInStyle = (styleBlock.match(HEX) || []).length
+  const hexAll = (src.match(HEX) || []).length
+  rows.push({
+    file: rel,
+    lines: src.split('\n').length,
+    hex: hexAll,
+    hexStyle: hexInStyle,
+    oldBlue: (styleBlock.match(OLD_BLUE) || []).length,
+    transAll: (styleBlock.match(TRANS_ALL) || []).length,
+    sysInfo: (styleBlock.match(SYSINFO) || []).length,
+    inlineStyle: (src.match(INLINE_STYLE) || []).length,
+    px: (styleBlock.match(PX_UNIT) || []).length,
+    done: DONE_PAGES.has(rel),
+  })
+}
+
+// 债务分:硬编码色权重最高(与品牌令牌脱钩的直接证据),旧品牌蓝次之
+for (const r of rows) {
+  r.debt = r.hex * 3 + r.oldBlue * 5 + r.transAll * 2 + r.sysInfo * 2 + r.px * 0.1
+}
+
+const pagesCfg = JSON.parse(fs.readFileSync(path.join(ROOT, 'pages.json'), 'utf8'))
+const mainPaths = pagesCfg.pages.map((p) => p.path + '.vue')
+
+console.log('========== 汇总 ==========')
+console.log('页面文件总数(不含 components):', rows.length)
+console.log('硬编码色总数:', rows.reduce((s, r) => s + r.hex, 0))
+console.log('旧品牌蓝 #5B9BD5 总数:', rows.reduce((s, r) => s + r.oldBlue, 0))
+console.log('transition:all 总数:', rows.reduce((s, r) => s + r.transAll, 0))
+console.log('getSystemInfoSync 总数:', rows.reduce((s, r) => s + r.sysInfo, 0))
+
+console.log('\n========== 主包 7 门面页 ==========')
+console.log('file|lines|hex|oldBlue|transAll|px|inlineStyle|debt')
+for (const p of mainPaths) {
+  const r = rows.find((x) => x.file === p)
+  if (r) console.log(`${r.file}|${r.lines}|${r.hex}|${r.oldBlue}|${r.transAll}|${r.px}|${r.inlineStyle}|${r.debt.toFixed(1)}`)
+}
+
+console.log('\n========== 旧品牌蓝 TOP25(品牌残留,必须收敛) ==========')
+console.log('file|oldBlue|hex|lines')
+rows
+  .filter((r) => r.oldBlue > 0)
+  .sort((a, b) => b.oldBlue - a.oldBlue || b.hex - a.hex)
+  .slice(0, 25)
+  .forEach((r) => console.log(`${r.file}|${r.oldBlue}|${r.hex}|${r.lines}`))
+
+console.log('\n========== 硬编码色 TOP30(样式债务) ==========')
+console.log('file|hex|hexStyle|oldBlue|transAll|px|lines|debt|done')
+rows
+  .filter((r) => !r.done)
+  .sort((a, b) => b.debt - a.debt)
+  .slice(0, 30)
+  .forEach((r) => console.log(`${r.file}|${r.hex}|${r.hexStyle}|${r.oldBlue}|${r.transAll}|${r.px}|${r.lines}|${r.debt.toFixed(1)}|${r.done}`))
+
+console.log('\n========== transition:all 分布 ==========')
+rows
+  .filter((r) => r.transAll > 0)
+  .sort((a, b) => b.transAll - a.transAll)
+  .forEach((r) => console.log(`${r.file}|${r.transAll}`))
+
+console.log('\n========== getSystemInfoSync 分布 ==========')
+rows
+  .filter((r) => r.sysInfo > 0)
+  .forEach((r) => console.log(`${r.file}|${r.sysInfo}`))
+
+// 债务分层
+const alive = rows.filter((r) => !r.done)
+const buckets = { P0: [], P1: [], P2: [], P3: [] }
+for (const r of alive) {
+  if (r.debt >= 120) buckets.P0.push(r)
+  else if (r.debt >= 60) buckets.P1.push(r)
+  else if (r.debt >= 25) buckets.P2.push(r)
+  else buckets.P3.push(r)
+}
+console.log('\n========== 债务分层(已重制 5 页除外) ==========')
+for (const k of ['P0', 'P1', 'P2', 'P3']) {
+  console.log(`${k}: ${buckets[k].length} 页`)
+  buckets[k]
+    .sort((a, b) => b.debt - a.debt)
+    .slice(0, 12)
+    .forEach((r) => console.log(`   ${r.file} (debt ${r.debt.toFixed(0)})`))
+}