@bovinphang/frontend-craft 2.5.0
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.
- package/.claude-plugin/marketplace.json +61 -0
- package/.claude-plugin/plugin.json +32 -0
- package/.mcp.json +44 -0
- package/CHANGELOG.md +229 -0
- package/CHANGELOG.zh-CN.md +228 -0
- package/CODE_OF_CONDUCT.md +34 -0
- package/CODE_OF_CONDUCT.zh-CN.md +34 -0
- package/CONTRIBUTING.md +356 -0
- package/CONTRIBUTING.zh-CN.md +356 -0
- package/LICENSE +21 -0
- package/README.md +467 -0
- package/README.openclaw.md +262 -0
- package/README.openclaw.zh-CN.md +262 -0
- package/README.zh-CN.md +467 -0
- package/SECURITY.md +44 -0
- package/SECURITY.zh-CN.md +44 -0
- package/agents/fec-architect.md +125 -0
- package/agents/fec-code-reviewer.md +152 -0
- package/agents/fec-debugger.md +44 -0
- package/agents/fec-design-token-mapper.md +75 -0
- package/agents/fec-doc-updater.md +30 -0
- package/agents/fec-e2e-runner.md +107 -0
- package/agents/fec-figma-implementer.md +104 -0
- package/agents/fec-performance-optimizer.md +293 -0
- package/agents/fec-refactor-cleaner.md +32 -0
- package/agents/fec-security-reviewer.md +116 -0
- package/agents/fec-test-planner.md +50 -0
- package/agents/fec-typescript-reviewer.md +142 -0
- package/agents/fec-ui-checker.md +120 -0
- package/commands/fec-debug.md +30 -0
- package/commands/fec-doc-sync.md +18 -0
- package/commands/fec-init.md +70 -0
- package/commands/fec-plan.md +94 -0
- package/commands/fec-refactor-clean.md +19 -0
- package/commands/fec-review.md +66 -0
- package/commands/fec-scaffold.md +205 -0
- package/commands/fec-tdd.md +21 -0
- package/dist/bin/frontend-craft.js +82 -0
- package/dist/hooks/fec-cleanup-claude-cache.js +4 -0
- package/dist/hooks/fec-format-changed-file.js +1 -0
- package/dist/hooks/fec-notify.js +1 -0
- package/dist/hooks/fec-run-tests.js +1 -0
- package/dist/hooks/fec-security-check.js +2 -0
- package/dist/hooks/fec-session-start.js +1 -0
- package/docs/example-prompts.md +124 -0
- package/docs/ja-JP/README.md +467 -0
- package/docs/ko-KR/README.md +467 -0
- package/docs/project-structure.md +119 -0
- package/docs/runtimes/antigravity.md +10 -0
- package/docs/runtimes/augment.md +10 -0
- package/docs/runtimes/claude.md +171 -0
- package/docs/runtimes/claude.zh-CN.md +169 -0
- package/docs/runtimes/cline.md +10 -0
- package/docs/runtimes/codebuddy.md +10 -0
- package/docs/runtimes/codex.md +10 -0
- package/docs/runtimes/copilot.md +10 -0
- package/docs/runtimes/cursor.md +10 -0
- package/docs/runtimes/gemini.md +10 -0
- package/docs/runtimes/kilo.md +10 -0
- package/docs/runtimes/openclaw.md +10 -0
- package/docs/runtimes/opencode.md +10 -0
- package/docs/runtimes/qoder.md +19 -0
- package/docs/runtimes/trae.md +10 -0
- package/docs/runtimes/windsurf.md +10 -0
- package/docs/superpowers/plans/2026-05-29-fec-debug.md +491 -0
- package/docs/superpowers/specs/2026-05-29-fec-debug-design.md +340 -0
- package/docs/zh-CN/example-prompts.md +124 -0
- package/docs/zh-CN/project-structure.md +119 -0
- package/docs/zh-TW/README.md +467 -0
- package/hooks/hooks.json +71 -0
- package/openclaw.plugin.json +26 -0
- package/package.json +101 -0
- package/skills/TEMPLATE.md +155 -0
- package/skills/eval_queries.json +890 -0
- package/skills/fec-accessibility-check/SKILL.md +39 -0
- package/skills/fec-accessibility-check/references/report-template.md +23 -0
- package/skills/fec-accessibility-check/references/screen-reader-testing.md +33 -0
- package/skills/fec-api-integration/SKILL.md +78 -0
- package/skills/fec-api-integration/references/integration-patterns.md +80 -0
- package/skills/fec-browser-storage/SKILL.md +34 -0
- package/skills/fec-browser-storage/references/storage-patterns.md +65 -0
- package/skills/fec-canvas-threejs/SKILL.md +66 -0
- package/skills/fec-canvas-threejs/references/rendering-patterns.md +67 -0
- package/skills/fec-canvas-threejs/references/shader-webgl-patterns.md +67 -0
- package/skills/fec-code-review/SKILL.md +135 -0
- package/skills/fec-code-review/references/report-template.md +29 -0
- package/skills/fec-component-testing/SKILL.md +119 -0
- package/skills/fec-data-fetching/SKILL.md +62 -0
- package/skills/fec-data-fetching/references/query-patterns.md +77 -0
- package/skills/fec-debug-framework/SKILL.md +162 -0
- package/skills/fec-dependency-upgrade/SKILL.md +34 -0
- package/skills/fec-dependency-upgrade/references/dependency-upgrade-workflow.md +56 -0
- package/skills/fec-doc-sync/SKILL.md +37 -0
- package/skills/fec-e2e-testing/SKILL.md +40 -0
- package/skills/fec-e2e-testing/references/e2e-advanced.md +176 -0
- package/skills/fec-e2e-testing/references/playwright-patterns.md +95 -0
- package/skills/fec-form-handling/SKILL.md +76 -0
- package/skills/fec-form-handling/references/advanced-form-patterns.md +72 -0
- package/skills/fec-implement-from-design/SKILL.md +122 -0
- package/skills/fec-implement-from-design/references/design-plan-template.md +36 -0
- package/skills/fec-legacy-to-modern-migration/SKILL.md +180 -0
- package/skills/fec-legacy-to-modern-migration/references/migration-report-template.md +41 -0
- package/skills/fec-legacy-web-standard/SKILL.md +35 -0
- package/skills/fec-legacy-web-standard/references/legacy-patterns.md +85 -0
- package/skills/fec-list-virtualization/SKILL.md +34 -0
- package/skills/fec-list-virtualization/references/virtualization-patterns.md +52 -0
- package/skills/fec-monorepo-project-standard/SKILL.md +142 -0
- package/skills/fec-motion-interaction/SKILL.md +66 -0
- package/skills/fec-motion-interaction/references/motion-patterns.md +112 -0
- package/skills/fec-nextjs-project-standard/SKILL.md +117 -0
- package/skills/fec-nuxt-project-standard/SKILL.md +122 -0
- package/skills/fec-performance-optimization/SKILL.md +72 -0
- package/skills/fec-pwa-implementation/SKILL.md +36 -0
- package/skills/fec-pwa-implementation/references/manifest-and-icons.md +53 -0
- package/skills/fec-pwa-implementation/references/service-worker-workbox.md +68 -0
- package/skills/fec-react-project-standard/SKILL.md +83 -0
- package/skills/fec-react-project-standard/references/react-project-details.md +642 -0
- package/skills/fec-refactor-clean/SKILL.md +48 -0
- package/skills/fec-responsive-layout/SKILL.md +34 -0
- package/skills/fec-responsive-layout/references/responsive-layout-patterns.md +59 -0
- package/skills/fec-route-protection/SKILL.md +135 -0
- package/skills/fec-security-review/SKILL.md +38 -0
- package/skills/fec-security-review/references/report-template.md +27 -0
- package/skills/fec-security-review/references/security-checklist.md +64 -0
- package/skills/fec-source-driven-development/SKILL.md +61 -0
- package/skills/fec-state-management/SKILL.md +140 -0
- package/skills/fec-state-management/references/state-patterns.md +109 -0
- package/skills/fec-storybook-component-doc/SKILL.md +37 -0
- package/skills/fec-storybook-component-doc/references/story-patterns.md +118 -0
- package/skills/fec-svg-animation/SKILL.md +148 -0
- package/skills/fec-tailwind-design-system/SKILL.md +34 -0
- package/skills/fec-tailwind-design-system/references/tailwind-system-patterns.md +55 -0
- package/skills/fec-tdd-workflow/SKILL.md +52 -0
- package/skills/fec-testing-strategy/SKILL.md +45 -0
- package/skills/fec-typescript-type-safety/SKILL.md +157 -0
- package/skills/fec-typescript-type-safety/references/type-safety-patterns.md +102 -0
- package/skills/fec-ui-design/SKILL.md +90 -0
- package/skills/fec-ui-design/data/product-rules.json +110 -0
- package/skills/fec-ui-design/data/stack-ui-rules.json +14 -0
- package/skills/fec-ui-design/data/style-archetypes.json +74 -0
- package/skills/fec-ui-design/data/ux-quality-rules.json +56 -0
- package/skills/fec-ui-design/references/design-intelligence.md +37 -0
- package/skills/fec-ui-design/references/master-page-overrides.md +30 -0
- package/skills/fec-ui-design/references/pre-delivery-checklist.md +33 -0
- package/skills/fec-ui-design/scripts/design-system.mjs +530 -0
- package/skills/fec-validation-fix/SKILL.md +48 -0
- package/skills/fec-vite-project-standard/SKILL.md +83 -0
- package/skills/fec-vue3-project-standard/SKILL.md +49 -0
- package/skills/fec-vue3-project-standard/references/vue3-project-details.md +547 -0
- package/skills/fec-web-workers/SKILL.md +36 -0
- package/skills/fec-web-workers/references/advanced-workers.md +54 -0
- package/skills/fec-web-workers/references/basic-worker.md +67 -0
- package/skills/metadata.json +1422 -0
- package/skills/relations.json +644 -0
- package/templates/claude/CLAUDE.md +106 -0
- package/templates/claude/settings.json +62 -0
- package/templates/codex/AGENTS.md +105 -0
- package/templates/codex/config.toml +32 -0
- package/templates/openclaw/AGENTS.md +101 -0
- package/templates/openclaw/OPENCLAW-CONFIG.md +12 -0
- package/templates/shared/rules/fec-agent-workflow.md +54 -0
- package/templates/shared/rules/fec-api-layer.md +99 -0
- package/templates/shared/rules/fec-ci-cd.md +128 -0
- package/templates/shared/rules/fec-code-comments.md +33 -0
- package/templates/shared/rules/fec-design-system.md +248 -0
- package/templates/shared/rules/fec-error-handling.md +200 -0
- package/templates/shared/rules/fec-git-conventions.md +73 -0
- package/templates/shared/rules/fec-i18n.md +112 -0
- package/templates/shared/rules/fec-naming-conventions.md +120 -0
- package/templates/shared/rules/fec-performance.md +101 -0
- package/templates/shared/rules/fec-react.md +82 -0
- package/templates/shared/rules/fec-refactoring.md +43 -0
- package/templates/shared/rules/fec-rendering-patterns.md +183 -0
- package/templates/shared/rules/fec-responsive-design.md +227 -0
- package/templates/shared/rules/fec-source-driven-development.md +31 -0
- package/templates/shared/rules/fec-state-management.md +163 -0
- package/templates/shared/rules/fec-testing.md +98 -0
- package/templates/shared/rules/fec-typescript.md +355 -0
- package/templates/shared/rules/fec-vue.md +64 -0
- package/templates/shared/rules/fec-working-modes.md +50 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# CI/CD 规则
|
|
2
|
+
|
|
3
|
+
本文件约定持续集成与部署流水线的结构与行为。
|
|
4
|
+
|
|
5
|
+
## 流水线阶段
|
|
6
|
+
|
|
7
|
+
建议顺序:
|
|
8
|
+
|
|
9
|
+
1. **安装依赖** — `npm ci` 或 `pnpm install --frozen-lockfile`
|
|
10
|
+
2. **Lint** — ESLint、Stylelint
|
|
11
|
+
3. **类型检查** — `tsc --noEmit`
|
|
12
|
+
4. **单元测试** — Jest / Vitest
|
|
13
|
+
5. **构建** — `npm run build` 或 `pnpm build`
|
|
14
|
+
6. **包体/性能预算**(可选)— size-limit、Lighthouse CI、bundle analyzer
|
|
15
|
+
7. **依赖与供应链检查**(可选)— audit、license、lockfile diff、依赖升级验证
|
|
16
|
+
8. **E2E 测试**(可选)— Playwright / Cypress
|
|
17
|
+
9. **部署** — 构建产物上传或触发部署服务
|
|
18
|
+
|
|
19
|
+
任一阶段失败则中止后续步骤。
|
|
20
|
+
|
|
21
|
+
## GitHub Actions 示例
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
name: CI
|
|
25
|
+
|
|
26
|
+
on:
|
|
27
|
+
push:
|
|
28
|
+
branches: [main, develop]
|
|
29
|
+
pull_request:
|
|
30
|
+
branches: [main, develop]
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
ci:
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
|
|
38
|
+
- uses: pnpm/action-setup@v2
|
|
39
|
+
with:
|
|
40
|
+
version: 8
|
|
41
|
+
|
|
42
|
+
- uses: actions/setup-node@v4
|
|
43
|
+
with:
|
|
44
|
+
node-version: '20'
|
|
45
|
+
cache: 'pnpm'
|
|
46
|
+
|
|
47
|
+
- run: pnpm install --frozen-lockfile
|
|
48
|
+
- run: pnpm run lint
|
|
49
|
+
- run: pnpm run typecheck
|
|
50
|
+
- run: pnpm run test
|
|
51
|
+
- run: pnpm run build
|
|
52
|
+
|
|
53
|
+
- name: Upload build
|
|
54
|
+
if: success() && github.ref == 'refs/heads/main'
|
|
55
|
+
uses: actions/upload-artifact@v4
|
|
56
|
+
with:
|
|
57
|
+
name: dist
|
|
58
|
+
path: dist/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## GitLab CI 示例
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
stages:
|
|
65
|
+
- install
|
|
66
|
+
- lint
|
|
67
|
+
- test
|
|
68
|
+
- build
|
|
69
|
+
- deploy
|
|
70
|
+
|
|
71
|
+
variables:
|
|
72
|
+
PNPM_VERSION: "8"
|
|
73
|
+
|
|
74
|
+
install:
|
|
75
|
+
stage: install
|
|
76
|
+
script:
|
|
77
|
+
- corepack enable pnpm
|
|
78
|
+
- pnpm install --frozen-lockfile
|
|
79
|
+
cache:
|
|
80
|
+
key: ${CI_COMMIT_REF_SLUG}
|
|
81
|
+
paths:
|
|
82
|
+
- node_modules/
|
|
83
|
+
- .pnpm-store/
|
|
84
|
+
|
|
85
|
+
lint:
|
|
86
|
+
stage: lint
|
|
87
|
+
script:
|
|
88
|
+
- pnpm run lint
|
|
89
|
+
- pnpm run typecheck
|
|
90
|
+
needs: [install]
|
|
91
|
+
|
|
92
|
+
test:
|
|
93
|
+
stage: test
|
|
94
|
+
script:
|
|
95
|
+
- pnpm run test
|
|
96
|
+
needs: [install]
|
|
97
|
+
|
|
98
|
+
build:
|
|
99
|
+
stage: build
|
|
100
|
+
script:
|
|
101
|
+
- pnpm run build
|
|
102
|
+
artifacts:
|
|
103
|
+
paths:
|
|
104
|
+
- dist/
|
|
105
|
+
needs: [lint, test]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 环境变量与密钥
|
|
109
|
+
|
|
110
|
+
- 敏感信息使用 CI 平台的 Secrets,不写入仓库
|
|
111
|
+
- 构建时注入 `VITE_*` / `NEXT_PUBLIC_*` 等前端环境变量
|
|
112
|
+
- E2E 的 baseURL、测试账号等从 Secrets 读取
|
|
113
|
+
- 只允许公开前缀的环境变量进入客户端 bundle;服务端密钥不得使用 `VITE_*` / `NEXT_PUBLIC_*`
|
|
114
|
+
|
|
115
|
+
## 产物与证据
|
|
116
|
+
|
|
117
|
+
- 上传测试报告、覆盖率、E2E trace、截图、构建产物和性能预算结果。
|
|
118
|
+
- CI 失败时保留足够日志定位根因,不只返回“命令失败”。
|
|
119
|
+
- 发布前确认版本、变更说明、迁移事项和回滚路径。
|
|
120
|
+
- 依赖升级 PR 保留 lockfile diff、关键包版本、release notes 摘要和验证矩阵。
|
|
121
|
+
- Monorepo affected 快速验证可以用于 PR 反馈,但 release 或主干合并前应保留全量验证入口。
|
|
122
|
+
|
|
123
|
+
## 强约束
|
|
124
|
+
|
|
125
|
+
- 使用锁文件(`package-lock.json`、`pnpm-lock.yaml`),禁止 `npm install` 无锁安装
|
|
126
|
+
- 构建产物不提交到仓库,由 CI 生成并上传
|
|
127
|
+
- 部署前必须通过 lint、typecheck、test、build
|
|
128
|
+
- 不跳过失败门禁直接部署,除非有明确风险接受和回滚方案
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# 代码注释
|
|
2
|
+
|
|
3
|
+
编写或评审前端实现时应用本文件。
|
|
4
|
+
|
|
5
|
+
## 原则
|
|
6
|
+
|
|
7
|
+
- 意图优先靠**命名、类型与结构**表达;注释用于说明**为什么**、**约束与背景**,而不是复述代码在做什么。
|
|
8
|
+
- 避免「整文件零注释」:在**非显而易见**处用**简短**注释降低误改成本,与「不写废话注释」不矛盾。
|
|
9
|
+
|
|
10
|
+
## 应当注释的情况
|
|
11
|
+
|
|
12
|
+
- **业务或产品规则**:权限、展示条件、校验逻辑背后的依据(与需求或领域约定相关时)。
|
|
13
|
+
- **非直观的实现或取舍**:为何选用当前写法(性能、兼容、与后端/第三方约定等)。
|
|
14
|
+
- **外部契约**:与接口、设计稿、枚举或单位相关的字段含义、映射关系。
|
|
15
|
+
- **临时方案与技术债**:`TODO` / `FIXME` 应写明预期收尾或关联工单(若有)。
|
|
16
|
+
- **易踩坑点**:第三方库版本差异、必须满足的调用顺序、已知限制。
|
|
17
|
+
|
|
18
|
+
## 应避免的情况
|
|
19
|
+
|
|
20
|
+
- 逐行翻译已能从代码直接看出的行为。
|
|
21
|
+
- 注释与实现长期不一致;修改逻辑时同步更新或删除误导性注释。
|
|
22
|
+
- 用大段注释代替应抽取的函数或应补全的类型。
|
|
23
|
+
|
|
24
|
+
## 形式建议
|
|
25
|
+
|
|
26
|
+
- 语言与仓库现有注释保持一致(中文或英文)。
|
|
27
|
+
- 复杂模块或组件可在文件顶部用 **1~3 行** 说明职责与关键约束;跨包或对外导出的 API 宜用 **JSDoc** 说明参数、返回值与副作用。
|
|
28
|
+
- 复杂条件分支或 `useEffect`:若依赖或触发条件不直观,用一行说明**触发条件**或**不变量**。
|
|
29
|
+
- 临时规避、兼容旧系统或性能取舍必须说明原因和退出条件。
|
|
30
|
+
|
|
31
|
+
## 文档同步
|
|
32
|
+
|
|
33
|
+
当修改公开命令、skill、agent、模板、报告命名或安装路径时,同步更新 README、runtime docs、项目结构文档和多语言说明。注释解释局部代码,公开文档解释团队如何使用能力,两者不要互相替代。
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# 设计系统规则
|
|
2
|
+
|
|
3
|
+
凡是任务涉及 UI 实现、设计稿转代码、样式、设计 Token 或组件复用时,都应用本文件。
|
|
4
|
+
|
|
5
|
+
## 核心优先级
|
|
6
|
+
|
|
7
|
+
按以下顺序优先处理:
|
|
8
|
+
|
|
9
|
+
1. 复用已有组件
|
|
10
|
+
2. 在已有组件上扩展
|
|
11
|
+
3. 创建新的叶子组件
|
|
12
|
+
4. 只有在理由非常充分时,才创建新的共享基础组件
|
|
13
|
+
|
|
14
|
+
## 产品化设计方向
|
|
15
|
+
|
|
16
|
+
开始 UI 实现前,先明确界面语气:
|
|
17
|
+
|
|
18
|
+
- 工具型页面、SaaS 后台、CRM、运营台:优先安静、密集、可扫描,首屏直接呈现核心工作区
|
|
19
|
+
- 品牌页、作品集、发布页:可以更有表现力,但 H1 应是品牌/产品/对象/品类,说明文案放在副标题
|
|
20
|
+
- 可视化、游戏、创作工具:可以使用更强视觉资产和动效,但必须保持交互可控、状态清晰
|
|
21
|
+
- 每个重要界面都应有一个贴合业务的视觉锚点:真实媒体、数据形态、行业材质、字体性格、空间组织或交互节奏
|
|
22
|
+
- 大胆设计必须服务场景;高频工具重效率和稳定,展示型页面重主体识别和记忆点
|
|
23
|
+
|
|
24
|
+
避免:
|
|
25
|
+
|
|
26
|
+
- 把日常高频工具做成营销落地页
|
|
27
|
+
- 默认使用紫色渐变、装饰光斑、堆叠卡片或空泛 hero
|
|
28
|
+
- 使用无语境默认字体、平均分布的弱对比配色、模板化双栏 hero 或重复圆角卡片作为通用答案
|
|
29
|
+
- 页面区块大面积卡片化,尤其是卡片套卡片
|
|
30
|
+
- 用可见说明文字解释常见控件本该表达的功能
|
|
31
|
+
- 让整个界面只由一个色相的深浅变化组成
|
|
32
|
+
|
|
33
|
+
### 视觉语言基线
|
|
34
|
+
|
|
35
|
+
- 字体:优先复用项目字体体系;新建方向时,标题和正文应形成性格与可读性的分工
|
|
36
|
+
- 色彩:区分主色、强调色、状态色和中性色,关键动作与风险状态不能只靠透明度表达
|
|
37
|
+
- 动效:只为入场、层级展开、状态确认、错误反馈和重点引导编排节奏,并尊重 `prefers-reduced-motion`
|
|
38
|
+
- 空间:根据任务选择高密度、留白、非对称、分栏、画布式或编辑器式布局,不套用固定卡片模板
|
|
39
|
+
- 质感:背景、纹理、阴影和透明度应解释层级或语境,不作为无内容装饰
|
|
40
|
+
|
|
41
|
+
### 设计系统生成与覆盖
|
|
42
|
+
|
|
43
|
+
- 项目缺少设计方向时,可先生成轻量设计系统建议,再根据真实业务、组件库和数据校正
|
|
44
|
+
- `design-system/<project>/MASTER.md` 记录跨页面共享的产品类型、视觉语言、token 方向、动效、图表和 QA 规则
|
|
45
|
+
- `design-system/<project>/pages/<page>.md` 只记录页面差异:首屏结构、组件密度、图表选择、状态覆盖和局部 token 调整
|
|
46
|
+
- 构建页面或检查 UI 时,先读取页面 override,再读取 Master;页面规则不能复制全量 Master
|
|
47
|
+
- 产品类型推理要落到界面决策:行业风险、用户频率、数据密度、触摸/鼠标场景、图表任务和转化路径
|
|
48
|
+
- 交付前 QA 至少覆盖可访问性、交互反馈、布局溢出、字体色彩、动效降级、表单、导航和图表可读性
|
|
49
|
+
|
|
50
|
+
## 设计稿转代码规则
|
|
51
|
+
|
|
52
|
+
当存在设计上下文时:
|
|
53
|
+
|
|
54
|
+
- 先通过 MCP 读取设计上下文(Figma / MasterGo / Pixso / 墨刀 / Sketch,摹客则使用截图/标注)
|
|
55
|
+
- 设计稿中的颜色/间距 token 必须从 design token 文件中引用
|
|
56
|
+
- 如果已有设计上下文,不要靠猜测来决定布局、间距、字体、颜色或状态
|
|
57
|
+
- 在创建新组件前,先检查现有组件,优先复用现有组件库中的组件
|
|
58
|
+
- 响应式断点: mobile(375px) / tablet(768px) / desktop(1440px)
|
|
59
|
+
- 像素还原精度要求: ≥ 95%
|
|
60
|
+
- 在改文件前先给出简短实现计划
|
|
61
|
+
|
|
62
|
+
始终要考虑:
|
|
63
|
+
|
|
64
|
+
- loading 状态
|
|
65
|
+
- empty 状态
|
|
66
|
+
- error 状态
|
|
67
|
+
- disabled 状态
|
|
68
|
+
- hover 状态
|
|
69
|
+
- focus 状态
|
|
70
|
+
- 在相关场景下的 selected 状态
|
|
71
|
+
- 响应式行为
|
|
72
|
+
|
|
73
|
+
## 设计 Token 规则
|
|
74
|
+
|
|
75
|
+
- 优先使用已有 design token、CSS 变量或主题变量
|
|
76
|
+
- 当已有 Token 可用时,不要硬编码颜色、圆角、间距、阴影和字体取值
|
|
77
|
+
- 如果缺少所需 Token,要明确指出,不要悄悄到处硬编码
|
|
78
|
+
- Token 使用方式要与周边模块保持一致
|
|
79
|
+
- Tailwind 项目中,token 应通过语义化 `theme.extend`、CSS 变量或组件 variant 承接;不要把 `blue-600`、`rounded-xl` 等具体值复制成事实标准
|
|
80
|
+
- 组件 variant 应区分语义 tone、尺寸 size、密度 density 和状态 state;不要让一个字符串参数承载多种业务含义
|
|
81
|
+
- 动态 Tailwind class 必须可被构建扫描识别;复杂映射使用显式对象、variant 工具或 safelist
|
|
82
|
+
|
|
83
|
+
## 样式规则
|
|
84
|
+
|
|
85
|
+
- 优先使用局部、受控的样式,而不是大范围全局覆盖
|
|
86
|
+
- 保持当前断点下的响应式行为
|
|
87
|
+
- 与项目现有样式体系保持一致
|
|
88
|
+
- 检查 hover、active、focus、disabled、selected 等状态
|
|
89
|
+
- 除非没有合适 Token 或刻度值,否则不要使用 magic number
|
|
90
|
+
|
|
91
|
+
### 界面质感基线
|
|
92
|
+
|
|
93
|
+
- 嵌套圆角保持光学关系:外层圆角约等于内层圆角 + 间距
|
|
94
|
+
- 图标按钮、箭头、播放三角等非对称图形按视觉中心微调
|
|
95
|
+
- 小控件命中区域至少 40x40px,空间允许时优先 44x44px
|
|
96
|
+
- 标题和短文本可用 `text-wrap: balance`,短中正文可用 `text-wrap: pretty`
|
|
97
|
+
- 计数器、价格、时间、表格数字使用 `font-variant-numeric: tabular-nums`
|
|
98
|
+
- 图片在浅/深色背景上边缘不清时,使用中性 alpha 内描边,不使用品牌色描边
|
|
99
|
+
- 动效只声明实际变化属性,禁止 `transition: all` 和 `will-change: all`
|
|
100
|
+
- 进入/退出动效要克制,并尊重 `prefers-reduced-motion`
|
|
101
|
+
|
|
102
|
+
## 暗色模式
|
|
103
|
+
|
|
104
|
+
提供与系统主题同步的手动切换能力,减少视觉疲劳并满足可访问性要求。
|
|
105
|
+
|
|
106
|
+
### CSS 变量方案
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
:root {
|
|
110
|
+
--color-bg-primary: #ffffff;
|
|
111
|
+
--color-bg-secondary: #f5f5f5;
|
|
112
|
+
--color-text-primary: #1a1a1a;
|
|
113
|
+
--color-text-secondary: #666666;
|
|
114
|
+
--color-border: #e0e0e0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
[data-theme="dark"] {
|
|
118
|
+
--color-bg-primary: #1a1a1a;
|
|
119
|
+
--color-bg-secondary: #2a2a2a;
|
|
120
|
+
--color-text-primary: #f0f0f0;
|
|
121
|
+
--color-text-secondary: #a0a0a0;
|
|
122
|
+
--color-border: #404040;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
body {
|
|
126
|
+
background-color: var(--color-bg-primary);
|
|
127
|
+
color: var(--color-text-primary);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Tailwind 方案
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
// tailwind.config.js
|
|
135
|
+
module.exports = {
|
|
136
|
+
darkMode: "class", // 通过 .dark 类控制,而非 prefers-color-scheme
|
|
137
|
+
};
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```html
|
|
141
|
+
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
|
|
142
|
+
<!-- 内容 -->
|
|
143
|
+
</div>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 主题切换 Hook
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
import { useState, useEffect } from "react";
|
|
150
|
+
|
|
151
|
+
function useTheme() {
|
|
152
|
+
const [theme, setTheme] = useState<"light" | "dark">("light");
|
|
153
|
+
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
// 1. 优先读取用户保存的偏好
|
|
156
|
+
const saved = localStorage.getItem("theme") as "light" | "dark" | null;
|
|
157
|
+
if (saved) {
|
|
158
|
+
setTheme(saved);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// 2. 回退到系统偏好
|
|
162
|
+
const prefersDark = window.matchMedia(
|
|
163
|
+
"(prefers-color-scheme: dark)",
|
|
164
|
+
).matches;
|
|
165
|
+
setTheme(prefersDark ? "dark" : "light");
|
|
166
|
+
}, []);
|
|
167
|
+
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
const root = document.documentElement;
|
|
170
|
+
if (theme === "dark") {
|
|
171
|
+
root.classList.add("dark");
|
|
172
|
+
root.setAttribute("data-theme", "dark");
|
|
173
|
+
} else {
|
|
174
|
+
root.classList.remove("dark");
|
|
175
|
+
root.setAttribute("data-theme", "light");
|
|
176
|
+
}
|
|
177
|
+
localStorage.setItem("theme", theme);
|
|
178
|
+
}, [theme]);
|
|
179
|
+
|
|
180
|
+
const toggle = () => setTheme((t) => (t === "light" ? "dark" : "light"));
|
|
181
|
+
|
|
182
|
+
return { theme, toggle };
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### FOUC 防护(主题闪烁)
|
|
187
|
+
|
|
188
|
+
在 `<head>` 中同步执行主题初始化脚本(阻塞渲染),避免首次加载时出现错误的主题色:
|
|
189
|
+
|
|
190
|
+
```html
|
|
191
|
+
<head>
|
|
192
|
+
<script>
|
|
193
|
+
// 同步执行 — 在 body 渲染前确定主题
|
|
194
|
+
(function () {
|
|
195
|
+
const theme =
|
|
196
|
+
localStorage.getItem("theme") ||
|
|
197
|
+
(window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
198
|
+
? "dark"
|
|
199
|
+
: "light");
|
|
200
|
+
if (theme === "dark") {
|
|
201
|
+
document.documentElement.classList.add("dark");
|
|
202
|
+
document.documentElement.setAttribute("data-theme", "dark");
|
|
203
|
+
}
|
|
204
|
+
})();
|
|
205
|
+
</script>
|
|
206
|
+
</head>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 暗色模式注意事项
|
|
210
|
+
|
|
211
|
+
- **图片**: 亮色图片在暗色模式下刺眼,使用 `filter: brightness(0.8)` 降低亮度
|
|
212
|
+
- **阴影**: 暗色模式下阴影不明显,改用 `box-shadow: 0 0 15px rgba(255,255,255,0.05)` 或边框替代
|
|
213
|
+
- **颜色对比度**: 确保暗色模式下文本与背景的对比度 ≥ 4.5:1(WCAG AA)
|
|
214
|
+
- **表单控件**: 输入框、下拉框、开关等原生控件在暗色模式下需要自定义样式
|
|
215
|
+
- **第三方组件**: 检查 UI 组件库是否支持暗色模式,必要时用 CSS 变量覆盖
|
|
216
|
+
- **Tailwind 组件**: 暗色模式下需复核 focus、disabled、selected、invalid、skeleton、chart 和阴影层级,不只补 `dark:` 背景色
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 可访问性基线
|
|
221
|
+
|
|
222
|
+
优先使用语义化 HTML。
|
|
223
|
+
|
|
224
|
+
确保:
|
|
225
|
+
|
|
226
|
+
- 表单控件具备标签
|
|
227
|
+
- 纯图标按钮具有可访问名称
|
|
228
|
+
- 菜单、标签页、对话框和自定义控件支持键盘操作
|
|
229
|
+
- 焦点样式可见
|
|
230
|
+
- 编辑页面时标题层级正确
|
|
231
|
+
- 真实表格数据使用正确表格语义
|
|
232
|
+
|
|
233
|
+
## UI 任务的输出要求
|
|
234
|
+
|
|
235
|
+
对于较复杂的设计类任务,开始时先给出:
|
|
236
|
+
|
|
237
|
+
- 复用的组件
|
|
238
|
+
- 新建的组件
|
|
239
|
+
- 可能改动的文件
|
|
240
|
+
- 响应式策略
|
|
241
|
+
- Token 映射或样式策略
|
|
242
|
+
|
|
243
|
+
实现完成后,需要说明:
|
|
244
|
+
|
|
245
|
+
- 复用了什么
|
|
246
|
+
- 新建了什么
|
|
247
|
+
- 与设计稿有哪些偏差
|
|
248
|
+
- 缺少哪些 Token、资源或交互细节
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# 错误处理规范
|
|
2
|
+
|
|
3
|
+
## 错误分层
|
|
4
|
+
|
|
5
|
+
| 层级 | 错误类型 | 处理方式 |
|
|
6
|
+
|------|----------|----------|
|
|
7
|
+
| 全局 | 未捕获异常、Promise rejection | 全局捕获 + 上报 + 降级 UI |
|
|
8
|
+
| 路由/页面 | 页面级组件渲染错误 | Error Boundary + 页面级降级 |
|
|
9
|
+
| 模块 | 功能模块内的运行时错误 | Error Boundary + 模块级降级 |
|
|
10
|
+
| 组件 | 数据请求失败、操作失败 | 用户提示 + 重试机制 |
|
|
11
|
+
| 表单 | 校验失败 | 字段级错误提示 |
|
|
12
|
+
|
|
13
|
+
## 全局错误捕获
|
|
14
|
+
|
|
15
|
+
### React
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
// main.tsx — 未捕获的 Promise
|
|
19
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
20
|
+
reportError(event.reason);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// 推荐:react-error-boundary,业务侧保持函数组件 + FallbackComponent
|
|
24
|
+
import { ErrorBoundary } from "react-error-boundary";
|
|
25
|
+
|
|
26
|
+
function GlobalErrorFallback({
|
|
27
|
+
error,
|
|
28
|
+
resetErrorBoundary,
|
|
29
|
+
}: {
|
|
30
|
+
error: Error;
|
|
31
|
+
resetErrorBoundary: () => void;
|
|
32
|
+
}) {
|
|
33
|
+
return (
|
|
34
|
+
<div role="alert">
|
|
35
|
+
<p>页面出现异常</p>
|
|
36
|
+
<button type="button" onClick={resetErrorBoundary}>
|
|
37
|
+
重试
|
|
38
|
+
</button>
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 根节点包裹示例(root 来自 createRoot(document.getElementById("root")!) 等)
|
|
44
|
+
root.render(
|
|
45
|
+
<ErrorBoundary
|
|
46
|
+
FallbackComponent={GlobalErrorFallback}
|
|
47
|
+
onError={(error, info) => {
|
|
48
|
+
reportError(error, { componentStack: info.componentStack });
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
<App />
|
|
52
|
+
</ErrorBoundary>,
|
|
53
|
+
);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Vue
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// main.ts
|
|
60
|
+
app.config.errorHandler = (err, instance, info) => {
|
|
61
|
+
reportError(err, {
|
|
62
|
+
component: instance?.$options.name,
|
|
63
|
+
lifecycleHook: info,
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
window.addEventListener('unhandledrejection', (event) => {
|
|
68
|
+
reportError(event.reason);
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Error Boundary 策略
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
App (GlobalErrorBoundary)
|
|
76
|
+
├── Header
|
|
77
|
+
├── Main
|
|
78
|
+
│ ├── Sidebar (ErrorBoundary)
|
|
79
|
+
│ └── Content
|
|
80
|
+
│ ├── Dashboard (ErrorBoundary)
|
|
81
|
+
│ └── UserList (ErrorBoundary)
|
|
82
|
+
└── Footer
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- 每个独立功能模块用 Error Boundary 包裹
|
|
86
|
+
- 模块崩溃不应导致整个页面白屏
|
|
87
|
+
- 降级 UI 应提供"重试"操作
|
|
88
|
+
|
|
89
|
+
## API 错误处理
|
|
90
|
+
|
|
91
|
+
### 统一错误格式
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
interface ApiError {
|
|
95
|
+
code: string;
|
|
96
|
+
message: string;
|
|
97
|
+
details?: Record<string, string[]>;
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 错误分级处理
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
function handleApiError(error: ApiError) {
|
|
105
|
+
switch (error.code) {
|
|
106
|
+
case 'UNAUTHORIZED':
|
|
107
|
+
redirectToLogin();
|
|
108
|
+
break;
|
|
109
|
+
case 'FORBIDDEN':
|
|
110
|
+
showToast('无权限执行此操作');
|
|
111
|
+
break;
|
|
112
|
+
case 'VALIDATION_ERROR':
|
|
113
|
+
return error.details; // 返回给表单显示字段级错误
|
|
114
|
+
case 'NETWORK_ERROR':
|
|
115
|
+
showToast('网络异常,请检查网络连接');
|
|
116
|
+
break;
|
|
117
|
+
default:
|
|
118
|
+
showToast(error.message || '操作失败,请稍后重试');
|
|
119
|
+
reportError(error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 请求拦截器
|
|
125
|
+
|
|
126
|
+
在 axios / fetch 封装层统一处理:
|
|
127
|
+
|
|
128
|
+
- 401 → 跳转登录(或刷新 token)
|
|
129
|
+
- 403 → 权限不足提示
|
|
130
|
+
- 500 → 通用错误提示 + 上报
|
|
131
|
+
- 网络超时 → 超时提示 + 可选重试
|
|
132
|
+
|
|
133
|
+
### 用户可恢复动作
|
|
134
|
+
|
|
135
|
+
每类错误都应对应明确下一步:
|
|
136
|
+
|
|
137
|
+
- `401`:重新登录或静默刷新失败后跳转登录
|
|
138
|
+
- `403`:说明无权限并提供返回或申请权限路径
|
|
139
|
+
- `404`:返回列表、重新搜索或创建入口
|
|
140
|
+
- `409`:展示冲突对象和刷新/覆盖/取消选择
|
|
141
|
+
- `422`:字段级错误回填表单
|
|
142
|
+
- `429`:告知等待时间或稍后重试
|
|
143
|
+
- `5xx` / 网络错误:重试、离线提示或联系支持
|
|
144
|
+
|
|
145
|
+
UI 可显示 request id / trace id 方便支持排查,但不得暴露内部堆栈、SQL、服务名或敏感字段。
|
|
146
|
+
|
|
147
|
+
## 用户体验
|
|
148
|
+
|
|
149
|
+
### 错误状态 UI
|
|
150
|
+
|
|
151
|
+
每个数据展示区域应处理四种状态:
|
|
152
|
+
|
|
153
|
+
1. **Loading** — 骨架屏或 spinner
|
|
154
|
+
2. **Error** — 错误描述 + 重试按钮
|
|
155
|
+
3. **Empty** — 空状态引导
|
|
156
|
+
4. **Success** — 正常数据展示
|
|
157
|
+
|
|
158
|
+
### 降级 UI 设计
|
|
159
|
+
|
|
160
|
+
- 全局级:显示友好的错误页面,提供"返回首页"和"重试"
|
|
161
|
+
- 模块级:显示该模块的占位错误卡片,页面其他部分正常
|
|
162
|
+
- 操作级:Toast 提示 + 具体的下一步指引
|
|
163
|
+
|
|
164
|
+
### 重试策略
|
|
165
|
+
|
|
166
|
+
- 用户手动重试(按钮)
|
|
167
|
+
- 自动重试(指数退避,最多 3 次)
|
|
168
|
+
- 数据请求库的内置重试(React Query retries 等)
|
|
169
|
+
|
|
170
|
+
## 错误上报
|
|
171
|
+
|
|
172
|
+
<!-- 请根据项目实际的错误监控平台调整:Sentry / 自建 / 其他 -->
|
|
173
|
+
|
|
174
|
+
上报内容应包含:
|
|
175
|
+
|
|
176
|
+
- 错误堆栈
|
|
177
|
+
- 用户 ID / 会话 ID
|
|
178
|
+
- 当前页面 URL
|
|
179
|
+
- 浏览器/设备信息
|
|
180
|
+
- 复现上下文(操作步骤、请求参数)
|
|
181
|
+
|
|
182
|
+
## 反模式
|
|
183
|
+
|
|
184
|
+
- 空 catch 块吞掉错误
|
|
185
|
+
- 所有错误统一用 `alert()` 提示
|
|
186
|
+
- 接口失败时 UI 无任何反馈
|
|
187
|
+
- Error Boundary 没有重试机制,用户只能刷新页面
|
|
188
|
+
- 在组件中到处写重复的 try/catch 而不是统一封装
|
|
189
|
+
- 不上报错误,依赖用户反馈来发现问题
|
|
190
|
+
- 用 Error Boundary 承接普通 API 错误,导致用户无法理解或恢复
|
|
191
|
+
- 把后端原始异常、内部错误码或敏感字段直接展示给用户
|
|
192
|
+
|
|
193
|
+
## 检查清单
|
|
194
|
+
|
|
195
|
+
- [ ] 全局有未捕获异常和 Promise rejection 的监听
|
|
196
|
+
- [ ] 关键功能模块有 Error Boundary(React)或 onErrorCaptured(Vue)包裹
|
|
197
|
+
- [ ] API 请求有统一的错误拦截和分级处理
|
|
198
|
+
- [ ] 所有数据展示区域处理了 Loading / Error / Empty / Success 四种状态
|
|
199
|
+
- [ ] 降级 UI 提供了"重试"操作
|
|
200
|
+
- [ ] 错误信息上报到监控平台
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Git 提交规范
|
|
2
|
+
|
|
3
|
+
凡是创建 commit、编写 commit message 或准备提交代码时,都应用本文件。
|
|
4
|
+
|
|
5
|
+
## Conventional Commits 格式
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
<type>(<scope>): <subject>
|
|
9
|
+
|
|
10
|
+
[body]
|
|
11
|
+
|
|
12
|
+
[footer]
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### type 取值
|
|
16
|
+
|
|
17
|
+
| type | 用途 |
|
|
18
|
+
|------|------|
|
|
19
|
+
| `feat` | 新功能 |
|
|
20
|
+
| `fix` | 修复 bug |
|
|
21
|
+
| `refactor` | 重构(不改变行为) |
|
|
22
|
+
| `style` | 代码格式调整(不影响逻辑) |
|
|
23
|
+
| `docs` | 文档变更 |
|
|
24
|
+
| `test` | 测试相关 |
|
|
25
|
+
| `chore` | 构建、工具、依赖等杂项 |
|
|
26
|
+
| `perf` | 性能优化 |
|
|
27
|
+
| `ci` | CI/CD 配置变更 |
|
|
28
|
+
|
|
29
|
+
### scope
|
|
30
|
+
|
|
31
|
+
可选,标明影响范围,如模块名、组件名或功能域:
|
|
32
|
+
|
|
33
|
+
- `feat(auth): 新增手机号登录`
|
|
34
|
+
- `fix(table): 修复排序列未高亮`
|
|
35
|
+
- `refactor(api): 统一请求错误处理`
|
|
36
|
+
|
|
37
|
+
### subject 规范
|
|
38
|
+
|
|
39
|
+
- 使用祈使句("增加 xxx" 而非 "增加了 xxx")
|
|
40
|
+
- 不超过 72 个字符
|
|
41
|
+
- 不以句号结尾
|
|
42
|
+
- 如果影响范围较大,在 body 中详细说明
|
|
43
|
+
|
|
44
|
+
## 分支命名
|
|
45
|
+
|
|
46
|
+
- `feature/xxx` — 新功能
|
|
47
|
+
- `fix/xxx` — 修复
|
|
48
|
+
- `refactor/xxx` — 重构
|
|
49
|
+
- `hotfix/xxx` — 紧急修复
|
|
50
|
+
|
|
51
|
+
## 提交前检查
|
|
52
|
+
|
|
53
|
+
提交前必须通过:
|
|
54
|
+
|
|
55
|
+
1. lint
|
|
56
|
+
2. type-check
|
|
57
|
+
3. 与变更相关的测试
|
|
58
|
+
|
|
59
|
+
未经用户确认不要直接执行 `git commit`。
|
|
60
|
+
|
|
61
|
+
## 提交粒度
|
|
62
|
+
|
|
63
|
+
- 一个提交只包含一个清晰目的:功能、修复、测试、文档或清理。
|
|
64
|
+
- 大型计划应拆成可验证的小批次,每批都有说明和命令结果。
|
|
65
|
+
- 清理、格式化和行为变更不要混在同一提交中。
|
|
66
|
+
- 推送或发 PR 前先复查 diff,确认没有本地配置、密钥、临时报告或调试输出。
|
|
67
|
+
|
|
68
|
+
## 反模式
|
|
69
|
+
|
|
70
|
+
- 一个 commit 混合不相关的改动
|
|
71
|
+
- commit message 过于笼统(如 "update"、"fix bug"、"wip")
|
|
72
|
+
- 在 commit 中包含调试代码、console.log 或临时 hack
|
|
73
|
+
- 未说明验证命令或已知剩余风险就提交高风险改动
|