|
|
@@ -100,6 +100,84 @@ Draft
|
|
|
### 管理后台页面设计
|
|
|
基于 [docs/prd/epic-005-travel-service-core.md#管理后台页面任务],需要实现以下页面:
|
|
|
|
|
|
+#### 前端RPC实现规范
|
|
|
+严格遵循 [RPC Client 使用规范](../architecture/admin-dashboard-standards.md#rpc-client-使用规范):
|
|
|
+
|
|
|
+**客户端导入和类型定义**:
|
|
|
+```typescript
|
|
|
+// 从统一的API模块导入客户端
|
|
|
+import { activityClient, routeClient } from '@/client/api';
|
|
|
+import type { InferRequestType, InferResponseType } from 'hono/client';
|
|
|
+
|
|
|
+// 类型提取规范
|
|
|
+type ActivityResponse = InferResponseType<typeof activityClient.$get, 200>['data'][0];
|
|
|
+type RouteResponse = InferResponseType<typeof routeClient.$get, 200>['data'][0];
|
|
|
+type CreateActivityRequest = InferRequestType<typeof activityClient.$post>['json'];
|
|
|
+type UpdateActivityRequest = InferRequestType<typeof activityClient[':id']['$put']>['json'];
|
|
|
+```
|
|
|
+
|
|
|
+**数据获取规范**:
|
|
|
+```typescript
|
|
|
+// 使用React Query进行数据获取
|
|
|
+const { data, isLoading, refetch } = useQuery({
|
|
|
+ queryKey: ['activities', searchParams],
|
|
|
+ queryFn: async () => {
|
|
|
+ const res = await activityClient.$get({
|
|
|
+ query: {
|
|
|
+ page: searchParams.page,
|
|
|
+ pageSize: searchParams.limit,
|
|
|
+ keyword: searchParams.keyword
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (res.status !== 200) throw new Error('获取数据失败');
|
|
|
+ return await res.json();
|
|
|
+ },
|
|
|
+ staleTime: 5 * 60 * 1000, // 5分钟缓存
|
|
|
+ cacheTime: 10 * 60 * 1000, // 10分钟缓存
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+**统一错误处理**:
|
|
|
+```typescript
|
|
|
+// 统一操作处理函数
|
|
|
+const handleOperation = async (operation: () => Promise<any>) => {
|
|
|
+ try {
|
|
|
+ await operation();
|
|
|
+ toast.success('操作成功');
|
|
|
+ } catch (error) {
|
|
|
+ console.error('操作失败:', error);
|
|
|
+ toast.error('操作失败,请重试');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 创建活动示例
|
|
|
+const handleCreateActivity = async (data: CreateActivityRequest) => {
|
|
|
+ await handleOperation(async () => {
|
|
|
+ const res = await activityClient.$post({ json: data });
|
|
|
+ if (res.status !== 201) throw new Error('创建失败');
|
|
|
+ });
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+**防抖搜索实现**:
|
|
|
+```typescript
|
|
|
+// 防抖搜索函数
|
|
|
+const debounce = (func: Function, delay: number) => {
|
|
|
+ let timeoutId: NodeJS.Timeout;
|
|
|
+ return (...args: any[]) => {
|
|
|
+ clearTimeout(timeoutId);
|
|
|
+ timeoutId = setTimeout(() => func(...args), delay);
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+const debouncedSearch = useCallback(
|
|
|
+ debounce((keyword: string) => {
|
|
|
+ setSearchParams(prev => ({ ...prev, keyword, page: 1 }));
|
|
|
+ }, 300),
|
|
|
+ []
|
|
|
+);
|
|
|
+```
|
|
|
+
|
|
|
**活动管理页面**:
|
|
|
- 活动类型配置和管理
|
|
|
- 支持创建、编辑、删除活动
|
|
|
@@ -109,6 +187,7 @@ Draft
|
|
|
- 使用 [数据表格规范](../architecture/admin-dashboard-standards.md#数据表格规范) 显示活动列表
|
|
|
- 实现 [搜索和筛选功能](../architecture/admin-dashboard-standards.md#搜索和筛选规范)
|
|
|
- 使用 [表单处理规范](../architecture/admin-dashboard-standards.md#表单处理规范) 处理活动创建和编辑
|
|
|
+- 严格遵循 [RPC Client 使用规范](../architecture/admin-dashboard-standards.md#rpc-client-使用规范)
|
|
|
|
|
|
**路线管理页面**:
|
|
|
- 路线信息配置和管理
|
|
|
@@ -119,6 +198,7 @@ Draft
|
|
|
- 使用 [数据表格规范](../architecture/admin-dashboard-standards.md#数据表格规范) 显示路线列表
|
|
|
- 实现 [搜索和筛选功能](../architecture/admin-dashboard-standards.md#搜索和筛选规范)
|
|
|
- 使用 [表单处理规范](../architecture/admin-dashboard-standards.md#表单处理规范) 处理路线创建和编辑
|
|
|
+- 严格遵循 [RPC Client 使用规范](../architecture/admin-dashboard-standards.md#rpc-client-使用规范)
|
|
|
|
|
|
### 种子数据要求
|
|
|
- 创建示例活动数据:至少包含去程活动和返程活动各3个
|
|
|
@@ -173,6 +253,7 @@ Draft
|
|
|
## Change Log
|
|
|
| Date | Version | Description | Author |
|
|
|
|------|---------|-------------|--------|
|
|
|
+| 2025-10-16 | 1.5 | 添加前端RPC实现规范,确保符合管理后台RPC Client使用规范 | Bob (Scrum Master) |
|
|
|
| 2025-10-16 | 1.4 | 添加通用CRUD规范引用,完善API实现细节 | Bob (Scrum Master) |
|
|
|
| 2025-10-16 | 1.3 | 添加管理后台开发规范引用,确保符合标准 | Bob (Scrum Master) |
|
|
|
| 2025-10-16 | 1.2 | 修正故事,移除班次实体,与epic005和数据模型保持一致 | Bob (Scrum Master) |
|