# Dashboard 常见失败与修正

## 0. 快查索引

- **我看到异常现象，但不知道根因**：用「症状→99%根因→修复」快速定位
- **我用了黑色 / 非 data 色 / 色板乱用**：看 §1
- **我需要滚动/抖动相关反例**：看 §2、§4、§5
- **我需要对齐/留白/底部对齐反例**：看 §7、§8
- **我需要图表被截断的处理**：看 §9
- **我需要组件缺失如何降级**：看 §6
- **我需要嵌入 B 端页面（frame 过宽/不对齐）**：看 §10
- **我用了含 TagBar 的页面，TagBar 顶部错位 / 折叠按钮没了 / 滚动条外露**：看 §11、§12
- **我有个别图表的颜色和别的图不一样**：看 §13
- **我的顶部 Tab 在灰底页面上"飘"，或与下方白卡标题打架**：看 §14
- **我卡内 AI 摘要看起来"白底套白底"或灰胶囊语义不对**：看 §15
- **我同一页的卡片操作按钮高矮不一**：看 §16
- **我固定了 chart 高度但图表内部 plot 区比预期小一半**：看 §17
- **我修了一处图表，业务源/pattern/运行时镜像没同步**：看 §18
- **我的复杂业务组件预览被压扁/挤压**：看 §19
- **我用 8 位 hex（带 alpha）做透明度，但渲染没色 / 报错**：看 §20
- **我新增了 data-N 但显示成了 data-1**：看 §21
- **我的趋势折线像一条平滑斜线，没有明显折点**：看 §1.2
- **关联阅读**：
  - P0/P1/P2 自检：`CHECKLIST.md`
  - 滚动决策树与抖动防线：`LAYOUT_RULES.md`
  - Token 兜底：`GLOBAL_DESIGN_RULES.md`

---

## 1) 图表颜色乱用（手写 hex / 黑色 / 非 data 色 / 遍历色板）

- **症状**：
  - 出现 `#70E5C0` 等硬编码色值。
  - **用黑色/近黑/灰文字色**画文字、图标、描边、甚至系列色（`black`、`text-black`、`#000`、`#111`、`rgba(0,0,0,..)`）。
  - 多维图表从色板头部 `data-0/1/2…` 顺序硬取，整页花花绿绿、纯净度差。
- **99% 根因**：没有走 Dashboard data 色槽 `--color-data-*` 与语义 token；把文字色/黑色当系列色用；没有按"维度数 + 语义"决定取色。
- **修复**：
  - 文字一律 `--color-foreground`（主）/ `--color-foreground-secondary`（副）/ `--color-foreground-muted`（辅助），**杜绝任何黑色**。
  - 系列色优先 `--color-data-*`（或 `resolveColorToken` 解析），**允许**用品牌色 `--color-brand-*`（前提非黑）；**仍禁止**用 foreground/灰文字色/任意 hex/黑色冒充系列色。
  - 取色按维度数：单维统一主色 `--color-data-0`；≤3 维用同色系/邻近色；>3 维才遍历色板。**涨跌/升降色用 dashboard 专属 `--status-success`(绿#24CDA5)/`--status-danger`(红#FC7E90)/中立灰**，中立面积可用 `--color-data-19/20`（见 `GLOBAL_DESIGN_RULES.md` §2）。
  - ⚠️ **不要用 theme.css 的 `--color-success/--color-danger` 当涨跌色**：它们底层是 data-7（浅蓝）/data-5（紫），不是绿红，会让"涨绿跌红"出错。

## 1.1) 直接使用三方图表库默认外观（Recharts/ECharts/AntV 直出）

- **症状**：
  - 直接 import/使用 `recharts` / `echarts` / `@antv/*` 的默认组件与默认 tooltip/legend 结构
  - 出现 `<ResponsiveContainer>`、Recharts `<Tooltip>` / `<Legend>` 等直出痕迹
  - 为了“看起来像平台”，在外层套一层 Card 然后手搓样式
- **99% 根因**：没有走 `@tfdesign/dashboard` 的 Smart*Chart + `useChartChrome` 封装链路，误把“能画出来”当成“符合平台封装样式”
- **修复**：
  - 图表必须替换为 `@tfdesign/dashboard` 的 `Smart*Chart` / `*Preview` / 已注册图表模块
  - tooltip/legend 必须复用封装输出，禁止自造 DOM 结构
  - 颜色全部走 `token-resolver/resolveColorToken` 与 `--color-data-n` 色槽；禁止 hex/rgba/任意值
  - 图表高度交给容器：等高分组 / `flex-1` / 自适应（`fillContainer`）场景**不写** `spec.config.height`；仅"独立、无等高约束、需固定防抖"才显式写高度。预留 legend 区避免抖动（参见 `LAYOUT_RULES.md` §3.1/§4）

## 1.2) 趋势折线像平滑斜线、没有明显折点

- **症状**：折线图 / 组合图折线几乎是一条缓慢上升或下降的直线，折点不明显，看起来“很平滑”。
- **99% 根因**：Mock 数据写成等差递增/递减或近似直线；或者示例沿用了 `curve: 'monotone'`，把原本的折点进一步弱化。
- **修复**：
  - 默认使用 `curveType: "linear"`；除非需求明确写“平滑曲线”，不要用 `monotone`。
  - Mock 数据必须有上下波动：7 个点以内至少出现 2 次方向变化，并让相邻点差值有大有小。
  - 避免 `[72, 74, 76, 78, 80, 82, 84]`；优先 `[72, 76, 74, 81, 78, 84, 82]` 这类有清晰折点的数据。

## 2) 看板滚动模型错误（整页滚 + 面板也滚）

- **症状**：筛选区滚走、图表区高度不稳定、面板内滚动条叠加
- **99% 根因**：没有先做滚动模型裁决
- **修复**：按 `LAYOUT_RULES.md` 选择唯一滚动 owner；看板多用“面板内滚”

## 3) KPI 卡堆太多导致噪音

- **症状**：一屏 12+ 指标卡，主线不清晰
- **修复**：按 `PAGE_ARCHETYPES.md` 做分组：核心 KPI 3–6 张，其余折叠/下沉/按 Tab 切换

## 4) 图表高度随 legend/tooltip 抖动（看起来“跳动”）

- **症状**：hover 某条数据时图表容器高度变化；legend 换行导致图表被挤压
- **99% 根因**：容器高度未固定；legend 文案长度不控；legend/图表区域耦合布局
- **修复**：按 `LAYOUT_RULES.md` §3/§4 做"容器层高度稳定（等高/`flex-1`，由容器决定高度）+ legend 区预留 + tooltip 格式固定"。注意：稳定的是**容器**高度，图表内部仍需 viewBox/aspect-ratio 等比自适应填满容器

## 5) 双列/对照布局失真（列宽被内容撑爆 / 负 margin 修对齐）

- **症状**：左/右列宽度随内容变化；出现 `-ml-*`、`w-[...]` 等任意值；窄屏严重挤压
- **99% 根因**：没有按 recipe 约束列策略；没有 `min-w-0`；把“对齐”当成“视觉修补”
- **修复**：选 `monitor-wall-split-columns` 或 `drilldown-compare`；列容器用 `min-w-0`；响应式从左右改上下堆叠（见 `LAYOUT_RULES.md` §5）

## 6) 缺组件就“自造一个看起来像的组件”（不可维护）

- **症状**：出现仓库里不存在的组件名；或复制粘贴一堆 Recharts 配置手搓图表
- **99% 根因**：没有走“组合优先→最小自绘→token 兜底”的降级路径
- **修复**：按 `SKILL.md` §4.2 降级；图表优先用 `@tfdesign/dashboard` 的 Smart*Chart；基础控件复用 `@tfdesign/dashboard` 内置基础组件

## 7) “底部对齐”靠给个别卡塞假高度（假对齐，后患无穷）

- **症状**：为了让同一行卡片底部对齐，给**某张**卡/包裹层单独加了 `height: 100%`、`flex-1` 或额外空白占位，导致该卡被拉长、内容稀疏、下方出现“假的大留白”；或反过来用 `items-start` 让矮卡贴顶，造成同分组卡片底边参差不齐。
- **99% 根因**：没有用**容器统一等高**来对齐，而是逐卡手动“凑”高度；或误用 `items-start` 放弃了等高对齐；等高后产生的富余空间没有让图表自适应吸收。
- **修复**：
  - 同语义分组：父容器统一 `items-stretch` + `gridAutoRows: 1fr` 做等高对齐（见 `LAYOUT_RULES.md` §2.0），不要逐卡塞高度、也不要用 `items-start` 贴顶。
  - 等高后的富余空间：由图表**自适应填满**（`flex-1` + viewBox/aspect-ratio 等比放大 / `fillContainer`）吸收（见 §2.0.2），而不是留下大留白、也不是把别的卡拉高。
  - 固定几何图（雷达/仪表盘）：让图表在容器内等比放大填满并保留端点安全边防截断，不要塞死固定高度。
  - 间距微调只允许 `--spacing-3/4/6`（卡片内边距用 `DASHBOARD_CARD_PADDING_CLASS` 豁免值），禁止任意值与负 margin。

## 8) 盲调 `pb` / 先动全局 `gap`（越调越乱）

- **症状**：出现“往上收/留白太大”后，第一反应是改全局 `gap` 或在外层疯狂加 `pb/mt`，导致其它模块间距被破坏，页面节奏失控。
- **99% 根因**：没把“密度调优”与“布局规则”分开；没有先判断滚动 owner 与模块骨架，直接在全局动刀。
- **修复**：
  - 先锁定 `recipeId + scrollOwner`，确认骨架不变（见 `LAYOUT_RECIPES.md` / `LAYOUT_RULES.md`）。
  - “收紧/留白”优先调整模块内部的标题区与图表容器高度、legend 区预留，而不是全局改 `gap`。
  - 间距只能用 `theme.css` 的 `--spacing-3/4/6`，不要写任意值。

## 9) 图表被卡片内边距截断（坐标文字/端点被切）

- **症状**：图表的 Y 轴/X 轴刻度文字、仪表盘刻度、饼图标签被卡片边缘切掉；或图表整体溢出卡片内边距。
- **99% 根因**：先怀疑卡片内边距是否被改大（标准是上16/左右下20，`DASHBOARD_CARD_PADDING_CLASS`）；内边距正常仍截断时，说明图表内部没有为坐标文字/端点预留安全边。
- **修复**（按 `LAYOUT_RULES.md` §3.2 降级顺序）：
  1. 先核对卡片内边距是否正确（不应大于上16/左右下20）。
  2. 内边距正常仍截断：隐藏坐标文字/数据标签（小尺寸下 hover 才显示）。
  3. 仍不够：图表整体等比轻微缩小（viewBox/aspect-ratio）。
  4. 端点类（仪表盘刻度、轴首尾标签）：在 viewBox 左右/上下预留安全边（如仪表盘左右各留 16）。
  - 禁止靠"放大卡片/缩小内边距/写死像素"硬塞。

## 9.1) 饼图 / 环图外部标签重叠、遗漏或引线杂乱

- **症状**：小占比扇区集中在同一侧，外部标签互相覆盖；百分比和类目名分离；低占比数值被隐藏；引线有的先水平、有的先折线，或末端散乱不成列。
- **99% 根因**：把每个扇区标签按“最短路径”独立外放，没有做同侧标签列、最小间距避让、小扇区收纳、跨侧平衡，也没有把百分比 + 类目作为一个整体标签块。
- **修复**（参考 `DESIGN_PRINCIPLES.md` §2.1）：
  1. 启用外部标签时，先把标签按左右侧分组，再按 y 轴统一避让；同侧 `textAnchor` 和末端 x 坐标必须一致。
  2. 引线统一为“两段式”：从扇区边缘先斜折到列端点，再水平连接到标签列；不要出现“先水平再末端小折”的混合形态。
  3. 百分比 + 类目名作为一个标签块排布；小扇区仍保留百分比，不要只显示类目或直接隐藏数值。
  4. 小扇区优先收纳进同侧标签列；一侧过重时，允许把低占比标签跨侧分配，平衡左右视觉重量。
  5. 标签整体应靠近环图，优先收紧 `labelBendOffset` / `labelEndOffset` / `labelBandPadding`，不要把标签拉到卡片边缘。
- **SmartPieChart 配置建议**：
  - 需要完整读数的异常/归因类环图：`labelLayoutMode: 'smart'`、`compactSmallSlices: false`、`hideOverflowLabels: false`、`balanceLabelSides: true`。
  - 个别标签需要跨侧时：用 `labelSideOverrides` 明确指定，例如 `{ 方案: 'right' }`。
- ❌ 禁止：为了解决重叠直接隐藏小占比百分比；禁止把标签拆成独立百分比文本和独立类目文本分别定位；禁止用绝对定位手搓每个标签。

## 10) 嵌入 B 端页面未用 embedded 模式（frame 过宽 / 不右对齐）

- **症状**：在 dashboard 里嵌入 B 端整页组件（如 `StrategyListPage`）时，frame 比上方卡片宽、与页面右侧不对齐、和上方模块间距过大。
- **99% 根因**：直接调用 B 端整页组件，未传 `embedded`，组件仍带页面级外边距（`PAGE_FRAME_CONTENT_MARGIN`）和固定宽度，没有撑满父容器红线。
- **修复**：
  - 调用时传 `embedded`（如 `<StrategyListPage embedded />`），embedded 模式去掉页面级外边距、`width: 100%`、容器用 `flex w-full min-w-0 flex-col overflow-hidden` 撑满父级（见 `LAYOUT_RULES.md` §6）。
  - 注意 monorepo 引用真值：dashboard 实际引用 `@tfdesign/b-end` 包（`packages/tfds-b-end/...`），改 `src/data/systems/b-end/...` 不生效。
  - 白卡及其内容必须 `w-full` 撑满容器，不要留出与上方卡片不一致的边距。

## 11) TagBar 自己 diy（去掉折叠按钮 / 改 b-end 源 / 滚动条乱处理）

- **症状**：含 TagBar 的 dashboard 页面里，要么折叠按钮被去掉（`collapsible={false}`），要么折叠按钮还在但点了没反应（白卡宽度没联动），要么内部出现一条灰色滚动条。
- **99% 根因**：
  1. 直接给 TagBar 传 `collapsible={false}` —— 误以为折叠按钮"多余"，实际是 b-end 标准能力，必须保留。
  2. 没接 `collapsed` + `onCollapsedChange` —— 折叠按钮内部状态变化，但外层白卡宽度没跟着变。
  3. 想隐藏滚动条就去改 b-end TagBar 内部 `overflow-y-auto` 或在 TagBar className 上加 hide 类，污染了 b-end 组件链路。
- **修复**：按 `LAYOUT_RULES.md` §6.1 的标准用法；本节只保留失败信号，不重复粘贴 JSX。
  - 折叠按钮保留（不要 `collapsible={false}`），外层白卡宽度受控（展开 / 收起联动）。
  - 滚动条美化只在外层 aside 加 `dashboard-scrollbar-hide`，**不动 b-end 一行代码**。

## 12) 含 TagBar 页面的标题/筛选写在 main 内导致 TagBar 顶部错位

- **症状**：左 TagBar + 右主区的 dashboard 页面，TagBar 从 NavBar 顶部开始、Banner 被压在标题下方一段，**TagBar 顶部明显高于 Banner 顶部**，整体视觉错位。
- **99% 根因**：把"标题 + 渠道筛选 + 时间Tab"这条 header 写在了 `<main>` 内部第一行，TagBar 不在 header 同级，它直接顶到了 NavBar 底边。
- **修复**：把 header 提到 **TagBar + main 同级的外层容器**，跨整宽显示，TagBar 顶部就和 Banner / 主内容顶部完全平齐（详见 `LAYOUT_RULES.md` §6.2）。
- ❌ 禁止：把 header 写在 `<main>` 内部第一行——这是含 TagBar 页面 P0 级布局错误。

## 13) 个别图表偏色（默认 data-1 / data-5 而不是模板默认 data-0 / data-4）

- **症状**：整个看板大部分图表是青绿+浅蓝（data-0/data-4），但某个组件（最常见 GaugeChart 仪表盘、BulletChart 子弹图）变成蓝紫+紫红（data-1/data-5），视觉上像两套设计系统。
- **99% 根因**：组件源（`Smart*Chart.jsx`）或 Preview 里**硬写**了 `colorToken: 'data-1'` 等具体槽位，绕过了默认序列 `getDefaultDataColorToken()`。例：
  - `SmartGaugeChart.jsx` 默认 `progressColorToken: 'data-1'`
  - `SmartBulletChart.jsx` 默认 `mainColorToken: 'data-1'` + `targetColorToken: 'data-5'`
  - `GaugeChartPreview.jsx` `tone` 未指定时 `return 'data-1'`
- **修复**（参考 `GLOBAL_DESIGN_RULES.md` §2.3；涉及业务组件副本时再按本文件 §18 同步镜像）：
  1. 改组件源默认值：`'data-1'` → `'data-0'`、`'data-5'` → `'data-4'`
  2. 改 Preview 默认 token
  3. 同步改 `*.tokens.js` 文档展示值（避免文档与实现脱节）
  4. tokens.js 文档里展示**所有可选 tone**而不只是默认蓝（如 GaugeChart：默认/蓝/红/黄/绿全列）
- ❌ 禁止：在组件源/Preview 里硬写 `data-1/data-2/data-5` 当默认色——默认色一律走 `data-0` / `data-4`，其它槽必须由业务通过 props 显式覆写。
- 🚨 **避免双蓝撞色**：`data-1`（蓝紫 #3D71FF）与 `data-4`（浅蓝 #3CCBFF）色相相近，**同图同时出现会糊**，模板默认避开 data-1 也是这个原因。

## 14) 顶部 Tabs 选错 variant（灰底页面用 line / 单白卡页用 pill）

- **症状**：
  - 多分组（B 型）页面的灰底顶栏 Tab 看起来"漂浮无依托"，下划线和下方白卡标题打架
  - 或单一大白卡（A 型）页面顶部 Tab 长着胶囊背景，与白底产生奇怪的色块感
- **99% 根因**：错把"白卡内子页签"语义的 `variant="line"` 用在灰底页面顶栏，或反过来在白卡顶部硬塞 `variant="pill"`。
- **修复**（参考 `PAGE_ARCHETYPES.md` §0.1 / §0.2）：
  - **B 型分组页**（灰底承载多张白卡）顶部业务切换 → **`variant="pill"`**
  - **A 型单一大白卡**（如原声反馈大屏）顶部子页签 → **`variant="line"`**
  - 时间筛选（24h / 7d / 30d）始终用 **`variant="segment"`**
- 一句话：**「在灰底上 → pill；在白卡内 → line；时间筛选 → segment」**
- ❌ 禁止：闭眼默认 `variant="line"` —— line 仅限 A 型白卡内顶部，B 型分组页是错误用法。

## 15) AISummary variant 错位（卡内嵌 page-summary / 整页用 chart-summary）

- **症状**：
  - 卡内 AI 摘要文字看起来"被一层很浅的白底再框了一次"——其实是把 `variant="page-summary"` 用在了卡内（嵌入了一个 `relative overflow-hidden rounded-xl border border-[#F2F4F7] bg-white px-4 py-3` 的二次容器，与外层白卡叠加产生"白底叠白底"）。
  - 或者整页级总结用 `chart-summary` 出现"灰胶囊小条"，没有页面级权重感。
- **99% 根因**：`AISummaryPreview` 的 `variant` 与场景错位。三种 variant 各有强语义：
  - `page-summary` ＝ **页面级总结**（自带白底卡片样式）→ 仅用于 A 型整页一张白卡的顶部，或独立摘要白卡
  - `chart-summary` ＝ **图表/卡内级总结**（小灰胶囊）→ 卡内、贴近图表展示业务洞察
  - `cluster-summary` ＝ **聚类原声总结**（带聚类列表）→ 仅用于原声/聚类业务
- **修复**：
  - **卡内嵌入摘要** → 改 `variant="chart-summary"`（不会再叠白底）
  - **整页统一摘要** → `variant="page-summary"`（A 型布局或独立摘要卡）
- ❌ 禁止：在分组多白卡（B 型）的某张白卡内塞 `page-summary`——视觉上变成"白底套白底"。

## 16) 卡片操作按钮 size 不统一（`sm` vs `md` 混用）

- **症状**：dashboard 同一页面里，有的卡片右上角操作按钮（如"自定义特征"）矮小，有的（如"关联分析"）正常高度，视觉跳跃。
- **99% 根因**：随手写了 `<Button size="sm">`，但 dashboard 卡片操作按钮的**统一标准是 `size="md"`**（与 Input/Filter md=36px 对齐）。
- **修复**：dashboard 模板里凡是**卡片右上角操作按钮、筛选区操作按钮、表格上方工具按钮**，**一律 `size="md"`**。`sm` 仅用于强密度场景（如表格行内 inline 操作），通常不出现在 dashboard 顶层卡片操作区。
- 一句话：**「Dashboard 卡片操作按钮 = `size="md"`，与 Input/Filter 对齐」**。
- 参考：[`ServiceDataScreenPattern`](file:///Users/bytedance/Desktop/TFDS/src/data/systems/dashboard/page-patterns/ServiceDataScreenPattern.jsx) / [`VoiceFeedbackScreenPattern`](file:///Users/bytedance/Desktop/TFDS/src/data/systems/dashboard/page-patterns/VoiceFeedbackScreenPattern.jsx) 全部 `outline-black size="md"`。

## 17) 给图表 wrapper 写了固定 height，但 plot 区只有一半（高度被各类 margin 吃掉）

- **症状**：把图表容器写成 `height: 210` 期望"图表本体 = 210"，但实际测出来 plot 区（柱图 0 到顶刻度的绘图带）只有 ~110，视觉上图表小了一圈。
- **99% 根因**：**plot 高 ≠ wrapper 高**。Smart*Chart 内部会用 wrapper 高度扣除 top/bottom margin、legend 区、Y 轴顶部刻度文字、X 轴标签等开销，剩下才是 plot 区。常见开销：
  - top legend：~52（图例 20 + gap 12 + Y 轴顶刻度 12 + 缓冲）
  - X 轴标签 + bottom margin：~32
  - top/bottom margin：~24
  - 合计被吃掉 ~100
- **修复**：
  - 想要 plot 区 ≈ N px，wrapper 通常需 **N + 100** 左右
  - 或者用 `fillContainer: true` + 父容器固定高度，让组件自己测算
  - **测试时先确认测的是哪一层**（wrapper / SVG / plot 区），不要凭外观估算
  - 设计稿尺寸标注通常是 plot 区，不是 wrapper

## 18) 改了图表/业务组件，运行时镜像没同步（外部消费方版本不一致）

- **症状**：在业务源（`src/data/systems/dashboard/components/*`）改对了，但页面 pattern 或 tfds-dashboard 外部消费方仍是旧版表现，调试时反复出现"明明改了"的错觉。
- **99% 根因**：dashboard 业务组件存在**三处镜像**，必须同步：
  1. 业务源：`src/data/systems/dashboard/components/*`
  2. 页面 pattern：`src/data/systems/dashboard/page-patterns/*`
  3. 运行时镜像：`packages/tfds-dashboard/src/_dashboard_runtime/components/*`
- **修复**：
  - 改一处必同步另两处；颜色/数据/spec config 三件套对齐
  - 修组件级（如 `SmartPieChart`）时也要看 `packages/tfds-dashboard/src/charts/*` 是否有镜像版本
  - 提交前用 Grep 搜关键常量（如 `SENTIMENT_DATA`、`yAxisWidth`）确认所有副本一致

## 19) 复杂业务组件预览被挤压 / 大屏下固定窄宽度

- **症状**：把多列业务组件（如 FeatureCardGroup `columns=3`）放进单组件预览页，窄屏时列宽被挤到极小；或大屏时组件仍停留在固定窄宽度，右侧出现大面积空白。
- **99% 根因**：preview-registry 的 `getPreviewScalerStyle` 写成固定自然宽度（如 `width: naturalW`），或默认 `width: min(100%, 1200px) + flex: 0 1 auto` 导致内容优先被压缩。
- **修复**：
  - 给业务组件配置“宽屏自适应 + 窄屏最小宽度横滚”：
    ```js
    getPreviewAreaStyle: () => ({
      overflowX: 'auto',
      justifyContent: 'flex-start',
    }),
    getPreviewScalerStyle: ({ controlValues }) => {
      const minW = columns * minColW + (columns - 1) * gap + outerPadding * 2;
      return {
        width: '100%',
        minWidth: minW,
        maxWidth: '100%',
        flex: '1 1 auto',
      };
    },
    ```
  - 让组件在大画布下主动撑满，在小画布下保留每列最小可读宽度并出现横向滚动条。
- ❌ 禁止：靠"缩小卡片内边距 / 减少 columns"硬塞预览；也禁止给大屏预览写死 `width: naturalW` 导致组件不自适应。

## 19.1) FeatureCardGroup 在页面里又包一层白卡，导致用户画像类页面显厚/显窄

- **症状**：用户画像 / 特征聚合页面里，“核心反馈特征”本来是一张大白卡，内部三张子图却又被 `FeatureCardGroup` 外层白卡包住，出现白卡套白卡、内边距变厚、宽度不跟随父卡的问题。
- **99% 根因**：把组件详情页的默认 `FeatureCardGroupPreview` 用法照搬到页面模板，没有区分“独立预览态”和“嵌入已有聚合卡态”。
- **修复**：
  - 页面已有大白卡 + 标题 + AI 摘要时，必须使用 `FeatureCardGroup bare columns={3}`，只渲染 grid + 子卡。
  - 外层标题、摘要、按钮由页面的大白卡统一承载，`FeatureCardGroup` 不再重复渲染外层白卡。
  - 组件详情页/独立演示可以使用非 bare 预览，但不要反向修改用户画像看板的正确 `bare` 用法。
- ❌ 禁止：为了修组件详情页宽度，去改用户画像看板的布局；用户画像看板是 `bare` 嵌入的正确参照。

## 20) 用 8 位 hex（含 alpha）做透明度但没显示颜色

- **症状**：在数据里写 `colorToken: '#FC7E9059'` 想要 35% 透明度的粉红，结果渲染出来没色（背景透明 / fallback 灰）。
- **99% 根因**：颜色解析函数把 8 位 hex 当成 token 名查询失败 → `var(--…)` 拿不到值 → 段不渲染。常见报错点：`StackedRatioBar` 的 `tokenNameToCssVar`、`SmartPieChart` 的 `resolveSliceFill`。
- **修复**：所有颜色解析入口必须**先判断是否为字面 hex**，再走 token 解析：
  ```js
  function resolveColor(c) {
    if (/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(c)) return c;
    return `var(${tokenNameToCssVar(c)})`;
  }
  ```
- **建议**：同语义不同程度（如负向轻/中/强）优先用 8 位 hex alpha 阶梯（35% / 60% / 100%），比 rgba 更易在 token 体系流转、也方便和饼图扇区/占比条复用同一份色值。

## 21) 新增 data 槽位但展示回退到 data-1

- **症状**：`theme.css` 加了 `--color-data-20`（中立灰 `#E4E7EC`），但图表里写 `colorToken: 'data-20'` 显示成了蓝色（data-1）。
- **99% 根因**：`chart-common.js` 里的 **`CHART_DATA_COLOR_SLOTS` 常量**比 `TOKEN_DATA_COLORS` 数组短，超过该常量的索引会被 normalize 回 `data-1`。
- **修复**：
  - `CHART_DATA_COLOR_SLOTS` 必须 **=** `TOKEN_DATA_COLORS.length`（当前 = 21）
  - 加新 data 槽时连同 `CHART_DATA_COLOR_SLOTS` 一起改，一并补 chart-common 的 fallback 数组
- 一句话：**"色槽常量与 token 数组长度对齐"是新增 data 槽的隐性必做项。**
