Approve
As a 系统管理员 I want 能够配置活动、路线等基础数据 so that 用户能够查询和使用出行服务
src/server/modules/routes/ 创建 route.entity.tssrc/server/modules/activities/ 创建 activity.entity.tssrc/share/ 创建相关类型定义src/server/modules/routes/ 创建 route.schema.ts (创建、更新、获取、列表Schema)src/server/modules/activities/ 创建 activity.schema.ts (创建、更新、获取、列表Schema)src/server/api/admin/activities/index.ts 使用 createCrudRoutes 创建活动管理APIsrc/server/api/admin/routes/index.ts 使用 createCrudRoutes 创建路线管理APItests/unit/server/)tests/integration/server/)tests/integration/server/)基于 [docs/prd/epic-005-travel-service-core.md#后端数据模型] 和 [docs/architecture/data-model-schema-changes.md],需要实现以下实体:
Route实体 (遵循 通用CRUD实体设计规范):
createdAt 和 updatedAt 时间戳Activity实体 (遵循 通用CRUD实体设计规范):
createdAt 和 updatedAt 时间戳routes 表,包含必要的字段和索引activities 表,包含必要的字段和索引基于 [docs/prd/epic-005-travel-service-core.md#管理后台API],使用 通用CRUD规范 实现以下API端点:
活动管理API (使用 createCrudRoutes):
GET /api/v1/admin/activities - 活动管理列表(支持分页、搜索、筛选)GET /api/v1/admin/activities/:id - 活动详情POST /api/v1/admin/activities - 创建活动PUT /api/v1/admin/activities/:id - 更新活动DELETE /api/v1/admin/activities/:id - 删除活动活动管理API配置:
['name', 'description']['routes']type (活动类型)[authMiddleware]路线管理API (使用 createCrudRoutes):
GET /api/v1/admin/routes - 路线管理列表(支持分页、搜索、筛选)GET /api/v1/admin/routes/:id - 路线详情POST /api/v1/admin/routes - 创建路线PUT /api/v1/admin/routes/:id - 更新路线DELETE /api/v1/admin/routes/:id - 删除路线路线管理API配置:
['startPoint', 'endPoint', 'vehicleType']['activity']vehicleType, price (范围查询)price, departureTime[authMiddleware]基于用户体验改进需求,需要实现活动选择组件来替换原有的数字ID输入框:
ActivitySelect组件功能要求:
组件位置:
src/client/admin/components/ActivitySelect.tsx集成要求:
基于 [docs/prd/epic-005-travel-service-core.md#管理后台页面任务],需要实现以下页面:
严格遵循 RPC Client 使用规范:
客户端导入和类型定义:
// 从统一的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'];
数据获取规范:
// 使用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分钟缓存
});
统一错误处理:
// 统一操作处理函数
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('创建失败');
});
};
防抖搜索实现:
// 防抖搜索函数
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),
[]
);
活动管理页面:
路线管理页面:
src/server/modules/routes/route.entity.tssrc/server/modules/activities/activity.entity.tssrc/server/modules/routes/route.schema.tssrc/server/modules/activities/activity.schema.tssrc/share/route.types.tssrc/share/activity.types.tssrc/server/api/admin/activities/index.tssrc/server/api/admin/routes/index.tsmini/src/pages/admin/activities/ActivityManagementPage.tsxmini/src/pages/admin/routes/RouteManagementPage.tsxsrc/client/admin/components/ActivitySelect.tsxsrc/server/migrations/ 目录src/server/seeds/ 目录| Date | Version | Description | Author |
|---|---|---|---|
| 2025-10-16 | 1.7 | 补充活动选择组件任务,提升用户体验 | Bob (Scrum Master) |
| 2025-10-16 | 1.6 | 完成管理后台页面所有功能:搜索筛选、创建编辑、启用/禁用 | James (Dev Agent) |
| 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) |
| 2025-10-16 | 1.1 | 修正故事,添加管理后台功能,完全满足epic005 US005-01需求 | Bob (Scrum Master) |
| 2025-10-16 | 1.0 | 初始故事创建,从005.002迁移基础数据实体任务 | Bob (Scrum Master) |
此部分由开发代理在实施过程中填写
Claude Sonnet 4.5 (2025-09-29)
✅ 已完成的任务:
✅ 技术实现细节:
已创建/修改的文件:
此部分由QA代理在审查完成后填写