probe-v2-panel-conflict.mjs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. // 票 15 取证(五):面板/表头/chip 的样式唯一性核对(冲突判定用)
  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 fillSig(node) {
  9. return (node.style?.fills || [])
  10. .map((f) => {
  11. if (f.type === 'color') return `color:${hex(f.color)}${alpha(f.color)}`
  12. const g = f.gradient
  13. if (g?.stops) return `grad${g.type}:${g.stops.map((s) => `${hex(s.color)}${alpha(s.color)}@${Math.round((s.position || 0) * 100)}`).join('>')}`
  14. return f.type
  15. })
  16. .join(' + ')
  17. }
  18. function borderSig(node) {
  19. return (node.style?.borders || []).map((b) => `${b.color ? hex(b.color) + alpha(b.color) : '-'} w${(b.width ?? 0).toFixed(2)}`).join(' + ')
  20. }
  21. const panels = new Map()
  22. const headers = new Map()
  23. const chips = new Map()
  24. const headings = new Map()
  25. const centralMaps = new Map()
  26. for (const n of boards) {
  27. const ab = load(n)
  28. ;(function walk(node, path = '') {
  29. const p = path ? `${path}/${node.name}` : node.name
  30. const key = `${node.type}:${node.name} ${Math.round(node.frame?.width ?? 0)}x${Math.round(node.frame?.height ?? 0)} | fills=${fillSig(node)} | borders=${borderSig(node)}`
  31. if (/^Panel$/i.test(node.name)) panels.set(key, (panels.get(key) || 0) + 1)
  32. if (/Header/i.test(node.name) && node.frame?.width >= 100) headers.set(key, (headers.get(key) || 0) + 1)
  33. if (/Chip/i.test(node.name)) chips.set(key, (chips.get(key) || 0) + 1)
  34. if (/Heading/i.test(node.name)) headings.set(key, (headings.get(key) || 0) + 1)
  35. if (/CentralMap/i.test(node.name)) centralMaps.set(key, (centralMaps.get(key) || 0) + 1)
  36. for (const c of node.layers || []) walk(c, p)
  37. })(ab, '')
  38. }
  39. function show(title, map, limit = 8) {
  40. console.log(`\n### ${title}(${map.size} 种形态)`)
  41. for (const [k, v] of [...map.entries()].sort((a, b) => b[1] - a[1]).slice(0, limit)) console.log(` ×${v} ${k}`)
  42. }
  43. show('Panel', panels, 10)
  44. show('Header(≥100宽)', headers, 10)
  45. show('Chip', chips, 6)
  46. show('Heading', headings, 6)
  47. show('CentralMap', centralMaps, 6)