# 星图达人批次提交设计 ## 背景 当前插件已经具备以下能力: - 使用 Logto 登录并获取访问 `https://talent-search.intelligrow.cn` 的 access token - 读取星图市场页中的达人列表数据 - 支持按当前页、前 5 页、前 10 页、全部、自定义页数进行多页采集 - 支持导出 CSV 下一阶段需要把“当前采集范围内的一批达人”提交给其他同学维护的后端接口,而不是逐条发送。用户期望在现有导出范围逻辑基础上,新增一个独立的“提交批次”动作,用来测试整批提交流程。 ## 目标 - 在现有工具栏中新增一个独立的 `提交批次` 按钮 - 提交动作复用当前导出范围逻辑,支持多页达人数据采集 - 提交前通过浏览器 `prompt()` 让用户输入批次名称 - 自动生成 `batchId = 批次名称 + 时间戳` - 将以下信息整合为单个批次 payload 发送给后端: - Logto 用户 ID - 星图达人 ID 列表 - 用户输入的批次名称 - 自动生成的批次 ID ## 非目标 - 不改造为逐条提交达人 - 不移除或替代现有 `导出 CSV` - 不在首版实现复杂弹窗或表单 UI - 不在首版实现批次列表管理、重试历史、草稿保存 ## 方案对比 ### 方案 A:只提交当前页 - 新按钮只处理当前页达人 - 优点:实现最简单 - 缺点:与现有多页导出/采集使用方式不一致,不符合真实业务需求 ### 方案 B:提交当前导出范围内的一整批达人 - 复用现有导出范围控制器,提交当前选择范围内的所有达人 - 优点:与用户当前使用习惯一致,便于从测试过渡到真实业务 - 缺点:比只提交当前页多一层批次组装逻辑 ### 方案 C:先导出 CSV,再从 CSV 结果提交 - 先走导出逻辑,再把导出结果转换为提交 payload - 优点:数据来源统一 - 缺点:流程绕、耦合高,不适合作为长期模式 推荐采用方案 B。 ## 交互设计 ### 工具栏按钮 在现有工具栏中保留 `导出 CSV`,并新增: - `提交批次` 两个按钮共享现有导出范围控件: - 当前页 - 前 5 页 - 前 10 页 - 全部 - 自定义 ### 批次名称输入 用户点击 `提交批次` 时: 1. 弹出浏览器 `prompt()` 2. 提示文案建议为:`请输入批次名称` 3. 用户输入如:`618 达人筛选第一批` 处理规则: - 用户取消:直接终止,不报错 - 输入为空或仅空格:提示 `请输入批次名称` - 输入有效:继续批次提交流程 ### 提交状态 批次提交过程中: - `提交批次` 按钮禁用 - `导出 CSV` 按钮与范围选择器一并禁用 - 状态文案可复用现有导出状态区域 建议状态文案: - 当前页:`提交中...` - 前 N 页:`提交中 3/5 页...` - 全部:`提交中 第 3 页...` ### 成功与失败反馈 成功: - 提示 `批次提交成功` 失败: - 未登录:`请先登录插件` - 批次名为空:`请输入批次名称` - 接口失败:`批次提交失败,请稍后重试` ## 批次数据模型 首版建议 payload 结构如下: ```json { "logtoUserId": "p7pdhhtde8kj", "creatorName": "王少卿", "resource": "https://talent-search.intelligrow.cn", "batchName": "618达人筛选第一批", "batchId": "618达人筛选第一批-2026-04-22T12:30:00.000Z", "createdAt": "2026-04-22T12:30:00.000Z", "authors": [ { "authorId": "111", "authorName": "达人A" }, { "authorId": "222", "authorName": "达人B" } ] } ``` ### 字段来源 - `logtoUserId` - 来源:当前登录用户的 Logto `sub` - `creatorName` - 来源:当前登录用户 `name` 或 `username` - `resource` - 来源:当前认证配置中的 API resource - `batchName` - 来源:用户在 `prompt()` 中输入 - `createdAt` - 来源:当前时间的 ISO 字符串 - `batchId` - 规则:`${batchName}-${createdAt}` - `authors` - 来源:当前导出范围内采集出的达人记录 ### 达人字段 首版只要求最小字段: - `authorId` - `authorName` 后续如有需要,可增加: - `price21To60s` - 看后搜率字段 - 城市/地区等补充信息 ## 数据流 完整流程如下: 1. 用户在工具栏选择导出范围 2. 用户点击 `提交批次` 3. 插件弹出 `prompt()` 请求输入批次名称 4. 插件检查登录状态与用户信息 5. 插件复用当前多页采集逻辑,获取当前范围内达人记录 6. 插件读取 Logto 用户 ID 7. 插件生成 `createdAt` 和 `batchId` 8. 插件组装整批 payload 9. 插件使用带 Bearer token 的客户端提交到后端 10. 插件显示成功或失败状态 ## 模块边界 建议按以下边界实现: ### 工具栏层 职责: - 渲染 `提交批次` 按钮 - 管理按钮禁用态 - 回传点击事件 ### 市场控制器层 职责: - 响应 `提交批次` 点击 - 调用 `prompt()` 获取批次名称 - 复用现有导出范围采集逻辑 - 调用批次 payload 组装器和提交客户端 ### 批次 payload 组装层 职责: - 接收用户信息、批次名、时间戳、达人记录 - 生成标准批次对象 该层不负责网络请求,方便后续根据后端要求调整结构。 ### 批次提交客户端 职责: - 获取 access token - 附带 `Authorization: Bearer ` 请求头 - 向后端提交整批 JSON 后续从 mock 接口切到真实接口时,应主要修改这一层。 ## 认证与授权 当前系统已具备: - Logto 登录能力 - 请求 `https://talent-search.intelligrow.cn` resource 的 access token - `talent-search:read` scope 首版批次提交如果是写操作,后端后续可能需要新增写权限,例如: - `talent-search:write` - 或 `talent-search:batch:submit` 如果后端要求新的写权限,则前端需要同步更新 `auth-config.ts` 中的 `scopes`。 ## 错误处理 ### 用户取消输入 - 直接停止,不提示错误 ### 批次名为空 - 不发请求 - 直接提示 `请输入批次名称` ### 未登录或取不到用户信息 - 不发请求 - 提示 `请先登录插件` ### 采集失败 - 复用当前导出多页采集失败逻辑 - 不生成不完整 payload ### 接口失败 - 提示 `批次提交失败,请稍后重试` ## 测试策略 ### 单元测试 - 点击 `提交批次` 时会弹出 `prompt()` - 用户取消输入时不会继续提交 - 空白批次名会报错 - `batchId` 按 `批次名 + ISO 时间戳` 生成 - payload 中包含: - `logtoUserId` - `batchName` - `batchId` - `authors[]` ### 集成测试 - `提交批次` 复用当前导出范围采集逻辑 - 当前页模式只提交当前页达人 - 多页模式会合并多页达人 - 接口调用时带 Bearer token - 成功时显示成功状态 - 失败时显示失败状态 ## 手动验证 1. 登录插件 2. 选择导出范围 3. 点击 `提交批次` 4. 在 `prompt()` 中输入批次名 5. 确认请求 payload 中包含: - Logto 用户 ID - 多个达人 ID - 批次名 - 批次 ID 6. 确认后端返回成功 ## 后续扩展 当真实接口稳定后,可以继续扩展: - 批次提交结果详情展示 - 最近提交批次列表 - 批次重试 - 批次备注、标签 - 写权限 scope 单独拆分