probe-v2-semantic-colors.mjs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // 票 15 取证(七):等级标签 / chip / 标题 / KPI 的精确配色与字号
  2. import { readFileSync } from 'node:fs'
  3. const dir = '.scratch/lanhu-cockpit-asset-replacement/research/raw-v2'
  4. const boards = [2, 3, 4, 5, 6, 7, 8, 9, 10]
  5. const hex = (c) => `#${[c.r, c.g, c.b].map((v) => Math.round(v * 255).toString(16).padStart(2, '0')).join('')}`
  6. const alpha = (c) => (c.a === undefined || c.a > 0.999 ? '' : `@${c.a.toFixed(2)}`)
  7. const load = (n) => JSON.parse(readFileSync(`${dir}/desktop-${String(n).padStart(2, '0')}.json`, 'utf8')).artboard
  8. function textOf(node) {
  9. return node.type === 'textLayer' && node.text?.style?.content ? String(node.text.style.content) : ''
  10. }
  11. // 1) 等级标签:文字命中 N级
  12. console.log('=== 等级标签(N级 / N 级)')
  13. const levels = new Map()
  14. for (const n of boards) {
  15. ;(function walk(node) {
  16. const t = textOf(node).trim()
  17. if (/^[1-4]\s*级$/.test(t)) {
  18. const f = node.text.style.font
  19. const c = node.text.style.color
  20. const k = `${t} → ${c ? hex(c) + alpha(c) : '-'} ${f.size}px ${f.name} w${f.fontWeight}`
  21. levels.set(k, (levels.get(k) || 0) + 1)
  22. }
  23. for (const ch of node.layers || []) walk(ch)
  24. })(load(n))
  25. }
  26. console.log([...levels.entries()].sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k} ×${v}`).join('\n') || '(无)')
  27. // 2) chip 文字:父节点名含 Chip 的文字
  28. console.log('\n=== Chip 内文字')
  29. const chips = new Map()
  30. for (const n of boards) {
  31. ;(function walk(node, inChip) {
  32. const here = inChip || /Chip/i.test(node.name)
  33. const t = textOf(node).trim()
  34. if (here && t) {
  35. const f = node.text.style.font
  36. const c = node.text.style.color
  37. const k = `"${t}" → ${c ? hex(c) + alpha(c) : '-'} ${f.size}px ${f.name}`
  38. chips.set(k, (chips.get(k) || 0) + 1)
  39. }
  40. for (const ch of node.layers || []) walk(ch, here)
  41. })(load(n), false)
  42. }
  43. console.log([...chips.entries()].sort((a, b) => b[1] - a[1]).slice(0, 30).map(([k, v]) => `${k} ×${v}`).join('\n') || '(无)')
  44. // 3) 面板标题:父节点名含 Heading 的文字
  45. console.log('\n=== 面板标题(Heading 内文字)')
  46. const heads = new Map()
  47. for (const n of boards) {
  48. ;(function walk(node, inHead) {
  49. const here = inHead || /Heading/i.test(node.name)
  50. const t = textOf(node).trim()
  51. if (here && t) {
  52. const f = node.text.style.font
  53. const c = node.text.style.color
  54. const k = `"${t}" → ${c ? hex(c) + alpha(c) : '-'} ${f.size}px ${f.name} w${f.fontWeight}`
  55. heads.set(k, (heads.get(k) || 0) + 1)
  56. }
  57. for (const ch of node.layers || []) walk(ch, here)
  58. })(load(n), false)
  59. }
  60. console.log([...heads.entries()].sort((a, b) => b[1] - a[1]).slice(0, 30).map(([k, v]) => `${k} ×${v}`).join('\n') || '(无)')
  61. // 4) KPI:父节点名含 Bold Text / KPI 的文字
  62. console.log('\n=== KPI 数值(Bold Text 内文字)')
  63. const kpis = new Map()
  64. for (const n of boards) {
  65. ;(function walk(node, inKpi) {
  66. const here = inKpi || /Bold Text|KPI/i.test(node.name)
  67. const t = textOf(node).trim()
  68. if (here && t) {
  69. const f = node.text.style.font
  70. const c = node.text.style.color
  71. const k = `"${t}" → ${c ? hex(c) + alpha(c) : '-'} ${f.size}px ${f.name} w${f.fontWeight}`
  72. kpis.set(k, (kpis.get(k) || 0) + 1)
  73. }
  74. for (const ch of node.layers || []) walk(ch, here)
  75. })(load(n), false)
  76. }
  77. console.log([...kpis.entries()].sort((a, b) => b[1] - a[1]).slice(0, 25).map(([k, v]) => `${k} ×${v}`).join('\n') || '(无)')
  78. // 5) 一级模式标签(nav 内文字)
  79. console.log('\n=== 一级模式标签(nav 内文字)')
  80. const navs = new Map()
  81. for (const n of boards) {
  82. ;(function walk(node, inNav) {
  83. const here = inNav || /^nav$/i.test(node.name)
  84. const t = textOf(node).trim()
  85. if (here && t) {
  86. const f = node.text.style.font
  87. const c = node.text.style.color
  88. const k = `"${t}" → ${c ? hex(c) + alpha(c) : '-'} ${f.size}px ${f.name} w${f.fontWeight}`
  89. navs.set(k, (navs.get(k) || 0) + 1)
  90. }
  91. for (const ch of node.layers || []) walk(ch, here)
  92. })(load(n), false)
  93. }
  94. console.log([...navs.entries()].sort((a, b) => b[1] - a[1]).slice(0, 20).map(([k, v]) => `${k} ×${v}`).join('\n') || '(无)')