@jahanxu/trellis 0.4.2 → 0.5.1
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/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +58 -1
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/constants/paths.d.ts +17 -0
- package/dist/constants/paths.d.ts.map +1 -1
- package/dist/constants/paths.js +19 -0
- package/dist/constants/paths.js.map +1 -1
- package/dist/templates/claude/commands/trellis/handoff.md +90 -387
- package/dist/templates/claude/commands/trellis/pick-task.md +74 -444
- package/dist/templates/claude/commands/trellis/update-spec.md +19 -3
- package/dist/templates/claude/hooks/inject-subagent-context.py +17 -101
- package/dist/templates/claude/hooks/ralph-loop.py +1 -0
- package/dist/templates/claude/hooks/session-start.py +170 -54
- package/dist/templates/iflow/commands/trellis/handoff.md +148 -0
- package/dist/templates/iflow/commands/trellis/pick-task.md +145 -0
- package/dist/templates/iflow/commands/trellis/update-spec.md +19 -3
- package/dist/templates/iflow/hooks/inject-subagent-context.py +1 -0
- package/dist/templates/iflow/hooks/ralph-loop.py +1 -0
- package/dist/templates/iflow/hooks/session-start.py +171 -0
- package/dist/templates/markdown/index.d.ts +9 -0
- package/dist/templates/markdown/index.d.ts.map +1 -1
- package/dist/templates/markdown/index.js +10 -0
- package/dist/templates/markdown/index.js.map +1 -1
- package/dist/templates/markdown/spec/roles/designer/index.md.txt +57 -0
- package/dist/templates/markdown/spec/roles/designer/mock-data-standards.md.txt +63 -0
- package/dist/templates/markdown/spec/roles/designer/prototype-guidelines.md.txt +49 -0
- package/dist/templates/markdown/spec/roles/frontend-impl/api-integration.md.txt +63 -0
- package/dist/templates/markdown/spec/roles/frontend-impl/index.md.txt +57 -0
- package/dist/templates/markdown/spec/roles/frontend-impl/prototype-to-production.md.txt +57 -0
- package/dist/templates/markdown/spec/roles/pm/index.md.txt +45 -0
- package/dist/templates/markdown/spec/roles/pm/prd-template.md.txt +64 -0
- package/dist/templates/markdown/spec/roles/pm/requirement-checklist.md.txt +43 -0
- package/dist/templates/trellis/index.d.ts +1 -0
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +2 -0
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/add_session.py +3 -2
- package/dist/templates/trellis/scripts/common/cli_adapter.py +4 -4
- package/dist/templates/trellis/scripts/common/developer.py +4 -4
- package/dist/templates/trellis/scripts/common/git_context.py +7 -7
- package/dist/templates/trellis/scripts/common/paths.py +64 -14
- package/dist/templates/trellis/scripts/common/phase.py +2 -2
- package/dist/templates/trellis/scripts/common/registry.py +16 -16
- package/dist/templates/trellis/scripts/common/task_queue.py +10 -10
- package/dist/templates/trellis/scripts/common/task_utils.py +5 -5
- package/dist/templates/trellis/scripts/common/worktree.py +8 -8
- package/dist/templates/trellis/scripts/pool.py +214 -266
- package/dist/templates/trellis/scripts/task.py +3 -116
- package/package.json +3 -3
- package/dist/templates/claude/commands/trellis/before-role-work.md +0 -364
- package/dist/templates/trellis/VERSION +0 -1
- package/dist/templates/trellis/deliverables/README.md +0 -51
- package/dist/templates/trellis/paths.README.md +0 -277
- package/dist/templates/trellis/paths.yaml +0 -41
- package/dist/templates/trellis/pool/implementations.json +0 -5
- package/dist/templates/trellis/pool/prototypes.json +0 -5
- package/dist/templates/trellis/pool/requirements.json +0 -5
- package/dist/templates/trellis/scripts/common/project_paths.py +0 -189
- package/dist/templates/trellis/scripts/handoff_generator.py +0 -380
- package/dist/templates/trellis/spec/roles/designer/index.md +0 -243
- package/dist/templates/trellis/spec/roles/designer/mock-data-standards.md +0 -481
- package/dist/templates/trellis/spec/roles/designer/prototype-guidelines.md +0 -429
- package/dist/templates/trellis/spec/roles/frontend-impl/api-integration.md +0 -565
- package/dist/templates/trellis/spec/roles/frontend-impl/index.md +0 -321
- package/dist/templates/trellis/spec/roles/frontend-impl/state-management.md +0 -599
- package/dist/templates/trellis/spec/roles/pm/index.md +0 -112
- package/dist/templates/trellis/spec/roles/pm/prd-template.md +0 -124
|
@@ -1,481 +0,0 @@
|
|
|
1
|
-
# Mock 数据标准
|
|
2
|
-
|
|
3
|
-
> Designer 角色创建和管理 Mock 数据的规范
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 核心原则
|
|
8
|
-
|
|
9
|
-
Mock 数据应该:
|
|
10
|
-
1. **结构完整** - 包含所有必需字段
|
|
11
|
-
2. **类型安全** - 符合 TypeScript 类型定义
|
|
12
|
-
3. **接近真实** - 数据内容符合真实场景
|
|
13
|
-
4. **易于替换** - Frontend 可以快速找到并替换
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 数据组织规范
|
|
18
|
-
|
|
19
|
-
### 目录结构
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
src/mocks/
|
|
23
|
-
├── index.ts # 统一导出
|
|
24
|
-
├── auth.mock.ts # 认证相关
|
|
25
|
-
├── user.mock.ts # 用户数据
|
|
26
|
-
├── product.mock.ts # 产品数据
|
|
27
|
-
└── order.mock.ts # 订单数据
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### 统一导出
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
// src/mocks/index.ts
|
|
34
|
-
export * from './auth.mock';
|
|
35
|
-
export * from './user.mock';
|
|
36
|
-
export * from './product.mock';
|
|
37
|
-
export * from './order.mock';
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
**使用方式**:
|
|
41
|
-
```typescript
|
|
42
|
-
import { mockUser, mockProductList } from '@/mocks';
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## 类型定义规范
|
|
48
|
-
|
|
49
|
-
### 1. 类型优先
|
|
50
|
-
|
|
51
|
-
先定义类型,再创建 Mock 数据:
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
// src/types/user.ts
|
|
55
|
-
export interface User {
|
|
56
|
-
id: string;
|
|
57
|
-
name: string;
|
|
58
|
-
email: string;
|
|
59
|
-
avatar?: string;
|
|
60
|
-
role: 'admin' | 'user' | 'guest';
|
|
61
|
-
createdAt: string;
|
|
62
|
-
updatedAt: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// src/mocks/user.mock.ts
|
|
66
|
-
import type { User } from '@/types/user';
|
|
67
|
-
|
|
68
|
-
export const mockUser: User = {
|
|
69
|
-
id: "user-001",
|
|
70
|
-
name: "张三",
|
|
71
|
-
email: "zhangsan@example.com",
|
|
72
|
-
avatar: "https://i.pravatar.cc/150?img=1",
|
|
73
|
-
role: "user",
|
|
74
|
-
createdAt: "2026-01-01T00:00:00Z",
|
|
75
|
-
updatedAt: "2026-02-01T10:30:00Z"
|
|
76
|
-
};
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### 2. 可选字段处理
|
|
80
|
-
|
|
81
|
-
对于可选字段,提供有值和无值两种 Mock:
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
export const mockUserWithAvatar: User = {
|
|
85
|
-
id: "user-001",
|
|
86
|
-
name: "张三",
|
|
87
|
-
email: "zhangsan@example.com",
|
|
88
|
-
avatar: "https://i.pravatar.cc/150?img=1",
|
|
89
|
-
role: "user",
|
|
90
|
-
createdAt: "2026-01-01T00:00:00Z",
|
|
91
|
-
updatedAt: "2026-02-01T10:30:00Z"
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
export const mockUserWithoutAvatar: User = {
|
|
95
|
-
id: "user-002",
|
|
96
|
-
name: "李四",
|
|
97
|
-
email: "lisi@example.com",
|
|
98
|
-
// avatar: undefined (可选字段,不提供)
|
|
99
|
-
role: "user",
|
|
100
|
-
createdAt: "2026-01-02T00:00:00Z",
|
|
101
|
-
updatedAt: "2026-02-02T11:00:00Z"
|
|
102
|
-
};
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
## 数据真实性规范
|
|
108
|
-
|
|
109
|
-
### 1. 字段内容要求
|
|
110
|
-
|
|
111
|
-
| 字段类型 | Mock 数据要求 | 示例 |
|
|
112
|
-
|---------|-------------|------|
|
|
113
|
-
| **ID** | 语义化前缀 + 数字 | `user-001`, `prod-A123` |
|
|
114
|
-
| **姓名** | 常见中文姓名 | 张三、李四、王五 |
|
|
115
|
-
| **邮箱** | 真实邮箱格式 | `zhangsan@example.com` |
|
|
116
|
-
| **URL** | 可访问的占位图 | `https://via.placeholder.com/150` |
|
|
117
|
-
| **日期** | ISO 8601 格式 | `2026-01-01T00:00:00Z` |
|
|
118
|
-
| **枚举** | 覆盖所有可能值 | `'pending' | 'approved' | 'rejected'` |
|
|
119
|
-
|
|
120
|
-
### 2. 数量要求
|
|
121
|
-
|
|
122
|
-
**单条数据**:包含所有字段
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
export const mockProduct: Product = {
|
|
126
|
-
id: "prod-001",
|
|
127
|
-
name: "iPhone 15 Pro",
|
|
128
|
-
description: "苹果最新旗舰手机,搭载A17 Pro芯片",
|
|
129
|
-
price: 7999,
|
|
130
|
-
stock: 50,
|
|
131
|
-
category: "电子产品",
|
|
132
|
-
tags: ["手机", "苹果", "5G"],
|
|
133
|
-
images: [
|
|
134
|
-
"https://via.placeholder.com/400x300",
|
|
135
|
-
"https://via.placeholder.com/400x300"
|
|
136
|
-
],
|
|
137
|
-
createdAt: "2026-01-15T10:30:00Z"
|
|
138
|
-
};
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
**列表数据**:10-20 条,覆盖边缘场景
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
export const mockProductList: Product[] = [
|
|
145
|
-
{
|
|
146
|
-
id: "prod-001",
|
|
147
|
-
name: "iPhone 15 Pro",
|
|
148
|
-
price: 7999,
|
|
149
|
-
stock: 50,
|
|
150
|
-
category: "电子产品",
|
|
151
|
-
// ...
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
id: "prod-002",
|
|
155
|
-
name: "MacBook Pro 16\"",
|
|
156
|
-
price: 19999,
|
|
157
|
-
stock: 20,
|
|
158
|
-
category: "电脑",
|
|
159
|
-
// ...
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
id: "prod-003",
|
|
163
|
-
name: "AirPods Pro 2",
|
|
164
|
-
price: 1899,
|
|
165
|
-
stock: 0, // ✅ 边缘场景:库存为0
|
|
166
|
-
category: "配件",
|
|
167
|
-
// ...
|
|
168
|
-
},
|
|
169
|
-
// ... 继续到 10-20 条
|
|
170
|
-
];
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### 3. 边缘场景覆盖
|
|
174
|
-
|
|
175
|
-
Mock 数据应该包含边缘场景:
|
|
176
|
-
|
|
177
|
-
```typescript
|
|
178
|
-
export const mockOrderList: Order[] = [
|
|
179
|
-
{
|
|
180
|
-
id: "order-001",
|
|
181
|
-
status: "pending", // 待支付
|
|
182
|
-
total: 7999,
|
|
183
|
-
// ...
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
id: "order-002",
|
|
187
|
-
status: "paid", // 已支付
|
|
188
|
-
total: 19999,
|
|
189
|
-
// ...
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
id: "order-003",
|
|
193
|
-
status: "cancelled", // 已取消
|
|
194
|
-
total: 1899,
|
|
195
|
-
// ...
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
id: "order-004",
|
|
199
|
-
status: "refunded", // 已退款
|
|
200
|
-
total: 5999,
|
|
201
|
-
// ...
|
|
202
|
-
},
|
|
203
|
-
];
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## API 响应格式规范
|
|
209
|
-
|
|
210
|
-
### 1. 统一响应结构
|
|
211
|
-
|
|
212
|
-
定义统一的 API 响应格式:
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
// src/types/api.ts
|
|
216
|
-
export interface ApiResponse<T> {
|
|
217
|
-
code: number;
|
|
218
|
-
message: string;
|
|
219
|
-
data: T;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
export interface ApiListResponse<T> {
|
|
223
|
-
code: number;
|
|
224
|
-
message: string;
|
|
225
|
-
data: {
|
|
226
|
-
items: T[];
|
|
227
|
-
total: number;
|
|
228
|
-
page: number;
|
|
229
|
-
pageSize: number;
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
### 2. Mock API 响应
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
// src/mocks/auth.mock.ts
|
|
238
|
-
import type { ApiResponse } from '@/types/api';
|
|
239
|
-
import type { User } from '@/types/user';
|
|
240
|
-
|
|
241
|
-
export const mockLoginResponse: ApiResponse<{ user: User; token: string }> = {
|
|
242
|
-
code: 200,
|
|
243
|
-
message: "登录成功",
|
|
244
|
-
data: {
|
|
245
|
-
user: mockUser,
|
|
246
|
-
token: "mock-jwt-token-xxx"
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
export const mockLoginErrorResponse: ApiResponse<null> = {
|
|
251
|
-
code: 401,
|
|
252
|
-
message: "邮箱或密码错误",
|
|
253
|
-
data: null
|
|
254
|
-
};
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### 3. 分页数据 Mock
|
|
258
|
-
|
|
259
|
-
```typescript
|
|
260
|
-
export const mockProductListResponse: ApiListResponse<Product> = {
|
|
261
|
-
code: 200,
|
|
262
|
-
message: "成功",
|
|
263
|
-
data: {
|
|
264
|
-
items: mockProductList.slice(0, 10), // 第一页
|
|
265
|
-
total: 50,
|
|
266
|
-
page: 1,
|
|
267
|
-
pageSize: 10
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
---
|
|
273
|
-
|
|
274
|
-
## Mock 函数规范
|
|
275
|
-
|
|
276
|
-
### 1. Mock API 函数
|
|
277
|
-
|
|
278
|
-
每个 API 端点对应一个 Mock 函数:
|
|
279
|
-
|
|
280
|
-
```typescript
|
|
281
|
-
// src/mocks/api/auth.mock.ts
|
|
282
|
-
import type { User } from '@/types/user';
|
|
283
|
-
import { mockUser, mockLoginErrorResponse } from '@/mocks/auth.mock';
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Mock 登录 API
|
|
287
|
-
* TODO: [Frontend] 替换为真实API调用 POST /api/auth/login
|
|
288
|
-
*/
|
|
289
|
-
export const mockLoginAPI = async (
|
|
290
|
-
email: string,
|
|
291
|
-
password: string
|
|
292
|
-
): Promise<{ user: User; token: string }> => {
|
|
293
|
-
return new Promise((resolve, reject) => {
|
|
294
|
-
setTimeout(() => {
|
|
295
|
-
// 模拟登录失败
|
|
296
|
-
if (email === "fail@example.com") {
|
|
297
|
-
reject(new Error(mockLoginErrorResponse.message));
|
|
298
|
-
} else {
|
|
299
|
-
resolve({
|
|
300
|
-
user: mockUser,
|
|
301
|
-
token: "mock-jwt-token-xxx"
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
}, 1000); // 模拟网络延迟
|
|
305
|
-
});
|
|
306
|
-
};
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
### 2. Mock 函数文档注释
|
|
310
|
-
|
|
311
|
-
必须包含:
|
|
312
|
-
- 功能说明
|
|
313
|
-
- TODO 标记(指明需要 Frontend 替换)
|
|
314
|
-
- 真实 API 路径
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
/**
|
|
318
|
-
* Mock 获取用户列表 API
|
|
319
|
-
*
|
|
320
|
-
* TODO: [Frontend] 替换为真实API调用 GET /api/users?page=1&pageSize=10
|
|
321
|
-
*
|
|
322
|
-
* @param page 页码
|
|
323
|
-
* @param pageSize 每页数量
|
|
324
|
-
* @returns 用户列表响应
|
|
325
|
-
*/
|
|
326
|
-
export const mockGetUsersAPI = async (
|
|
327
|
-
page: number = 1,
|
|
328
|
-
pageSize: number = 10
|
|
329
|
-
): Promise<ApiListResponse<User>> => {
|
|
330
|
-
// Mock 实现
|
|
331
|
-
};
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
---
|
|
335
|
-
|
|
336
|
-
## 占位资源规范
|
|
337
|
-
|
|
338
|
-
### 1. 图片占位
|
|
339
|
-
|
|
340
|
-
推荐使用的占位图服务:
|
|
341
|
-
|
|
342
|
-
| 服务 | URL 格式 | 示例 |
|
|
343
|
-
|------|---------|------|
|
|
344
|
-
| **Placeholder.com** | `https://via.placeholder.com/{width}x{height}` | `https://via.placeholder.com/400x300` |
|
|
345
|
-
| **Pravatar** | `https://i.pravatar.cc/{size}?img={id}` | `https://i.pravatar.cc/150?img=1` |
|
|
346
|
-
| **Picsum** | `https://picsum.photos/{width}/{height}` | `https://picsum.photos/400/300` |
|
|
347
|
-
|
|
348
|
-
**示例**:
|
|
349
|
-
```typescript
|
|
350
|
-
export const mockProduct: Product = {
|
|
351
|
-
id: "prod-001",
|
|
352
|
-
name: "iPhone 15 Pro",
|
|
353
|
-
images: [
|
|
354
|
-
"https://via.placeholder.com/400x300?text=iPhone+15+Pro",
|
|
355
|
-
"https://via.placeholder.com/400x300?text=Detail+View",
|
|
356
|
-
],
|
|
357
|
-
// ...
|
|
358
|
-
};
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
### 2. 头像占位
|
|
362
|
-
|
|
363
|
-
```typescript
|
|
364
|
-
export const mockUser: User = {
|
|
365
|
-
id: "user-001",
|
|
366
|
-
name: "张三",
|
|
367
|
-
avatar: "https://i.pravatar.cc/150?img=1", // 固定头像 ID
|
|
368
|
-
// ...
|
|
369
|
-
};
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
---
|
|
373
|
-
|
|
374
|
-
## Mock 数据维护规范
|
|
375
|
-
|
|
376
|
-
### 1. 文件大小控制
|
|
377
|
-
|
|
378
|
-
单个 Mock 文件不超过 **300 行**
|
|
379
|
-
|
|
380
|
-
**✅ 推荐**:按功能拆分
|
|
381
|
-
```
|
|
382
|
-
src/mocks/
|
|
383
|
-
├── user.mock.ts # 用户相关
|
|
384
|
-
├── product.mock.ts # 产品相关
|
|
385
|
-
└── order.mock.ts # 订单相关
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
**❌ 避免**:所有 Mock 放在一个文件
|
|
389
|
-
```
|
|
390
|
-
src/mocks/
|
|
391
|
-
└── data.mock.ts # 1000+ 行,难以维护
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### 2. 更新频率
|
|
395
|
-
|
|
396
|
-
- **需求变更时**:同步更新 Mock 数据结构
|
|
397
|
-
- **Frontend 反馈时**:补充缺失字段或场景
|
|
398
|
-
|
|
399
|
-
### 3. 删除时机
|
|
400
|
-
|
|
401
|
-
**不要删除 Mock 数据**!Frontend 需要用于测试。
|
|
402
|
-
|
|
403
|
-
建议:
|
|
404
|
-
- 保留在 `src/mocks/` 目录
|
|
405
|
-
- Frontend 会将其移动到 `__tests__/mocks/` 用于测试
|
|
406
|
-
|
|
407
|
-
---
|
|
408
|
-
|
|
409
|
-
## 检查清单
|
|
410
|
-
|
|
411
|
-
在交接给 Frontend 前,确保:
|
|
412
|
-
|
|
413
|
-
- [ ] 所有 Mock 数据符合 TypeScript 类型定义
|
|
414
|
-
- [ ] 列表数据包含 10-20 条记录
|
|
415
|
-
- [ ] 覆盖主要边缘场景(空值、错误状态等)
|
|
416
|
-
- [ ] Mock API 函数包含 TODO 注释
|
|
417
|
-
- [ ] 占位图片 URL 可访问
|
|
418
|
-
- [ ] 日期格式统一为 ISO 8601
|
|
419
|
-
- [ ] 统一导出到 `src/mocks/index.ts`
|
|
420
|
-
|
|
421
|
-
---
|
|
422
|
-
|
|
423
|
-
## 常见问题
|
|
424
|
-
|
|
425
|
-
### Q: Mock 数据量应该多大?
|
|
426
|
-
A:
|
|
427
|
-
- **单条数据**:完整包含所有字段
|
|
428
|
-
- **列表数据**:10-20 条,覆盖边缘场景
|
|
429
|
-
- **分页数据**:模拟 total 为 50-100,但只返回当前页
|
|
430
|
-
|
|
431
|
-
### Q: 如何处理关联数据?
|
|
432
|
-
A: 使用外键 ID 关联,但 Mock 数据中可以直接嵌套对象
|
|
433
|
-
|
|
434
|
-
```typescript
|
|
435
|
-
// ✅ 推荐:嵌套完整对象(原型阶段方便显示)
|
|
436
|
-
export const mockOrder: Order = {
|
|
437
|
-
id: "order-001",
|
|
438
|
-
user: mockUser, // 嵌套完整用户对象
|
|
439
|
-
products: mockProductList.slice(0, 2),
|
|
440
|
-
// ...
|
|
441
|
-
};
|
|
442
|
-
|
|
443
|
-
// Frontend 会改为:
|
|
444
|
-
export const mockOrder: Order = {
|
|
445
|
-
id: "order-001",
|
|
446
|
-
userId: "user-001", // 只保留 ID
|
|
447
|
-
productIds: ["prod-001", "prod-002"],
|
|
448
|
-
// ...
|
|
449
|
-
};
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
### Q: Mock 数据需要模拟权限吗?
|
|
453
|
-
A: 不需要。权限验证由 Frontend 实现。
|
|
454
|
-
|
|
455
|
-
### Q: 如何模拟 API 错误?
|
|
456
|
-
A: 提供特定输入触发错误
|
|
457
|
-
|
|
458
|
-
```typescript
|
|
459
|
-
export const mockLoginAPI = async (email: string, password: string) => {
|
|
460
|
-
// TODO: [Frontend] 替换为真实API调用
|
|
461
|
-
return new Promise((resolve, reject) => {
|
|
462
|
-
setTimeout(() => {
|
|
463
|
-
if (email === "error@example.com") {
|
|
464
|
-
reject(new Error("网络错误"));
|
|
465
|
-
} else if (password === "wrong") {
|
|
466
|
-
reject(new Error("密码错误"));
|
|
467
|
-
} else {
|
|
468
|
-
resolve({ user: mockUser, token: "xxx" });
|
|
469
|
-
}
|
|
470
|
-
}, 1000);
|
|
471
|
-
});
|
|
472
|
-
};
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
---
|
|
476
|
-
|
|
477
|
-
## 相关文档
|
|
478
|
-
|
|
479
|
-
- [原型代码指南](./prototype-guidelines.md)
|
|
480
|
-
- [Designer 工作规范](./index.md)
|
|
481
|
-
- [TypeScript 类型规范](../../frontend/type-safety.md)
|