返回 Skill 列表
extension
分类: 其它无需 API Key

wxad-design-ruyi

>-

person作者: user_9209a79bhubcommunity

One Design Next — 设计系统总入口

所有涉及 One Design Next 设计系统的用户请求都从这里进入。本 skill 负责:

  1. 解析用户意图
  2. 立即加载并执行对应的子 skill(不是回答用户问题)
  3. 在 readonly 模式下防止修改组件库和区块目录

⚠️ 写代码前必读的硬约束

  1. 单次 Write 行数上限 800——估算 > 800 行时先拆文件(详见 p3-page-implement/GUIDE.md#单次-writeedit-的物理限制)。历史 trace 多次出现 1700 行 Write 被截断 → 重写又截断 → 浪费 40% 时间。
  2. 修代码报错必须先跑 tsc——禁止凭空通读规则猜(详见 constraints.md#错误排查铁律 或本文件「错误排查铁律」节)。

语气

直接、具体。说文件名、组件名、命令。不说"让我们来看看"、"首先我需要"。 禁止 AI 式废话:不说"综合考虑"、"值得注意的是"、"需要指出"。 短段落。结尾给行动项。

强制路由规则

当用户请求匹配任何子 skill 时,必须立即加载该 skill 的 GUIDE.md 并按其流程执行。 不要直接回答用户问题。不要跳过 skill 流程。子 skill 有结构化的多步工作流, 效果始终优于即兴回答。

只有在没有任何 skill 匹配时,才直接回答。

整体架构

主流水线是横向的 5 个 skill 串联;p2 是一条并列的三层知识带,主流水线各阶段按需消费。

           主流水线(PHASE 1 分析 → PHASE 3 执行 → PHASE 4 质保;PHASE 2 是知识层)
    用户输入 → design-analyst → design-spec → page-implement → audit → polish
              (需求分析+提问)  (Prompt+区块匹配) (代码)     (审查) (精修)

        │             │               │                │          │        │
        ▼             ▼               ▼                ▼          ▼        ▼
    ┌────────────────────────────────────────────────────────────────────────────┐
    │                p2 知识层(三个并列知识包,按需加载)                          │
    ├───────────────────────┬──────────────────────┬─────────────────────────────┤
    │ p2-business-knowledge │ p2-block-catalog     │ p2-one-design               │
    │ 业务语境 / 站点地图     │ 区块清单 / rules /    │ 组件 / rules /               │
    │ 模块 / 页面知识         │ references(tsx)    │ references / design-tokens   │
    │                       │                      │                             │
    │ design-analyst 消费    │ design-spec 消费     │ design-spec / page-implement │
    │ design-spec 消费       │ page-implement 消费  │ / audit / polish 都消费      │
    └───────────────────────┴──────────────────────┴─────────────────────────────┘

关键认知

  • 主流水线:5 个 skill 用 next_skill 前后咬合,自动接力
  • p2 知识层:三个并列知识包,不是一个大库。做不同事情的 skill 只加载它需要的那部分
  • 例如 design-analyst 只用 business-knowledge(+ 可选 block-catalog 作参考),不需要加载 one-design

路由规则

当你看到这些模式时,立即加载对应的 skill:

| 用户说了什么 | 加载的 Skill | 路径 | | ------------------------------------------------------------------- | ----------------- | ---------------------------- | | 「修这个错」/「报错了帮我看下」/「修正以上错误」/「ts 报错」/「编译失败」 | constraints「错误排查铁律」(先跑 tsc 拿真实报错,禁止读散文猜) | constraints.md#错误排查铁律 | | 贴了截图/草稿图/线框图 | design-analyst | p1-design-analyst/GUIDE.md | | "做一个页面"、"搭建 XX"、"生成区块"、"开发 XX 功能" | design-analyst | p1-design-analyst/GUIDE.md | | "分析这个需求"、"分析一下" | design-analyst | p1-design-analyst/GUIDE.md | | 给了结构化需求文档、设计 Prompt | design-spec | p1-design-spec/GUIDE.md | | "审查"、"检查"、"review"、"合规检查" | audit | p4-audit/GUIDE.md | | "精修"、"polish"、"优化细节"、"发布前" | polish | p4-polish/GUIDE.md | | "创建项目"、"新建项目"、"初始化"、"scaffold"、"template"、"starter" | 本 skill 直接处理 | 见下方「创建项目」 | | "GenUI"、"AI对话页面"、"聊天界面"、"对话组件" | 本 skill 直接处理 | 见下方「知识查询」 | | "有哪些组件"、"怎么用 XX"、"查一下"、"设计规范" | 本 skill 直接处理 | 见下方「知识查询」 | | "实现页面"、"生成页面代码"、"把设计稿转成代码" | page-implement | p3-page-implement/GUIDE.md |

page-implement 处理页面级设计实现,用已有区块 + 设计系统拼装完整页面。design-spec 完成后默认接力到 page-implement。

路由消歧规则

当用户说的话同时匹配多个 skill 时,按以下优先级判断:

  1. "创建模板"/"直接用 workshop"/"不需要改动" → 走「创建项目」(从 references/ 组装),不走设计流水线。用户要的是拿到一个可运行的项目,不是让 AI 生成代码。
  2. "做一个 XX 页面"但当前不在 ODN 项目中 → 先走「创建项目」scaffold,再进 design-analyst。
  3. "做一个 XX 页面"且已在 ODN 项目中 → 直接进 design-analyst。
  4. 同时出现"创建"+"页面"但语义更像脚手架(如"创建如翼首页的模板") → 走「创建项目」。关键区分词:"模板"、"template"、"starter"、"scaffold"、"直接用" 指向创建项目;"做"、"搭建"、"生成"、"开发" 指向设计流水线。

不确定分什么类? 问用户,不猜。格式: "您想要 (A) 创建新项目、(B) 创建页面/区块、(C) 审查已有代码、(D) 查询组件用法、(E) 其他?"

项目环境检查(前置步骤)

在执行 design-analyst、design-spec、page-implement 之前,先检查当前是否在 ODN 项目中:

  1. 查看当前目录是否有 package.json,且 dependencies 中包含 one-design-next
  2. 如果不在 ODN 项目中 → 先执行「创建项目」(从 references/ 组装),再继续原流程
  3. 如果已在 ODN 项目中 → 直接进入对应 skill

这保证用户说"做一个数据看板"时,AI 会先 scaffold 项目、再进入设计流水线,而不是在一个空目录里生成代码。

区块路由检查(前置步骤 · 写代码前必跑)

在 page-implement 写任何 .tsx 之前,必须先把需求文本扫一遍,命中以下关键词就强制查 p2-block-catalog,禁止自行重写:

| 需求文本里出现的词 | 必须查的区块 | 文件 | |------------------|------------|------| | 触点 / 媒体 / 多媒体对比 | touchpoint-analysis (L2) | p2-block-catalog/rules.md | | 渗透 / 渗透率 | penetration-analysis (L2) | 同上 | | 排名 / 榜 / TOP / 飙升 | ranking-list (L2,4 变体) | 同上 | | 5R / 拉新 / 促活 / 回流 / R1-R5 | metric-card-group (L2) | 同上 | | 心智 / 份额 / 趋势(品牌) | metrics-overview (L2) | 同上 | | 雷达 / 本品 vs 参照 | radar-with-metrics-panel (L2) | 同上 | | 词云 | wordcloud-section (L2) / mindshare-dictionary (L3) | 同上 | | 转化复盘 / 转化指标 | conversion-metrics / conversion-trend (L3) | 同上 | | 涟漪 / 相似度 | ripple-chart (L3) | 同上 | | 桑基 / 资产流转 | sankey-chart (L3) | 同上 | | TreeMap / 心智图谱 | treemap-panel (L3) | 同上 | | 四象限 / 矩阵 / 资产×R3 | quadrant-scatter (L3) | 同上 | | 主从 / 复盘布局 | review-master-detail-layout (L1) | 同上 | | 页面头部 / 筛选栏 / 顶部 Tab | page-header (L1,14 种模式) | 同上 | | 候选池 / 人群挑选 | crowd-pick-card-grid (L2) | 同上 | | 日期范围(任何场景) | ry-date-range-picker 区块 | references/blocks/ry-date-range-picker.tsx |

判断准则

  • 命中关键词 → 必须 Read 对应区块源码(在 references/blocks/<slug>.tsx
  • 区块逻辑能覆盖需求 → 直接 import 复用,不准重写
  • 区块逻辑差异 < 30% → 复用 + 传 props 调整
  • 区块逻辑差异 ≥ 30% → 在区块基础上扩展,并把变更登记到候选区块(见 p2-block-catalog/GUIDE.md 候选区块小节)
  • 完全无对应区块 → 用 ODN 组件从零搭建

这条规则专门治"看到'触点对比'就自己写一个 <table> + 排序按钮"的复发模式。区块清单里有的,必须用清单里的。

短路规则:空目录 + 无终端

如果以下条件同时满足,直接输出组装步骤让用户手动执行,不进入子 skill:

  1. 当前目录为空 或 不含 package.json
  2. 无终端执行能力(无法运行 shell 命令)
  3. 用户意图为「创建项目」或「直接使用模板」

输出「创建项目」章节中的完整组装步骤,让用户在终端中自行执行。所有文件都在 references/ 目录下,不需要网络。

设计底线(全流水线强制 · 零容忍)

以下规则适用于所有子 skill、所有阶段,无论是用组件还是手写 div。 违反任何一条,audit 必须判定为 🔴 严重。

视觉铁律

| 禁止 | 原因 | 替代 | |------|------|------| | linear-gradient / radial-gradient / bg-gradient-to-* / from-* / via-* | ODN 是实色系统,不用渐变 | 实色 bg-brand-6 / bg-white / bg-[#f2f5fa] | | 毛玻璃 backdrop-blur / 霓虹 glow / neon | AI 审美陷阱 | 投影层级 shadow-1 ~ shadow-4 | | Tailwind 默认色板 blue-500 / purple-600 / indigo-* | 未映射到 ODN Token | ODN 语义色 text-brand-6 / text-black-12 | | 硬编码色值 #296BEF / rgb(41,107,239) | 绕过 Token 体系 | var(--odn-color-*) 或 Tailwind 语义色(ECharts option 除外:Canvas 不支持直接写 var(),用 getComputedStyle 读取实际值后传入,见 data-display.md Chart 段) | | 外部图标库 lucide-react / react-icons / heroicons | ODN 有内置 Icon 组件 | <Icon name="..." /> |

组件选用铁律(与视觉铁律同级 · 零容忍)

ODN 已经提供的控件/容器,禁止用原生 HTML 或别的组件拼装替代。命中以下任意一项,audit 必须判定为 🔴 严重。

| 场景 | ❌ 禁止 | ✅ 必须用 | |------|--------|----------| | 数据表格 | <table> / <thead> / <tbody> / <tr> / <th> 自己拼整张表 | <Table columns dataSource> | | 日期范围(如翼) | <DateRangePicker> / <DatePicker mode="range"> / 用两个 Select 拼"年/月" / 自画日历面板 | RyDateRangePicker 区块(blocks/ry-date-range-picker.tsx) | | 单日期 | 自画日历 / 用 Select 拼日期 | <DatePicker prefix="日期" className="w-[200px]"> | | 下拉选择 | <select> / <input> + 弹层自己写 / 用 Popover + 列表自拼 | <Select options value onChange> | | 级联选择 | 多个 Select 嵌套 / 自写树形面板 | <Cascader>(树形场景统一 Cascader,禁止 TreeSelect) | | 表单布局 | 裸 <label> + <input> + 手写栅格 | <Form labelSize> + <Form.Item label required tooltip> | | 弹窗 | 自写遮罩 + 居中容器 | <Dialog visible onVisibleChange title intent> | | 抽屉 | 自写右滑面板 | <Drawer visible onVisibleChange placement> | | 浮层提示 | 自写 absolute 气泡 / title 属性 | <Popover> / <Tooltip> | | 下拉菜单 | 自写 Popover + 列表 | <Dropdown menu trigger> | | 全局消息 | alert() / 自写 toast | Message.info() / Message.success() | | 警告提示 | 自写黄/红条 | <Alert intent title message> | | 卡片 | 裸 <div className="bg-white rounded-xl shadow"> 当主卡片 | <Card elevation> + <Card.Header title topContent> | | 空状态 | 自写"暂无数据"插图 | <Empty type title description> | | 加载态 | 自写 spinner SVG | <Loading type tip> | | Tab 切换 | 自写按钮组切换 | <Tabs.Default items value onChange>(按需选 5 种变体) | | 分页 | 自写"上一页/下一页"按钮 | <Pagination value totalSize onChange> | | 头像 | <img> + 圆形 | <Avatar src fallback> | | 折叠面板 | <details> / 自写展开 | <Collapse items> / <Collapsible> | | 滚动区 | 裸 overflow-auto 当主滚动壳 | <ScrollArea> | | 虚拟列表 | 自己截窗渲染 | <VirtualList> | | 图标 | lucide-react / inline SVG(业务图标) | <Icon name="..." size> |

唯一例外(白名单)

  • Popover / Tooltip / Dropdown 的浮层内嵌小表(行数固定、列 ≤ 5、无排序/筛选/分页),可用 <table> 直拼,但仍须用 ODN 颜色 token
  • Select 拼接(-ml-px + 自定义 border-radius)的复合控件场景允许 DateRangePicker,其他场景一律走 RyDateRangePicker
  • 装饰性 sparkline 段(< 50 px、无交互)允许内联 SVG,无需 ECharts

判断准则:如果你正在用原生标签拼一个完整的交互控件,方向已经走偏了——回头查 p2-one-design/GUIDE.md 的组件速查表。如果速查表里有,必须用速查表里的。

基调铁律

如果生成的 UI 看起来像 SaaS 官网(渐变 Hero、全屏大图、动态粒子、紫蓝配色),那就偏离了 ODN。

ODN 是 B 端工具 UI:白底、实色、方正、无装饰。用信息层级传达重要性,不用视觉装饰。

遇到「上线公告 / Hero / 头图 / 封面 / 落地页」等需求时,尤其要警惕渐变先验。正确做法:白底容器 + 实色标签/徽章 + 字号层级制造视觉冲击。

生成后自检(所有产出代码的 skill 必须执行)

视觉自检:

  • [ ] 代码中无 gradient / from- / via- / to-(AP-15)
  • [ ] 代码中无 Tailwind 默认色板(AP-01)
  • [ ] 代码中无硬编码 hex / rgb(AP-02)
  • [ ] 代码中无 lucide-react / react-icons / heroicons(AP-11)
  • [ ] 整体视觉是 B 端工具风,不是营销落地页风

组件选用自检(与视觉同级 · 缺一项即不准报 DONE):

  • [ ] 代码中无 <table> / <thead> / <tbody>(除浮层内嵌小表白名单外,AP-19)
  • [ ] 代码中无原生 <select> / <input type="checkbox"> / <input type="radio"> / <input type="date">(AP-19)
  • [ ] 日期范围用 RyDateRangePicker,不是 DateRangePicker、不是两个 Select 拼"年/月"(AP-20)
  • [ ] <Table> 设了 scroll={{ x: 'max-content' }}(不是固定数字),且每列 width 不小于中文 title 的实际宽度(AP-21)
  • [ ] 表单结构是 Form + Form.Item,不是裸 <label> + Input
  • [ ] 空状态/加载态/弹窗/抽屉/折叠都走 ODN 组件,不是自写 div

完整反模式清单(AP-01 ~ AP-20)见 p2-one-design/rules/design-paradigm.md。完整组件选用映射见上方「组件选用铁律」表。

终极检验:把生成的页面截图和如翼现有页面并排放——看得出哪个是新做的吗?如果新页面明显"更好看""更现代""更有设计感",那就偏了。ODN 追求的是融入,不是突出

流水线

子 skill 之间有固定的接力关系。当一个 skill 执行完毕后,自动加载下一个:

[项目环境检查] → design-analyst → design-spec → page-implement → audit → polish

每个 skill 的 frontmatter 中声明了 next_skill,按此执行。 mode 参数沿流水线向下透传。

mode 参数

readonly 模式(外部平台默认)

mode=readonly 时:

  • 不写入 docs-pages/、不更新 block-catalogbusiness-knowledge 等知识文件
  • 不修改 components/ 下的组件源码
  • page-implement 输出代码到用户工作目录
  • polish 输出修复建议但不自动修改
  • audit 和知识查询正常工作

向下游传递时标注:mode: readonly

full 模式(本项目内部默认)

完整功能,所有操作正常执行。

知识查询

当用户只是提问(不是要创建/审查/修复),本 skill 直接回答,不转发。

| 用户问题类型 | 读取的文件 | | -------------------------------------------- | ----------------------------------------------------------------------------------- | | 组件用法("Button 怎么用") | p2-one-design/GUIDE.md + p2-one-design/rules/ 对应文件 | | 组件列表 | p2-one-design/references/component-list.md | | 设计规范("颜色"、"间距"、"Token") | p2-one-design/rules/design-tokens.md | | 图标("搜索图标叫什么") | p2-one-design/rules/icons.md | | GenUI 组件("对话组件怎么用") | p2-one-design/rules/genui.md + GUIDE.md GenUI 章节 | | 区块("有没有筛选区块") | p2-block-catalog/GUIDE.md | | 业务知识("5R 是什么") | p2-business-knowledge/GUIDE.md + rules/ | | 页面类型("仪表盘长什么样") | p2-business-knowledge/GUIDE.md 页面类型参考 | | 已有 workshop 页(slug、改某页、和某页对齐) | p2-page-catalog/GUIDE.md(含 /<slug> 路由约定)+ p2-page-catalog/rules.md |

流程:识别问题类型 → 读取对应文件 → 提取信息 → 简洁回答。

已有 workshop 页面(与 p2-page-catalog 联跑时)

当用户要改已实现的如翼 workshop 页时:

  1. 路由:浏览器访问 /<slug> 直达该页;slugp2-page-catalog/rules.md 中的章节标题一致。文件名与 slug 不一致时查 references/workshop/workshopModules.tsWORKSHOP_SLUG_TO_IMPORT
  2. 文档站区别:dumi 上为 /workshop/<slug>;模板独立跑时为 /<slug>
  3. 源码位置references/workshop/<slug>.tsx(skills 内自包含),详见 p2-page-catalog/GUIDE.md

区块查询 · 按"想解决什么产品问题"路由

区块目录(p2-block-catalog)按 L1/L2/L3/L4 分层。当用户问"要做 XX 该用什么区块"时,按产品问题映射:

| 产品问题 | 优先考虑的区块 | 层级 | | ------------------------------------------------------------- | ---------------------------------------------- | ---- | | 页面壳(复盘主从布局) | review-master-detail-layout | L1 | | 页面头部/筛选栏/Tab | page-header(14 种模式) | L1 | | 从候选池挑选人群 | crowd-pick-card-grid | L2 | | 某维度的排位展示 | ranking-list(brand/share/hot/surge 4 变体) | L2 | | 5R 人群资产指标 | metric-card-group | L2 | | 品牌心智量 + 份额 + 趋势 | metrics-overview | L2 | | 渗透率对比 + 榜单联动 | penetration-analysis | L2 | | 多媒体触点对比 | touchpoint-analysis | L2 | | 通用词云段落 | wordcloud-section | L2 | | 本品 vs 参照系雷达对比 | radar-with-metrics-panel | L2 | | 转化复盘的核心指标 | conversion-metrics / conversion-trend | L3 | | 人群相似度涟漪 | ripple-chart | L3 | | 资产流转桑基图 | sankey-chart | L3 | | 心智图谱 TreeMap | treemap-panel | L3 | | 四象限分布图(资产×R3 或心智双矩阵,同一 quadrant-scatter) | quadrant-scatter | L3 | | 结构化"热词榜+多层词云" | mindshare-dictionary | L3 |

选择准则

  • 优先 L1(页面壳)和 L2(多页复用)。L3(场景专属)只在业务语境匹配时用,误用会引入不相关的 UI 复杂度
  • L4 层级用于「交互模式」类知识;当前无独立区块 slug,复杂弹窗/表单在对应 workshop 页面内联实现
  • 找不到匹配的区块 → 内联实现;判断是否应该纳入"候选区块"观察(见 p2-block-catalog/GUIDE.md 的候选区块小节)

创建项目

当用户意图为创建新项目时,从 references/ 目录组装一个基于 one-design-next 的完整项目。

强制规则:必须使用 Vite + React + TypeScript + Tailwind CSS + one-design-next 组件库。 禁止用纯 HTML/CSS、Material UI、Ant Design 或其他 UI 库替代。 所有如翼页面必须以 RuyiLayout 组件为页面壳。

处理流程

  1. 读取 MANIFEST(强制):第一步必须 Read references/MANIFEST.json。它预计算了每个页面的文件、区块依赖和数据依赖,不需要自行扫描 import禁止跳过 MANIFEST 直接靠 Glob/列目录决定要哪些文件——Glob 在某些环境下会失败(已观测到"查找目录失败"复发),此时 MANIFEST 是唯一可靠的清单
  2. 推断项目名称:从用户描述中提取项目名(如"创建一个数据看板"→ data-dashboard),无法推断时用 odn-app
  3. 判断复制范围
    • 用户要全部页面 → 复制全量 workshop + blocks(见「全量复制」)
    • 用户指定了具体页面(如"首页")→ 按 MANIFEST 只复制该页面 + 依赖(见「按需复制」)
  4. 创建项目目录,组装 scaffold + 选定的 workshop/blocks
  5. 安装依赖:运行 npm install(pnpm v10+ 必须先确保 .npmrc + package.jsonpnpm.onlyBuiltDependencies 已就位,见「1. 创建 Vite + React + Tailwind 项目骨架」)
  6. 定制(可跳过):根据用户需求修改。如果用户明确说"不需要改动"/"直接用",跳过此步
  7. 告知用户
    • npm run dev 启动开发服务器
    • 如果用户提到了具体页面(如"首页"对应 slug home)→ 告知 http://localhost:5173/<slug> 直达该页
    • http://localhost:5173/ 是空壳起始页,用于从零搭新页面

MANIFEST 兜底原则:当 Glob、列目录或 find 类操作失败时,永远回退到 Read references/MANIFEST.json——它包含完整的 pages / allBlocks / allWorkshop / allData 清单。不准在缺失目录信息时凭空臆想要哪些文件。

降级策略

| 条件 | 行为 | | ------ | ------------------------------------------------ | | 有终端 | 自动执行下方全部步骤 | | 无终端 | 输出完整步骤让用户手动执行(包括文件列表和命令) |

不存在"网络不通"的问题——所有文件都在本地 references/ 里,不需要 clone 或 degit。

组装步骤

1. 创建 Vite + React + Tailwind 项目骨架

mkdir <项目名> && cd <项目名>
npm init -y

设置 package.jsonpnpm v10+ 必须包含 pnpm.onlyBuiltDependenciespackageManager,否则会卡 ERR_PNPM_IGNORED_BUILDS):

{
  "name": "<项目名>",
  "private": true,
  "type": "module",
  "packageManager": "pnpm@9.15.0",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "pnpm": {
    "onlyBuiltDependencies": ["esbuild", "sharp", "@swc/core"]
  }
}

同时把 references/scaffold/.npmrc 复制到项目根目录,包含 auto-install-peers=true 等 pnpm v10 兼容配置。

安装依赖:

npm install one-design-next react react-dom react-router-dom
npm install -D @tailwindcss/vite tailwindcss @vitejs/plugin-react vite typescript @types/react @types/react-dom

创建 tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "resolveJsonModule": true
  },
  "include": ["src"]
}

创建 index.html

<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><项目名></title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

2. 复制 scaffold 关键文件

references/scaffold/ 复制到项目根目录和 src/

| 来源 | 目标 | 说明 | | -------------------------------------------------------------------------- | ------------------- | --------------------------------------- | | references/scaffold/vite.config.ts | vite.config.ts | React dedupe,不可删减 | | references/scaffold/main.tsx | src/main.tsx | 全局 React 兼容,不可删减 | | references/scaffold/app.css | src/app.css | ODN token → Tailwind 桥接,不可删减 | | references/scaffold/App.tsx | src/App.tsx | 路由入口 | | references/scaffold/vite-env.d.ts | src/vite-env.d.ts | Vite 类型声明 | | references/scaffold/pages/ | src/pages/ | WorkshopPage | | (内联生成) | .npmrc | pnpm v10 兼容,scaffold 脚本内联生成 |

3. 复制 workshop 页面和区块

| 来源 | 目标 | 说明 | | ---------------------------------------- | -------------------- | ------------------- | | references/workshop/*.tsx | src/workshop/ | 33 个完整页面 | | references/workshop/workshopModules.ts | src/workshop/ | 页面注册表 | | references/workshop/data/*.json | src/workshop/data/ | mock 数据(精简版) | | references/blocks/ | src/blocks/ | 31 个可复用区块 |

全量复制(快捷命令,有终端时一键执行)

# 假设 SKILLS_DIR 指向 skills/ 目录的绝对路径
SKILLS_DIR="<skills目录路径>"

cp "$SKILLS_DIR/references/scaffold/vite.config.ts" .
cat > .npmrc << 'EOF'
auto-install-peers=true
strict-peer-dependencies=false
EOF
mkdir -p src/pages src/workshop/data src/blocks

cp "$SKILLS_DIR/references/scaffold/main.tsx" src/
cp "$SKILLS_DIR/references/scaffold/app.css" src/
cp "$SKILLS_DIR/references/scaffold/App.tsx" src/
cp "$SKILLS_DIR/references/scaffold/vite-env.d.ts" src/
cp "$SKILLS_DIR/references/scaffold/pages/"*.tsx src/pages/

cp "$SKILLS_DIR/references/workshop/"*.tsx src/workshop/
cp "$SKILLS_DIR/references/workshop/"*.ts src/workshop/
cp "$SKILLS_DIR/references/workshop/data/"*.json src/workshop/data/
cp -r "$SKILLS_DIR/references/blocks/"* src/blocks/

按需复制(用户只要特定页面时)

当用户只要一个或几个页面(如"创建如翼首页的模板"):

  1. 读 MANIFESTreferences/MANIFEST.json → 找到 pages.<slug>
  2. scaffold 不变:scaffold 全部复制(同上)
  3. 只复制需要的页面 + 依赖

home 为例,MANIFEST 记录:

{
  "file": "workshop/home.tsx",
  "blocks": ["blocks/ry-date-range-picker.tsx"],
  "data": [
    "workshop/data/home-trend-data.json",
    "workshop/data/home-view-data.json",
    "workshop/data/market-rank-config.json",
    "workshop/data/market-rank-data.json"
  ]
}

只需复制:

  • workshop/home.tsxsrc/workshop/
  • workshop/workshopModules.tssrc/workshop/始终需要,但只保留选中页面的注册条目)
  • workshop/data/home-*.json + workshop/data/market-rank-*.jsonsrc/workshop/data/
  • blocks/ry-date-range-picker.tsxsrc/blocks/
  • 如果区块依赖 _internal/*,也一并复制 blocks/_internal/

不需要逐个读 tsx 文件来分析 import——MANIFEST 已预计算。

项目架构

组装后的项目使用 React Router 做 URL 路由:

| 路由 | 组件 | 用途 | | -------- | -------------- | ------------------------------------------------ | | /:slug | WorkshopPage | 动态路由,从 workshopModules.ts 懒加载指定页面 |

每个 workshop 页面(src/workshop/<slug>.tsx)是完全自包含的——内置 RuyiLayout + 菜单 + 业务内容 + mock 数据,不依赖外部状态。

页面注册表 src/workshop/workshopModules.ts 包含:

  • WORKSHOP_SLUG_TO_IMPORT:slug → 懒加载 import 映射(/:slug 路由用)
  • WORKSHOP_INDEX{ slug, title }[] 数组

定制要点

| 修改项 | 位置 | 说明 | | ------------ | ------------------------- | -------------------------- | | 页面标题 | index.html<title> | 修改为项目名称 | | 新增业务页面 | src/workshop/<slug>.tsx | 创建页面文件(见下方流程) |

新增页面

  1. 写页面文件src/workshop/<slug>.tsx(每个页面自包含 RuyiLayout + 菜单 + 内容)
  2. 注册到 workshopModules.ts
// 在 WORKSHOP_SLUG_TO_IMPORT 中添加:
"<slug>": () => import("./<slug>"),

// 在 WORKSHOP_INDEX 中添加:
{ slug: "<slug>", title: "页面中文名" },
  1. 注册后即可通过 /<slug> 路由访问

注意事项

  • 颜色/图标全部丢失的排查入口:正常情况下 import { Button } from 'one-design-next' 会通过 dist/index.js → dist/style/index.js → base.css 自动引入样式,无需显式引入 base.css。若出现样式全丢,检查是否用了子路径导入(import Button from 'one-design-next/dist/button')——子路径绕过了 dist/index.js,样式链会断掉,此时需在 main.tsx 最顶部加:
    import "one-design-next/dist/style/base.css"
    
  • app.css 第一行必须是 @import 'tailwindcss' important;——末尾的 important 不可省略,否则 Tailwind utility class 无法覆盖 ODN 组件内部样式。如果不用 references/scaffold/app.css 而自行创建,务必确保这一行正确。
  • app.css 中的 @theme 块是核心——它将 ODN CSS 变量桥接到 Tailwind 4 的工具类体系。必须原样保留,不可删减。
  • main.tsx 中的 globalThis.React = React 是 one-design-next 兼容所需,不可删除
  • vite.config.ts 中的 resolve.dedupe + resolve.alias 防止 React 多副本,不可删除

完成状态协议

每个 skill 完成后,报告以下状态之一:

| 状态 | 含义 | | ---------------------- | -------------------------------------------- | | DONE | 全部步骤完成。给出证据(tsc 0 error / 预览跑起来 / 用户确认)。 | | DONE_PENDING_VERIFICATION | 改完了但当前环境装不上依赖、跑不了 tsc,需用户在自己环境验证。 | | DONE_WITH_CONCERNS | 完成了,但有问题需要用户知道。列出每个问题。 | | BLOCKED | 无法继续。说明原因和已尝试的方法。 | | NEEDS_CONTEXT | 缺少信息。明确说需要什么。 | | NEEDS_VERIFICATION | 用户要求纯静态 review(明确说"不要跑"),代码改完但未跑过 tsc/预览。 |

错误排查铁律(修代码前必读)

用户说「修这个错」「报错了」「修正以上错误」但没贴具体报错信息时——你的第一动作不是通读代码 + 翻规则 md 猜。

✅ 正确流程

  1. 先跑 npx tsc --noEmit 2>&1 | head -80(或 npm run dev / vite build)拿真实报错
  2. 按报错文件:行号精准修
  3. 修完再跑 tsc 验证 0 error

❌ 严禁

  • 不准在没看到 tsc / vite 真实报错时通读 rules/*.md 来猜哪儿不对
  • 不准修改"看起来可疑但 tsc 没报"的代码——错杀比漏诊更糟
  • 不准在没装依赖、没跑 tsc 的环境下交付 DONE——必须降级为 DONE_PENDING_VERIFICATION / BLOCKED

这条专门治"用户说有 bug 但没给报错 → AI 凭空通读 5 个 rules.md → 错杀对的 prop → 没装依赖也敢交付"的灾难循环。一次失败 trace 烧掉 80K+ token 的 80% 都是这种"读散文猜错"。

涉及代码产出时的强约束(page-implement / polish 必读)

只要本次会话产出了 .tsx / .ts / .css 等代码文件,DONE 必须满足以下两条

  1. 跑过 p4-audit:必须有一次明确的"加载 p4-audit/GUIDE.md → 对生成代码执行审查 → 输出审查报告"动作,且报告判定为 ✅ 合规
  2. 跑过生成后自检:必须输出「设计底线 · 生成后自检」5 条 checkbox 的勾选结果

未满足任一条 → 最多只能报 DONE_WITH_CONCERNS,且必须在第一行写明"未运行 audit"或"未执行自检"。

这条约束专门治"构建跑通 = 完成"的错觉。预览能打开不代表组件用对了——历史上多次出现 <table> 替代 TableSelect 拼日期范围这类问题,根因都是跳过了 audit。

熔断机制

  • 同一步骤尝试 3 次仍然失败 → 停止,报告 BLOCKED
  • 对安全敏感的操作没有把握 → 停止,让用户决定
  • 工作范围超出可验证的范围 → 停止,告知用户

构建工具/依赖问题专项熔断

构建失败、依赖安装失败、包管理器报错(如 ERR_PNPM_IGNORED_BUILDSpeer dep 冲突、版本不兼容)算同一步骤,3 次失败必须停止,禁止继续:

  • ❌ 不准来回试 .npmrc 的不同变体
  • ❌ 不准在 package.json.npmrcpnpm-workspace.yaml 之间反复腾挪
  • ❌ 不准切换包管理器(pnpm / npm / yarn)"碰运气"
  • 不要把环境决策抛给用户——用户不需要知道 .npmrc 写什么、为什么 pnpm 报错。用户只关心"页面有没有跑起来"
  • ✅ 应该停下来,按以下顺序处置:
    1. 先按 scaffold 模板兜底:检查 .npmrc + package.json 是否包含必要的 pnpm 兼容字段(auto-install-peerspnpm.onlyBuiltDependenciespackageManager);缺哪条补哪条,再装一次
    2. 兜底后仍失败 → 报告 BLOCKED,附上具体报错信息 + 建议的修复方向(如"建议把 Node 升到 ≥ 20.10"),不要让用户自己想方案
    3. 把无法继续的事实直接告诉用户,可以建议他换个本地环境或 CI 跑一下,但不要让用户去决定 .npmrc 改什么

这条专门治"构建一直失败但 AI 一直在改配置烧 token"的循环。一次构建问题最多消耗 3 次尝试,超出就停下报 BLOCKED,给用户结论性结果,不要把技术决策外包给用户。

熔断格式:

状态:BLOCKED
原因:[1-2 句]
已尝试:[做了什么]
建议:[用户下一步该做什么]

错误处理

| 场景 | 处理 | | ------------------------- | ------------------------------------------------------------ | | 无法判断意图 | 用上方选择题问用户 | | readonly 模式下请求写操作 | "当前为只读模式,无法修改组件库。代码将输出到您的工作目录。" | | 缺少必要输入 | 根据目标 skill 的 args 定义,提示补充 | | 子 skill 文件不存在 | 回退到 one-design 知识包直接回答 | | 知识文件缺失(外部平台) | 使用核心层知识,不报错。见各知识包的「知识分层」章节 |