## 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