# Story 13.20: 残疾人企业查询功能

Status: review

> **[2025-01-17 变更说明]**: 移除了"新增、编辑、删除"操作按钮
> - 这是一个查询页面，不是管理页面
> - 残疾人-企业关系是通过订单建立的，不应在查询页面直接操作
> - 如需修改关系，应通过订单管理页面进行

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

## Story

作为管理员，
我想要在管理后台左侧菜单栏增加"残疾人企业查询"功能，
以便查询残疾人对应的企业关系，支持按多维度筛选。

## Acceptance Criteria

1. **后端 API 开发**
   - 创建残疾人企业查询 API，支持多条件筛选（性别、残疾类别、残疾等级、年龄、户籍、残疾证号、公司、区、市）
   - API 返回数据包含：姓名、残疾类别、残疾等级、公司、户籍、残疾证号、区、市
   - 支持分页查询

2. **前端页面开发**
   - 在管理后台左侧菜单栏新增"残疾人企业查询"菜单项
   - 创建查询页面，包含筛选条件区域和数据表格
   - 表格列名：姓名、残疾类别、残疾等级、公司、户籍、残疾证号、区、市

3. **筛选和操作功能**
   - 筛选条件：性别、残疾类别、残疾等级、年龄、户籍、残疾证号、公司、区、市
   - 操作按钮：重置、查询
   - 支持分页显示

4. **数据关系说明**
   - 残疾人与企业的关系通过 OrderPerson -> EmploymentOrder -> Company 建立
   - 一个残疾人可能关联多个企业（通过不同的订单）

## Tasks / Subtasks

- [x] Task 1: 后端 API 开发 (AC: 1)
  - [x] Subtask 1.1: 在 disability-module 中创建查询服务方法
  - [x] Subtask 1.2: 创建查询 API 路由和 Schema
  - [x] Subtask 1.3: 实现多条件筛选逻辑（join OrderPerson 和 EmploymentOrder）
  - [x] Subtask 1.4: 添加分页支持

- [x] Task 2: 前端菜单配置 (AC: 2)
  - [x] Subtask 2.1: 在管理后台菜单配置中添加新菜单项
  - [x] Subtask 2.2: 配置路由指向新页面

- [x] Task 3: 前端页面开发 (AC: 2, 3)
  - [x] Subtask 3.1: 创建查询页面组件
  - [x] Subtask 3.2: 实现筛选条件表单（性别、残疾类别、残疾等级、年龄、户籍、残疾证号、公司、区、市）
  - [x] Subtask 3.3: 实现数据表格组件（姓名、残疾类别、残疾等级、公司、户籍、残疾证号、区、市）
  - [x] Subtask 3.4: 实现操作按钮（重置、查询）
  - [x] Subtask 3.5: 集成 API 调用和数据展示

- [ ] Task 4: 测试验证 (AC: 1, 2, 3, 4)
  - [ ] Subtask 4.1: 单元测试（API 筛选逻辑）
  - [ ] Subtask 4.2: 集成测试（页面功能验证）
  - [ ] Subtask 4.3: E2E 测试（完整流程验证）

## Dev Notes

### 数据模型关系

残疾人与企业的关系链：
```
DisabledPerson (残疾人)
  -> OrderPerson (订单人员关联)
    -> EmploymentOrder (用工订单)
      -> Company (企业)
```

查询需要关联三个表：
1. `disabled_person` - 残疾人基本信息
2. `order_person` - 订单人员关联
3. `employment_order` - 用工订单
4. `employer_company` - 企业信息

### 技术实现要点

#### 后端实现

**模块位置**: `allin-packages/disability-module/`

1. **Service 层** (`src/services/disabled-person.service.ts`)
   - 新增查询方法 `findPersonsWithCompany(query, pagination)`
   - 使用 QueryBuilder 关联查询 OrderPerson 和 EmploymentOrder

2. **Routes 层** (`src/routes/disabled-person.routes.ts`)
   - 新增路由 `/persons/with-company` (GET)
   - 支持查询参数：gender, disabilityType, disabilityLevel, age, city, district, disabilityId, companyId

3. **Schema 层** (`src/schemas/`)
   - 创建查询参数 Schema
   - 创建响应数据 Schema

#### 前端实现

**UI 组件包位置**: `allin-packages/disability-person-management-ui/` 或新建独立包

1. **API 客户端** (`src/api/`)
   - 扩展 `disabilityClient.ts` 添加新 API 方法
   - 使用 RPC 类型推断

2. **页面组件** (`src/components/DisabilityPersonCompanyQuery.tsx`)
   - 使用 React Hook Form 管理筛选表单
   - 使用 TanStack Query 管理数据获取
   - 使用 Radix UI Select 组件（参考现有残疾人管理页面）

3. **菜单配置**
   - 在管理后台菜单配置文件中添加新菜单项
   - 配置路由：`/admin/disability-person-company-query`

### 参考现有实现

**参考页面**: `allin-packages/disability-person-management-ui/src/components/DisabilityPersonManagement.tsx`
- 表格实现模式
- 筛选表单实现模式
- API 调用模式

**参考实体关系**:
- `DisabledPerson` -> `OrderPerson` (通过 @OneToMany)
- `OrderPerson` -> `EmploymentOrder` (通过 @ManyToOne)
- `EmploymentOrder` -> `Company` (通过 @ManyToOne)

### 筛选条件说明

| 筛选条件 | 字段来源 | 类型 | 说明 |
|---------|---------|------|------|
| 性别 | disabled_person.gender | enum | 男/女 |
| 残疾类别 | disabled_person.disability_type | enum | 视力/听力/言语/肢体/智力/精神 |
| 残疾等级 | disabled_person.disability_level | enum | 一级/二级/三级/四级 |
| 年龄 | disabled_person.birth_date | date | 计算得出 |
| 户籍 | disabled_person.city/district | string | 市级/区县级 |
| 残疾证号 | disabled_person.disability_id | string | 精确匹配 |
| 公司 | employment_order.company_id | int | 公司ID |
| 区 | disabled_person.district | string | 区县级 |
| 市 | disabled_person.city | string | 市级 |

### 表格列名说明

| 列名 | 数据来源 | 说明 |
|-----|---------|------|
| 姓名 | disabled_person.name | |
| 残疾类别 | disabled_person.disability_type | |
| 残疾等级 | disabled_person.disability_level | |
| 公司 | employer_company.company_name | 通过 OrderPerson -> EmploymentOrder -> Company |
| 户籍 | disabled_person.city + district | 拼接显示 |
| 残疾证号 | disabled_person.disability_id | |
| 区 | disabled_person.district | |
| 市 | disabled_person.city | |

### Project Structure Notes

- 后端模块位于 `allin-packages/disability-module/`
- 前端 UI 包位于 `allin-packages/disability-person-management-ui/`
- 遵循 Monorepo workspace 协议：`@d8d/allin-disability-module`
- 使用 TypeScript 严格模式，禁止 `any` 类型
- 使用 TypeORM 进行数据库操作

### References

- 项目上下文: `_bmad-output/project-context.md`
- 残疾人实体: `allin-packages/disability-module/src/entities/disabled-person.entity.ts`
- 订单人员实体: `allin-packages/order-module/src/entities/order-person.entity.ts`
- 用工订单实体: `allin-packages/order-module/src/entities/employment-order.entity.ts`
- 公司实体: `allin-packages/company-module/src/entities/company.entity.ts`
- 残疾人管理页面参考: `allin-packages/disability-person-management-ui/src/components/DisabilityPersonManagement.tsx`
- RPC 客户端参考: `allin-packages/disability-person-management-ui/src/api/disabilityClient.ts`
- 原型图片: `docs/问题反映/查询残疾人对应的企业.jpg`

## Dev Agent Record

### Agent Model Used

claude-opus-4-5-20251101

### Debug Log References

### Completion Notes List

- Task 1 (后端 API 开发): 已完成
  - 在 `DisabledPersonService` 中添加 `findPersonsWithCompany` 方法
  - 创建 `FindPersonsWithCompanyQuerySchema` 和 `PersonsWithCompanyResponseSchema`
  - 创建 `/findPersonsWithCompany` 路由，支持多条件筛选和分页

- Task 2 (前端菜单配置): 已完成
  - 在 `web/src/client/admin/menu.tsx` 中添加新菜单项
  - 在 `web/src/client/admin/routes.tsx` 中配置新路由

- Task 3 (前端页面开发): 已完成
  - 创建 `DisabilityPersonCompanyQuery` 组件
  - 实现完整的筛选表单和数据表格
  - 集成 API 调用和分页功能

- Task 4 (测试验证): 待完成
  - 单元测试框架已创建，需要完善 mock
  - 集成测试和 E2E 测试需要后续实现

### File List

# 新增文件
- allin-packages/disability-module/tests/unit/find-persons-with-company.test.ts
- allin-packages/disability-module/src/routes/person-company.routes.ts
- allin-packages/disability-person-management-ui/src/components/DisabilityPersonCompanyQuery.tsx

# 修改文件
- allin-packages/disability-module/src/services/disabled-person.service.ts (添加 findPersonsWithCompany 方法)
- allin-packages/disability-module/src/schemas/disabled-person.schema.ts (添加新 Schema 定义)
- allin-packages/disability-module/src/routes/disabled-person.routes.ts (添加新路由导入)
- allin-packages/disability-person-management-ui/src/api/disabilityClient.ts (添加新类型定义)
- allin-packages/disability-person-management-ui/src/components/index.ts (导出新组件)
- web/src/client/admin/menu.tsx (添加新菜单项)
- web/src/client/admin/routes.tsx (添加新路由)
