Files
one-pipe-system/openspec/changes/add-admin-task-and-audit-log-file-download/design.md
sexygoat 950520635d
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 3m54s
feat: 文件下载
2026-04-30 18:04:01 +08:00

93 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Design: 后台任务页与操作审计日志文件下载入口
## Context
当前项目已经具备对象存储上传与下载地址获取能力:
- `StorageService.getUploadUrl()` 已用于上传导入文件
- `StorageService.batchDownloadUrls()` 已封装 `POST /api/admin/storage/batch-download-urls`
但在后台实际业务入口上,下载链路还没有被接起来:
- IoT 卡任务页和设备任务页只有“失败数据”等操作,没有“下载原始导入文件”
- 共享的资产操作审计日志组件虽然会显示 `文件存储键`,但只能看见 `file_key` 字符串,不能直接下载
此外,操作审计日志组件是共享组件,同时用于:
- 资产详情页
- IoT 卡列表中的操作审计日志弹窗
- 设备列表中的操作审计日志弹窗
这意味着“下载文件”能力既要复用统一实现,又要允许三个入口使用不同权限编码。
## Goals / Non-Goals
- Goals:
- 为 IoT 卡任务页增加原始导入文件下载入口
- 为设备任务页增加原始导入文件下载入口
- 为三个后台审计日志入口增加基于 `file_key` 的内联下载入口
- 为以上 5 个入口分别施加独立权限控制
- 复用现有 `batch-download-urls` 接口完成下载
- Non-Goals:
- 不改造对象存储上传流程
- 不增加批量下载多个文件的 UI
- 不扩展到 C 端页面
- 不在本次提案中统一所有历史权限命名差异
## Decisions
- Decision: 所有“下载文件”入口统一通过 `POST /api/admin/storage/batch-download-urls` 获取下载 URL
- Rationale: 现有基础设施已经覆盖私有文件下载,不需要新增独立接口;单文件下载可直接以 `file_keys: [file_key]` 方式复用批量接口。
- Decision: 任务页“下载文件”继续放在现有操作列中,而不是新增文件列
- Rationale: IoT 卡任务页和设备任务页已经有行级操作模式;把下载文件放入操作列,和“失败数据”等现有动作一致,改动面更小。
- Decision: 审计日志中的“下载文件”必须紧跟在 `文件存储键` / `file_key` 值后,而不是放到日志行外层操作区
- Rationale: 需求明确指出“如果变更内容出现了文件存储键,后面也要跟上下载文件”,因此入口应与该字段形成强绑定。
- Decision: 共享 `OperationLogsCard` 作为唯一实现,但下载权限由调用入口传入
- Rationale: 三个审计日志入口复用同一组件如果把权限写死在组件内部就无法满足“3 个不同权限编码”的要求。
- Decision: 本提案默认新增权限编码建议如下
- 任务页:
- `iot_card_task:download_file`
- `device_task:download_file`
- 审计日志入口:
- `asset_info:download_log_file`
- `iot_card:download_log_file`
- `device:download_log_file`
- Rationale: 任务页下载权限与现有同页行级动作前缀保持一致;日志下载权限与各自入口页面前缀保持一致,便于角色配置时理解来源。
- Decision: 不在本次变更中顺带统一 IoT 卡任务页历史上的 `lot_task:*` / `iot_card_task:*` 前缀差异
- Rationale: 当前需求只要求增加下载文件权限入口;若同时做权限前缀清理,会把提案扩大为权限命名治理,超出本次范围。
- Decision: 当 `file_key` 缺失、为空或下载 URL 获取失败时,页面只提示失败,不影响列表或日志正常渲染
- Rationale: 下载属于增强能力,不应把原有任务列表和审计日志变成硬依赖下载服务的阻塞页面。
## Risks / Trade-offs
- 任务列表前端类型当前未显式声明 `file_key`,实施时若接口已返回但类型未补齐,容易出现“功能依赖字段存在但类型缺口”的问题。
- `OperationLogsCard` 的 props 和渲染逻辑一旦调整会同时影响资产详情页、IoT 卡列表弹窗和设备列表弹窗,需要联动验证。
- IoT 卡任务页现存 `lot_task:bulk_import``iot_card_task:*` 并存,新增权限虽可落地,但会继续保留命名历史包袱。
## Migration Plan
1. 明确导入任务记录的 `file_key` 契约,并补齐前端类型。
2. 在 IoT 卡任务页和设备任务页的操作列增加“下载文件”。
3. 为两个任务页接入各自独立的下载权限编码。
4. 扩展共享 `OperationLogsCard`,在 `file_key` 场景渲染内联“下载文件”入口。
5. 由资产详情页、IoT 卡列表、设备列表分别传入对应的日志下载权限编码。
6. 联调验证 5 个入口的权限隔离与下载行为。
## Open Questions
- IoT 卡任务新增下载权限默认建议使用 `iot_card_task:download_file`。如果后端权限树仍希望完全沿用 `lot_task:*` 前缀,需要在评审阶段确认是否改为 `lot_task:download_file`
- 当前导入任务列表接口是否已经返回 `file_key` 需要评审确认;若未返回,则实施范围需要同步包含接口契约补齐。