# Story 10.1: 创建订单管理 Page Object

Status: done

<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->

## Story

作为测试开发者，
我想要创建订单管理的 Page Object，
以便组织订单管理相关的页面元素和操作。

## Acceptance Criteria

**Given** Epic 9 的 Page Object 模式已验证
**When** 创建 `web/tests/e2e/pages/admin/order-management.page.ts`
**Then** 定义订单列表页面的选择器和操作方法
**And** 定义创建订单表单的选择器和操作方法
**And** 定义编辑订单表单的选择器和操作方法
**And** 定义订单详情对话框的选择器和操作方法
**And** 定义人员关联相关的选择器和操作方法
**And** 定义附件上传相关的选择器和操作方法
**And** 遵循现有 Page Object 设计模式
**And** 所有方法有完整的 TypeScript 类型定义

**参考：**
- `web/tests/e2e/pages/admin/disability-person.page.ts` 作为参考
- `web/tests/e2e/pages/admin/region-management.page.ts` 作为参考
- 遵循项目的 Page Object 设计模式

## Tasks / Subtasks

- [x] 创建订单管理 Page Object 基础结构 (AC: Given, When, And)
  - [x] 定义订单列表页面选择器（标题、新增按钮、搜索框、表格等）
  - [x] 实现 goto() 方法导航到订单管理页面
  - [x] 实现 expectToBeVisible() 方法验证关键元素可见
- [x] 定义订单列表相关方法和选择器 (AC: When)
  - [x] 定义订单名称搜索输入框和搜索按钮
  - [x] 定义订单筛选器（状态、平台、公司、渠道、日期范围）
  - [x] 定义订单列表表格选择器
  - [x] 实现搜索功能方法 searchByName()
  - [x] 实现筛选功能方法
- [x] 定义订单 CRUD 相关方法和选择器 (AC: When)
  - [x] 实现打开创建订单对话框方法 openCreateDialog()
  - [x] 实现填写订单表单方法 fillOrderForm()
  - [x] 实现提交表单方法 submitForm()
  - [x] 实现打开编辑订单对话框方法 openEditDialog()
  - [x] 实现打开删除确认对话框方法 openDeleteDialog()
  - [x] 实现订单是否存在验证方法 orderExists()
- [x] 定义订单详情相关方法和选择器 (AC: When)
  - [x] 实现打开订单详情对话框方法 openDetailDialog()
  - [x] 定义详情对话框内的选择器（订单信息、人员列表、附件列表）
- [x] 定义人员关联相关方法和选择器 (AC: When)
  - [x] 实现打开人员管理对话框方法 openPersonManagementDialog()
  - [x] 实现添加人员方法 addPersonToOrder()
  - [x] 实现修改工作状态方法 updatePersonWorkStatus()
- [x] 定义附件管理相关方法和选择器 (AC: When)
  - [x] 实现打开添加附件对话框方法 openAddAttachmentDialog()
  - [x] 实现上传附件方法 uploadAttachment()
- [x] 添加 TypeScript 类型定义和 JSDoc 注释 (AC: And)
  - [x] 定义 OrderData 接口
  - [x] 定义 OrderPersonData 接口
  - [x] 定义 FormSubmitResult 接口
  - [x] 为所有公共方法添加 JSDoc 注释

## Dev Notes

### Epic Context

**Epic 10: 订单管理 E2E 测试 (Epic C - 业务测试 Epic)**

- **目标**: 为订单管理功能编写完整的 E2E 测试，验证订单的 CRUD、状态流转、人员关联和附件管理功能
- **业务分组**: Epic C（业务测试 Epic）
- **背景**: 订单管理是招聘系统的核心业务功能，涉及复杂表单（多选择器联动）、状态流转、人员关联等场景
- **模式**: 业务测试为主，工具包支持为辅（遵循 Epic A 成功模式）

**依赖:**
- Epic 1: ✅ 已完成（Select 工具基础框架）
- Epic 2: ✅ 已完成（Select 工具在真实 E2E 测试中验证）
- Epic 9: 🔄 进行中（残疾人管理完整 E2E 测试覆盖）

### 订单管理功能概述

根据 epics.md，订单管理涉及以下核心功能：

1. **订单列表**: 查看、搜索、筛选、分页
2. **订单 CRUD**: 创建、编辑、删除订单
3. **订单状态流转**: 草稿 → 已确认 → 进行中 → 已完成
4. **订单详情**: 查看订单完整信息、人员列表、附件列表
5. **人员关联**: 添加残疾人到订单、管理工作状态（未就业、待就业、已就业、已离职）
6. **附件管理**: 为订单人员添加附件

### Page Object 设计模式参考

本项目已建立成熟的 Page Object 设计模式，参考以下文件：

**1. disability-person.page.ts** (残疾人管理 - 复杂表单示例)
- 位置: `web/tests/e2e/pages/admin/disability-person.page.ts`
- 特点: 多步骤表单、照片上传、动态列表（银行卡、备注、回访记录）
- 关键模式:
  - 使用 `@d8d/e2e-test-utils` 的 `selectRadixOption` 和 `selectProvinceCity`
  - 网络响应监听和 Toast 消息验证
  - 表单调试使用 `console.debug`

**2. region-management.page.ts** (区域管理 - 业务模块示例)
- 位置: `web/tests/e2e/pages/admin/region-management.page.ts`
- 特点: 树形结构、CRUD 操作、状态切换
- 关键模式:
  - 导出的类型定义（RegionData, RegionLevel, FormSubmitResult 等）
  - 完整的 JSDoc 注释
  - 网络响应监听（NetworkResponse 接口）
  - Toast 消息验证（data-sonner-toast）

### 技术要求

**导入依赖:**
```typescript
import { Page, Locator } from '@playwright/test';
import { selectRadixOption, selectRadixOptionAsync } from '@d8d/e2e-test-utils';
```

**选择器策略:**
- 优先使用 `data-testid` 属性
- 其次使用 `role + name` 组合（如 `getByRole('button', { name: '新增订单' })`）
- 避免使用 CSS 类名（不稳定）
- 文本匹配使用 `exact: true` 避免误匹配

**网络响应监听模式:**
```typescript
// 收集网络响应
const responses: NetworkResponse[] = [];

// 监听所有网络请求
this.page.on('response', async (response: Response) => {
  const url = response.url();
  if (url.includes('/orders') || url.includes('order')) {
    // 收集响应数据
  }
});

// 执行操作后等待网络空闲
await this.page.waitForLoadState('networkidle', { timeout: 10000 });
```

**Toast 消息验证:**
```typescript
const errorToast = this.page.locator('[data-sonner-toast][data-type="error"]');
const successToast = this.page.locator('[data-sonner-toast][data-type="success"]');
```

### Project Structure Notes

**文件位置:**
- Page Object 文件: `web/tests/e2e/pages/admin/order-management.page.ts`
- 测试文件目录: `web/tests/e2e/specs/admin/`
- Fixtures 目录: `web/tests/e2e/fixtures/`

**对齐统一项目结构:**
- 遵循 `project-context.md` 中的 TypeScript 严格模式规则
- 函数参数、返回值必须有明确类型注解
- 禁止使用 `any` 类型
- 公共 API 必须包含完整 JSDoc 注释

### 测试标准参考

遵循以下测试标准文档（来自 epics.md）：
- `docs/standards/testing-standards.md` - 测试规范
- `docs/standards/web-ui-testing-standards.md` - Web UI 测试规范
- `docs/standards/e2e-radix-testing.md` - Radix UI E2E 测试标准（核心）

**选择器优先级（来自 e2e-radix-testing.md）:**
1. `data-testid` - 最高优先级
2. `aria-label + role`
3. `text content + role` - 兜底

**错误消息格式标准:**
```
Error: 操作失败
  上下文信息
  💡 修复建议
```

### 类型定义参考

基于 `region-management.page.ts` 的类型定义模式：

```typescript
/**
 * 订单状态常量
 */
export const ORDER_STATUS = {
  DRAFT: 'draft',
  CONFIRMED: 'confirmed',
  IN_PROGRESS: 'in_progress',
  COMPLETED: 'completed',
} as const;

/**
 * 工作状态常量
 */
export const WORK_STATUS = {
  NOT_EMPLOYED: 'not_employed',
  PENDING: 'pending',
  EMPLOYED: 'employed',
  RESIGNED: 'resigned',
} as const;

/**
 * 订单数据接口
 */
export interface OrderData {
  /** 订单名称 */
  name: string;
  /** 预计开始日期 */
  expectedStartDate?: string;
  /** 平台ID */
  platformId?: number;
  /** 公司ID */
  companyId?: number;
  /** 渠道ID */
  channelId?: number;
  /** 订单状态 */
  status?: typeof ORDER_STATUS[keyof typeof ORDER_STATUS];
  /** 工作状态 */
  workStatus?: typeof WORK_STATUS[keyof typeof WORK_STATUS];
}

/**
 * 订单人员数据接口
 */
export interface OrderPersonData {
  /** 残疾人ID */
  disabledPersonId: number;
  /** 入职日期 */
  hireDate?: string;
  /** 薪资 */
  salary?: number;
  /** 工作状态 */
  workStatus?: typeof WORK_STATUS[keyof typeof WORK_STATUS];
  /** 实际入职日期 */
  actualHireDate?: string;
  /** 离职日期 */
  resignDate?: string;
}

/**
 * 网络响应数据
 */
export interface NetworkResponse {
  url: string;
  method: string;
  status: number;
  ok: boolean;
  responseHeaders: Record<string, string>;
  responseBody: unknown;
}

/**
 * 表单提交结果
 */
export interface FormSubmitResult {
  /** 提交是否成功 */
  success: boolean;
  /** 是否有错误 */
  hasError: boolean;
  /** 是否有成功消息 */
  hasSuccess: boolean;
  /** 错误消息 */
  errorMessage?: string;
  /** 成功消息 */
  successMessage?: string;
  /** 网络响应列表 */
  responses?: NetworkResponse[];
}
```

### 订单管理页面元素（待验证）

**注意**: 以下元素基于 PRD 描述，实际实现时需要通过浏览器开发工具验证 DOM 结构。

**订单列表页面:**
- 页面路径: `/admin/orders`（待确认）
- 页面标题: "订单管理"
- 新增订单按钮: "新增订单"
- 搜索输入框: placeholder="搜索订单名称"
- 搜索按钮: "搜索"
- 筛选器: 订单状态、工作状态、平台、公司、渠道、日期范围
- 订单列表表格: 显示订单名称、平台、公司、渠道、订单状态、工作状态等

**订单表单:**
- 订单名称: 必填
- 预计开始日期: 必填，日期选择器
- 平台: 可选，下拉选择器
- 公司: 可选，下拉选择器
- 渠道: 可选，下拉选择器

**订单详情对话框:**
- 显示订单基本信息
- 显示关联人员列表
- 显示附件列表

**人员管理对话框:**
- 选择残疾人: 下拉选择器
- 入职日期: 日期选择器
- 薪资: 数字输入
- 工作状态: 下拉选择器

**附件上传对话框:**
- 选择订单人员: 下拉选择器
- 上传附件: 文件上传组件

### 调试技巧

**表单调试:**
```typescript
// 在 form.handleSubmit 的第二个参数中添加 console.debug
form.handleSubmit(handleSubmit, (errors) => console.debug('表单验证错误:', errors))
```

**E2E 测试失败调试:**
- 查看 `test-results/**/error-context.md`
- 使用 `timeout` 命令限制运行时间
- `timeout 60 pnpm test:e2e:chromium <测试文件名>`

### References

- [Source: _bmad-output/planning-artifacts/epics.md#Epic 10](../planning-artifacts/epics.md)
- [Source: _bmad-output/project-context.md](../project-context.md)
- [Source: web/tests/e2e/pages/admin/region-management.page.ts](../../web/tests/e2e/pages/admin/region-management.page.ts)
- [Source: web/tests/e2e/pages/admin/disability-person.page.ts](../../web/tests/e2e/pages/admin/disability-person.page.ts)

## Dev Agent Record

### Agent Model Used

claude-opus-4-5-20251101

### Debug Log References

### Completion Notes List

✅ **Story 10.1 完成实现**

创建了订单管理 Page Object (`web/tests/e2e/pages/admin/order-management.page.ts`)，包含以下功能：

1. **类型定义和常量**:
   - `ORDER_STATUS` - 订单状态常量（草稿、已确认、进行中、已完成）
   - `WORK_STATUS` - 工作状态常量（未就业、待就业、已就业、已离职）
   - `ORDER_STATUS_LABELS` / `WORK_STATUS_LABELS` - 状态显示名称映射
   - `OrderData` 接口 - 订单数据类型
   - `OrderPersonData` 接口 - 订单人员数据类型
   - `NetworkResponse` 接口 - 网络响应类型
   - `FormSubmitResult` 接口 - 表单提交结果类型

2. **页面基础功能**:
   - `goto()` - 导航到订单管理页面
   - `expectToBeVisible()` - 验证关键元素可见
   - 页面选择器：标题、新增按钮、表格、搜索框等

3. **搜索和筛选**:
   - `searchByName()` - 按订单名称搜索
   - `openFilterDialog()` - 打开高级筛选对话框
   - `setFilters()` - 设置筛选条件（状态、平台、公司、渠道、日期范围）
   - `applyFilters()` - 应用筛选
   - `clearFilters()` - 清空筛选

4. **订单 CRUD**:
   - `openCreateDialog()` - 打开创建订单对话框
   - `openEditDialog()` - 打开编辑订单对话框
   - `openDeleteDialog()` - 打开删除确认对话框
   - `fillOrderForm()` - 填写订单表单
   - `submitForm()` - 提交表单（包含网络响应监听和 Toast 消息验证）
   - `cancelDialog()` - 取消对话框
   - `confirmDelete()` - 确认删除
   - `cancelDelete()` - 取消删除
   - `orderExists()` - 验证订单是否存在

5. **高级操作（完整流程）**:
   - `createOrder()` - 创建订单（完整流程）
   - `editOrder()` - 编辑订单（完整流程）
   - `deleteOrder()` - 删除订单（完整流程）

6. **订单详情**:
   - `openDetailDialog()` - 打开订单详情对话框
   - `getOrderDetailInfo()` - 获取订单详情中的基本信息

7. **人员关联管理**:
   - `openPersonManagementDialog()` - 打开人员管理对话框
   - `addPersonToOrder()` - 添加人员到订单
   - `updatePersonWorkStatus()` - 修改人员工作状态

8. **附件管理**:
   - `openAddAttachmentDialog()` - 打开添加附件对话框
   - `uploadAttachment()` - 上传附件

**实现要点**:
- 遵循项目 Page Object 设计模式（参考 region-management.page.ts 和 disability-person.page.ts）
- 使用 `@d8d/e2e-test-utils` 的 `selectRadixOption` 和 `selectRadixOptionAsync` 处理 Radix UI 组件
- 使用 `role + name` 组合选择器，符合项目无障碍测试标准
- 所有公共方法都包含完整的 JSDoc 注释
- 网络响应监听模式用于验证 API 调用
- Toast 消息验证（使用 `data-sonner-toast` 属性）

**注意**: 实际 DOM 结构和选择器可能需要根据实际页面实现进行调整，建议在编写测试时通过浏览器开发工具验证。

### File List

- web/tests/e2e/pages/admin/order-management.page.ts

## Change Log

### 2026-01-11

- ✅ 创建订单管理 Page Object (`web/tests/e2e/pages/admin/order-management.page.ts`)
- ✅ 定义订单状态和工作状态常量及类型
- ✅ 实现页面基础功能（导航、可见性验证）
- ✅ 实现搜索和筛选功能
- ✅ 实现订单 CRUD 操作方法
- ✅ 实现订单详情相关方法
- ✅ 实现人员关联管理方法
- ✅ 实现附件管理方法
- ✅ 添加完整 TypeScript 类型定义和 JSDoc 注释
- ✅ 类型检查通过
