create-dwy 0.5.0 → 0.6.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.
Files changed (156) hide show
  1. package/bin/index.js +1 -1
  2. package/package.json +2 -2
  3. package/src/create.js +61 -37
  4. package/src/sync.js +213 -53
  5. package/templates/claude-global/CLAUDE.md +92 -0
  6. package/templates/claude-global/rules/dwy-android-core.md +610 -0
  7. package/templates/claude-global/rules/dwy-api-design.md +110 -0
  8. package/templates/claude-global/rules/dwy-db-migration.md +46 -0
  9. package/templates/claude-global/rules/dwy-flutter-core.md +564 -0
  10. package/templates/claude-global/rules/dwy-flutter-network.md +222 -0
  11. package/templates/claude-global/rules/dwy-flutter-router.md +97 -0
  12. package/templates/claude-global/rules/dwy-flutter-testing.md +94 -0
  13. package/templates/claude-global/rules/dwy-git-commit-convention.md +82 -0
  14. package/templates/claude-global/rules/dwy-git-security.md +53 -0
  15. package/templates/claude-global/rules/dwy-payload-limits.md +178 -0
  16. package/templates/claude-global/rules/{prefer-open-source.md → dwy-prefer-open-source.md} +4 -0
  17. package/templates/claude-global/rules/dwy-project-structure.md +181 -0
  18. package/templates/claude-global/rules/{python-code-style.md → dwy-python-core.md} +314 -357
  19. package/templates/claude-global/rules/dwy-python-fastapi.md +272 -0
  20. package/templates/claude-global/rules/dwy-python-orm.md +61 -0
  21. package/templates/claude-global/rules/{backend-security.md → dwy-python-security.md} +116 -79
  22. package/templates/claude-global/rules/dwy-python-testing.md +53 -0
  23. package/templates/claude-global/rules/{server-security.md → dwy-server-security.md} +1 -2
  24. package/templates/claude-global/rules/dwy-tdd-development.md +70 -0
  25. package/templates/claude-global/rules/dwy-tech-stack.md +60 -0
  26. package/templates/claude-global/rules/dwy-vue-api.md +146 -0
  27. package/templates/claude-global/rules/{vue-code-style.md → dwy-vue-core.md} +361 -152
  28. package/templates/claude-global/rules/dwy-vue-pinia.md +75 -0
  29. package/templates/claude-global/rules/dwy-vue-testing.md +102 -0
  30. package/templates/claude-global/settings.json +20 -0
  31. package/templates/claude-global/skills/dwy-deploy-audit/SKILL.md +481 -0
  32. package/templates/claude-global/skills/dwy-deploy-audit/references/checks-data.md +117 -0
  33. package/templates/claude-global/skills/dwy-deploy-audit/references/checks-network.md +74 -0
  34. package/templates/claude-global/skills/dwy-deploy-audit/references/checks-runtime.md +184 -0
  35. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_base.sh +39 -0
  36. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_capacity.sh +278 -0
  37. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_db.sh +122 -0
  38. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_docker.sh +249 -0
  39. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_env.sh +64 -0
  40. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_https.sh +60 -0
  41. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_logs.sh +209 -0
  42. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_nginx.sh +92 -0
  43. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_resilience.sh +157 -0
  44. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_secrets.sh +327 -0
  45. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_services.sh +77 -0
  46. package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_ssh.sh +56 -0
  47. package/templates/claude-global/skills/dwy-deploy-audit/scripts/run_all.sh +105 -0
  48. package/templates/claude-global/skills/dwy-docker/SKILL.md +187 -0
  49. package/templates/claude-global/skills/dwy-docker/references/ask-templates.md +142 -0
  50. package/templates/claude-global/skills/dwy-docker/references/templates.md +479 -0
  51. package/templates/claude-global/skills/dwy-docker/references/version-rules.md +76 -0
  52. package/templates/claude-global/skills/dwy-docker/scripts/query_dockerhub.py +204 -0
  53. package/templates/claude-global/skills/dwy-docker/scripts/scan_images.sh +185 -0
  54. package/templates/claude-global/skills/dwy-eapi/SKILL.md +433 -0
  55. package/templates/claude-global/skills/dwy-eapi/references/tasks-integration-guide.md +387 -0
  56. package/templates/claude-global/skills/dwy-ekit/SKILL.md +85 -0
  57. package/templates/claude-global/skills/dwy-ekit/references/data.md +135 -0
  58. package/templates/claude-global/skills/dwy-ekit/references/form.md +68 -0
  59. package/templates/claude-global/skills/dwy-ekit/references/request.md +183 -0
  60. package/templates/claude-global/skills/dwy-ekit/references/ui.md +109 -0
  61. package/templates/claude-global/skills/{dwy-frontend-eui → dwy-eui}/SKILL.md +129 -15
  62. package/templates/claude-global/skills/dwy-eui/references/eui-design-guide.md +257 -0
  63. package/templates/claude-global/skills/dwy-eui/references/eui-integration-guide.md +302 -0
  64. package/templates/claude-global/skills/dwy-eui/references/eui-landing-design-guide.md +437 -0
  65. package/templates/claude-global/skills/dwy-fullstack-scaffold/SKILL.md +214 -0
  66. package/templates/claude-global/skills/dwy-mirror-source/SKILL.md +275 -0
  67. package/templates/claude-global/skills/dwy-mirror-source/references/dockerfile-snippets.md +228 -0
  68. package/templates/claude-global/skills/dwy-mirror-source/references/mirror-providers.md +150 -0
  69. package/templates/claude-global/skills/dwy-mirror-source/scripts/__pycache__/check_mirrors.cpython-313.pyc +0 -0
  70. package/templates/claude-global/skills/dwy-mirror-source/scripts/apply_mirrors.py +666 -0
  71. package/templates/claude-global/skills/dwy-mirror-source/scripts/check_mirrors.py +868 -0
  72. package/templates/claude-global/skills/dwy-pentest/SKILL.md +344 -0
  73. package/templates/claude-global/skills/dwy-pentest/scripts/lib/__init__.py +1 -0
  74. package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/__init__.cpython-311.pyc +0 -0
  75. package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/config.cpython-311.pyc +0 -0
  76. package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/executor.cpython-311.pyc +0 -0
  77. package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/severity.cpython-311.pyc +0 -0
  78. package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/validator.cpython-311.pyc +0 -0
  79. package/templates/claude-global/skills/dwy-pentest/scripts/lib/config.py +109 -0
  80. package/templates/claude-global/skills/dwy-pentest/scripts/lib/executor.py +157 -0
  81. package/templates/claude-global/skills/dwy-pentest/scripts/lib/severity.py +96 -0
  82. package/templates/claude-global/skills/dwy-pentest/scripts/lib/validator.py +113 -0
  83. package/templates/claude-global/skills/dwy-pentest/scripts/pentest_auth.py +289 -0
  84. package/templates/claude-global/skills/dwy-pentest/scripts/pentest_recon.py +217 -0
  85. package/templates/claude-global/skills/dwy-pentest/scripts/pentest_report.py +343 -0
  86. package/templates/claude-global/skills/dwy-pentest/scripts/pentest_scan.py +205 -0
  87. package/templates/claude-global/skills/dwy-pentest/scripts/pentest_ssl.py +208 -0
  88. package/templates/claude-global/skills/dwy-pentest/scripts/pentest_vuln.py +205 -0
  89. package/templates/claude-global/skills/dwy-pentest/scripts/pentest_web.py +330 -0
  90. package/templates/claude-global/skills/dwy-pentest/scripts/pyproject.toml +14 -0
  91. package/templates/claude-global/skills/dwy-pentest/scripts/setup_tools.sh +97 -0
  92. package/templates/claude-global/skills/dwy-pentest/scripts/uv.lock +415 -0
  93. package/templates/claude-global/skills/dwy-publish/SKILL.md +135 -0
  94. package/templates/claude-global/skills/dwy-vue-core/SKILL.md +890 -0
  95. package/templates/project/backend/.dwy.hbs +5 -0
  96. package/templates/project/backend/.python-version +1 -0
  97. package/templates/project/backend/CLAUDE.md.hbs +40 -0
  98. package/templates/project/{web/backend → backend}/alembic/script.py.mako +2 -0
  99. package/templates/project/{web/backend → backend}/alembic.ini.hbs +0 -1
  100. package/templates/project/backend/deploy.sh.hbs +18 -0
  101. package/templates/project/{web → backend}/docker-compose.prod.yml.hbs +1 -1
  102. package/templates/project/{web/backend → backend}/pyproject.toml.hbs +4 -5
  103. package/templates/project/{web/backend → backend}/src/app/config.py.hbs +1 -1
  104. package/templates/project/backend/src/app/database.py +10 -0
  105. package/templates/project/backend/src/app/dependencies.py +5 -0
  106. package/templates/project/{web/backend → backend}/src/app/main.py.hbs +3 -3
  107. package/templates/project/backend/src/app/models/base.py +5 -0
  108. package/templates/project/web/CLAUDE.md.hbs +29 -36
  109. package/templates/project/web/{frontend → apps/web}/index.html.hbs +1 -0
  110. package/templates/project/web/{frontend → apps/web}/package.json.hbs +4 -3
  111. package/templates/project/web/apps/web/src/App.vue +9 -0
  112. package/templates/project/web/apps/web/src/api/client.ts +5 -0
  113. package/templates/project/web/apps/web/src/composables/.gitkeep +0 -0
  114. package/templates/project/web/apps/web/src/layouts/DefaultLayout.vue +8 -0
  115. package/templates/project/web/{frontend → apps/web}/src/router/index.ts +1 -1
  116. package/templates/project/web/{frontend → apps/web}/src/stores/auth.ts +4 -2
  117. package/templates/project/web/apps/web/src/style.css +2 -0
  118. package/templates/project/web/apps/web/src/types/router.d.ts +8 -0
  119. package/templates/project/web/apps/web/src/views/HomeView.vue +8 -0
  120. package/templates/project/web/apps/web/tsconfig.app.json +18 -0
  121. package/templates/project/web/apps/web/tsconfig.json +6 -0
  122. package/templates/project/web/{frontend → apps/web}/vite.config.ts.hbs +7 -1
  123. package/templates/project/web/package.json.hbs +16 -0
  124. package/templates/project/web/packages/.gitkeep +0 -0
  125. package/templates/project/web/pnpm-workspace.yaml +3 -0
  126. package/templates/claude-global/rules/agent-team-execution.md +0 -138
  127. package/templates/claude-global/rules/agent-team-patterns.md +0 -157
  128. package/templates/claude-global/rules/git-security.md +0 -144
  129. package/templates/claude-global/skills/dwy-auto-sync/SKILL.md +0 -52
  130. package/templates/claude-global/skills/dwy-backend-base/SKILL.md +0 -279
  131. package/templates/claude-global/skills/dwy-frontend-core/SKILL.md +0 -181
  132. package/templates/project/web/.claude/commands/deploy.md +0 -4
  133. package/templates/project/web/backend/src/app/models/base.py +0 -5
  134. package/templates/project/web/deploy.sh.hbs +0 -113
  135. package/templates/project/web/frontend/src/App.vue +0 -3
  136. package/templates/project/web/frontend/src/api/client.ts +0 -13
  137. package/templates/project/web/frontend/src/style.css +0 -1
  138. package/templates/project/web/frontend/src/views/HomeView.vue +0 -5
  139. package/templates/project/web/frontend/tsconfig.app.json +0 -14
  140. package/templates/project/web/frontend/tsconfig.json +0 -4
  141. /package/templates/{project/web/backend → claude-global/skills/dwy-pentest/scripts}/.python-version +0 -0
  142. /package/templates/project/{web/backend → backend}/Dockerfile +0 -0
  143. /package/templates/project/{web/backend → backend}/alembic/env.py.hbs +0 -0
  144. /package/templates/{claude-global/skills → project/backend/alembic/versions}/.gitkeep +0 -0
  145. /package/templates/project/{web → backend}/docker-compose.dev.yml.hbs +0 -0
  146. /package/templates/project/{web/backend → backend}/src/app/__init__.py +0 -0
  147. /package/templates/project/{web/backend → backend}/src/app/models/__init__.py +0 -0
  148. /package/templates/project/{web/backend → backend}/src/app/routers/__init__.py +0 -0
  149. /package/templates/project/{web/backend → backend}/src/app/routers/health.py +0 -0
  150. /package/templates/project/{web/backend → backend}/src/app/schemas/__init__.py +0 -0
  151. /package/templates/project/{web/backend → backend}/src/app/services/__init__.py +0 -0
  152. /package/templates/project/{web/backend → backend}/tests/__init__.py +0 -0
  153. /package/templates/project/{web/backend → backend}/tests/conftest.py.hbs +0 -0
  154. /package/templates/project/{web/backend/alembic/versions → mobile}/.gitkeep +0 -0
  155. /package/templates/project/web/{frontend → apps/web}/src/components/.gitkeep +0 -0
  156. /package/templates/project/web/{frontend → apps/web}/src/main.ts +0 -0
@@ -0,0 +1,178 @@
1
+ # 数据载荷三层长度限制规则
2
+
3
+ 防止大文本 DoS、内存耗尽、带宽滥用。所有涉及用户输入 / HTTP 请求体 / 文件上传的场景必须遵循三层限制,单层失守即高风险。
4
+
5
+ 本文件是"长度 / 大小 / 数量"规则的**唯一权威源**。其他规则文件(`dwy-server-security.md`、`dwy-python-security.md`)的对应章节只做引用,不重复定义。
6
+
7
+ ## 为什么需要三层
8
+
9
+ - **前端 = UX 边界**:给用户即时反馈,避免无效输入浪费带宽和后端算力
10
+ - **网关 = 流量边界**:Nginx / CDN / 负载均衡层拦截异常大请求,保护后端不被打满
11
+ - **后端 = 业务边界**:字段级严格校验,阻断绕过前端的恶意请求
12
+ - 三层职责不可互相替代。只靠前端易被绕过;只靠后端流量先耗在 TCP/TLS 握手和解析上;只靠网关无法挡住"多个小字段组合起来刚好达到 body 上限"的攻击
13
+
14
+ 三层数字必须对齐:**前端 maxlength ≤ 后端 max_length**,**后端字段累加加冗余 ≤ 网关 client_max_body_size**。
15
+
16
+ ## 第一层:前端输入限制
17
+
18
+ ### 强制规则
19
+
20
+ - 所有 `<input type="text">` / `<input type="search">` / `<textarea>` 必须设 `maxlength` 属性
21
+ - `@dwydev/eui` 的 `EInput` / `ETextarea` / 可搜索 `ESelect` / 可输入 `ETag` 必须传 `maxlength` prop
22
+ - 富文本编辑器(tiptap / quill 等)必须配置字符数上限,超出禁止输入
23
+ - 文件选择控件必须在前端预校验大小和 MIME 类型(`accept` 属性 + JS 二次校验)
24
+ - 批量操作前端必须做分页 / 分批,不允许一次性超过 items 上限
25
+ - 表单校验层必须用 zod `.max()` 再补一道,防粘贴 / 脚本绕过 HTML `maxlength`
26
+
27
+ ### 禁止事项
28
+
29
+ - 禁止 `EInput` / `ETextarea` 不带 `maxlength` 上线
30
+ - 禁止富文本编辑器无字符上限
31
+ - 禁止"前端不限制,全部让后端兜底"
32
+ - 禁止大文件(>10MB)走普通 API 中转
33
+
34
+ ### 示例
35
+
36
+ ```vue
37
+ <!-- ✅ 正确 -->
38
+ <EInput v-model="form.title" :maxlength="100" show-word-limit />
39
+ <ETextarea v-model="form.desc" :maxlength="500" show-word-limit />
40
+
41
+ <!-- ❌ 违规 -->
42
+ <EInput v-model="form.title" />
43
+ <ETextarea v-model="form.desc" />
44
+ ```
45
+
46
+ 配套 zod schema(vee-validate):
47
+
48
+ ```ts
49
+ import { z } from 'zod'
50
+
51
+ const schema = z.object({
52
+ title: z.string().max(100),
53
+ desc: z.string().max(500),
54
+ })
55
+ ```
56
+
57
+ ## 第二层:网关 / 部署限制
58
+
59
+ ### 强制规则
60
+
61
+ - Nginx `client_max_body_size` 必须显式配置,不允许使用默认值
62
+ - 无文件上传业务时:全局 `client_max_body_size 1m`,**禁止** > `10m`
63
+ - 有上传业务时:针对上传路径单独放宽(如 `location /api/upload` 设 `20m`),**禁止**全局放宽
64
+ - 上传大文件(>10MB)必须走对象存储直传(MinIO / S3 预签名 URL),**禁止**走 API 中转
65
+ - CDN / 负载均衡层的 body 限制和超时必须与 Nginx 数字对齐
66
+
67
+ ### 示例
68
+
69
+ ```nginx
70
+ # server 块 — 全局默认
71
+ client_max_body_size 1m;
72
+ client_body_timeout 10s;
73
+ client_header_timeout 10s;
74
+
75
+ # 仅上传路径放宽
76
+ location /api/upload {
77
+ client_max_body_size 20m;
78
+ proxy_pass http://127.0.0.1:8000;
79
+ }
80
+ ```
81
+
82
+ ### 违规检测
83
+
84
+ - Nginx 配置缺少 `client_max_body_size` 或值 > `10m` 但业务不是文件上传
85
+ - 大文件上传路由走 API 中转而非对象存储直传
86
+ - CDN 和 Nginx 的 body 上限不一致
87
+
88
+ ## 第三层:后端数据校验
89
+
90
+ ### 强制规则
91
+
92
+ - Pydantic 每个 `str` 字段必须 `max_length`
93
+ - Pydantic 每个 `list` 字段必须 `max_length`(限制数组元素数量)
94
+ - `Query()` / `Path()` / `Header()` 参数同样必须 `max_length`
95
+ - FastAPI 路由必须显式声明 Pydantic schema,**禁止** `data: dict` / `data: Any`
96
+ - 分页 `page_size` 必须有 `le`(默认 `le=100`)
97
+ - 后端不信任网关,必须在中间件做 request body 大小二次兜底(超出直接 413)
98
+ - 图片上传除文件大小外,**必须**校验实际像素尺寸(Pillow `image.size`),防 decompression bomb
99
+ - 文件大小后端二次校验,不信任前端声明的 `Content-Length`
100
+
101
+ ### 示例
102
+
103
+ ```python
104
+ from pydantic import BaseModel, Field
105
+
106
+ # ✅ 正确
107
+ class UserCreate(BaseModel):
108
+ name: str = Field(max_length=32)
109
+ title: str = Field(max_length=100)
110
+ desc: str = Field(max_length=500)
111
+ tags: list[str] = Field(max_length=20)
112
+
113
+ class ListParams(BaseModel):
114
+ page: int = Field(default=1, ge=1)
115
+ page_size: int = Field(default=20, ge=1, le=100)
116
+
117
+ # ❌ 违规
118
+ @router.post("/users")
119
+ async def create_user(data: dict): ...
120
+
121
+ class BadParams(BaseModel):
122
+ page_size: int = 20 # 无 le,攻击者可传 999999
123
+ name: str # 无 max_length
124
+ tags: list[str] # 无 max_length
125
+ ```
126
+
127
+ > 说明:格式校验(`EmailStr` / 手机号 `pattern` / `HttpUrl` / 数字 `ge` / `le` 的数值范围)不是长度议题,仍归属 `dwy-python-security.md` §四,本文件不重复。
128
+
129
+ ## 统一尺寸参考表
130
+
131
+ 三层数字必须对齐。下表为全局默认,项目 CLAUDE.md 可为特殊业务覆盖个别字段(须显式说明原因)。
132
+
133
+ | 场景 | 前端 maxlength | 后端 max_length | 网关 / 上传 |
134
+ |------|---------------|----------------|-------------|
135
+ | 用户名 | 32 | 32 | — |
136
+ | 邮箱 | 254 | 254(RFC 5321) | — |
137
+ | 密码(输入框) | 128 | 128 | — |
138
+ | 手机号 | 20 | 20 | — |
139
+ | 标题 / 短名称 | 100 | 100 | — |
140
+ | 描述 / 摘要 | 500 | 500 | — |
141
+ | 正文 / 评论 | 2000 | 2000 | — |
142
+ | 富文本(HTML 串) | 100 KB | 100 KB | 走 body_size |
143
+ | 搜索关键词 | 100 | 100 | — |
144
+ | URL 字段 | 2048 | 2048 | — |
145
+ | JSON body(默认) | — | 中间件兜底 1 MB | `client_max_body_size 1m` |
146
+ | 图片上传(直发 API) | 前端预检 5 MB | 5 MB + 像素 `<= 8000×8000` | 上传路径 `10m` |
147
+ | 通用小文件上传 | 前端预检 10 MB | 10 MB | 上传路径 `20m` |
148
+ | 大文件(>10 MB) | — | — | 走对象存储直传,不过 API |
149
+ | 批量接口 items | UI 分批 | `max_length=100` | — |
150
+ | 查询分页 page_size | — | `le=100` | — |
151
+
152
+ ### 边界原则
153
+
154
+ - 前端 `maxlength` ≤ 后端 `max_length`(前端更严,UX 明确)
155
+ - 后端所有字段 `max_length` 总和加冗余 ≤ 网关 `client_max_body_size`
156
+ - 超出表中范围的业务必须在项目 CLAUDE.md 中显式记录并说明原因
157
+
158
+ ## 全局禁止事项
159
+
160
+ - 禁止任一层以"无限制"上线
161
+ - 禁止三层数字互相冲突(例如前端 1000 但后端 100)
162
+ - 禁止只靠前端 `maxlength` 而后端不校验
163
+ - 禁止只靠后端 `max_length` 而前端不限
164
+ - 禁止只靠网关 `client_max_body_size` 而无字段级 `max_length`
165
+
166
+ ## 违规检测
167
+
168
+ 发现以下任一情况,立即停止并提示用户:
169
+
170
+ 1. `.vue` 文件中 `EInput` / `ETextarea` 没有 `maxlength`
171
+ 2. 富文本组件(tiptap / quill)未配置字符上限
172
+ 3. Pydantic `BaseModel` 有 `str` 字段但未设 `max_length`
173
+ 4. Pydantic `BaseModel` 有 `list` 字段但未设 `max_length`
174
+ 5. FastAPI 路由以 `dict` / `Any` 作为 body 参数
175
+ 6. 分页参数无 `le` 上限
176
+ 7. Nginx 配置缺失 `client_max_body_size`,或值 > `10m` 但业务不是文件上传
177
+ 8. 上传 > 10MB 文件走 API 中转而非对象存储直传
178
+ 9. 图片上传仅校验文件大小而不校验像素尺寸
@@ -1,3 +1,7 @@
1
+ ---
2
+ description: 优先使用成熟开源库,避免重复造轮子
3
+ ---
4
+
1
5
  # 优先使用成熟开源方案
2
6
 
3
7
  开发新功能时,优先选用成熟的开源项目/库,而不是手写实现。只有在确认没有合适的开源方案时,才自行实现。
@@ -0,0 +1,181 @@
1
+ ---
2
+ description: 后端/前端/Flutter/Monorepo 项目目录结构模板(按项目入口文件触发)
3
+ paths:
4
+ - "**/package.json"
5
+ - "**/pyproject.toml"
6
+ - "**/pubspec.yaml"
7
+ - "**/pnpm-workspace.yaml"
8
+ ---
9
+
10
+ # 项目目录结构模板
11
+
12
+ AI 创建文件时**必须**遵循以下目录结构,不得自造目录名或层级。
13
+
14
+ ---
15
+
16
+ ## 一、后端项目(FastAPI)
17
+
18
+ ```
19
+ backend/
20
+ ├── src/app/
21
+ │ ├── __init__.py
22
+ │ ├── main.py # FastAPI 应用入口 + lifespan
23
+ │ ├── config.py # 继承 eapi BaseSettings
24
+ │ ├── database.py # create_async_engine_factory + create_session_factory
25
+ │ ├── dependencies.py # FastAPI Depends(get_db, get_current_user)
26
+ │ ├── exceptions.py # 项目级异常(继承 eapi AppError)
27
+ │ ├── validators.py # 输入校验工具(防注入等)
28
+ │ ├── models/ # SQLAlchemy ORM 模型
29
+ │ │ ├── __init__.py
30
+ │ │ ├── user.py # 每个实体一个文件
31
+ │ │ └── ...
32
+ │ ├── schemas/ # Pydantic v2 请求/响应模型
33
+ │ │ ├── __init__.py
34
+ │ │ ├── user.py # UserCreate, UserUpdate, UserResponse
35
+ │ │ └── ...
36
+ │ ├── routers/ # FastAPI 路由(按业务域拆分)
37
+ │ │ ├── __init__.py
38
+ │ │ ├── auth.py # 认证端点
39
+ │ │ ├── user.py # 每个业务域一个文件
40
+ │ │ └── ...
41
+ │ ├── services/ # 业务逻辑层
42
+ │ │ ├── __init__.py
43
+ │ │ ├── auth.py
44
+ │ │ ├── user.py # 与 router 同名,一一对应
45
+ │ │ └── ...
46
+ │ ├── tasks.py # ARQ 任务注册(@register 装饰器)
47
+ │ └── worker.py # ARQ Worker 入口
48
+ ├── alembic/ # 数据库迁移
49
+ │ ├── versions/ # 迁移文件
50
+ │ ├── env.py
51
+ │ └── alembic.ini
52
+ ├── scripts/ # 初始化/运维脚本
53
+ │ ├── init_db.py # 初始化数据库表结构
54
+ │ └── seed_admin.py # 创建初始管理员
55
+ ├── tests/
56
+ │ ├── conftest.py # pytest fixtures(SQLite 内存库、mock)
57
+ │ ├── test_auth.py # 与 routers/ 同名
58
+ │ └── ...
59
+ ├── pyproject.toml # UV 依赖配置
60
+ ├── Dockerfile.dev # 开发容器(--reload)
61
+ ├── Dockerfile.prod # 生产容器(只读、non-root)
62
+ ├── .env.example # 环境变量模板
63
+ └── TEST_CASES.md # 测试用例清单
64
+ ```
65
+
66
+ **强制规则:**
67
+ - 分层:`routers → schemas → services → models → database`,不可跨层调用
68
+ - services 层抛 eapi 异常(AppError 子类),**不抛 HTTPException**
69
+ - routers 层只做参数接收和 response 包装,**不写业务逻辑**
70
+ - models/ schemas/ routers/ services/ 四个目录内文件按业务域一一对应
71
+
72
+ ---
73
+
74
+ ## 二、前端项目(Vue 3)
75
+
76
+ ```
77
+ frontend/
78
+ ├── src/
79
+ │ ├── main.ts # createApp + 插件注册
80
+ │ ├── App.vue # 根组件
81
+ │ ├── router/
82
+ │ │ └── index.ts # Vue Router 配置 + 守卫
83
+ │ ├── stores/ # Pinia Setup Store
84
+ │ │ ├── auth.ts # 认证状态
85
+ │ │ └── ...
86
+ │ ├── api/ # HTTP 客户端(按业务域拆分)
87
+ │ │ ├── client.ts # ekit createRequest() 实例
88
+ │ │ ├── auth.ts # 登录/注册接口
89
+ │ │ ├── user.ts # 用户接口
90
+ │ │ └── ...
91
+ │ ├── views/ # 页面级组件(路由对应)
92
+ │ │ ├── LoginView.vue
93
+ │ │ ├── DashboardView.vue
94
+ │ │ └── ...
95
+ │ ├── components/ # 共享 UI 组件(非页面级)
96
+ │ ├── composables/ # Vue 3 组合式函数(use* 前缀)
97
+ │ ├── utils/ # 纯工具函数
98
+ │ └── index.css # Tailwind CSS 入口
99
+ ├── tests/
100
+ │ ├── api/
101
+ │ ├── stores/
102
+ │ ├── router/
103
+ │ └── utils/
104
+ ├── package.json
105
+ ├── vite.config.ts
106
+ ├── tsconfig.json
107
+ ├── Dockerfile # 生产构建(多阶段)
108
+ └── TEST_CASES.md
109
+ ```
110
+
111
+ **强制规则:**
112
+ - views/ 放页面组件(路由直接引用),components/ 放复用组件
113
+ - api/ 每个文件对应后端一个 router 模块,保持命名一致
114
+ - stores/ 统一 Setup Store 写法(`export const useXxxStore = defineStore('xxx', () => {...})`)
115
+
116
+ ---
117
+
118
+ ## 三、Flutter 项目
119
+
120
+ ```
121
+ lib/
122
+ ├── main.dart # runApp + ProviderScope
123
+ ├── app.dart # MaterialApp.router + GoRouter
124
+ ├── core/
125
+ │ ├── config/
126
+ │ │ └── env.dart # 环境配置
127
+ │ ├── network/
128
+ │ │ ├── dio_client.dart # Dio 实例 + 拦截器
129
+ │ │ └── api_response.dart # 统一响应模型(对齐 eapi 格式)
130
+ │ ├── storage/
131
+ │ │ └── secure_storage.dart
132
+ │ ├── theme/
133
+ │ │ └── app_theme.dart # ThemeData + 设计 tokens
134
+ │ └── utils/
135
+ ├── features/ # 按功能模块拆分(feature-first)
136
+ │ └── {feature_name}/
137
+ │ ├── data/
138
+ │ │ ├── {feature}_repository.dart # Repository 实现
139
+ │ │ └── {feature}_dto.dart # 数据传输对象
140
+ │ ├── domain/
141
+ │ │ └── {feature}_entity.dart # 领域实体
142
+ │ └── presentation/
143
+ │ ├── {feature}_page.dart # 页面
144
+ │ ├── {feature}_provider.dart # Riverpod Provider
145
+ │ └── widgets/ # 功能内专属 Widget
146
+ ├── shared/
147
+ │ ├── providers/ # 全局 Provider(auth, theme)
148
+ │ ├── widgets/ # 跨功能共享 Widget
149
+ │ └── models/ # 共享数据模型
150
+ test/
151
+ ├── features/
152
+ │ └── {feature_name}/
153
+ └── core/
154
+ ```
155
+
156
+ **强制规则:**
157
+ - features/ 按功能模块拆分,每个模块自包含 data/domain/presentation
158
+ - core/ 放全局基础设施(网络、存储、主题),不放业务代码
159
+ - shared/ 放跨功能共享的 provider/widget/model
160
+
161
+ ---
162
+
163
+ ## 四、Monorepo 项目结构(pnpm workspace)
164
+
165
+ 当项目包含前端 + 后端时,使用 monorepo:
166
+
167
+ ```
168
+ project-root/
169
+ ├── backend/ # FastAPI 后端(上述第一节结构)
170
+ ├── frontend/ # Vue 前端(上述第二节结构)
171
+ ├── mobile/ # Flutter 移动端(上述第三节结构,独立管理)
172
+ ├── docker-compose.dev.yml # 开发环境
173
+ ├── docker-compose.prod.yml # 生产环境
174
+ ├── dev.sh # 一键启动脚本
175
+ ├── pnpm-workspace.yaml # pnpm monorepo 配置
176
+ ├── package.json # 根 package.json(scripts)
177
+ ├── CLAUDE.md # 项目规范
178
+ └── .env.example # 全局环境变量模板
179
+ ```
180
+
181
+ **注意:** Flutter 项目(mobile/)不纳入 pnpm workspace,独立用 `flutter pub get` 管理依赖。