@lark-apaas/coding-miaoda-sandbox-skills 0.1.0-dev.12ae0d8 → 0.1.0-dev.152c593

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/miaoda/ai-data-processing/SKILL.md +4 -1
  2. package/miaoda/charts-skill/SKILL.md +1 -1
  3. package/miaoda/creative-to-fullstack/SKILL.md +56 -149
  4. package/miaoda/debug-investigation/SKILL.md +17 -8
  5. package/miaoda/feishu/SKILL.md +4 -4
  6. package/miaoda/forms-skill/SKILL.md +46 -4
  7. package/miaoda/lark-apps-db/SKILL.md +34 -31
  8. package/miaoda/lark-apps-db/references/full-reference.md +128 -6
  9. package/miaoda/lark-apps-ops/SKILL.md +11 -5
  10. package/miaoda/lark-apps-ops/references/lark-apps-access-scope-get.md +1 -1
  11. package/miaoda/lark-apps-ops/references/lark-apps-export.md +46 -0
  12. package/miaoda/lark-apps-ops/references/lark-apps-features.md +50 -0
  13. package/miaoda/lark-apps-ops/references/lark-apps-local-dev.md +6 -4
  14. package/miaoda/lark-apps-ops/references/lark-apps-mcp.md +25 -0
  15. package/miaoda/lark-apps-ops/references/lark-apps-release-create.md +13 -6
  16. package/miaoda/lark-apps-ops/references/lark-apps-release-get.md +34 -3
  17. package/miaoda/lark-apps-ops/references/lark-apps-user-id-convert.md +63 -0
  18. package/miaoda/lark-design-prototype/DESIGN.md +603 -0
  19. package/miaoda/lark-design-prototype/SKILL.md +85 -0
  20. package/miaoda/lark-design-prototype/references/assets/card-illustration-library.md +113 -0
  21. package/miaoda/lark-design-prototype/references/case-matching.md +53 -0
  22. package/miaoda/lark-design-prototype/references/cases/conversational-ai-home.md +27 -0
  23. package/miaoda/lark-design-prototype/references/cases/data-table.md +30 -0
  24. package/miaoda/lark-design-prototype/references/cases/official-home.md +26 -0
  25. package/miaoda/lark-design-prototype/references/cases/workspace-home.md +34 -0
  26. package/miaoda/lark-design-prototype/references/color-roles.md +163 -0
  27. package/miaoda/lark-design-prototype/references/component-selection.md +134 -0
  28. package/miaoda/lark-design-prototype/references/design-quality-checklist.md +156 -0
  29. package/miaoda/lark-design-prototype/references/form-shell-patterns.md +77 -0
  30. package/miaoda/lark-design-prototype/references/icon-semantics.md +237 -0
  31. package/miaoda/lark-design-prototype/references/layout-interaction.md +164 -0
  32. package/miaoda/lark-design-prototype/references/page-contract.md +281 -0
  33. package/miaoda/lark-design-prototype/references/product-patterns.md +93 -0
  34. package/miaoda/lark-design-prototype/references/prompt-expansion.md +107 -0
  35. package/miaoda/lark-design-prototype/references/restoration-traps.md +113 -0
  36. package/miaoda/lark-design-prototype/references/token-semantics.md +112 -0
  37. package/miaoda/lark-design-prototype/references/visual-brief.md +125 -0
  38. package/miaoda/lark-design-prototype/references/visual-style-prompts.md +61 -0
  39. package/miaoda/lark-design-prototype/scripts/icon-query.mjs +272 -0
  40. package/miaoda/lark-design-prototype/scripts/token-query.mjs +76 -0
  41. package/miaoda/lark-design-prototype/scripts/verify-static-html.mjs +117 -0
  42. package/miaoda/miaoda-sql/SKILL.md +15 -0
  43. package/miaoda/performance-review/SKILL.md +3 -3
  44. package/miaoda/semantic-search/SKILL.md +6 -4
  45. package/miaoda/table-skill/SKILL.md +2 -0
  46. package/miaoda/testing-guide/SKILL.md +119 -13
  47. package/miaoda-design/lark-apps-comment/SKILL.md +44 -35
  48. package/miaoda-design/lark-apps-ops/SKILL.md +2 -0
  49. package/miaoda-design/lark-apps-ops/references/lark-apps-release-create.md +3 -2
  50. package/miaoda-design/lark-apps-ops/references/lark-apps-release-get.md +34 -3
  51. package/miaoda-modern/charts-skill/SKILL.md +1 -1
  52. package/miaoda-modern/debug-investigation/SKILL.md +1 -1
  53. package/miaoda-modern/forms-skill/SKILL.md +70 -7
  54. package/miaoda-modern/lark-apps-ops/SKILL.md +11 -5
  55. package/miaoda-modern/lark-apps-ops/references/lark-apps-access-scope-get.md +1 -1
  56. package/miaoda-modern/lark-apps-ops/references/lark-apps-export.md +46 -0
  57. package/miaoda-modern/lark-apps-ops/references/lark-apps-features.md +50 -0
  58. package/miaoda-modern/lark-apps-ops/references/lark-apps-local-dev.md +6 -4
  59. package/miaoda-modern/lark-apps-ops/references/lark-apps-mcp.md +25 -0
  60. package/miaoda-modern/lark-apps-ops/references/lark-apps-release-create.md +13 -6
  61. package/miaoda-modern/lark-apps-ops/references/lark-apps-release-get.md +34 -3
  62. package/miaoda-modern/lark-apps-ops/references/lark-apps-user-id-convert.md +63 -0
  63. package/miaoda-modern/lark-design-prototype/DESIGN.md +603 -0
  64. package/miaoda-modern/lark-design-prototype/SKILL.md +85 -0
  65. package/miaoda-modern/lark-design-prototype/references/assets/card-illustration-library.md +113 -0
  66. package/miaoda-modern/lark-design-prototype/references/case-matching.md +53 -0
  67. package/miaoda-modern/lark-design-prototype/references/cases/conversational-ai-home.md +27 -0
  68. package/miaoda-modern/lark-design-prototype/references/cases/data-table.md +30 -0
  69. package/miaoda-modern/lark-design-prototype/references/cases/official-home.md +26 -0
  70. package/miaoda-modern/lark-design-prototype/references/cases/workspace-home.md +34 -0
  71. package/miaoda-modern/lark-design-prototype/references/color-roles.md +163 -0
  72. package/miaoda-modern/lark-design-prototype/references/component-selection.md +134 -0
  73. package/miaoda-modern/lark-design-prototype/references/design-quality-checklist.md +156 -0
  74. package/miaoda-modern/lark-design-prototype/references/form-shell-patterns.md +77 -0
  75. package/miaoda-modern/lark-design-prototype/references/icon-semantics.md +237 -0
  76. package/miaoda-modern/lark-design-prototype/references/layout-interaction.md +164 -0
  77. package/miaoda-modern/lark-design-prototype/references/page-contract.md +281 -0
  78. package/miaoda-modern/lark-design-prototype/references/product-patterns.md +93 -0
  79. package/miaoda-modern/lark-design-prototype/references/prompt-expansion.md +107 -0
  80. package/miaoda-modern/lark-design-prototype/references/restoration-traps.md +113 -0
  81. package/miaoda-modern/lark-design-prototype/references/token-semantics.md +112 -0
  82. package/miaoda-modern/lark-design-prototype/references/visual-brief.md +125 -0
  83. package/miaoda-modern/lark-design-prototype/references/visual-style-prompts.md +61 -0
  84. package/miaoda-modern/lark-design-prototype/scripts/icon-query.mjs +272 -0
  85. package/miaoda-modern/lark-design-prototype/scripts/token-query.mjs +76 -0
  86. package/miaoda-modern/lark-design-prototype/scripts/verify-static-html.mjs +117 -0
  87. package/miaoda-modern/performance-review/SKILL.md +3 -3
  88. package/miaoda-modern/reviewer-usage/SKILL.md +2 -0
  89. package/package.json +1 -1
  90. package/shared/attachment/SKILL.md +5 -1
  91. package/shared/lark-cli/SKILL.md +4 -4
  92. package/shared/lark-cli/lark-base/README.md +7 -2
  93. package/shared/lark-cli/lark-base/references/lark-base-commands.md +20 -5
  94. package/shared/lark-cli/lark-calendar/README.md +1 -1
  95. package/shared/lark-cli/lark-calendar/references/lark-calendar-room-find.md +2 -2
  96. package/shared/lark-cli/lark-doc/README.md +1 -0
  97. package/shared/lark-cli/lark-doc/references/lark-doc-fetch.md +3 -3
  98. package/shared/lark-cli/lark-drive/README.md +36 -7
  99. package/shared/lark-cli/lark-drive/references/lark-drive-batch-query-comments.md +44 -0
  100. package/shared/lark-cli/lark-drive/references/lark-drive-list-replies.md +49 -0
  101. package/shared/lark-cli/lark-im/README.md +0 -14
  102. package/shared/lark-cli/lark-sheets/README.md +6 -5
  103. package/shared/lark-cli/lark-sheets/references/lark-sheets-chart.md +3 -2
  104. package/shared/lark-cli/lark-sheets/references/lark-sheets-filter-view.md +2 -0
  105. package/shared/lark-cli/lark-sheets/references/lark-sheets-read-data.md +95 -24
  106. package/shared/lark-cli/lark-sheets/scripts/lark_detect_subtables.py +596 -0
  107. package/shared/lark-cli/lark-sheets/scripts/lark_inspect_workbook.py +193 -0
  108. package/shared/lark-cli/lark-sheets/scripts/lark_profile_table.py +616 -0
  109. package/shared/lark-cli/lark-sheets/scripts/lark_sheet_range.py +176 -0
  110. package/shared/lark-cli/lark-sheets/scripts/lark_sheet_read_cli.py +221 -0
  111. package/shared/lark-cli/lark-sheets/scripts/sheets_df.py +21 -3
  112. package/shared/lark-cli/lark-slides/README.md +16 -15
  113. package/shared/lark-cli/lark-slides/references/lark-slides-history.md +32 -20
  114. package/shared/lark-cli/lark-slides/references/lark-slides-xml-presentation-slide-get.md +2 -2
  115. package/shared/lark-cli/lark-whiteboard/README.md +1 -2
  116. package/shared/lark-cli/lark-wiki/references/lark-wiki-node-get.md +11 -0
  117. package/shared/lark-cli/lark-wiki/references/lark-wiki-node-list.md +1 -1
  118. package/miaoda/creative-to-fullstack/references/artifact-signals.md +0 -46
  119. package/miaoda/creative-to-fullstack/references/ui-to-function.md +0 -134
  120. package/miaoda-modern/testing-guide/SKILL.md +0 -218
  121. package/shared/dev-channel-probe/SKILL.md +0 -40
@@ -47,6 +47,8 @@ SELECT * FROM rds_ai.list_model();
47
47
 
48
48
  按业务需求选定模型,取其 `model_name` 作为第二个参数。
49
49
 
50
+ ⚠️ **模型可用性由租户管理后台管控。** `list_model()` 返回的是平台预置清单;管理员下架或停用其中某个模型后,平台自动在其余可用预置模型中选择,业务 SQL 无需改动。因此除非用户明确要求锁定模型,否则不传 `model_name`;锁定的模型被停用时,加工结果可能出现风格波动。预置模型全部不可用时调用直接失败,处置见「关键注意事项」。
51
+
50
52
  ## 实现步骤
51
53
 
52
54
  以下 SQL 使用 `tickets` / `priority` 作为示例。Agent 生成实际方案时,必须替换成用户应用里的真实表名、字段名、主键和 `task_kind`。
@@ -378,10 +380,11 @@ LIMIT 20;
378
380
  | ❌ 业务事务路径(同步 trigger / 大批量 UPDATE)里直接调 `rds_ai.ai_query` | HTTP 调用会因网络抖动、限流、超时、模型异常抛错,阻塞业务写入、占锁并产生大额模型调用 | trigger 只入队,模型调用统一由 `ai_run_pending_jobs()` 的 EXCEPTION 块兜住;批量场景先小样本验证,再经 `ai_job` 分批处理 |
379
381
  | ❌ 422 / `quota_exceeded` 报错后继续重试 | 当前应用 AI 调用额度已用完,重试只会继续报错 | 任务直接置 `failed`、停止入队,续费后批量重跑;提示用户「AI 调用额度已耗尽,请联系应用 Owner 在控制台续费或升级套餐后再试」 |
380
382
  | ❌ 429 / `rate_limit_exceeded` 报错后原速重跑 | 调用过于密集触发限流 | 保持重试 + 指数退避;调小 `ai_run_pending_jobs` 单次批量、放慢 worker 节奏;提示用户「AI 调用过于频繁触发了限流,已自动放慢节奏,稍后会继续跑完」 |
383
+ | ❌ 500 / `model_unavailable` 报错后继续重试或继续入队 | 租户预置模型已被全部下架或停用,平台无模型可选,重试不会恢复 | 任务置 `failed` 并停止入队;提示用户「当前租户无可用 AI 模型,请联系租户管理员恢复后再试」;模型恢复后重跑失败任务即可 |
381
384
  | ❌ prompt 不约束输出格式 | 解释性文本会作为脏值写回业务表 | 分类任务写清枚举值并在 SQL 函数里校验结果;JSON 抽取写清 JSON schema |
382
385
  | ❌ trigger 只靠 `UPDATE OF <col>` 判断变化 | 无关更新会重复入队、重复消耗 | 函数里再用 `IS NOT DISTINCT FROM` 判断源字段变化 |
383
386
 
384
- `rds_ai.ai_query` 抛错时,PG 错误信息通常带 HTTP 状态码或 `quota_exceeded` / `rate_limit_exceeded` 关键字;失败任务停在 `ai_job` 表,错误码可从 `error_message` 字段读出供 UI 展示和告警归类。
387
+ `rds_ai.ai_query` 抛错时,PG 错误信息通常带 HTTP 状态码(422 / 429 / 500)或 `quota_exceeded` / `rate_limit_exceeded` / `model_unavailable` 关键字;失败任务停在 `ai_job` 表,错误码可从 `error_message` 字段读出供 UI 展示和告警归类。
385
388
 
386
389
  **禁止**的写法(会阻塞业务写入事务):
387
390
 
@@ -5,7 +5,7 @@ description: "shadcn/ui + ReactECharts 图表开发规范。Use when creating or
5
5
 
6
6
  ## L0 基础配置
7
7
 
8
- - **库**: `import ReactECharts from 'echarts-for-react'` (v5.6.0)
8
+ - **库**: `import ReactECharts from 'echarts-for-react'` (echarts v6.1.x)
9
9
  - **主题**: `theme="ud"`
10
10
  - **颜色**: 🚨 只能用 hex(如 `#1890ff`),禁止 hsl/rgb
11
11
  - **高度**: ≥300px (`className='h-[300px]'`)
@@ -6,152 +6,59 @@ workspace-contains:
6
6
  - source_package/creative/.upgrade-manifest.json
7
7
  ---
8
8
 
9
- # 根据创意设计稿生成全栈应用
10
-
11
- `source_package/creative/` 是一份创意模式产物(UX 设计稿),它定义了应用的外观和功能,两者都要交付:视觉效果原样照抄源稿,功能实现为真实链路。架构从源稿分析得出,数据从源稿原样复制得出,都不允许自行设计或编造。
12
-
13
- 术语约定:**初始数据**指源稿默认展示的内容写入数据库后形成的记录;**源稿定位**指源稿文件路径加行号区间。
14
-
15
- ## Quick Reference
16
-
17
- | 阶段 | 做什么 | 细则 |
18
- |------|--------|------|
19
- | 第 0 步 | 确认素材:读 manifest,写 AGENTS.md 溯源 | 本文档 |
20
- | 第 1 步 | 判定产物类型与支持范围 | `references/artifact-signals.md` |
21
- | 第 2 步 | 分析源稿,产出实现方案(2.1 至 2.7 七份产物) | 本文档 |
22
- | 第 3 步 | 实现:共享骨架、建表与初始数据、插件、并行页面开发 | 本文档 |
23
- | 第 4 步 | 验收:逐字段对照、逐表计数、逐项功能核对 | 本文档 |
24
-
25
- ## 禁止事项
26
-
27
- | 禁止 | 原因 |
28
- |------|------|
29
- | 修改、删除或让构建引用 `source_package/creative/` | 该目录是 UX 权威规格,只读,实现期间要反复对照 |
30
- | 派 Worker 实现却不带源文件、只给文字概述 | Worker 看不到源码必然按概述重画;必须带源文件并命令读源(见 3.5) |
31
- | 交付前端写死业务数据的页面 | 稿内示例数据应写入数据库成为初始数据,页面走真实查询 |
32
- | 改写可见文案、示例数据、条目数量或顺序,或用生成图片替换稿内已有素材 | 默认展示内容和素材也是 UX 规格,不只是布局与配色 |
33
- | 照抄创意稿里用假逻辑模拟的 AI 能力和飞书能力 | 这类能力必须用真实插件实现(见 2.6 与 plugin-guide skill) |
34
- | 把可交互控件做成无事件处理、空链接、占位或假成功反馈 | 可见功能必须产生真实、可验证的结果 |
35
- | 跳过页面清单直接写代码 | 多屏产物不拆清单必然漏页、导航断链 |
36
- | 对范围外产物(deck 演示稿、纯动画、报表看板)做任何生成或转换 | 产品仅支持产品设计与可交互原型,范围外一律停止并告知 |
37
-
38
- ## 第 0 步:确认素材
39
-
40
- 1. 读 `source_package/creative/.upgrade-manifest.json`(字段:`sourceAppId`、`archiveName`、`checkpointId`、`exportedAt`、`fileCount`)。
41
- 2. 目录不存在或为空时,用源应用 ID 重试一次:`miaoda app export <source-app-id> --out source_package/creative --json`;仍失败则告知用户源应用没有可用的设计内容,停止,不要虚构设计稿。
42
- 3. 追加 `AGENTS.md`(不存在则创建)溯源说明:
43
-
44
- > 本应用根据创意设计稿 `<应用名>`(`<sourceAppId>`)生成。`source_package/creative/` 是 UX 权威规格:只读,勿改勿删,勿让构建引用。稿内 `data-miaoda-*` 属性与 `<script type="text/babel">` 是创意平台预览机制,本工程不使用。
45
-
46
- ## 第 1 步:判定产物类型与支持范围
47
-
48
- 读 `source_package/creative/index.html`(及 `components/`、`screens/`,若存在),按 `references/artifact-signals.md` 的信号表判定类型。产品仅支持「产品设计」(多屏设计稿、移动端 mockup 等画布类)与「可交互原型」两类;范围外类型(deck 演示稿、纯动画、报表看板)停止:告知用户不支持,不做静态转换、不虚构功能、不产出代码。
49
-
50
- ## 第 2 步:分析源稿,制定实现方案
51
-
52
- 方案必须包含 2.1 至 2.7 全部产物,任何一项缺失都不得进入第 3 步。
53
-
54
- - 2.1 **页面、路由与导航清单**
55
- - 2.1.1 逐屏扫描源稿,为每一屏(每一个画板)规划一个路由页面,并记录该页面的源稿定位。
56
- - 2.1.2 产出全局路由表并指定默认页。每条路由写明四项:路径模板、对应页面、每个路由参数的真实来源(哪个接口返回的哪个字段)、入口(用户从哪里到达该路由)。全局路由表是唯一权威:后续所有任务接入路由、编写跳转都以它为准,不得自行发明路径。
57
- - 2.1.3 入口规则:每个页面至少有一个入口。带参数的路由,入口必须传入真实数据的参数值(如列表项点击传当前数据的 id);静态导航项只能指向无参数路由,禁止用占位值(demo、default、写死的 ID)拼路径;需要从导航进入带参数页面时,规划无参数的列表页或在路由表写明取哪条真实数据。
58
- - 2.1.4 导航栏、页脚等出现在多个页面上的共享组件单独列出,同样记录源稿定位。
59
- - 2.1.5 清单完成后对照源稿逐屏检查:每一屏都有对应页面、每个页面都有入口、每个路由参数都有真实来源;缺任何一项即清单不完整,立即补齐。
60
- - 2.1.6 页面拆分、导航项处理、设备框处理的细则见 `references/artifact-signals.md`。
61
- - 2.2 **主题 token**
62
- - 2.2.1 把源稿中的 `:root` CSS 变量或主题常量对象整套提取为工程主题 token,色值、字体、间距保持原值。
63
- - 2.3 **数据模型与存放位置**
64
- - 2.3.1 根据源稿中的数据结构推导数据库表、字段和关联关系,推导方法见 `references/ui-to-function.md`。
65
- - 2.3.2 为每一个页面可见的值判定存放位置。存入数据库:需要参与查询、筛选、聚合的值,以及属于单条数据自身内容的视觉值(例如每门课程的封面渐变、每条路径的标识色)。写在前端代码里(组件常量或主题 token):仅用于展示、集合由设计稿固定、不参与任何后端逻辑的纯视觉值(例如分类的字符图标、装饰 emoji、固定区块配色)。
66
- - 2.3.3 统计数字和图表逐项写明展示文案、接口字段、数据库聚合口径和比较周期。文案和口径必须与源稿一致;聚合得出的数值随真实数据变化,不要求等于源稿中的数字。
67
- - 2.4 **初始数据清单**
68
- - 2.4.1 逐页登记每一块默认展示的内容,写明五件事:源稿定位、全部可见字段(文案、字符图标、色值、数值、单位、顺序、默认选中状态)、写入哪张表、经过哪个接口、显示在哪个页面。
69
- - 2.4.2 导航、页脚等共享组件的可见内容(项数、文案、顺序)同样登记,不因为不属于某一个页面而遗漏。
70
- - 2.4.3 清单登记字段名和源稿定位即可,不把大段源码复制进方案。
71
- - 2.5 **可见功能清单**
72
- - 2.5.1 逐页登记源稿中每一个可交互元素,写明四件事:用户做什么操作、应看到什么结果、经过哪条前后端链路实现、如何验收。
73
- - 2.5.2 控件类型与易漏场景的枚举见 `references/ui-to-function.md`。
74
- - 2.6 **插件能力清单**
75
- - 2.6.1 找出源稿中用假逻辑模拟的 AI 能力和飞书能力,逐项登记,实现时调用真实插件。识别信号见 `references/ui-to-function.md`,插件目录与调用规范读取 `plugin-guide` skill。
76
- - 2.6.2 数据库和文件存储不是插件,使用平台内置服务。
77
- - 2.7 **架构边界与验收标准**
78
- - 2.7.1 规划 Layout、shared 类型入口和服务端模块入口(路由与导航结构已在 2.1)。
79
- - 2.7.2 为每一个后续任务写明允许修改的目录范围;多个并行任务不得修改同一个共享文件。
80
- - 2.7.3 为每一个后续任务写一句可验证的完成标准,标准落在真实能力上(如「提交后写入数据库且刷新后仍可见」),不得写成「页面渲染正常」「按钮可以点击」。
81
-
82
- **方案完整性门禁**:用模拟、占位、静态展示、仅 Toast、仅记录日志代替真实功能的方案不完整,必须改为真实实现;能力不可用时写明阻塞原因。方案确认后按方案执行,用 TodoWrite 追踪进度。
83
-
84
- ## 第 3 步:实现
85
-
86
- **任务依赖**:
87
-
88
- - 串行:3.1 共享骨架、3.2 数据库与初始数据、3.3 插件依次完成,然后进入 3.4。
89
- - 并行:3.4 的页面任务相互独立、可以并行;每个页面任务只依赖 3.1 的骨架、自己用到的表和初始数据、自己用到的插件;页面任务之间不得互相依赖。
90
- - 第 4 步验收在全部开发任务完成后进行。
91
-
92
- **通用要求**:动手写任何会产生页面可见内容的代码(页面、组件、初始数据、共享组件)之前,必须重新读取对应的源稿定位。探索阶段读过不算数;上下文经过压缩或大量其他实现之后必须重读。
93
-
94
- - 3.1 **共享骨架**
95
- - 3.1.1 按 2.1 的全局路由表和 2.7 的规划一次性建好全局路由、Layout、shared 类型入口和服务端模块入口;后续任务不得再修改这些共享文件。
96
- - 3.1.2 编写导航、页脚等共享组件之前,先读取 2.1.2 登记的源稿定位;组件的项数、文案、顺序必须与源稿一致。
97
- - 3.1.3 本任务提交时工程必须可以运行:前端有最小可渲染页面,服务端可以编译启动;不得引用后续任务才会创建的文件。
98
- - 3.2 **数据库与初始数据**
99
- - 3.2.1 按 2.3 的数据模型建表。
100
- - 3.2.2 建表完成后立即写入初始数据。按 2.4 清单**一块一块地**处理,每一块都执行同一套动作序列:
101
- - 第一步:读取这一块登记的源稿定位,让这段源稿内容出现在当前上下文里。
102
- - 第二步:立即把这一块的默认展示内容逐字段原样复制成 INSERT 语句,用 `miaoda db sql` 执行。此时源稿内容就在眼前,照着源稿写,不凭记忆写。不改文案,不换近义词,不改数值和单位,色值保持原样,字符图标保持原字符。
103
- - 第三步:用 SELECT 查回刚写入的记录,与第一步读到的源稿逐字段核对(文案、数值、单位、色值、字符图标、顺序);发现不一致立即修正,核对通过后再处理下一块。
104
- - 3.2.3 两条禁止:禁止读完全部源稿后一次性批量写入所有表;禁止不读源稿、凭方案摘要或记忆直接写 INSERT。
105
- - 3.2.4 初始数据必须在本步全部写入数据库,进入页面开发之前已经在库。禁止把初始数据做成运行时接口,禁止由页面在浏览器加载时写入数据,禁止依赖第一个访问者触发写入。
106
- - 3.3 **插件**
107
- - 3.3.1 按 2.6 清单逐个创建插件实例,自检参数与调用方式;禁止手工修改 `server/capabilities/` 目录。
108
- - 3.4 **页面开发**(每个源稿页面一个任务,可并行)
109
- - 3.4.1 读取本页的源稿定位对应内容。本任务只读本页源稿定位与相关 shared 契约文件,缺了按需补读,不得重新推导架构。
110
- - 3.4.2 实现本页的服务端 service 和 controller:做真实查询、写入和聚合,遵守 2.7 的模块边界,不写只做转发的空壳接口。
111
- - 3.4.3 实现本页前端页面:写每个页面和组件之前先读对应源稿定位,按下方视觉还原规则原样还原;页面数据一律来自真实接口调用,禁止在前端写死业务数据。发现本页数据缺失或与源稿不符时,按 3.2.2 的方式补写数据库并在结果中说明,不得在前端内置数据。
112
- - 3.4.4 页面内的组件可以并行开发,完成后集成到页面。
113
- - 3.4.5 自查:前后端类型一致、shared 契约一致、未越出文件边界;本页每个跳转的路径与参数和 2.1 路由表一致,参数值来自真实数据;把本页源稿值与实现值逐字段并排列出对照。
114
- - 3.5 **派工规则**
115
- - 3.5.1 派给 Worker 的每个任务必须把对应的 `source_package/creative/` 源文件放进 `include_files`。
116
- - 3.5.2 任务提示词的第一条指令必须是:先读取该源文件的指定区段,以源码为视觉、文案、布局、数据的唯一权威;提示词文字仅作辅助,与源码冲突时以源码为准。
117
- - 3.5.3 禁止只用文字概述替代源文件;禁止在提示词里改写源稿中的文案、数值和字段。
118
- - 3.5.4 Worker 完成后回传读取过的源稿定位和验收证据;主 Agent 检查代码本身,不能只凭文字汇报下结论。
119
-
120
- ### 视觉还原规则(3.1.2 与 3.4.3 遵守)
121
-
122
- - 布局用 flex 或 grid 加 gap 直接转写源稿布局,不重新设计。
123
- - 页面上一切可见内容(文案、条目数量与顺序、示例值与单位、字符图标、色值、选中状态、素材)与源稿逐字段一致。存入数据库的内容经由初始数据和接口到达页面;写在前端的内容直接从源稿代码复制。
124
- - 字符图标保持原字符,不改成图标库的图标名称。
125
- - 源稿中已有的图片、SVG 和 CSS 渐变必须复用或等价转写,不得用生成的图片替换。
126
- - 内联 SVG、文案、字体声明保留;`miaoda.feishu.cn/fonts` 字体镜像在生产环境可用。
127
- - 确有必要的转换(例如固定画布改响应式)必须在方案中登记转换前后的形态并验证视觉等价;响应式转换不得改变源稿参考尺寸下的构图。
128
-
129
- ### 可见功能规则(3.4 遵守)
130
-
131
- - 源稿中具有交互语义的可见元素必须全部实现;只有源代码和视觉上都明确是装饰的元素可以不实现;不得添加源稿没有展示的功能。
132
- - 页面跳转、Tab 和弹窗必须到达正确的路由或状态;搜索、筛选、排序、分页的参数必须传入真实查询。
133
- - 写操作必须走完「前端事件、接口、数据库或外部能力、界面反馈」的完整链路;写入的结果在刷新后必须仍能读到。
134
- - 持久化的业务结果由服务端校验前提并原子写入,前端只展示重新读取到的事实;可能重复触发的操作要定义重复、并发、超时和中断时的行为。
135
- - 禁止用没有事件处理的控件、空链接、错误路由、只切换图标、写死的结果或假的成功提示冒充功能完成。
136
-
137
- ## 第 4 步:验收与完成标准
138
-
139
- 交付前逐条核验并写进交付说明,任何一条不达标都不算完成:
140
-
141
- - 4.1 **页面**:2.1 清单中的页面全部实现,且沿路由表登记的入口实际操作可以到达;导航项的数量、文案、顺序与源稿逐项一致;没有占位页,没有用空状态冒充的正式页。
142
- - 4.2 **视觉与数据对照**:逐页把源稿和实现并排重读,按 2.4 清单逐字段核对,并列出「源稿值、数据库值、页面渲染值」三列对照;导航、页脚等共享组件单独对照一次。数据库非空、接口 200、条数正确、结构相似都不能代替逐字段核对。
143
- - 4.3 **初始数据**:对 2.4 清单涉及的每张表执行 COUNT 查询,行数与清单登记的条目数一致;页面首次真实查询即可展示源稿的默认内容,不允许交付空表。
144
- - 4.4 **可见功能**:按 2.5 清单逐项从页面入口操作核对,用页面实际发送的参数和响应确认达到约定结果;只验证接口成功不算通过。持久化结果验证正常、重复、不满足前提的操作及刷新后重读;插件验证真实调用结果。
145
- - 4.5 **数据链路**:全部功能走真实查询和写入;前端没有写死的业务数据、没有用 localStorage/sessionStorage 冒充持久化;grep 确认 simulate、setTimeout 写死结果、picsum、假 toast、Math.random 零残留。
146
- - 4.6 **结果汇报**:报告读取过的源稿定位、逐字段对照结论、功能清单通过情况、必要转换清单、未完成项及原因(没有则写「无」);不得只报文件列表或笼统声称完成。
147
- - 4.7 **摘除注入标记**:4.1–4.6 全部通过后执行 `rm -f source_package/creative/.upgrade-manifest.json`。该文件是本指引的注入门控(兼 export 幂等标记与第 0 步信息源,验收通过时后两者已完成使命:溯源已固化进 AGENTS.md,工程侧在应用初始化后也不再重复导出)——删除后本指引停止注入,后续迭代不再受建应用流程干扰;源稿其余文件保留,供以后对照参考。任何一条验收未通过时**不得删除**(下轮修复仍需本指引在场)。
148
-
149
- > 注:commit 静态检查(CheckTask)只覆盖编译、类型和 lint,不能证明视觉一致、功能可用和数据持久化,必须按上表逐项自检。
150
-
151
- ## Common Mistakes
152
-
153
- | 错误 | 正确做法 |
154
- |------|----------|
155
- | 把设备框(iPhone 壳)实现进产品 UI | 只取框内内容做响应式页面 |
156
- | 声明用了某接口就当按钮已实现 | 按 2.5 清单逐项检查事件处理、前后端链路和可观察结果 |
157
- | 生成后仍保留 `source_package/creative/` 的构建引用 | 该目录只读留档,工程代码不依赖它 |
9
+ # 把创意设计稿实现为全栈应用
10
+
11
+ 以 `source_package/creative/` 中的原创意设计应用为依据,在当前工程中交付真实可运行的全栈应用,而不是静态原型。源稿是只读的视觉与业务意图权威,不能作为交付应用的运行时依赖。目标是在保证以下结果的前提下尽快完成。
12
+
13
+ ## 工程规范与最小规划
14
+
15
+ - **开发前必读 `coding-guide`**:使用当前技术栈的工程、共享类型、平台能力及规范。开发 Worker 同样必读,只按需加载专项 skill;不另发明行数/目录规则或限定文件数。在独占页面/模块目录内,首次编码即可按该规范拆私有组件与逻辑文件;必要的后置重构须基于完整源码局部移动,不能依据截断读取整体重写。
16
+ - **先写 `docs/business-design.md` 再编码**:只写支持实现与验收的决策,不誊写源稿视觉细节、实际种子值或逐控件功能全集。正文需覆盖下表,短列表或合并表格均可;同一事实只定义一次。
17
+ - **契约先行**:当前并行批次所需的最小 shared 类型、路由参数、ID/状态/单位口径、实际 schema 与接口落盘可引用后即可开工,不等全部业务契约或公共组件实现完成;代码契约不与文档维护两份字段定义。执行期主 Agent 与 Worker 均不得擅改契约;阻断核心链路时暂停受影响任务,统一修订设计与契约,只通知受影响消费者并调整其任务。
18
+ - 用 TodoWrite 记录实现、验收及未完成项,每批完成或提交前按事实更新。实际阻塞在设计文档中登记,交付时如实披露。
19
+
20
+ ### 业务设计必须回答的问题
21
+
22
+ | 内容 | 最小产出 |
23
+ | --- | --- |
24
+ | 核心链路 | 按用户目标识别核心链路,每条链路定义:真实可见入口与目标对象 → 输入/动作 → 必要中间态 → 真实结果 → 回读位置。链路内各步骤作用于同一目标对象,每一步写入产生的对象、状态及其关联记录须满足下一步操作与回读页所需的数据条件,任一条件不满足即视为链路未闭环。 |
25
+ | 非核心功能 | 不属于任何核心链路的功能点逐项列出,全部保留源稿视觉;其展示数据来自数据库中的真实记录,不实现业务写入、状态流转与外部能力接入。对应控件保持外观并呈现不可用语义,不显示虚假成功,不删除页面或区块。该清单与核心链路清单共同构成本次交付范围,收尾时按同一清单如实说明。 |
26
+ | 页面与视觉来源 | 记录全部源稿页面对应的目标路由/目录、对象参数、源文件/区块,以及用户可见的到达路径;核心结果页明确其上游操作入口。记录全局 Layout 和真正跨页组件的归属,以及素材来源与迁移/复用方案。 |
27
+ | 最小业务模型 | 核心实体、稳定 ID/关联、关键状态及前置条件、必要唯一性与可空规则;初始事实的源稿位置与字段映射,缺失事实按空态展示。 |
28
+ | 接口与结果口径 | 核心动作的必要用户输入、前置条件、状态变化与回读结果在接口契约中一一对应。记录方法/路径、请求/响应类型及 shared 路径、错误/空态语义;动态结果明确事实来源、计算/筛选口径与变化触发。前后端共同引用对象 ID、状态、单位/取整、时间及可空字段口径。平台/插件能力按实际需要选型并确认可用契约。 |
29
+ | 验收与阻塞 | 按源事实定义每条核心链路的可见操作路径、目标对象/状态、可判定的结果与刷新/跨页回读;覆盖相关中间态及动态变化,合并共享链路,另列全页面视觉检查。记录影响核心交付的外部依赖、资源缺失及实际阻塞。 |
30
+
31
+ 设计以能开工、能判定结果为止;不扩成全产品设计、字段血缘大全或多层门禁。遇到新事实只改受影响条目,不反复读写整份文档。视觉实现者直接读取对应源稿,不凭主 Agent 转述实现。
32
+
33
+ ## 交付目标
34
+
35
+ ### 1. 页面视觉效果 100% 还原
36
+
37
+ 保留所有源稿页面、导航、布局、层级、尺寸、间距、字体、颜色、固定文案、素材主体与图表形态。素材优先复用/迁移;不可复用时替代图须保持原用途、主体、色调和裁切。以源稿中的实际业务页面为还原对象。
38
+
39
+ 动态数字来自当前业务事实,保持与源稿一致的单位、格式和排布。视觉验收关注整体呈现效果,允许动态数值和无影响的小图标差异。
40
+
41
+ ### 2. 核心功能完整,操作链路与数据闭环
42
+
43
+ - **承诺与结果一致**:核心动作必须真实完成其业务含义,写入后可按对象 ID 重新查询,成功页刷新/重进仍能显示该结果;仅 toast、跳页、接口 200 或数据库有记录不足以证明闭环。中间态与终态区分,不能提前显示全部完成或过早清空后续页面所需状态。
44
+ - **对象身份一致**:入口、路由参数、详情、子记录和结果内容属于同一对象。已存在的合法对象不能仅因未出现在最近/摘要列表中就不可访问。无效 ID、无关联记录返回明确空态/错误,不能默认第一条记录来掩盖问题;新对象的可空字段不得使详情崩溃,空链接不渲染可点击目标。
45
+ - **事实与状态来源**:初始数据从源稿明确的既有事实映射、去重并建立有依据的关联,保留各对象所处的业务状态。核心操作按业务规则生成必要关联记录,状态、时间与用户输入随实际执行更新;结果页读取执行后的事实。缺失事实如实展示空态,业务完成依据实际状态判定。
46
+ - **动态数据同一口径**:会随业务变化的展示从事实实时计算,不用预置统计字段/常数替代。写入后的计数、进度、余额与聚合联动;周期选择一致作用于标题、明细和统计;分子分母、过程/结算/历史、时钟与取整口径统一。只为本身具有独立业务生命周期的快照保留持久化,不为展示另造真源。
47
+ - **真实能力与明确边界**:核心 AI、媒体和外部能力取得真实结果或明确失败;检索计数/字符串模板不是 AI 回答,动画计时不是播放。按需读取 `plugin-guide` 并确认运行时 schema,不把普通数据库、定位/导航/扫码或内部演示支付机械判成插件。已明确采用内部演示的能力标识模拟边界,并使用一致、可复核的状态/计算,不能伪称外部执行成功;缺少核心资源则报告阻塞。
48
+
49
+ ## 提效时的执行约束
50
+
51
+ - 共享层只准备当前批次必要结构与接口,复用已有模板;不批量造空 API/DTO,主 Agent 不先写完所有服务和 SQL 才派发业务任务。
52
+ - 以独占写入范围拆任务。优先按页面拆前端、按 server module 拆后端,让独立页面、后端模块与种子任务同批开始;不要把多页与整个后端塞进一个长任务。公共层一个写入者;公共组件有稳定接口即可并行消费,不等其实现完成。仅消费必要插件/素材的任务等待其结果,不让无关任务一起等待。
53
+ - 种子数据:CodeAct 写种子数据与业务任务并行,按实际 schema 写入源稿已有对象及必要关联,写入成功即完成。统计数据基于实际数据计算,允许与源稿数值不同;运行时验证统一由主 Agent 完成。
54
+ - 开发任务只检查自己改动的类型/契约等静态问题,达标即返回。不运行接口冒烟、启动服务联调、读运行时日志、读库验收或执行 E2E;运行时验证交由主 Agent 组织,避免开发与测试同时改同一资源。
55
+ - 任务单引用所属核心链路、契约路径和独占写入范围,仅补充本任务特有的实现信息。前后端沿用同一结果、状态与统计口径;契约缺口由主 Agent 定点协调修订。回传改动文件、检查结果、实际阻塞和未完成项。
56
+
57
+ ## 验收准则
58
+
59
+ **验收前必读 `testing-guide`**,使用设计阶段已确定的清单,不在验收阶段重新扩展业务或以实际弱化实现改写通过标准。
60
+
61
+ 1. **真实操作核心链路**:验收从应用首页或正常业务起点开始,通过用户可见的导航、按钮或业务操作到达目标页面,记录入口操作与到达结果。同一核心链路连续使用同一对象;包含创建时,将新建结果用于后续操作。一次执行核对必要输入的保存与回读、关键状态变化、真实结果及关联动态输出,并完成刷新或跨页回读。
62
+ 2. **完整视觉**:覆盖全部源稿页面,逐页确认主要布局、内容、图表、导航与图片;允许动态数值和无影响的小图标差异。
63
+ 3. **针对性修复**:先看失败步骤的请求、ID、状态及相关代码,结合源事实区分应用缺陷、测试假设错误与平台问题;只修核心功能问题或实质视觉问题,不新增身份/权限体系或源稿外业务。已有平台与 coding-guide 约束仍须满足。应用或测试修正、平台恢复后定向复测受影响链路;提交自动修复改变关键行为后也须复测。同一结果复用证据,不重复整套无关验收。不以关键词命中或同名组件一概判错,不搞全库对账。
64
+ 4. **如实交付**:清单逐项记录通过/失败/未测和证据,复测保留各核心功能的实际验收状态,披露核心阻塞。核心功能和视觉验收全部通过后宣称完成,并移除 `source_package/creative/.upgrade-manifest.json` 停止重复注入;其他源稿保留。存在失败或未测项时保留标记与证据,如实交付当前状态。
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: debug-investigation
3
- description: "Debug investigation methodology for the Reviewer agent. LOAD THIS SKILL (via read_file) when caller prompt contains symptom keywords: 卡死 / 白屏 / 修不好 / 修不掉 / 报错 / 定位 bug / 为什么 X 不工作 / 出 bug / 故障 / 已经修了 N 次 / 线上报错 / 线上异常 / 发布后出问题 / 用户反馈线上 / hang / crash / broken / doesn't work / can't figure out / still broken / production error / online issue. For 'user reported symptom, find root cause' tasks. Runs alongside security/performance/correctness review but does not replace them — pattern libraries come from those skills, this skill only owns the investigation flow (Phase 1-3 + 4.5 Architecture Questioning). 触发词:定位 bug, root cause, 症状排查, 线上异常排查"
3
+ description: "Debug investigation methodology for the Reviewer agent. LOAD THIS SKILL (via the Skill tool) when caller prompt contains symptom keywords: 卡死 / 白屏 / 修不好 / 修不掉 / 报错 / 定位 bug / 为什么 X 不工作 / 出 bug / 故障 / 已经修了 N 次 / 线上报错 / 线上异常 / 发布后出问题 / 用户反馈线上 / hang / crash / broken / doesn't work / can't figure out / still broken / production error / online issue. For 'user reported symptom, find root cause' tasks. Runs alongside security/performance/correctness review but does not replace them — pattern libraries come from those skills, this skill only owns the investigation flow (Phase 1-3 + 4.5 Architecture Questioning). 触发词:定位 bug, root cause, 症状排查, 线上异常排查"
4
4
  available-agents:
5
5
  - Reviewer
6
6
  ---
@@ -15,33 +15,42 @@ Reviewer 的工具白名单已物理强制此规则:你无 Edit/Write 权限
15
15
  # Phase 1 — Root Cause Investigation (必做)
16
16
 
17
17
  1. 读 caller prompt 提取症状:What / When / Where / 触发条件,并判定症状
18
- 发生环境:沙箱预览(dev 态) vs 线上(已发布应用)。caller 出现
19
- 线上 / 发布后 / 线上用户反馈 / production / online 等表述 → 按线上处理
18
+ 发生环境:沙箱预览(dev 态) vs 线上(已发布应用)。从 caller 转述的用户
19
+ 原话判断:出现 线上 / 发布后 / 线上用户反馈 / production / online 等表述 →
20
+ 按线上处理;用户描述的是应用使用者看到的现象,或判断不了 → 两条链路都查
21
+ (都是只读)
20
22
  2. 日志证据(按环境选链路,两条链路日志互不相通):
21
23
  - **沙箱 dev 态** → ReadLogs browser / server-devserver / client-devserver /
22
24
  server,找对应错误栈、请求 / 响应、console error
23
25
  - **线上(已发布)** → 见下方「Phase 1 子步骤:线上异常取证」,按当前沙箱
24
26
  的线上观测手册拉线上日志。ReadLogs 读不到线上日志——
25
27
  不要拿沙箱日志当线上症状的证据
28
+ - 一条链路查不到事件痕迹(没有对应请求、没有报错)时,不要下「无法考证」的
29
+ 结论:事件多半发生在另一条链路,先查另一条。数据库查询、审计开关只反映
30
+ 当前状态,说明不了是谁、何时改的
26
31
  3. 近期改动:`git log --oneline -20 <suspected_file>`,必要时看 `git show <sha>`
27
32
  4. 数据流反向追溯(见下方 5 步流程)
28
33
  5. 跨组件证据:即使没法 runtime 埋点,也要在报告里列清每层"当前行为 vs
29
34
  期望行为",指出断点
30
35
 
31
- ## Phase 1 子步骤:线上异常取证(caller 明确描述线上异常时必做)
36
+ ## Phase 1 子步骤:线上异常取证(第 1 步判定需要查线上时必做)
32
37
 
33
- 当 caller 明确描述**线上(已发布)环境**的异常表现时,必须拉取线上日志作为
38
+ 当第 1 步判定需要查**线上(已发布应用)**时,必须拉取线上日志作为
34
39
  证据,禁止只凭静态代码阅读下结论。所有取证在 Phase 1 内完成(Reviewer 的
35
40
  Phase 3 禁止工具调用规则不变)。
36
41
 
37
- 1. **加载命令手册**:Glob 定位当前沙箱的线上观测手册,依次试
38
- `**/lark-apps-ops/references/lark-apps-observability.md` 和
39
- `**/miaoda-cli/references/observability.md`,命中哪份就用 Read 加载哪份。
42
+ 1. **加载命令手册**:在 Available Skills 里找 `lark-apps-ops` 或 `miaoda-cli`,
43
+ 按其 location 推出同目录下的 `references/lark-apps-observability.md` /
44
+ `references/observability.md`,用 Read 加载存在的那份(不要用 Glob / rg
45
+ 在文件系统里搜:`.agent/` 被应用 .gitignore 忽略,会搜不到)。
40
46
  完整命令 / flag / 默认值一律以该文档为准,不要凭记忆拼命令。
41
47
  两份都找不到 → 当前栈不支持线上日志查询,在报告里注明
42
48
  「线上日志不可用」,回退沙箱日志 + 静态分析,不阻塞调查
43
49
  2. **错误日志**:按手册的日志检索条目拉 ERROR 级日志,时间窗按 caller 描述
44
50
  的发生时间收敛(如最近 1 小时);有关键词或具体接口时,按手册支持的方式收窄
51
+ **请求追溯**:要找某个数据 / 资源被哪个请求改动时,不限 ERROR 级,按资源
52
+ id、标题、关键词或接口路径加时间窗检索;日志条目带时间戳、method、path、
53
+ user_id、trace_id,可直接回答「哪个请求、谁、何时」
45
54
  3. **链路追溯**:从日志取 `trace_id`,按手册的 trace 检索条目看完整调用链,
46
55
  定位慢点 / 失败环节
47
56
  4. **前端报错反解源码**:日志含前端错误时,按手册的前端源码反解条目拿到
@@ -143,14 +143,14 @@ npm install @larksuiteoapi/node-sdk
143
143
 
144
144
  ### FeishuService 单例
145
145
 
146
- > ⚠️ **凭证写入源码**:全栈框架不支持自定义环境变量,因此 `FEISHU_APP_ID` 和 `FEISHU_APP_SECRET` 必须直接写在源码常量中,**不要改为 `process.env`**。
146
+ > ⚠️ **凭证直接写入源码常量**:妙搭全栈当前不提供这类飞书自建应用凭证的运行时环境变量注入。用户提供真实的 `FEISHU_APP_ID` 和 `FEISHU_APP_SECRET` 后,直接写入 `FeishuService` 源码常量;不要把它们称为环境变量,也不要改成 `process.env`。在用户提供凭证前,不生成真实值或占位值。
147
147
 
148
148
  ```typescript
149
149
  import { Injectable } from '@nestjs/common';
150
150
  import * as lark from '@larksuiteoapi/node-sdk';
151
151
 
152
- const FEISHU_APP_ID = 'cli_xxxx'; // ← 用户提供的真实值
153
- const FEISHU_APP_SECRET = 'xxxx'; // ← 用户提供的真实值
152
+ const FEISHU_APP_ID = '用户提供的真实 App ID';
153
+ const FEISHU_APP_SECRET = '用户提供的真实 App Secret';
154
154
 
155
155
  @Injectable()
156
156
  export class FeishuService {
@@ -258,7 +258,7 @@ for await (const items of await client.contact.user.listWithIterator({
258
258
 
259
259
  | 错误 | 正确做法 |
260
260
  |------|----------|
261
- | 将凭证改为 process.env 读取 | 全栈框架不支持自定义环境变量,凭证必须写入源码常量 |
261
+ | 把凭证称为环境变量或改用 `process.env` | 按当前全栈平台契约,在用户提供真实凭证后写入 `FeishuService` 源码常量;未提供前不要生成代码中的凭证值 |
262
262
  | `content` 传对象而非 JSON 字符串 | `content: JSON.stringify({ text: 'hello' })` |
263
263
  | 每次请求都新建 `lark.Client` | NestJS `@Injectable()` 单例模式复用 |
264
264
  | `receive_id_type` 与 ID 前缀不匹配 | `oc_` → `chat_id`, `ou_` → `open_id`, `on_` → `union_id` |
@@ -13,6 +13,12 @@ Shadcn Form + React Hook Form + Zod 表单开发。
13
13
  - 所有字段必须有默认值
14
14
  - 必须用 Shadcn 组件,禁止原生 input
15
15
  - 同行 FormField 必须等宽
16
+ - 每个控件都要有能读出来的字段名(读屏和自动化验收都按它找控件):FormField 内用 `FormLabel` + `FormControl`,id 会自动关联;FormField 外的筛选、搜索控件用 `<Label htmlFor="x">` 配控件 `id="x"`,没有可见标签时加 `aria-label`。不要只靠 placeholder 或当前选中值表达字段含义
17
+ - 必填星号加 `aria-hidden="true"`,别让 `*` 混进字段名
18
+ - 字段校验错误用 `<FormMessage />` 显示在字段下方;toast 只用于提交结果(成功 / 接口失败),不要用 toast 提示「请输入 xx」
19
+ - 日期字段用 `Popover` + `Calendar`,`FormControl` 包住触发按钮,禁止 `input[type="date"]`
20
+ - 自定义输入组件(富文本等)也放进 `FormControl`,并把 `id`、`aria-*` 透传到真正可编辑的元素上
21
+ - 表单提交到必填 API/DTO/Request/interface 前,先读目标 shared/server 类型,在 `handleSubmit` 回调里用 `data` 逐字段构造 typed request(见 Patterns);不要整体传 `data`、`schema.parse(data)` 或 `.required().parse(data)`,也不要用 `any`/`as` 绕过 TS2322。修完后跑 LSP 或 `typecheck`。
16
22
 
17
23
  ---
18
24
 
@@ -48,14 +54,14 @@ export function StudentForm() {
48
54
  <div className="flex flex-wrap gap-4">
49
55
  <FormField control={form.control} name="name" render={({ field }) => (
50
56
  <FormItem className="flex-1">
51
- <FormLabel>姓名 <span className="text-destructive">*</span></FormLabel>
57
+ <FormLabel>姓名 <span aria-hidden="true" className="text-destructive">*</span></FormLabel>
52
58
  <FormControl><Input placeholder="请输入姓名" {...field} /></FormControl>
53
59
  <FormMessage />
54
60
  </FormItem>
55
61
  )} />
56
62
  <FormField control={form.control} name="age" render={({ field }) => (
57
63
  <FormItem className="flex-1">
58
- <FormLabel>年龄 <span className="text-destructive">*</span></FormLabel>
64
+ <FormLabel>年龄 <span aria-hidden="true" className="text-destructive">*</span></FormLabel>
59
65
  <FormControl><Input type="number" {...field} /></FormControl>
60
66
  <FormMessage />
61
67
  </FormItem>
@@ -63,7 +69,7 @@ export function StudentForm() {
63
69
  </div>
64
70
  <FormField control={form.control} name="grade" render={({ field }) => (
65
71
  <FormItem>
66
- <FormLabel>年级 <span className="text-destructive">*</span></FormLabel>
72
+ <FormLabel>年级 <span aria-hidden="true" className="text-destructive">*</span></FormLabel>
67
73
  <Select onValueChange={field.onChange} defaultValue={field.value}>
68
74
  <FormControl><SelectTrigger><SelectValue placeholder="请选择" /></SelectTrigger></FormControl>
69
75
  <SelectContent>
@@ -98,7 +104,43 @@ const form = useForm<FormData>({ resolver: zodResolver(schema), defaultValues: {
98
104
  </div>
99
105
 
100
106
  // 必填标记
101
- <FormLabel>字段 <span className="text-destructive">*</span></FormLabel>
107
+ <FormLabel>字段 <span aria-hidden="true" className="text-destructive">*</span></FormLabel>
108
+
109
+ // 表单外的筛选 / 搜索控件:可见标签用 htmlFor + id 关联;没有可见标签必须加 aria-label
110
+ <Label htmlFor="status-filter">状态</Label>
111
+ <Select value={status} onValueChange={setStatus}>
112
+ <SelectTrigger id="status-filter"><SelectValue placeholder="全部状态" /></SelectTrigger>
113
+ <SelectContent>{/* SelectItem ... */}</SelectContent>
114
+ </Select>
115
+ <Input aria-label="搜索姓名或职位" placeholder="搜索姓名或职位" value={keyword} onChange={(e) => setKeyword(e.target.value)} />
116
+
117
+ // 日期:Popover + Calendar,FormControl 包住触发按钮,label 才能关联到它
118
+ <FormField control={form.control} name="dueDate" render={({ field }) => (
119
+ <FormItem>
120
+ <FormLabel>截止日期</FormLabel>
121
+ <Popover>
122
+ <PopoverTrigger asChild>
123
+ <FormControl>
124
+ <Button variant="outline" className="w-full justify-start font-normal">
125
+ {field.value ? dayjs(field.value).format("YYYY-MM-DD") : "请选择日期"}
126
+ </Button>
127
+ </FormControl>
128
+ </PopoverTrigger>
129
+ <PopoverContent className="w-auto p-0" align="start">
130
+ <Calendar mode="single" selected={field.value} onSelect={field.onChange} />
131
+ </PopoverContent>
132
+ </Popover>
133
+ <FormMessage />
134
+ </FormItem>
135
+ )} />
136
+
137
+ // 必填 Request/DTO 桥接:zodResolver 负责运行时校验,DTO 边界负责静态类型匹配。
138
+ // 用 handleSubmit 回调的 data,不要用 getValues(拿到的是 coerce 前的原始值)。
139
+ import type { SaveRequest } from "@/shared/api";
140
+ form.handleSubmit(async (data) => {
141
+ const request: SaveRequest = { field: data.field };
142
+ await api.save(request);
143
+ });
102
144
 
103
145
  // 调试
104
146
  logger.info("errors:", form.formState.errors);