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.
- package/bin/index.js +1 -1
- package/package.json +2 -2
- package/src/create.js +61 -37
- package/src/sync.js +213 -53
- package/templates/claude-global/CLAUDE.md +92 -0
- package/templates/claude-global/rules/dwy-android-core.md +610 -0
- package/templates/claude-global/rules/dwy-api-design.md +110 -0
- package/templates/claude-global/rules/dwy-db-migration.md +46 -0
- package/templates/claude-global/rules/dwy-flutter-core.md +564 -0
- package/templates/claude-global/rules/dwy-flutter-network.md +222 -0
- package/templates/claude-global/rules/dwy-flutter-router.md +97 -0
- package/templates/claude-global/rules/dwy-flutter-testing.md +94 -0
- package/templates/claude-global/rules/dwy-git-commit-convention.md +82 -0
- package/templates/claude-global/rules/dwy-git-security.md +53 -0
- package/templates/claude-global/rules/dwy-payload-limits.md +178 -0
- package/templates/claude-global/rules/{prefer-open-source.md → dwy-prefer-open-source.md} +4 -0
- package/templates/claude-global/rules/dwy-project-structure.md +181 -0
- package/templates/claude-global/rules/{python-code-style.md → dwy-python-core.md} +314 -357
- package/templates/claude-global/rules/dwy-python-fastapi.md +272 -0
- package/templates/claude-global/rules/dwy-python-orm.md +61 -0
- package/templates/claude-global/rules/{backend-security.md → dwy-python-security.md} +116 -79
- package/templates/claude-global/rules/dwy-python-testing.md +53 -0
- package/templates/claude-global/rules/{server-security.md → dwy-server-security.md} +1 -2
- package/templates/claude-global/rules/dwy-tdd-development.md +70 -0
- package/templates/claude-global/rules/dwy-tech-stack.md +60 -0
- package/templates/claude-global/rules/dwy-vue-api.md +146 -0
- package/templates/claude-global/rules/{vue-code-style.md → dwy-vue-core.md} +361 -152
- package/templates/claude-global/rules/dwy-vue-pinia.md +75 -0
- package/templates/claude-global/rules/dwy-vue-testing.md +102 -0
- package/templates/claude-global/settings.json +20 -0
- package/templates/claude-global/skills/dwy-deploy-audit/SKILL.md +481 -0
- package/templates/claude-global/skills/dwy-deploy-audit/references/checks-data.md +117 -0
- package/templates/claude-global/skills/dwy-deploy-audit/references/checks-network.md +74 -0
- package/templates/claude-global/skills/dwy-deploy-audit/references/checks-runtime.md +184 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_base.sh +39 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_capacity.sh +278 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_db.sh +122 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_docker.sh +249 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_env.sh +64 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_https.sh +60 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_logs.sh +209 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_nginx.sh +92 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_resilience.sh +157 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_secrets.sh +327 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_services.sh +77 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_ssh.sh +56 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/run_all.sh +105 -0
- package/templates/claude-global/skills/dwy-docker/SKILL.md +187 -0
- package/templates/claude-global/skills/dwy-docker/references/ask-templates.md +142 -0
- package/templates/claude-global/skills/dwy-docker/references/templates.md +479 -0
- package/templates/claude-global/skills/dwy-docker/references/version-rules.md +76 -0
- package/templates/claude-global/skills/dwy-docker/scripts/query_dockerhub.py +204 -0
- package/templates/claude-global/skills/dwy-docker/scripts/scan_images.sh +185 -0
- package/templates/claude-global/skills/dwy-eapi/SKILL.md +433 -0
- package/templates/claude-global/skills/dwy-eapi/references/tasks-integration-guide.md +387 -0
- package/templates/claude-global/skills/dwy-ekit/SKILL.md +85 -0
- package/templates/claude-global/skills/dwy-ekit/references/data.md +135 -0
- package/templates/claude-global/skills/dwy-ekit/references/form.md +68 -0
- package/templates/claude-global/skills/dwy-ekit/references/request.md +183 -0
- package/templates/claude-global/skills/dwy-ekit/references/ui.md +109 -0
- package/templates/claude-global/skills/{dwy-frontend-eui → dwy-eui}/SKILL.md +129 -15
- package/templates/claude-global/skills/dwy-eui/references/eui-design-guide.md +257 -0
- package/templates/claude-global/skills/dwy-eui/references/eui-integration-guide.md +302 -0
- package/templates/claude-global/skills/dwy-eui/references/eui-landing-design-guide.md +437 -0
- package/templates/claude-global/skills/dwy-fullstack-scaffold/SKILL.md +214 -0
- package/templates/claude-global/skills/dwy-mirror-source/SKILL.md +275 -0
- package/templates/claude-global/skills/dwy-mirror-source/references/dockerfile-snippets.md +228 -0
- package/templates/claude-global/skills/dwy-mirror-source/references/mirror-providers.md +150 -0
- package/templates/claude-global/skills/dwy-mirror-source/scripts/__pycache__/check_mirrors.cpython-313.pyc +0 -0
- package/templates/claude-global/skills/dwy-mirror-source/scripts/apply_mirrors.py +666 -0
- package/templates/claude-global/skills/dwy-mirror-source/scripts/check_mirrors.py +868 -0
- package/templates/claude-global/skills/dwy-pentest/SKILL.md +344 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__init__.py +1 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/__init__.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/config.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/executor.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/severity.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/validator.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/config.py +109 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/executor.py +157 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/severity.py +96 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/validator.py +113 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_auth.py +289 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_recon.py +217 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_report.py +343 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_scan.py +205 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_ssl.py +208 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_vuln.py +205 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_web.py +330 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pyproject.toml +14 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/setup_tools.sh +97 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/uv.lock +415 -0
- package/templates/claude-global/skills/dwy-publish/SKILL.md +135 -0
- package/templates/claude-global/skills/dwy-vue-core/SKILL.md +890 -0
- package/templates/project/backend/.dwy.hbs +5 -0
- package/templates/project/backend/.python-version +1 -0
- package/templates/project/backend/CLAUDE.md.hbs +40 -0
- package/templates/project/{web/backend → backend}/alembic/script.py.mako +2 -0
- package/templates/project/{web/backend → backend}/alembic.ini.hbs +0 -1
- package/templates/project/backend/deploy.sh.hbs +18 -0
- package/templates/project/{web → backend}/docker-compose.prod.yml.hbs +1 -1
- package/templates/project/{web/backend → backend}/pyproject.toml.hbs +4 -5
- package/templates/project/{web/backend → backend}/src/app/config.py.hbs +1 -1
- package/templates/project/backend/src/app/database.py +10 -0
- package/templates/project/backend/src/app/dependencies.py +5 -0
- package/templates/project/{web/backend → backend}/src/app/main.py.hbs +3 -3
- package/templates/project/backend/src/app/models/base.py +5 -0
- package/templates/project/web/CLAUDE.md.hbs +29 -36
- package/templates/project/web/{frontend → apps/web}/index.html.hbs +1 -0
- package/templates/project/web/{frontend → apps/web}/package.json.hbs +4 -3
- package/templates/project/web/apps/web/src/App.vue +9 -0
- package/templates/project/web/apps/web/src/api/client.ts +5 -0
- package/templates/project/web/apps/web/src/composables/.gitkeep +0 -0
- package/templates/project/web/apps/web/src/layouts/DefaultLayout.vue +8 -0
- package/templates/project/web/{frontend → apps/web}/src/router/index.ts +1 -1
- package/templates/project/web/{frontend → apps/web}/src/stores/auth.ts +4 -2
- package/templates/project/web/apps/web/src/style.css +2 -0
- package/templates/project/web/apps/web/src/types/router.d.ts +8 -0
- package/templates/project/web/apps/web/src/views/HomeView.vue +8 -0
- package/templates/project/web/apps/web/tsconfig.app.json +18 -0
- package/templates/project/web/apps/web/tsconfig.json +6 -0
- package/templates/project/web/{frontend → apps/web}/vite.config.ts.hbs +7 -1
- package/templates/project/web/package.json.hbs +16 -0
- package/templates/project/web/packages/.gitkeep +0 -0
- package/templates/project/web/pnpm-workspace.yaml +3 -0
- package/templates/claude-global/rules/agent-team-execution.md +0 -138
- package/templates/claude-global/rules/agent-team-patterns.md +0 -157
- package/templates/claude-global/rules/git-security.md +0 -144
- package/templates/claude-global/skills/dwy-auto-sync/SKILL.md +0 -52
- package/templates/claude-global/skills/dwy-backend-base/SKILL.md +0 -279
- package/templates/claude-global/skills/dwy-frontend-core/SKILL.md +0 -181
- package/templates/project/web/.claude/commands/deploy.md +0 -4
- package/templates/project/web/backend/src/app/models/base.py +0 -5
- package/templates/project/web/deploy.sh.hbs +0 -113
- package/templates/project/web/frontend/src/App.vue +0 -3
- package/templates/project/web/frontend/src/api/client.ts +0 -13
- package/templates/project/web/frontend/src/style.css +0 -1
- package/templates/project/web/frontend/src/views/HomeView.vue +0 -5
- package/templates/project/web/frontend/tsconfig.app.json +0 -14
- package/templates/project/web/frontend/tsconfig.json +0 -4
- /package/templates/{project/web/backend → claude-global/skills/dwy-pentest/scripts}/.python-version +0 -0
- /package/templates/project/{web/backend → backend}/Dockerfile +0 -0
- /package/templates/project/{web/backend → backend}/alembic/env.py.hbs +0 -0
- /package/templates/{claude-global/skills → project/backend/alembic/versions}/.gitkeep +0 -0
- /package/templates/project/{web → backend}/docker-compose.dev.yml.hbs +0 -0
- /package/templates/project/{web/backend → backend}/src/app/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/models/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/routers/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/routers/health.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/schemas/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/services/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/tests/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/tests/conftest.py.hbs +0 -0
- /package/templates/project/{web/backend/alembic/versions → mobile}/.gitkeep +0 -0
- /package/templates/project/web/{frontend → apps/web}/src/components/.gitkeep +0 -0
- /package/templates/project/web/{frontend → apps/web}/src/main.ts +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 跨栈技术选型强制约束(FastAPI/Vue3/Flutter/UV/pnpm/Docker/S3 等,全局加载)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# 跨栈技术选型强制约束
|
|
6
|
+
|
|
7
|
+
每个领域只有一个方案,AI 不得选替代,不得"建议改用 XX"。
|
|
8
|
+
|
|
9
|
+
## 后端
|
|
10
|
+
|
|
11
|
+
| 领域 | 唯一方案 | 禁止替代 |
|
|
12
|
+
|------|---------|---------|
|
|
13
|
+
| Web 框架 | FastAPI | Django, Flask, Tornado, Sanic |
|
|
14
|
+
| ORM | SQLAlchemy 2.0 (异步) | Tortoise ORM, Peewee, Django ORM |
|
|
15
|
+
| 关系数据库 | PostgreSQL | MySQL, MariaDB, SQLite(生产) |
|
|
16
|
+
| 缓存 / 消息队列 | Redis | Memcached, RabbitMQ, Kafka |
|
|
17
|
+
| 异步任务 | ARQ (eapi[tasks]) | Celery, Dramatiq, Huey |
|
|
18
|
+
| 数据库迁移 | Alembic | 手动 DDL, Django migrations |
|
|
19
|
+
| 包管理 | UV | pip, Poetry, Pipenv |
|
|
20
|
+
| 密码哈希 | bcrypt (eapi security) | argon2, scrypt, 自实现 |
|
|
21
|
+
| JWT | python-jose (eapi security) | PyJWT, 自实现 |
|
|
22
|
+
| 数据校验 | Pydantic v2 | marshmallow, attrs, 手动校验 |
|
|
23
|
+
| 基础设施层 | dwyeapi | 自造框架、手写基础设施 |
|
|
24
|
+
| Linter/Formatter | Ruff | Black, isort, flake8, pylint |
|
|
25
|
+
|
|
26
|
+
## 前端(Web)
|
|
27
|
+
|
|
28
|
+
| 领域 | 唯一方案 | 禁止替代 |
|
|
29
|
+
|------|---------|---------|
|
|
30
|
+
| 框架 | Vue 3 (Composition API) | React, Svelte, Angular, Vue 2 |
|
|
31
|
+
| 构建工具 | Vite | Webpack, Rollup, esbuild 直接用 |
|
|
32
|
+
| 组件库 | @dwydev/eui | Element Plus, Ant Design Vue, Naive UI |
|
|
33
|
+
| 工具库 | @dwydev/ekit | 手写 request/storage/validators |
|
|
34
|
+
| 状态管理 | Pinia (Setup Store) | Vuex, 手动 reactive/provide |
|
|
35
|
+
| 样式 | Tailwind CSS 4 | Sass/Less 手写、CSS Modules、UnoCSS |
|
|
36
|
+
| 包管理 | pnpm | npm, yarn |
|
|
37
|
+
| 项目结构 | pnpm monorepo (workspace) | Lerna, Nx, Turborepo |
|
|
38
|
+
| 表单校验 | vee-validate + zod | 手动 v-model 校验 |
|
|
39
|
+
| 路由 | Vue Router 4 | — |
|
|
40
|
+
| 测试 | Vitest | Jest |
|
|
41
|
+
|
|
42
|
+
## 移动端 / 桌面端
|
|
43
|
+
|
|
44
|
+
| 领域 | 唯一方案 | 禁止替代 |
|
|
45
|
+
|------|---------|---------|
|
|
46
|
+
| 框架 | Flutter | React Native, Kotlin Multiplatform, MAUI |
|
|
47
|
+
| 状态管理 | Riverpod | GetX, Bloc, Provider, MobX |
|
|
48
|
+
| HTTP 客户端 | Dio | http, Chopper, Retrofit |
|
|
49
|
+
| 路由 | GoRouter | auto_route, Routemaster |
|
|
50
|
+
| 本地存储 | shared_preferences + flutter_secure_storage | Hive, Isar, sqflite(非必要时) |
|
|
51
|
+
| 代码生成 | riverpod_generator + freezed + json_serializable | 手写 fromJson/toJson |
|
|
52
|
+
|
|
53
|
+
## 基础设施
|
|
54
|
+
|
|
55
|
+
| 领域 | 唯一方案 |
|
|
56
|
+
|------|---------|
|
|
57
|
+
| 容器化 | Docker + Docker Compose |
|
|
58
|
+
| 对象存储(开发) | MinIO (S3 协议) |
|
|
59
|
+
| 对象存储(生产) | 任何 S3 兼容云服务 |
|
|
60
|
+
| 时序数据库(量化金融) | DolphinDB |
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Vue 前端网络层(ekit createRequest + 拦截器插件)
|
|
3
|
+
paths:
|
|
4
|
+
- "**/api/**/*.ts"
|
|
5
|
+
- "**/api/**/*.vue"
|
|
6
|
+
- "**/api/client.ts"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Vue 前端网络层规范
|
|
10
|
+
|
|
11
|
+
## 六、API 请求规范
|
|
12
|
+
|
|
13
|
+
### 强制规则
|
|
14
|
+
|
|
15
|
+
- API 文件按**业务域拆分**(`api/user.ts`、`api/exam.ts`)
|
|
16
|
+
- 每个 API 函数**独立导出**,不使用 default export
|
|
17
|
+
- 请求参数和响应使用**类型标注**
|
|
18
|
+
- **禁止**在组件中直接创建 axios 实例或调用 `fetch`
|
|
19
|
+
|
|
20
|
+
### API 文件结构
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// api/user.ts
|
|
24
|
+
import request from '@/utils/request'
|
|
25
|
+
import type { UserInfo, UserCreate, UserUpdate } from '@/types/user'
|
|
26
|
+
|
|
27
|
+
export function getUsers(params?: { page?: number; page_size?: number }) {
|
|
28
|
+
return request.get<{ items: UserInfo[]; total: number }>('/users', { params })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getUser(id: number) {
|
|
32
|
+
return request.get<UserInfo>(`/users/${id}`)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function createUser(data: UserCreate) {
|
|
36
|
+
return request.post<UserInfo>('/users', data)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function updateUser(id: number, data: UserUpdate) {
|
|
40
|
+
return request.put<UserInfo>(`/users/${id}`, data)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function deleteUser(id: number) {
|
|
44
|
+
return request.delete(`/users/${id}`)
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 请求实例配置
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// utils/request.ts
|
|
52
|
+
import axios from 'axios'
|
|
53
|
+
|
|
54
|
+
const request = axios.create({
|
|
55
|
+
baseURL: '/api',
|
|
56
|
+
timeout: 30000,
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
// Token 注入
|
|
60
|
+
request.interceptors.request.use((config) => {
|
|
61
|
+
const token = localStorage.getItem('token')
|
|
62
|
+
if (token) {
|
|
63
|
+
config.headers.Authorization = `Bearer ${token}`
|
|
64
|
+
}
|
|
65
|
+
return config
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
// 401 处理
|
|
69
|
+
request.interceptors.response.use(
|
|
70
|
+
(response) => response,
|
|
71
|
+
(error) => {
|
|
72
|
+
if (error.response?.status === 401) {
|
|
73
|
+
localStorage.removeItem('token')
|
|
74
|
+
window.location.href = '/login'
|
|
75
|
+
}
|
|
76
|
+
return Promise.reject(error)
|
|
77
|
+
},
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
export default request
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 禁止的写法
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// ❌ 在组件中直接调用
|
|
87
|
+
const res = await axios.get('/api/users')
|
|
88
|
+
|
|
89
|
+
// ✅ 通过 API 模块调用
|
|
90
|
+
import { getUsers } from '@/api/user'
|
|
91
|
+
const res = await getUsers()
|
|
92
|
+
|
|
93
|
+
// ❌ API 函数使用 default export
|
|
94
|
+
export default { getUsers, createUser }
|
|
95
|
+
|
|
96
|
+
// ✅ 每个函数独立导出
|
|
97
|
+
export function getUsers() { ... }
|
|
98
|
+
export function createUser() { ... }
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 网络层规范(ekit 统一方案)
|
|
104
|
+
|
|
105
|
+
### Vue 前端
|
|
106
|
+
|
|
107
|
+
**唯一方式:** ekit `createRequest()` + 插件。
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// api/client.ts
|
|
111
|
+
import { createRequest } from '@dwydev/ekit'
|
|
112
|
+
|
|
113
|
+
export const request = createRequest({
|
|
114
|
+
baseURL: import.meta.env.VITE_API_BASE_URL,
|
|
115
|
+
plugins: [
|
|
116
|
+
tokenPlugin(), // 注入 Authorization header
|
|
117
|
+
refreshTokenPlugin(), // 401 自动刷新
|
|
118
|
+
unwrapPlugin(), // 解包响应 → data
|
|
119
|
+
],
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
// api/user.ts — 按业务域拆分
|
|
123
|
+
export function getUsers(params: { page: number; page_size: number }) {
|
|
124
|
+
return request.get('/users', { params })
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function createUser(data: UserCreate) {
|
|
128
|
+
return request.post('/users', data)
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**禁止:** `axios.create()`、`fetch()`、`new XMLHttpRequest()`
|
|
133
|
+
|
|
134
|
+
### 响应解包
|
|
135
|
+
|
|
136
|
+
前端的解包逻辑必须与后端 eapi response 格式对齐:
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
后端返回: { code: "SUCCESS", message: "success", data: {...}, timestamp: ... }
|
|
140
|
+
↓ unwrap
|
|
141
|
+
前端拿到: {...} (直接是 data 的内容)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
分页响应解包后拿到 `{ items, total, page, page_size }`(保持 snake_case 对齐后端 JSON)。
|
|
145
|
+
|
|
146
|
+
业务失败时(`code !== "SUCCESS"`),unwrapPlugin 抛出的 HttpError 携带 `businessCode` 和 `apiResponse`。业务 catch 中用 `isApiBusinessError(err)` 做类型守卫后按 `err.businessCode` 分支(如 `NOT_FOUND` / `VALIDATION_ERROR` / `PERMISSION_DENIED`);`VALIDATION_ERROR` 场景可用 `extractValidationErrors(err)` 直接给 vee-validate 的 `setErrors` 回填。
|