@lark-apaas/coding-miaoda-sandbox-skills 0.1.0-dev.ec88bb5 → 0.1.0-dev.f111120

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 (206) hide show
  1. package/miaoda/ai-data-processing/SKILL.md +4 -1
  2. package/miaoda/animation-skill/SKILL.md +348 -0
  3. package/miaoda/authz-cli/SKILL.md +1 -0
  4. package/miaoda/charts-skill/SKILL.md +264 -0
  5. package/miaoda/creative-to-fullstack/SKILL.md +257 -0
  6. package/miaoda/creative-to-fullstack/references/artifact-signals.md +47 -0
  7. package/miaoda/creative-to-fullstack/references/ui-to-function.md +70 -0
  8. package/miaoda/data-analysis/SKILL.md +151 -0
  9. package/miaoda/data-analysis/references/json-output-specification.md +277 -0
  10. package/miaoda/data-analysis/references/post-analysis-guide.md +77 -0
  11. package/miaoda/data-analysis/references/python-analysis-reference.md +272 -0
  12. package/miaoda/data-analysis/references/tmp-file-management-guide.md +100 -0
  13. package/miaoda/debug-investigation/SKILL.md +21 -18
  14. package/miaoda/extract-json-schema/SKILL.md +147 -0
  15. package/miaoda/feishu/SKILL.md +4 -4
  16. package/miaoda/forms-skill/SKILL.md +9 -0
  17. package/miaoda/lark-apps/SKILL.md +37 -0
  18. package/miaoda/lark-apps/references/openapi-key.md +80 -0
  19. package/miaoda/lark-apps-authz/SKILL.md +292 -0
  20. package/miaoda/lark-apps-authz/references/permission-points.md +39 -0
  21. package/miaoda/lark-apps-authz/references/role.md +122 -0
  22. package/miaoda/lark-apps-db/SKILL.md +221 -0
  23. package/miaoda/lark-apps-db/references/full-reference.md +422 -0
  24. package/miaoda/lark-apps-file/SKILL.md +216 -0
  25. package/miaoda/lark-apps-ops/SKILL.md +64 -0
  26. package/miaoda/lark-apps-ops/references/lark-apps-access-scope-get.md +30 -0
  27. package/miaoda/lark-apps-ops/references/lark-apps-access-scope-set.md +40 -0
  28. package/miaoda/lark-apps-ops/references/lark-apps-cache.md +62 -0
  29. package/miaoda/lark-apps-ops/references/lark-apps-env.md +46 -0
  30. package/miaoda/lark-apps-ops/references/lark-apps-local-dev.md +26 -0
  31. package/miaoda/lark-apps-ops/references/lark-apps-mcp.md +26 -0
  32. package/miaoda/lark-apps-ops/references/lark-apps-member.md +93 -0
  33. package/miaoda/lark-apps-ops/references/lark-apps-observability.md +46 -0
  34. package/miaoda/lark-apps-ops/references/lark-apps-plugin-install.md +36 -0
  35. package/miaoda/lark-apps-ops/references/lark-apps-plugin-list.md +23 -0
  36. package/miaoda/lark-apps-ops/references/lark-apps-plugin-uninstall.md +25 -0
  37. package/miaoda/lark-apps-ops/references/lark-apps-release-create.md +30 -0
  38. package/miaoda/lark-apps-ops/references/lark-apps-release-get.md +28 -0
  39. package/miaoda/lark-apps-ops/references/lark-apps-release-list.md +31 -0
  40. package/miaoda/lark-apps-ops/references/lark-apps-update.md +30 -0
  41. package/miaoda/lark-apps-ops/references/lark-apps-user-id-convert.md +63 -0
  42. package/miaoda/lark-apps-ops/references/openapi-key.md +80 -0
  43. package/miaoda/lark-design-prototype/DESIGN.md +603 -0
  44. package/miaoda/lark-design-prototype/SKILL.md +85 -0
  45. package/miaoda/lark-design-prototype/references/assets/card-illustration-library.md +113 -0
  46. package/miaoda/lark-design-prototype/references/case-matching.md +53 -0
  47. package/miaoda/lark-design-prototype/references/cases/conversational-ai-home.md +27 -0
  48. package/miaoda/lark-design-prototype/references/cases/data-table.md +30 -0
  49. package/miaoda/lark-design-prototype/references/cases/official-home.md +26 -0
  50. package/miaoda/lark-design-prototype/references/cases/workspace-home.md +34 -0
  51. package/miaoda/lark-design-prototype/references/color-roles.md +163 -0
  52. package/miaoda/lark-design-prototype/references/component-selection.md +134 -0
  53. package/miaoda/lark-design-prototype/references/design-quality-checklist.md +156 -0
  54. package/miaoda/lark-design-prototype/references/form-shell-patterns.md +77 -0
  55. package/miaoda/lark-design-prototype/references/icon-semantics.md +237 -0
  56. package/miaoda/lark-design-prototype/references/layout-interaction.md +164 -0
  57. package/miaoda/lark-design-prototype/references/page-contract.md +281 -0
  58. package/miaoda/lark-design-prototype/references/product-patterns.md +93 -0
  59. package/miaoda/lark-design-prototype/references/prompt-expansion.md +107 -0
  60. package/miaoda/lark-design-prototype/references/restoration-traps.md +113 -0
  61. package/miaoda/lark-design-prototype/references/token-semantics.md +112 -0
  62. package/miaoda/lark-design-prototype/references/visual-brief.md +125 -0
  63. package/miaoda/lark-design-prototype/references/visual-style-prompts.md +61 -0
  64. package/miaoda/lark-design-prototype/scripts/icon-query.mjs +272 -0
  65. package/miaoda/lark-design-prototype/scripts/token-query.mjs +76 -0
  66. package/miaoda/lark-design-prototype/scripts/verify-static-html.mjs +117 -0
  67. package/miaoda/miaoda-file/SKILL.md +1 -0
  68. package/miaoda/miaoda-sql/SKILL.md +15 -2
  69. package/miaoda/performance-review/SKILL.md +144 -0
  70. package/miaoda/performance-review/references/business-analyzer.md +139 -0
  71. package/miaoda/performance-review/references/examples.md +107 -0
  72. package/miaoda/semantic-search/SKILL.md +6 -4
  73. package/miaoda/table-skill/SKILL.md +2 -0
  74. package/{shared → miaoda}/testing-guide/SKILL.md +109 -13
  75. package/miaoda-design/lark-apps-comment/SKILL.md +119 -0
  76. package/miaoda-design/lark-apps-ops/SKILL.md +45 -0
  77. package/miaoda-design/lark-apps-ops/references/lark-apps-release-create.md +51 -0
  78. package/miaoda-design/lark-apps-ops/references/lark-apps-release-get.md +28 -0
  79. package/miaoda-design/lark-apps-ops/references/lark-apps-release-list.md +31 -0
  80. package/miaoda-design/lark-apps-ops/references/lark-apps-update.md +33 -0
  81. package/{shared → miaoda-modern}/charts-skill/SKILL.md +1 -1
  82. package/miaoda-modern/forms-skill/SKILL.md +33 -3
  83. package/{shared → miaoda-modern}/lark-apps/SKILL.md +5 -5
  84. package/miaoda-modern/lark-apps/references/openapi-key.md +80 -0
  85. package/miaoda-modern/lark-apps-ops/SKILL.md +64 -0
  86. package/miaoda-modern/lark-apps-ops/references/lark-apps-access-scope-get.md +30 -0
  87. package/miaoda-modern/lark-apps-ops/references/lark-apps-access-scope-set.md +40 -0
  88. package/miaoda-modern/lark-apps-ops/references/lark-apps-cache.md +62 -0
  89. package/miaoda-modern/lark-apps-ops/references/lark-apps-env.md +46 -0
  90. package/miaoda-modern/lark-apps-ops/references/lark-apps-local-dev.md +26 -0
  91. package/miaoda-modern/lark-apps-ops/references/lark-apps-mcp.md +26 -0
  92. package/miaoda-modern/lark-apps-ops/references/lark-apps-member.md +93 -0
  93. package/miaoda-modern/lark-apps-ops/references/lark-apps-observability.md +46 -0
  94. package/miaoda-modern/lark-apps-ops/references/lark-apps-plugin-install.md +36 -0
  95. package/miaoda-modern/lark-apps-ops/references/lark-apps-plugin-list.md +23 -0
  96. package/miaoda-modern/lark-apps-ops/references/lark-apps-plugin-uninstall.md +25 -0
  97. package/miaoda-modern/lark-apps-ops/references/lark-apps-release-create.md +30 -0
  98. package/miaoda-modern/lark-apps-ops/references/lark-apps-release-get.md +28 -0
  99. package/miaoda-modern/lark-apps-ops/references/lark-apps-release-list.md +31 -0
  100. package/miaoda-modern/lark-apps-ops/references/lark-apps-update.md +30 -0
  101. package/miaoda-modern/lark-apps-ops/references/lark-apps-user-id-convert.md +63 -0
  102. package/{shared/lark-apps → miaoda-modern/lark-apps-ops}/references/openapi-key.md +3 -3
  103. package/miaoda-modern/lark-design-prototype/DESIGN.md +603 -0
  104. package/miaoda-modern/lark-design-prototype/SKILL.md +85 -0
  105. package/miaoda-modern/lark-design-prototype/references/assets/card-illustration-library.md +113 -0
  106. package/miaoda-modern/lark-design-prototype/references/case-matching.md +53 -0
  107. package/miaoda-modern/lark-design-prototype/references/cases/conversational-ai-home.md +27 -0
  108. package/miaoda-modern/lark-design-prototype/references/cases/data-table.md +30 -0
  109. package/miaoda-modern/lark-design-prototype/references/cases/official-home.md +26 -0
  110. package/miaoda-modern/lark-design-prototype/references/cases/workspace-home.md +34 -0
  111. package/miaoda-modern/lark-design-prototype/references/color-roles.md +163 -0
  112. package/miaoda-modern/lark-design-prototype/references/component-selection.md +134 -0
  113. package/miaoda-modern/lark-design-prototype/references/design-quality-checklist.md +156 -0
  114. package/miaoda-modern/lark-design-prototype/references/form-shell-patterns.md +77 -0
  115. package/miaoda-modern/lark-design-prototype/references/icon-semantics.md +237 -0
  116. package/miaoda-modern/lark-design-prototype/references/layout-interaction.md +164 -0
  117. package/miaoda-modern/lark-design-prototype/references/page-contract.md +281 -0
  118. package/miaoda-modern/lark-design-prototype/references/product-patterns.md +93 -0
  119. package/miaoda-modern/lark-design-prototype/references/prompt-expansion.md +107 -0
  120. package/miaoda-modern/lark-design-prototype/references/restoration-traps.md +113 -0
  121. package/miaoda-modern/lark-design-prototype/references/token-semantics.md +112 -0
  122. package/miaoda-modern/lark-design-prototype/references/visual-brief.md +125 -0
  123. package/miaoda-modern/lark-design-prototype/references/visual-style-prompts.md +61 -0
  124. package/miaoda-modern/lark-design-prototype/scripts/icon-query.mjs +272 -0
  125. package/miaoda-modern/lark-design-prototype/scripts/token-query.mjs +76 -0
  126. package/miaoda-modern/lark-design-prototype/scripts/verify-static-html.mjs +117 -0
  127. package/miaoda-modern/memory/SKILL.md +86 -0
  128. package/miaoda-modern/reviewer-usage/SKILL.md +113 -0
  129. package/package.json +1 -1
  130. package/shared/attachment/SKILL.md +5 -1
  131. package/shared/lark-cli/SKILL.md +221 -0
  132. package/shared/lark-cli/lark-base/README.md +56 -0
  133. package/shared/lark-cli/lark-base/references/lark-base-commands.md +108 -0
  134. package/shared/lark-cli/lark-calendar/README.md +158 -0
  135. package/shared/lark-cli/lark-calendar/references/lark-calendar-meeting.md +30 -0
  136. package/shared/lark-cli/lark-calendar/references/lark-calendar-room-find.md +108 -0
  137. package/shared/lark-cli/lark-calendar/references/lark-calendar-suggestion.md +120 -0
  138. package/shared/lark-cli/lark-contact/README.md +35 -0
  139. package/shared/lark-cli/lark-contact/references/lark-contact-get-user.md +13 -0
  140. package/shared/lark-cli/lark-contact/references/lark-contact-search-user.md +121 -0
  141. package/shared/lark-cli/lark-doc/README.md +67 -0
  142. package/shared/lark-cli/lark-doc/references/lark-doc-fetch.md +138 -0
  143. package/shared/lark-cli/lark-doc/references/lark-doc-history.md +61 -0
  144. package/shared/lark-cli/lark-drive/README.md +158 -0
  145. package/shared/lark-cli/lark-drive/references/lark-drive-batch-query-comments.md +44 -0
  146. package/shared/lark-cli/lark-drive/references/lark-drive-files-list.md +183 -0
  147. package/shared/lark-cli/lark-drive/references/lark-drive-list-replies.md +49 -0
  148. package/shared/lark-cli/lark-im/README.md +70 -0
  149. package/shared/lark-cli/lark-im/references/lark-im-chat-list.md +140 -0
  150. package/shared/lark-cli/lark-im/references/lark-im-chat-members-list.md +84 -0
  151. package/shared/lark-cli/lark-im/references/lark-im-chat-search.md +135 -0
  152. package/shared/lark-cli/lark-im/references/lark-im-reactions.md +232 -0
  153. package/shared/lark-cli/lark-minutes/README.md +51 -0
  154. package/shared/lark-cli/lark-minutes/references/lark-minutes-download.md +130 -0
  155. package/shared/lark-cli/lark-sheets/README.md +174 -0
  156. package/shared/lark-cli/lark-sheets/references/lark-sheets-changeset.md +105 -0
  157. package/shared/lark-cli/lark-sheets/references/lark-sheets-chart.md +45 -0
  158. package/shared/lark-cli/lark-sheets/references/lark-sheets-conditional-format.md +42 -0
  159. package/shared/lark-cli/lark-sheets/references/lark-sheets-filter-view.md +49 -0
  160. package/shared/lark-cli/lark-sheets/references/lark-sheets-filter.md +42 -0
  161. package/shared/lark-cli/lark-sheets/references/lark-sheets-float-image.md +43 -0
  162. package/shared/lark-cli/lark-sheets/references/lark-sheets-formula-verify.md +64 -0
  163. package/shared/lark-cli/lark-sheets/references/lark-sheets-history.md +70 -0
  164. package/shared/lark-cli/lark-sheets/references/lark-sheets-pivot-table.md +44 -0
  165. package/shared/lark-cli/lark-sheets/references/lark-sheets-read-data.md +286 -0
  166. package/shared/lark-cli/lark-sheets/references/lark-sheets-search-replace.md +67 -0
  167. package/shared/lark-cli/lark-sheets/references/lark-sheets-sheet-structure.md +52 -0
  168. package/shared/lark-cli/lark-sheets/references/lark-sheets-sparkline.md +47 -0
  169. package/shared/lark-cli/lark-sheets/references/lark-sheets-workbook.md +69 -0
  170. package/shared/lark-cli/lark-sheets/scripts/lark_detect_subtables.py +593 -0
  171. package/shared/lark-cli/lark-sheets/scripts/lark_inspect_workbook.py +188 -0
  172. package/shared/lark-cli/lark-sheets/scripts/lark_profile_table.py +614 -0
  173. package/shared/lark-cli/lark-sheets/scripts/lark_sheet_range.py +176 -0
  174. package/shared/lark-cli/lark-sheets/scripts/lark_sheet_read_cli.py +184 -0
  175. package/shared/lark-cli/lark-sheets/scripts/sheets_df.py +50 -0
  176. package/shared/lark-cli/lark-slides/README.md +87 -0
  177. package/shared/lark-cli/lark-slides/references/lark-slides-history.md +117 -0
  178. package/shared/lark-cli/lark-slides/references/lark-slides-xml-presentation-slide-get.md +108 -0
  179. package/shared/lark-cli/lark-slides/references/lark-slides-xml-presentations-get.md +77 -0
  180. package/shared/lark-cli/lark-task/README.md +93 -0
  181. package/shared/lark-cli/lark-task/references/lark-task-get-my-tasks.md +57 -0
  182. package/shared/lark-cli/lark-task/references/lark-task-get-related-tasks.md +49 -0
  183. package/shared/lark-cli/lark-task/references/lark-task-search.md +36 -0
  184. package/shared/lark-cli/lark-task/references/lark-task-tasklist-search.md +35 -0
  185. package/shared/lark-cli/lark-vc/README.md +40 -0
  186. package/shared/lark-cli/lark-vc/references/lark-vc-recording.md +31 -0
  187. package/shared/lark-cli/lark-whiteboard/README.md +34 -0
  188. package/shared/lark-cli/lark-whiteboard/references/lark-whiteboard-export.md +59 -0
  189. package/shared/lark-cli/lark-wiki/README.md +50 -0
  190. package/shared/lark-cli/lark-wiki/references/lark-wiki-node-get.md +70 -0
  191. package/shared/lark-cli/lark-wiki/references/lark-wiki-node-list.md +95 -0
  192. package/shared/lark-cli/lark-wiki/references/lark-wiki-space-list.md +68 -0
  193. package/miaoda-design/attachment/SKILL.md +0 -58
  194. package/shared/dev-channel-probe/SKILL.md +0 -40
  195. /package/{shared → miaoda}/memory/SKILL.md +0 -0
  196. /package/{shared → miaoda}/reviewer-usage/SKILL.md +0 -0
  197. /package/{shared → miaoda-modern}/animation-skill/SKILL.md +0 -0
  198. /package/{shared → miaoda-modern}/data-analysis/SKILL.md +0 -0
  199. /package/{shared → miaoda-modern}/data-analysis/references/json-output-specification.md +0 -0
  200. /package/{shared → miaoda-modern}/data-analysis/references/post-analysis-guide.md +0 -0
  201. /package/{shared → miaoda-modern}/data-analysis/references/python-analysis-reference.md +0 -0
  202. /package/{shared → miaoda-modern}/data-analysis/references/tmp-file-management-guide.md +0 -0
  203. /package/{shared → miaoda-modern}/extract-json-schema/SKILL.md +0 -0
  204. /package/{shared → miaoda-modern}/performance-review/SKILL.md +0 -0
  205. /package/{shared → miaoda-modern}/performance-review/references/business-analyzer.md +0 -0
  206. /package/{shared → miaoda-modern}/performance-review/references/examples.md +0 -0
@@ -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
 
@@ -0,0 +1,348 @@
1
+ ---
2
+ name: animation-skill
3
+ description: "React 动画动效开发规范(Framer Motion + AutoAnimate)。只要页面/组件涉及任何动画或动效——无论大小、无论是否紧急——都调用本 skill 获取实现规范再动手。选型优先级:列表增量增删/排序/accordion/toast/form-error 场景优先 AutoAnimate(3.28KB、零配置);退场/手势/布局/stagger 序列/滚动揭示/批量替换才用 Framer Motion(34KB)。"
4
+ ---
5
+
6
+ ## 依赖安装(前置动作)
7
+
8
+ 使用 Framer Motion 或 AutoAnimate 前,**必须先检查 `package.json`,缺失则调用 `依赖管理工具` 安装**,禁止在未安装时直接写 `import` 代码。
9
+
10
+ | 场景 | 包名 | 安装命令 |
11
+ |------|------|---------|
12
+ | Framer Motion(退场/手势/布局/滚动驱动/序列) | `framer-motion` | `npm install framer-motion` |
13
+ | AutoAnimate(列表增删/排序/accordion/toast) | `@formkit/auto-animate` | `npm install @formkit/auto-animate` |
14
+
15
+ **检查流程**:
16
+ 1. 读 `package.json`,确认所需包是否存在
17
+ 2. 不存在 → 调用依赖管理工具安装(禁止手动改 `package.json` 或跑 `npm i` 之外的命令)
18
+ 3. 已存在 → 直接使用,无需重复安装
19
+
20
+ ---
21
+
22
+ ## 选型决策流程
23
+
24
+ ```
25
+ 需要动画 → 能用 CSS/Tailwind 解决? → 是 → CSS transition / @keyframes
26
+ → 否 ↓
27
+ 是否列表增量增删/排序/accordion/toast/form-error?
28
+ → 是 → AutoAnimate(3.28KB gzip)
29
+ → 否 ↓
30
+ 需要手势/退场/布局/滚动驱动/stagger 序列/整批替换?
31
+ → 否 → CSS transition(同第一步)
32
+ → 是 → Framer Motion(~34KB gzip)
33
+ ```
34
+
35
+ **「增量增删」与「整批替换」的区分**(常见误判,AutoAnimate 的边界):
36
+
37
+ | 场景 | 属于 | 正确方案 |
38
+ |------|------|---------|
39
+ | Todo 列表新增一项 / 删除一项 / 拖动排序 | 增量增删 | **AutoAnimate** |
40
+ | Kanban 任务在列间移动 / 新增卡片 | 增量增删 | **AutoAnimate** |
41
+ | Accordion 展开/折叠子项 | 直接子元素显隐 | **AutoAnimate** |
42
+ | Toast 通知栈 push/pop | 增量进出 | **AutoAnimate** |
43
+ | Form 错误信息出现/消失 | 直接子元素显隐 | **AutoAnimate** |
44
+ | 搜索/筛选结果**整列表重新生成** | 整批替换 | **Framer Motion `AnimatePresence mode="wait"`** |
45
+ | 分组算法重新洗牌,所有卡片重建 | 整批替换 | **Framer Motion `AnimatePresence + stagger`** |
46
+ | Diff 结果重新比对,所有 diff 块重建 | 整批替换 | **Framer Motion `AnimatePresence mode="wait"`** |
47
+ | Tab 切换导致内容区整体替换 | 整批替换 | **Framer Motion `AnimatePresence`** |
48
+
49
+ > 判断要点:**同一批数据增减 1~几个条目 → 增量(AutoAnimate);数据源整体换新 → 批量(Framer Motion)**。
50
+
51
+ **优先级原则**:命中「列表增量增删 / 排序 / accordion / toast / form-error」先选 AutoAnimate,体积小、零配置;只有需要退场 mode、手势、布局 FLIP、stagger 序列、滚动揭示、整批替换这些 AutoAnimate 覆盖不到的能力时,才升级到 Framer Motion。不要为了统一技术栈把所有动画都塞进 Framer Motion。
52
+
53
+ **包体积对比:**
54
+
55
+ | 方案 | Gzip 体积 | 覆盖能力 |
56
+ |------|----------|---------|
57
+ | AutoAnimate | ~3.28 KB | 列表增量增删排序、accordion、toast、form-error |
58
+ | Framer Motion | ~34 KB | 全部(退场、手势、布局、MotionValue、stagger 序列、整批替换) |
59
+
60
+ ---
61
+
62
+ ## L2 禁止事项
63
+
64
+ > 生成代码后须逐条核对,每一条都不可跳过。
65
+
66
+ | # | 禁止 | 应该 |
67
+ |---|------|------|
68
+ | 1 | 动画 `width`/`height`/`top`/`left` 等触发 layout 的属性 | 使用 `transform`(`x`/`y`/`scale`/`rotate`)+ `opacity` |
69
+ | 2 | 在 Next.js Server Component 中使用 `motion` | 添加 `"use client"`,动画部分提取为 Client Component |
70
+ | 3 | `AnimatePresence` 内条件渲染子组件不给 `key` | 必须有唯一 `key`,否则退场动画不触发 |
71
+ | 4 | 弹窗/toast 退场无动画直接卸载 | 用 `AnimatePresence` 包裹 + `exit` prop |
72
+ | 5 | `spring` 不设 `damping` 导致无限弹跳 | 设置 `stiffness`(100-300)+ `damping`(10-30) |
73
+ | 6 | AutoAnimate 期望对孙元素生效 | 只对**直接子元素**生效;嵌套层级需逐层挂 ref |
74
+
75
+ ---
76
+
77
+ ## Framer Motion 核心用法
78
+
79
+ {% raw %}
80
+
81
+ ### 1. 基础动画(initial / animate / transition)
82
+
83
+ ```tsx
84
+ import { motion } from "framer-motion";
85
+
86
+ <motion.div
87
+ initial={{ opacity: 0, y: 20 }}
88
+ animate={{ opacity: 1, y: 0 }}
89
+ transition={{ duration: 0.5 }}
90
+ >
91
+ 内容
92
+ </motion.div>
93
+ ```
94
+
95
+ ### 2. 退场动画(AnimatePresence)
96
+
97
+ ```tsx
98
+ import { AnimatePresence, motion } from "framer-motion";
99
+
100
+ <AnimatePresence>
101
+ {show && (
102
+ <motion.div
103
+ key="modal"
104
+ initial={{ opacity: 0, scale: 0.95 }}
105
+ animate={{ opacity: 1, scale: 1 }}
106
+ exit={{ opacity: 0, scale: 0.95 }}
107
+ transition={{ duration: 0.2 }}
108
+ />
109
+ )}
110
+ </AnimatePresence>
111
+ ```
112
+
113
+ ### 3. Variants + Stagger
114
+
115
+ ```tsx
116
+ const container = {
117
+ hidden: {},
118
+ visible: { transition: { staggerChildren: 0.1, delayChildren: 0.2 } },
119
+ };
120
+ const item = {
121
+ hidden: { opacity: 0, y: 20 },
122
+ visible: { opacity: 1, y: 0 },
123
+ };
124
+
125
+ <motion.ul variants={container} initial="hidden" animate="visible">
126
+ {items.map((i) => (
127
+ <motion.li key={i.id} variants={item}>{i.name}</motion.li>
128
+ ))}
129
+ </motion.ul>
130
+ ```
131
+
132
+ ### 4. 手势动画
133
+
134
+ ```tsx
135
+ <motion.button
136
+ whileHover={{ scale: 1.05, backgroundColor: "#3b82f6" }}
137
+ whileTap={{ scale: 0.95 }}
138
+ whileFocus={{ boxShadow: "0 0 0 3px rgba(59,130,246,0.5)" }}
139
+ >
140
+ 按钮
141
+ </motion.button>
142
+
143
+ // 拖拽
144
+ <motion.div
145
+ drag="x"
146
+ dragConstraints={{ left: -100, right: 100 }}
147
+ dragElastic={0.2}
148
+ dragMomentum={false} // 关闭释放后惯性(默认 true)
149
+ onDragStart={(e, info) => { /* 用 info.point 更新 state 或触发副作用,禁止 console.log */ }}
150
+ onDrag={(e, info) => { /* 用 info.delta 计算偏移,可结合 useTransform 派生动画值 */ }}
151
+ onDragEnd={(e, info) => { /* 用 info.velocity 决定释放后行为(如滑动到吸附点) */ }}
152
+ />
153
+ ```
154
+
155
+ ### 5. 滚动动画
156
+
157
+ **whileInView(最常用):**
158
+
159
+ ```tsx
160
+ <motion.div
161
+ initial={{ opacity: 0, y: 50 }}
162
+ whileInView={{ opacity: 1, y: 0 }}
163
+ viewport={{ once: true, margin: "-100px" }}
164
+ transition={{ duration: 0.6 }}
165
+ >
166
+ 滚动到视口时显现
167
+ </motion.div>
168
+ ```
169
+
170
+ **useScroll 进度驱动:**
171
+
172
+ ```tsx
173
+ import { motion, useScroll, useTransform } from "framer-motion";
174
+
175
+ const { scrollYProgress } = useScroll();
176
+ const opacity = useTransform(scrollYProgress, [0, 0.5, 1], [1, 0.5, 0]);
177
+ const y = useTransform(scrollYProgress, [0, 1], [0, -200]);
178
+
179
+ <motion.div style={{ y, opacity }}>视差内容</motion.div>
180
+ ```
181
+
182
+ ### 6. 布局动画
183
+
184
+ **layout prop(位置/尺寸 FLIP 动画):**
185
+
186
+ ```tsx
187
+ <motion.div
188
+ layout
189
+ style={{ width: expanded ? 300 : 100 }}
190
+ transition={{ layout: { duration: 0.3 } }}
191
+ >
192
+ {expanded && <motion.p layout="position">详情</motion.p>}
193
+ </motion.div>
194
+ ```
195
+
196
+ **LayoutGroup + layoutId(Tabs underline 经典用例):**
197
+
198
+ ```tsx
199
+ import { LayoutGroup, motion } from "framer-motion";
200
+
201
+ <LayoutGroup>
202
+ {tabs.map((tab, i) => (
203
+ <button key={tab} onClick={() => onSelect(i)} style={{ position: "relative" }}>
204
+ {tab}
205
+ {selected === i && (
206
+ <motion.div
207
+ layoutId="underline"
208
+ style={{
209
+ position: "absolute", bottom: 0, left: 0, right: 0,
210
+ height: 2, background: "#3b82f6",
211
+ }}
212
+ />
213
+ )}
214
+ </button>
215
+ ))}
216
+ </LayoutGroup>
217
+ ```
218
+
219
+ ### 7. useAnimate 命令式序列
220
+
221
+ ```tsx
222
+ import { useAnimate, motion } from "framer-motion";
223
+
224
+ const [scope, animate] = useAnimate();
225
+
226
+ const handleClick = async () => {
227
+ await animate(scope.current, { scale: 1.2 });
228
+ await animate(scope.current, { rotate: 180 });
229
+ await animate(scope.current, { scale: 1, rotate: 0 });
230
+ };
231
+
232
+ <motion.div ref={scope} onClick={handleClick}>点击播放序列</motion.div>
233
+ ```
234
+
235
+ ### 8. MotionValue 响应式联动
236
+
237
+ ```tsx
238
+ import { motion, useMotionValue, useTransform } from "framer-motion";
239
+
240
+ const x = useMotionValue(0);
241
+ const opacity = useTransform(x, [-200, 0, 200], [0, 1, 0]);
242
+ const background = useTransform(x, [-200, 0, 200], ["#ff0000", "#00ff00", "#0000ff"]);
243
+
244
+ <motion.div drag="x" style={{ x, opacity, background }} />
245
+ ```
246
+
247
+ ### 9. 实用模式
248
+
249
+ **Loading Skeleton:**
250
+
251
+ ```tsx
252
+ <motion.div
253
+ animate={{ opacity: [0.5, 1, 0.5] }}
254
+ transition={{ duration: 1.5, repeat: Infinity }}
255
+ className="bg-gray-200 rounded h-4"
256
+ />
257
+ ```
258
+
259
+ **Number Counter:**
260
+
261
+ ```tsx
262
+ import { useEffect } from "react";
263
+ import { useSpring, useTransform, motion } from "framer-motion";
264
+
265
+ const spring = useSpring(0, { stiffness: 100, damping: 30 });
266
+ const display = useTransform(spring, (v) => Math.round(v));
267
+
268
+ useEffect(() => { spring.set(value); }, [value, spring]);
269
+
270
+ <motion.span>{display}</motion.span>
271
+ ```
272
+
273
+ {% endraw %}
274
+
275
+ ---
276
+
277
+ ## Transition 速查
278
+
279
+ | 类型 | 关键参数 | 适用场景 | 示例 |
280
+ |------|---------|---------|------|
281
+ | `spring` | `stiffness`, `damping`, `mass` | 自然弹性效果(默认) | `{ type: "spring", stiffness: 200, damping: 20 }` |
282
+ | `tween` | `duration`, `ease` | 精确时长控制 | `{ type: "tween", duration: 0.3, ease: "easeOut" }` |
283
+ | `inertia` | `velocity`, `power` | 拖拽释放惯性 | `{ type: "inertia", velocity: 200 }` |
284
+
285
+ **Ease presets:** `linear` · `easeIn` · `easeOut` · `easeInOut` · `circIn` · `circOut` · `backIn` · `backOut` · `anticipate`
286
+
287
+ **时长原则:** UI 动画 200-500ms;微交互 100-200ms;退场比进场短。
288
+
289
+ ---
290
+
291
+ ## AutoAnimate 用法
292
+
293
+ ### 安装
294
+
295
+ ```bash
296
+ npm install @formkit/auto-animate
297
+ ```
298
+
299
+ ### React Hook
300
+
301
+ ```tsx
302
+ import { useAutoAnimate } from "@formkit/auto-animate/react";
303
+
304
+ function TodoList({ items }: { items: Item[] }) {
305
+ const [parent] = useAutoAnimate({ duration: 250, easing: "ease-in-out" });
306
+
307
+ return (
308
+ <ul ref={parent}>
309
+ {items.map((item) => (
310
+ <li key={item.id}>{item.text}</li>
311
+ ))}
312
+ </ul>
313
+ );
314
+ }
315
+ ```
316
+
317
+ ### 适用场景
318
+
319
+ | 场景 | 说明 |
320
+ |------|------|
321
+ | 列表增删排序 | 自动检测 DOM 变更,零配置 |
322
+ | Accordion 展开/折叠 | 子元素显隐时自动过渡 |
323
+ | Toast 通知 | 通知项进出自动动画 |
324
+ | 表单错误提示 | 错误信息出现/消失自动过渡 |
325
+
326
+ ### 适用边界
327
+
328
+ | 有效 | 无效 |
329
+ |------|------|
330
+ | 直接子元素增删 | 孙元素变更 |
331
+ | 子元素排序 | CSS `display: contents` 的子元素 |
332
+ | 子元素属性变化 | `position: fixed` 的子元素 |
333
+
334
+ 禁用动画:`const [parent, enable] = useAutoAnimate(); enable(false);`
335
+
336
+ ---
337
+
338
+ ## 性能优化
339
+
340
+ | 要点 | 做法 |
341
+ |------|------|
342
+ | 避免 layout thrashing | 只动画 `transform` + `opacity` |
343
+ | 控制并发 | 同屏 ≤ 3 组动画;stagger 避免 50+ 项同时启动 |
344
+ | 避免重渲染 | `useMotionValue` / `useTransform` 不触发 React 重渲染 |
345
+ | 跳过首次动画 | `initial={false}` |
346
+ | 滚动只触发一次 | `viewport` 设 `once: true, amount: 0.2` |
347
+
348
+ ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: authz-cli
3
3
  description: "Use when AI Agent needs to run miaoda-auth-cli commands in sandbox to manage roles, or run `miaoda db sql` in sandbox to manage permission point tables (create, seed, add, update, delete). All commands are executed by the Agent in its sandbox terminal. NOT for writing permission control code — CanRole/@Can coding should use authz-guide skill instead. 触发词:miaoda-auth-cli, authz-cli, 查询角色列表, 模拟角色, 创建角色, 批量创建角色, 权限点位, 权限表, 新增点位, 更新点位, 删除点位, role mock, role list CLI"
4
+ control-by-feature-ab: true
4
5
  ---
5
6
 
6
7
  # authz CLI — 权限管理工具
@@ -0,0 +1,264 @@
1
+ ---
2
+ name: charts-skill
3
+ description: "shadcn/ui + ReactECharts 图表开发规范。Use when creating or modifying charts/visualizations with ECharts. Covers 18 chart types (Line, Bar, Pie, Radar, Scatter, Heatmap, Sankey, Map, WordCloud, etc.) with strict constraints. 触发词:图表, chart, ECharts, 可视化, 饼图, 柱状图, 折线图, 数据图表, visualization, 甘特图, 词云, 热力图, 数据展示"
4
+ ---
5
+
6
+ ## L0 基础配置
7
+
8
+ - **库**: `import ReactECharts from 'echarts-for-react'` (echarts v6.1.x)
9
+ - **主题**: `theme="ud"`
10
+ - **颜色**: 🚨 只能用 hex(如 `#1890ff`),禁止 hsl/rgb
11
+ - **高度**: ≥300px (`className='h-[300px]'`)
12
+ - **地图**: 需引入 `@/lib/echartsMap`
13
+ - **必须配置**: tooltip.trigger + legend + grid.containLabel(坐标系图表)
14
+
15
+ ### TypeScript 类型定义
16
+
17
+ 编写 ECharts option 时,**必须**为 option 对象补充 `EChartsOption` 类型定义,确保类型安全:
18
+
19
+ ```tsx
20
+ import ReactECharts from 'echarts-for-react';
21
+ import type { EChartsOption } from 'echarts';
22
+
23
+ const option: EChartsOption = {
24
+ tooltip: { trigger: 'axis' },
25
+ legend: { bottom: 0 },
26
+ grid: { left: '3%', right: '4%', bottom: '20%', containLabel: true },
27
+ xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed'] },
28
+ yAxis: { type: 'value' },
29
+ series: [{ type: 'line', data: [120, 200, 150] }],
30
+ };
31
+
32
+ <ReactECharts option={option} theme="ud" className="h-[300px]" />;
33
+ ```
34
+
35
+ **关键点:** 从 `echarts` 导入 `EChartsOption` 类型(使用 `import type`),为 option 变量显式标注类型。复杂场景可按需使用更精确的子类型(如 `LineSeriesOption`、`BarSeriesOption`)。
36
+
37
+ ### Callback 参数类型
38
+
39
+ `tooltip.formatter` / `label.formatter` / `itemStyle.color` 三类 callback 入参类型不同。自定义参数 shape(如 `(params: { name: string; value: number }) => ...`)会触发 TS2322。直接抄下面范例:
40
+
41
+ ```tsx
42
+ import type { EChartsOption } from 'echarts';
43
+ import type { CallbackDataParams, TopLevelFormatterParams } from 'echarts/types/dist/shared';
44
+
45
+ const option: EChartsOption = {
46
+ tooltip: {
47
+ trigger: 'axis',
48
+ // axis 触发是数组,item 触发是单对象;先 Array.isArray 分流
49
+ formatter: (params: TopLevelFormatterParams) => {
50
+ const list = Array.isArray(params) ? params : [params];
51
+ return list.map((p) => `${p.name}: ${p.value}`).join('<br/>');
52
+ },
53
+ },
54
+ series: [{
55
+ type: 'bar',
56
+ data: [120, 200, 150],
57
+ label: {
58
+ show: true,
59
+ formatter: (p: CallbackDataParams) => `${p.value}`,
60
+ },
61
+ itemStyle: {
62
+ color: (p: CallbackDataParams) => (Number(p.value) > 150 ? '#f00' : '#00f'),
63
+ },
64
+ }],
65
+ };
66
+ ```
67
+
68
+ `xAxis.axisLabel.formatter` / `yAxis.axisLabel.formatter` 入参是 `(value, index)`,与上面三类不同,按需查 ECharts 类型,不要套用上面 callback 写法。
69
+
70
+ ### 渐变色用法
71
+
72
+ 需要额外导入并注册 GraphicComponent:
73
+
74
+ ```tsx
75
+ import * as echarts from 'echarts/core';
76
+ import { GraphicComponent } from 'echarts/components';
77
+ echarts.use([GraphicComponent]);
78
+
79
+ // 线性渐变 (x, y, x2, y2, colorStops)
80
+ new echarts.graphic.LinearGradient(0, 0, 0, 1, [
81
+ { offset: 0, color: '#fff' },
82
+ { offset: 1, color: '#000' }
83
+ ])
84
+
85
+ // 径向渐变 (cx, cy, r, colorStops)
86
+ new echarts.graphic.RadialGradient(0.5, 0.5, 0.5, [...colorStops])
87
+ ```
88
+
89
+ ### 甘特图用法
90
+
91
+ 🚫 禁止用堆叠柱状图模拟甘特图,必须使用 custom 系列:
92
+
93
+ ```tsx
94
+ const timelineData = [
95
+ { name: '设计阶段', start: '2024-11-20', end: '2024-11-30', days: 10 },
96
+ { name: '开发阶段', start: '2024-12-01', end: '2024-12-30', days: 30 },
97
+ ];
98
+
99
+ const option = {
100
+ tooltip: {
101
+ trigger: 'item',
102
+ formatter: (params) => {
103
+ const item = timelineData[params.dataIndex];
104
+ return `${item.name}<br/>${item.start} 至 ${item.end}<br/>共 ${item.days} 天`;
105
+ },
106
+ },
107
+ grid: { left: '3%', right: '4%', bottom: '3%', top: '3%', containLabel: true },
108
+ xAxis: {
109
+ type: 'time',
110
+ min: new Date('2024-11-15').getTime(),
111
+ max: new Date('2025-01-31').getTime(),
112
+ },
113
+ yAxis: {
114
+ type: 'category',
115
+ data: timelineData.map((item) => item.name),
116
+ },
117
+ series: [{
118
+ type: 'custom',
119
+ renderItem: (params, api) => {
120
+ const categoryIndex = api.value(0);
121
+ const start = api.coord([api.value(1), categoryIndex]);
122
+ const end = api.coord([api.value(2), categoryIndex]);
123
+ const height = api.size([0, 1])[1] * 0.5;
124
+ return {
125
+ type: 'rect',
126
+ shape: { x: start[0], y: start[1] - height / 2, width: end[0] - start[0], height },
127
+ style: { fill: ['#3370eb', '#1bcebf', '#ffc60a'][categoryIndex], radius: 4 },
128
+ };
129
+ },
130
+ encode: { x: [1, 2], y: 0 },
131
+ data: timelineData.map((item, i) => [i, new Date(item.start).getTime(), new Date(item.end).getTime()]),
132
+ }],
133
+ };
134
+ ```
135
+
136
+ **关键点:** xAxis 用 `type: 'time'`,yAxis 用 `type: 'category'`,通过 `api.coord()` 计算坐标。
137
+
138
+ ### markPoint 最佳实践
139
+
140
+ 🚫 避免语义重复或位置重叠的 markPoint:
141
+
142
+ ```tsx
143
+ // ❌ 错误:双十一和 max 指向同一个 x 轴位置
144
+ markPoint: {
145
+ data: [
146
+ { type: 'max', name: '最大值' },
147
+ { name: '双十一', coord: ['2024-11-11', 1000] } // 恰好也是最大值
148
+ ]
149
+ }
150
+
151
+ // ✅ 正确:只保留业务语义更强的标注
152
+ markPoint: {
153
+ data: [
154
+ { name: '双十一', coord: ['2024-11-11', 1000] } // 业务含义优先于统计含义
155
+ ]
156
+ }
157
+ ```
158
+
159
+ **原则:** 当 max/min 与业务事件(如促销日)重合时,只保留业务标注。
160
+
161
+ ### 双 Y 轴组合图零点对齐
162
+
163
+ 🚫 双 Y 轴(正负值混合)时,左右零点必须对齐:
164
+
165
+ ```tsx
166
+ // ❌ 错误:左轴 [0, 100],右轴 [-50, 50],零点不对齐
167
+ yAxis: [
168
+ { type: 'value' },
169
+ { type: 'value' }
170
+ ]
171
+
172
+ // ✅ 正确:手动计算 min/max 确保零点对齐
173
+ const leftMax = 100, rightMax = 50, rightMin = -50;
174
+ const leftMin = (rightMin / rightMax) * leftMax; // -100
175
+
176
+ yAxis: [
177
+ { type: 'value', min: leftMin, max: leftMax },
178
+ { type: 'value', min: rightMin, max: rightMax }
179
+ ]
180
+ ```
181
+
182
+ **原则:** 两轴的 `|min| / max` 比例必须相同,零点才能对齐。
183
+
184
+ ### 词云用法
185
+
186
+ WordCloud 非 ECharts 内置图表,系列类型为 `type: 'wordCloud'`。
187
+
188
+ ⚠️ 使用前必须通过**依赖安装工具**安装 `echarts-wordcloud`。
189
+
190
+ 安装后在组件顶部引入(无需解构,导入即注册):
191
+
192
+ ```tsx
193
+ import 'echarts-wordcloud';
194
+
195
+ // 系列配置
196
+ series: [{ type: 'wordCloud', data: [...] }]
197
+ ```
198
+
199
+ ---
200
+
201
+ ## L1 支持的图表类型
202
+
203
+ **允许使用的 18 种图表:**
204
+
205
+ | 类型 | 图表 | 关键约束 |
206
+ | ---- | ---- | -------- |
207
+ | 趋势 | Line, Area, ThemeRiver | Line ≤5 系列 |
208
+ | 比较 | Bar, Radar, Parallel | Radar ≤8 维度且禁止设各 indicator 项的 max,Bar 必须 boundaryGap: true |
209
+ | 占比 | Pie, Treemap, Sunburst | Pie ≤5 类别,禁止 itemStyle,🚨 必须隐藏 label(按 L2 CRITICAL #13 规则) |
210
+ | 分布 | Scatter, Heatmap, Boxplot | Scatter symbolSize ≤20,Heatmap 必须配 visualMap 且 grid.bottom ≥ '20%'(见 L2 CRITICAL #16) |
211
+ | 关系 | Graph, Tree, Sankey | - |
212
+ | 转化 | Funnel | label 必须显示且 `position: 'inside'`,禁止设 color |
213
+ | 金融 | Candlestick | - |
214
+ | 地理 | Map | 需引入 `@/lib/echartsMap` |
215
+ | 词云 | WordCloud | 非内置,需安装 echarts-wordcloud,安装后必须在组件顶部 `import 'echarts-wordcloud'`,见 L0 词云用法 |
216
+
217
+ **未列出的图表类型不要使用。**
218
+
219
+ ---
220
+
221
+ ## L2 禁止事项
222
+
223
+ > ⚠️ **违反将导致图表异常**
224
+
225
+ ### 🚨 FATAL
226
+
227
+ - **颜色格式** - 只能用 hex,禁止 hsl/hsla/rgb/rgba(hover 透明度计算异常)
228
+
229
+ ### 🔴 CRITICAL
230
+
231
+ > 生成代码后须逐条核对,每一条都不可跳过。
232
+
233
+ | # | 禁止 | 应该 |
234
+ |---|------|------|
235
+ | 1 | 饼图超过 5 个类别 | 改用横向柱状图 |
236
+ | 2 | 折线图超过 5 个系列 | 拆分图表或添加筛选 |
237
+ | 3 | Radar 的 indicator 各项设置 max 字段 | 禁止在 `radar.indicator` 数组的每一项中设置 `max`,让 ECharts 自动计算各维度范围 |
238
+ | 4 | Radar 多系列使用不同量纲 | 先归一化到相同量纲 |
239
+ | 5 | Bar 的 xAxis 不设 boundaryGap | 必须 `boundaryGap: true` |
240
+ | 6 | Funnel 隐藏 label 或 label 使用非 inside 位置 | 必须 `label: { show: true, position: 'inside' }`,禁止设 color |
241
+ | 7 | 图表高度小于 300px | 最小 `className='h-[300px]'` |
242
+ | 8 | 单图使用超过 8 种颜色 | 分组或聚合数据 |
243
+ | 9 | 饼图添加 itemStyle.border | 移除 itemStyle 配置 |
244
+ | 10 | 折线图连接时间无序的数据点 | 改用 Bar 或 Scatter |
245
+ | 11 | Scatter 的 symbolSize 超过 20 | 控制在 20 以内防止溢出 |
246
+ | 12 | 图表宽高超出容器导致溢出 | 使用相对单位或 `w-full`,禁止固定像素宽度 |
247
+ | 13 | 饼图(`type: 'pie'`)使用 label | 🚨 饼图必须同时关闭两处:`label: { show: false }` + `emphasis: { label: { show: false } }`,改用 tooltip |
248
+ | 14 | label 中设置 `color` 属性 | 🚨 所有 series 的 `label` 中禁止声明 `color`(如 `label: { color: '#333' }` ),颜色由主题自动控制 |
249
+ | 15 | label.formatter 使用字符串模板 | 禁止 `formatter: '{b}: {c}'` 等模板写法(`{a}/{b}/{c}/{d}` 易拼错),如需格式化请用回调函数 `formatter: (params) => ...` |
250
+ | 16 | legend 或 visualMap 与图表绘图区域重叠 | 有 legend 或 visualMap 时统一放底部:`legend: { type: 'scroll', bottom: 0 }`,`visualMap` 设 `orient: 'horizontal', left: 'center', bottom: 0`。坐标系图表(Bar/Line/Scatter/Heatmap 等)设 `grid.bottom` 至少 `'20%'`,x 轴标签较长或旋转时酌情增大;非坐标系图表(Pie/Radar 等)减小 `center` 纵向值上移避让(如 `['50%', '45%']`,不够则继续减小)。🚨 **Heatmap 底部同时存在 visualMap 和 x 轴标签,grid.bottom 酌情增至 `'25%'` 以上** |
251
+ | 17 | 桑基图(Sankey)数据存在环形引用 | Sankey links 必须构成有向无环图(DAG),禁止出现 A→B→…→A 的循环链路,生成数据后须验证无环 |
252
+ | 18 | 柱状图(Bar)正负数据共存时所有柱子使用相同 borderRadius | 按数据正负动态设置:正值圆角在顶部,负值圆角在底部 |
253
+ | 19 | option 对象不写 TypeScript 类型 | 必须 `const option: EChartsOption = { ... }`,从 `echarts` 导入 `EChartsOption`(`import type`),callback 参数类型见 L0 「Callback 参数类型」段 |
254
+
255
+ ### 🟡 SHOULD NOT
256
+
257
+ | 不建议 | 建议 |
258
+ |--------|------|
259
+ | Radar 超过 8 个维度 | 改用 Parallel 坐标图 |
260
+ | Heatmap 不配置 visualMap | 必须添加 visualMap |
261
+ | legend 与 title 位置重叠 | legend 放 `bottom: 0` |
262
+ | 小尺寸图表(<400px)显示 legend | 隐藏 legend |
263
+ | 用 Bar/堆叠柱状图绘制甘特图 | 使用 custom 系列,见 L0 甘特图用法 |
264
+ | 饼图/环形图 legend 放侧面 | legend 放顶部或底部,避免与图表重叠 |