|
|
@@ -0,0 +1,239 @@
|
|
|
+# Story 5.5: 乘客信息查看(管理后台)
|
|
|
+
|
|
|
+## Status
|
|
|
+Draft
|
|
|
+
|
|
|
+## Story
|
|
|
+**As a** 系统管理员
|
|
|
+**I want** 能够查看所有用户的乘客信息
|
|
|
+**so that** 了解用户乘车人情况和进行数据统计
|
|
|
+
|
|
|
+## Acceptance Criteria
|
|
|
+1. 支持查看所有乘客信息列表
|
|
|
+2. 支持按用户筛选乘客信息
|
|
|
+3. 显示乘客基本信息(姓名、证件类型、证件号码、手机号)
|
|
|
+4. 支持导出乘客数据
|
|
|
+
|
|
|
+## Tasks / Subtasks
|
|
|
+- [ ] 创建乘客实体和数据库表 (AC: 1, 2, 3)
|
|
|
+ - [ ] 创建 `src/server/modules/passengers/passenger.entity.ts` 实体文件
|
|
|
+ - [ ] 创建数据库迁移文件,添加passengers表
|
|
|
+ - [ ] 实现乘客与用户的关联关系
|
|
|
+- [ ] 创建乘客相关类型定义和Schema (AC: 1, 2, 3)
|
|
|
+ - [ ] 创建 `src/share/passenger.types.ts` 类型定义文件
|
|
|
+ - [ ] 创建 `src/server/modules/passengers/passenger.schema.ts` Zod Schema文件
|
|
|
+- [ ] 实现乘客CRUD服务 (AC: 1, 2, 3)
|
|
|
+ - [ ] 创建 `src/server/modules/passengers/passenger.service.ts` 服务文件
|
|
|
+ - [ ] 实现乘客列表查询、详情查询功能
|
|
|
+ - [ ] 支持按用户筛选乘客信息
|
|
|
+- [ ] 实现乘客管理API路由 (AC: 1, 2, 3)
|
|
|
+ - [ ] 创建 `src/server/api/passengers/index.ts` API路由文件
|
|
|
+ - [ ] 使用通用CRUD规范创建乘客管理API
|
|
|
+ - [ ] 实现按用户筛选的查询参数支持
|
|
|
+- [ ] 创建管理后台乘客信息页面 (AC: 1, 2, 3, 4)
|
|
|
+ - [ ] 创建 `src/client/admin/pages/Passengers.tsx` 页面组件
|
|
|
+ - [ ] 实现乘客列表表格显示
|
|
|
+ - [ ] 实现按用户筛选功能
|
|
|
+ - [ ] 实现数据导出功能
|
|
|
+- [ ] 集成乘客页面到管理后台路由 (AC: 1)
|
|
|
+ - [ ] 在管理后台路由配置中添加乘客页面
|
|
|
+ - [ ] 更新侧边栏菜单,添加乘客管理入口
|
|
|
+- [ ] 编写乘客管理测试 (AC: 1, 2, 3, 4)
|
|
|
+ - [ ] 编写乘客实体和服务单元测试
|
|
|
+ - [ ] 编写乘客API集成测试
|
|
|
+ - [ ] 编写管理后台页面组件测试
|
|
|
+ - [ ] 编写乘客数据导出功能测试
|
|
|
+
|
|
|
+## Dev Notes
|
|
|
+
|
|
|
+### 数据模型设计
|
|
|
+基于 [docs/architecture/data-model-schema-changes.md#乘客模型],需要实现以下乘客实体结构:
|
|
|
+
|
|
|
+**乘客实体关键属性** [Source: architecture/data-model-schema-changes.md#乘客模型]:
|
|
|
+- `id`: number - 主键标识符
|
|
|
+- `userId`: number - 用户ID
|
|
|
+- `name`: string - 乘客姓名
|
|
|
+- `idType`: IdType - 证件类型(身份证、港澳通行证、台湾通行证、护照等)
|
|
|
+- `idNumber`: string - 证件号码
|
|
|
+- `phone`: string - 手机号
|
|
|
+- `isDefault`: boolean - 是否默认乘客
|
|
|
+
|
|
|
+**证件类型枚举定义** [Source: architecture/data-model-schema-changes.md#枚举定义]:
|
|
|
+```typescript
|
|
|
+export enum IdType {
|
|
|
+ ID_CARD = '身份证',
|
|
|
+ HONG_KONG_MACAO_PASS = '港澳通行证',
|
|
|
+ TAIWAN_PASS = '台湾通行证',
|
|
|
+ PASSPORT = '护照',
|
|
|
+ OTHER = '其他证件'
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 通用CRUD规范要求
|
|
|
+基于 [docs/architecture/generic-crud-standards.md#使用指南],乘客管理必须遵循通用CRUD规范:
|
|
|
+
|
|
|
+**实体设计** [Source: architecture/generic-crud-standards.md#实体设计]:
|
|
|
+- 所有实体必须继承 `ObjectLiteral`
|
|
|
+- 包含 `createdAt` 和 `updatedAt` 时间戳
|
|
|
+- 使用TypeORM装饰器定义字段
|
|
|
+
|
|
|
+**Schema设计** [Source: architecture/generic-crud-standards.md#schema设计]:
|
|
|
+- 创建和更新使用不同的schema
|
|
|
+- 响应schema应包含完整字段
|
|
|
+- 使用 `.optional()` 和 `.nullable()` 明确字段可选性
|
|
|
+
|
|
|
+**CRUD路由注册** [Source: architecture/generic-crud-standards.md#注册crud路由]:
|
|
|
+```typescript
|
|
|
+export const passengerRoutes = createCrudRoutes({
|
|
|
+ entity: Passenger,
|
|
|
+ createSchema: PassengerCreateSchema,
|
|
|
+ updateSchema: PassengerUpdateSchema,
|
|
|
+ getSchema: PassengerGetSchema,
|
|
|
+ listSchema: PassengerListSchema,
|
|
|
+ searchFields: ['name', 'phone', 'idNumber'],
|
|
|
+ relations: ['user'],
|
|
|
+ middleware: [authMiddleware],
|
|
|
+ userTracking: {
|
|
|
+ createdByField: 'createdBy',
|
|
|
+ updatedByField: 'updatedBy'
|
|
|
+ }
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+### 管理后台开发规范
|
|
|
+基于 [docs/architecture/admin-dashboard-standards.md#页面开发规范],乘客信息页面必须遵循管理后台开发标准:
|
|
|
+
|
|
|
+**技术栈要求** [Source: architecture/admin-dashboard-standards.md#技术栈要求]:
|
|
|
+- **React**: 19.1.0+,使用函数组件和Hooks
|
|
|
+- **TypeScript**: 严格模式,类型安全优先
|
|
|
+- **React Router**: v7,声明式路由管理
|
|
|
+- **@tanstack/react-query**: 服务端状态管理
|
|
|
+- **React Hook Form**: 表单状态管理
|
|
|
+- **shadcn/ui**: 基于Radix UI的组件库
|
|
|
+
|
|
|
+**页面结构标准** [Source: architecture/admin-dashboard-standards.md#页面结构标准]:
|
|
|
+- 使用标准表格组件显示乘客列表
|
|
|
+- 实现搜索和筛选功能
|
|
|
+- 使用分页组件处理大量数据
|
|
|
+- 遵循统一的错误处理和加载状态
|
|
|
+
|
|
|
+**RPC客户端使用规范** [Source: architecture/admin-dashboard-standards.md#rpc-client-使用规范]:
|
|
|
+```typescript
|
|
|
+// 使用RPC方式提取类型
|
|
|
+type PassengerResponse = InferResponseType<typeof passengerClient.$get, 200>['data'][0];
|
|
|
+type PassengerListResponse = InferResponseType<typeof passengerClient.$get, 200>;
|
|
|
+
|
|
|
+// API调用规范
|
|
|
+const { data, isLoading, refetch } = useQuery({
|
|
|
+ queryKey: ['passengers', searchParams],
|
|
|
+ queryFn: async () => {
|
|
|
+ const res = await passengerClient.$get({
|
|
|
+ query: {
|
|
|
+ page: searchParams.page,
|
|
|
+ pageSize: searchParams.limit,
|
|
|
+ keyword: searchParams.keyword,
|
|
|
+ filters: hasActiveFilters ? JSON.stringify(filters) : undefined
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (res.status !== 200) throw new Error('获取数据失败');
|
|
|
+ return await res.json();
|
|
|
+ }
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+### 文件位置
|
|
|
+基于 [docs/architecture/source-tree.md#实际项目结构],所有乘客相关文件必须放置在指定位置:
|
|
|
+
|
|
|
+**后端文件位置** [Source: architecture/source-tree.md#实际项目结构]:
|
|
|
+- **实体定义**: `src/server/modules/passengers/passenger.entity.ts`
|
|
|
+- **业务服务**: `src/server/modules/passengers/passenger.service.ts`
|
|
|
+- **Zod Schema**: `src/server/modules/passengers/passenger.schema.ts`
|
|
|
+- **API路由**: `src/server/api/passengers/index.ts`
|
|
|
+
|
|
|
+**前端文件位置** [Source: architecture/source-tree.md#实际项目结构]:
|
|
|
+- **管理后台页面**: `src/client/admin/pages/Passengers.tsx`
|
|
|
+
|
|
|
+**共享类型位置** [Source: architecture/source-tree.md#实际项目结构]:
|
|
|
+- **类型定义**: `src/share/passenger.types.ts`
|
|
|
+
|
|
|
+### 技术栈要求
|
|
|
+基于 [docs/architecture/tech-stack.md#现有技术栈维护],必须使用项目标准技术栈:
|
|
|
+
|
|
|
+**后端框架** [Source: architecture/tech-stack.md#现有技术栈维护]:
|
|
|
+- **运行时**: Node.js 20.19.2
|
|
|
+- **框架**: Hono 4.8.5
|
|
|
+- **数据库**: PostgreSQL 17
|
|
|
+- **ORM**: TypeORM 0.3.25
|
|
|
+
|
|
|
+**前端框架** [Source: architecture/tech-stack.md#现有技术栈维护]:
|
|
|
+- **前端框架**: Taro + React
|
|
|
+- **样式**: Tailwind CSS 4.1.11
|
|
|
+- **状态管理**: React Query 5.83.0
|
|
|
+
|
|
|
+### 开发规范要求
|
|
|
+基于 [docs/architecture/coding-standards.md#通用crud开发规范],必须遵循编码标准:
|
|
|
+
|
|
|
+**CRUD开发** [Source: architecture/coding-standards.md#通用crud开发规范]:
|
|
|
+- 遵循通用CRUD规范进行开发
|
|
|
+- 所有实体必须继承 `ObjectLiteral`,包含时间戳字段
|
|
|
+- 创建、更新、响应使用不同的Zod schema
|
|
|
+- 使用 `createCrudRoutes` 自动生成API路由
|
|
|
+
|
|
|
+**管理后台开发** [Source: architecture/coding-standards.md#管理后台开发规范]:
|
|
|
+- 遵循管理后台开发规范进行开发
|
|
|
+- 统一页面结构和布局标准
|
|
|
+- 标准表格组件使用规范
|
|
|
+- 基于角色的访问控制实现
|
|
|
+
|
|
|
+### 数据导出功能要求
|
|
|
+基于 [docs/prd/epic-005-travel-service-core.md#us005-05-乘客信息查看管理后台],需要实现数据导出功能:
|
|
|
+
|
|
|
+**导出格式要求**:
|
|
|
+- 支持CSV格式导出
|
|
|
+- 包含所有乘客基本信息字段
|
|
|
+- 支持按当前筛选条件导出
|
|
|
+- 导出文件名包含时间戳
|
|
|
+
|
|
|
+### Testing
|
|
|
+
|
|
|
+**测试要求** [Source: architecture/testing-strategy.md#主项目测试体系]:
|
|
|
+- **主项目测试位置**: `tests/unit/`, `tests/integration/`, `tests/e2e/` 目录
|
|
|
+- **主项目测试框架**: Vitest + Testing Library + hono/testing + Playwright
|
|
|
+- **覆盖率目标**: 核心业务逻辑 > 80%
|
|
|
+
|
|
|
+**具体测试要求** [Source: architecture/testing-strategy.md#测试金字塔策略]:
|
|
|
+- **乘客实体和服务单元测试** (P0优先级)
|
|
|
+ - 验证乘客实体字段定义正确性
|
|
|
+ - 测试乘客服务CRUD操作
|
|
|
+ - 验证按用户筛选功能
|
|
|
+- **乘客API集成测试** (P1优先级)
|
|
|
+ - 测试乘客列表API端点
|
|
|
+ - 验证筛选参数处理
|
|
|
+ - 测试分页功能
|
|
|
+- **管理后台页面组件测试** (P1优先级)
|
|
|
+ - 测试乘客列表页面渲染
|
|
|
+ - 验证搜索和筛选功能
|
|
|
+ - 测试数据导出功能
|
|
|
+- **乘客数据导出E2E测试** (P0优先级)
|
|
|
+ - 验证导出功能完整流程
|
|
|
+ - 测试导出文件格式正确性
|
|
|
+ - 验证筛选条件在导出中的正确应用
|
|
|
+
|
|
|
+## Change Log
|
|
|
+| Date | Version | Description | Author |
|
|
|
+|------|---------|-------------|--------|
|
|
|
+| 2025-10-21 | 1.0 | 初始故事创建,基于史诗005 US005-05需求 | Bob (Scrum Master) |
|
|
|
+
|
|
|
+## Dev Agent Record
|
|
|
+*此部分由开发代理在实施过程中填写*
|
|
|
+
|
|
|
+### Agent Model Used
|
|
|
+
|
|
|
+### Debug Log References
|
|
|
+
|
|
|
+### Completion Notes List
|
|
|
+
|
|
|
+### File List
|
|
|
+
|
|
|
+## QA Results
|
|
|
+*此部分由QA代理在审查完成后填写*
|