## ADDED Requirements

### Requirement: Export Task API Integration

The admin frontend SHALL provide a typed API integration for unified export tasks using the REST contract from `docs/api.md`.

#### Scenario: Query export tasks with filters

- **GIVEN** 用户打开导出列表页面
- **WHEN** 用户按分页、场景、状态或创建时间范围查询导出任务
- **THEN** 系统 MUST call `GET /api/admin/export-tasks`
- **AND** 系统 MUST support optional query parameters `page`, `page_size`, `scene`, `status`, `start_time`, and `end_time`
- **AND** 系统 MUST parse `data.page`, `data.size`, `data.total`, and `data.items` from the response

#### Scenario: Create export task

- **GIVEN** 用户在业务列表中确认创建导出任务
- **WHEN** 系统提交导出任务
- **THEN** 系统 MUST call `POST /api/admin/export-tasks`
- **AND** 请求体 MUST include required `scene` and `format`
- **AND** 请求体 MAY include `query` containing the current list filter conditions
- **AND** 系统 MUST handle the response fields `task_id`, `task_no`, `status`, `status_name`, and `message`

#### Scenario: Fetch export task detail

- **GIVEN** 用户需要查看或下载某个导出任务
- **WHEN** 系统读取任务详情
- **THEN** 系统 MUST call `GET /api/admin/export-tasks/{id}` with the numeric task id
- **AND** 系统 MUST support detail fields including progress, row counts, shard counts, `file_key`, `error_message`, timestamps, `download_url`, and `download_expires_at`
- **AND** 系统 MUST treat `download_url` as available only when the task is completed and the backend returns it

#### Scenario: Cancel export task

- **GIVEN** 用户取消待处理或处理中的导出任务
- **WHEN** 系统提交取消请求
- **THEN** 系统 MUST call `POST /api/admin/export-tasks/{id}/cancel`
- **AND** 系统 MUST handle `task_id`, `status`, `status_name`, `cancel_requested`, and `message` from the response

### Requirement: Reusable Export Task Creation Dialog

The admin frontend SHALL provide a reusable dialog for creating export tasks from business list pages.

#### Scenario: Explain full export rule before task creation

- **GIVEN** 用户点击业务列表中的导出按钮
- **WHEN** 导出弹窗打开
- **THEN** 弹窗 MUST clearly state that export rules are based on the current list search conditions and export the full matched result set
- **AND** 弹窗 MUST NOT imply that only the current page rows will be exported

#### Scenario: Create IoT card export task from IoT card management

- **GIVEN** 用户在 IoT 卡管理页设置了列表检索条件
- **AND** 当前用户具备 IoT 卡导出权限
- **WHEN** 用户确认创建导出任务
- **THEN** 系统 MUST submit `scene="iot_card"`
- **AND** 系统 MUST submit the current IoT card list filter conditions as `query`

#### Scenario: Create device export task from device management

- **GIVEN** 用户在设备管理页设置了列表检索条件
- **AND** 当前用户具备设备导出权限
- **WHEN** 用户确认创建导出任务
- **THEN** 系统 MUST submit `scene="device"`
- **AND** 系统 MUST submit the current device list filter conditions as `query`

#### Scenario: Snapshot current filters at submission time

- **GIVEN** 用户修改业务列表筛选条件并重新搜索
- **WHEN** 用户随后打开弹窗并确认导出
- **THEN** 系统 MUST use the latest applied search conditions in the export task `query`
- **AND** 已提交任务的 `query` MUST NOT change when the user later edits the page filters

### Requirement: Asset Export Task List Page

The admin frontend SHALL add an export task list under Asset Management > Export Management for viewing and operating export tasks.

#### Scenario: Render export management navigation

- **GIVEN** 当前用户具备导出任务列表访问权限
- **WHEN** 系统渲染资产管理菜单
- **THEN** 系统 MUST provide an Export Management group under Asset Management
- **AND** 系统 MUST provide an Export List entry under that group
- **AND** 导出列表路由 MUST load the export task list page

#### Scenario: Display export task rows

- **GIVEN** 导出任务列表接口返回任务记录
- **WHEN** 页面渲染表格
- **THEN** 页面 MUST display task number, scene, status name, progress, format, total rows, processed rows, shard counts, file key, error message, and task timestamps when present
- **AND** 页面 MUST use stable empty placeholders for missing optional fields

#### Scenario: View task detail from row action

- **GIVEN** 用户具备导出任务详情权限
- **WHEN** 用户点击某条任务的详情操作
- **THEN** 系统 MUST call the task detail API for that row
- **AND** 页面 MUST present the returned task detail without losing the current list filters and pagination state

#### Scenario: Download completed task from row action

- **GIVEN** 某条导出任务状态为已完成
- **AND** 当前用户具备导出任务下载权限
- **WHEN** 用户点击下载操作
- **THEN** 系统 MUST call the task detail API to obtain `download_url`
- **AND** 系统 MUST open or download the file using the returned `download_url`
- **AND** 系统 MUST NOT construct a download URL from `file_key` on the frontend

#### Scenario: Cancel cancellable task from row action

- **GIVEN** 某条导出任务状态为待处理或处理中
- **AND** 当前用户具备导出任务取消权限
- **WHEN** 用户确认取消该任务
- **THEN** 系统 MUST call the cancel API for that task
- **AND** 系统 MUST refresh the list or update the row using the backend response

#### Scenario: Hide unavailable row actions

- **GIVEN** 某条导出任务状态为已完成、失败或已取消
- **WHEN** 页面渲染该行操作
- **THEN** 页面 MUST NOT show the cancel action for that row
- **AND** 页面 MUST show the download action only when the task is completed and the user has download permission

### Requirement: Export Task Permissions

The admin frontend MUST gate every export-task-related button and row action with explicit permission codes.

#### Scenario: Hide business export buttons without permission

- **GIVEN** 当前用户 lacks the IoT card export permission
- **WHEN** 用户打开 IoT 卡管理页
- **THEN** 页面 MUST NOT display the IoT card export button
- **AND** 缺少设备导出权限时，设备管理页 MUST NOT display the device export button

#### Scenario: Hide export task management operations without permission

- **GIVEN** 当前用户可以访问导出列表但 lacks download or cancel permissions
- **WHEN** 页面渲染导出任务行操作
- **THEN** 页面 MUST NOT display the download action without download permission
- **AND** 页面 MUST NOT display the cancel action without cancel permission

#### Scenario: Keep permissions isolated by entry point

- **GIVEN** 当前用户具备 `iot_card` 导出权限但不具备 `device` 导出权限
- **WHEN** 用户分别访问 IoT 卡管理页和设备管理页
- **THEN** IoT 卡管理页 MAY display its export button
- **AND** 设备管理页 MUST NOT display its export button because of the IoT card permission
