## Why

现有导出系统（2026-04-30 上线）存在三个影响实际可用性的缺陷：筛选条件被静默丢弃（query_json 存而不用）、finalize 阶段重查全量数据库（shard 产物废弃）、新增场景需要手写 Keyset 游标逻辑（难以支持多表 JOIN）。这三个问题共同导致"想加新导出就得开发介入、开发成本高、加完也无法按条件筛选"的现状。

## What Changes

- **引入 DataSource 接口**：替代 `SceneStrategy` 的 `NextShardBoundary` + `QueryRows` 设计，新接口仅要求实现 `Count / Headers / Fetch`，分片游标逻辑全部由框架接管，开发者只管写业务查询（支持任意 SQL / JOIN）
- **支持动态列**：`Headers` 方法接收 `ExportParams`，可在运行时根据数据决定列数，解决"设备绑了几张卡就要几列 ICCID"问题
- **query_json 真正生效**：`ExportParams` 将 `query_json` 解析结果和权限快照一并传入 DataSource，`Fetch` 和 `Count` 均可读取并应用筛选条件
- **修复 finalize 重查问题**：finalize 改为按 shard_no 顺序下载分片 OSS 文件直接拼接，不再重查数据库，shard 产物得到复用
- **迁移现有两个场景**：`device` 和 `iot_card` 迁移到新 DataSource 接口，同时补全 query_json 解析逻辑
- **保留原 SceneStrategy 接口**：作为复杂自定义场景的逃生通道，不强制所有场景使用 DataSource

## Capabilities

### New Capabilities

- `export-datasource`：DataSource 接口定义、ExportParams 类型、框架侧 offset/limit 分片驱动逻辑、动态列支持
- `export-query-params`：query_json 的解析规范与 ExportParams 注入机制，让筛选条件从创建任务一路传递到数据查询

### Modified Capabilities

- `unified-export-task-system`：finalize 合并策略从"重查数据库"改为"合并 shard OSS 文件"；shard 阶段需保证分片 CSV 可被 finalize 独立拼接（不含表头）

## Impact

- **删除**：`internal/exporter/SceneStrategy` 接口中的 `NextShardBoundary` 方法（仅框架调用，外部无直接依赖）
- **修改**：`internal/task/export_dispatch.go`（游标分片逻辑改为 offset 驱动）、`internal/task/export_finalize.go`（改为合并分片文件）、`internal/task/export_shard.go`（写分片文件时不含表头）
- **新增**：`internal/exporter/datasource.go`（接口 + ExportParams 定义）、`internal/exporter/query_params.go`（query_json 解析）
- **迁移**：`device_scene.go` / `iot_card_scene.go` 实现新接口，补 query_json 过滤
- **无 API 变更**：四个对外接口（创建/列表/详情/取消）签名不变，前端无感知
- **无数据库迁移**：不新增表或字段
