docs: add market favorites design
This commit is contained in:
@@ -0,0 +1,158 @@
|
|||||||
|
# 星图达人收藏夹设计
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
星图达人市场页已有列表筛选、导出和提交批次能力,但用户无法保存跨筛选条件、跨页面发现的优质达人。本功能新增本地收藏夹:用户可将达人归入多个不同主题的收藏夹,在需要时从收藏夹批量导入秒探。
|
||||||
|
|
||||||
|
收藏数据只保存在当前浏览器的当前插件配置中,不提供跨设备同步、团队共享或后端持久化。
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
|
||||||
|
- 支持创建、改名和删除收藏夹。
|
||||||
|
- 支持将同一达人加入多个收藏夹;同一达人在同一收藏夹内只保留一条关联。
|
||||||
|
- 在市场列表每一行提供独立收藏入口,收藏时立即选择一个或多个收藏夹。
|
||||||
|
- 在页面右侧提供常驻的收藏夹入口和抽屉,用于浏览、整理、筛选和导入已收藏达人。
|
||||||
|
- 从抽屉内复用既有批次提交接口导入秒探,不重新采集星图列表。
|
||||||
|
|
||||||
|
## 非目标
|
||||||
|
|
||||||
|
- 不改变星图原生筛选、列表、下单或右侧服务栏功能。
|
||||||
|
- 不把收藏夹塞入现有导出和筛选工具栏。
|
||||||
|
- 不做插件弹窗中的第二套收藏夹管理界面。
|
||||||
|
- 不保存完整市场行、视频、指标和画像快照;收藏夹不是历史报表。
|
||||||
|
- 不实现跨设备同步、协作共享、后端备份或导入历史。
|
||||||
|
|
||||||
|
## 方案选择
|
||||||
|
|
||||||
|
### 方案 A:右侧入口 + 抽屉 + 行内收藏选择器
|
||||||
|
|
||||||
|
页面右侧提供收藏夹入口,点击后打开抽屉;每行收藏图标只打开贴近图标的收藏夹选择器。
|
||||||
|
|
||||||
|
优点:收藏、查看和导入各自处于最合适的位置;不挤占现有工具栏;适合频繁浏览和长期整理。
|
||||||
|
|
||||||
|
缺点:需要处理与星图原生右侧服务栏的空间和层级关系。
|
||||||
|
|
||||||
|
### 方案 B:行内图标直接打开右侧抽屉
|
||||||
|
|
||||||
|
每次收藏都先打开抽屉,再在抽屉中选择收藏夹。
|
||||||
|
|
||||||
|
优点:交互组件较少。
|
||||||
|
|
||||||
|
缺点:单个达人收藏需要跨越页面宽度,频繁操作成本高。
|
||||||
|
|
||||||
|
### 方案 C:工具栏按钮 + 模态框
|
||||||
|
|
||||||
|
在现有插件工具栏中增加收藏相关按钮,使用模态框管理收藏夹。
|
||||||
|
|
||||||
|
优点:实现边界集中。
|
||||||
|
|
||||||
|
缺点:工具栏已经承担导出、提交和筛选;收藏夹作为长期资产放在这里会造成信息和操作拥挤。
|
||||||
|
|
||||||
|
采用方案 A。
|
||||||
|
|
||||||
|
## 页面与交互
|
||||||
|
|
||||||
|
### 右侧入口
|
||||||
|
|
||||||
|
- 在星图原生右侧服务栏左侧固定一个窄入口,使用书签图标和 `收藏夹` 文本。
|
||||||
|
- 入口避开原生的帮助、联系和客服按钮;在窄视口保持图标入口,不遮挡页面内容。
|
||||||
|
- 入口可显示总收藏数,但不使用红色未读角标,以免被理解为通知。
|
||||||
|
- 点击入口打开右侧抽屉;再次点击入口或抽屉关闭按钮可关闭抽屉。
|
||||||
|
|
||||||
|
### 行内收藏
|
||||||
|
|
||||||
|
- 在每个有效达人行的原生 `操作`/`下单` 控件之前增加书签图标,不修改或覆盖原生操作。
|
||||||
|
- 未收藏时显示描边书签,悬停提示 `加入收藏夹`。
|
||||||
|
- 已收藏至至少一个收藏夹时显示粉色实心书签,悬停提示 `已收藏至 N 个收藏夹`。
|
||||||
|
- 点击图标在图标附近打开小型选择器,列出所有收藏夹及该达人的当前归属状态;用户可多选或取消选择。
|
||||||
|
- 小型选择器提供 `新建收藏夹`,成功创建后立即把当前达人加入新收藏夹。
|
||||||
|
- 达人没有可用 `authorId` 时,图标不可用并说明无法收藏该达人。
|
||||||
|
|
||||||
|
### 收藏夹抽屉
|
||||||
|
|
||||||
|
- 抽屉从右侧滑入,宽度为 `380-420px`,位于原生右侧服务栏左侧;打开或关闭都不改变星图列表的筛选、滚动和横向滚动位置。
|
||||||
|
- 顶部包含 `收藏夹` 标题和 `新建收藏夹` 操作。
|
||||||
|
- 默认显示 `全部达人`。同一达人即使在多个收藏夹中,也只显示一条记录。
|
||||||
|
- 用户可切换为某个收藏夹,只查看该收藏夹中的达人;支持按达人名称搜索。
|
||||||
|
- 每个达人显示最小身份信息、加入时间和操作菜单。操作菜单支持从当前收藏夹移除;在 `全部达人` 中仅展示归属,不提供破坏性的一键全局删除。
|
||||||
|
- 抽屉列表支持复选,底部固定操作区显示已选人数。
|
||||||
|
|
||||||
|
### 导入秒探
|
||||||
|
|
||||||
|
- `导入已选 N 位达人`:抽屉内至少勾选一位达人后可用。
|
||||||
|
- `导入当前收藏夹全部达人`:仅在查看具体收藏夹时可用,点击后必须显示二次确认,并写明本次导入人数。
|
||||||
|
- 两个入口都先按 `authorId` 去重,再映射为既有批次 payload 所需的最小 `MarketRecord` 数据。
|
||||||
|
- 沿用既有登录校验、批次名称输入、`createBatchPayload()` 和秒探批次提交客户端。
|
||||||
|
- 导入成功后保留收藏和收藏夹成员关系;失败时不改变本地数据,并显示既有提交错误或明确的收藏夹错误。
|
||||||
|
|
||||||
|
## 本地数据
|
||||||
|
|
||||||
|
使用 `chrome.storage.local`,不使用内容脚本页面的 `window.localStorage`。插件清单已声明 `storage` 权限,插件存储不会与星图网页站点数据混用。
|
||||||
|
|
||||||
|
首版数据采用一个版本化根对象,便于整体校验和迁移:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type FavoritesStateV1 = {
|
||||||
|
version: 1;
|
||||||
|
folders: Array<{
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}>;
|
||||||
|
creators: Array<{
|
||||||
|
authorId: string;
|
||||||
|
authorName: string;
|
||||||
|
coreUserId?: string;
|
||||||
|
savedAt: string;
|
||||||
|
}>;
|
||||||
|
memberships: Array<{
|
||||||
|
authorId: string;
|
||||||
|
folderId: string;
|
||||||
|
addedAt: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
- `creator` 以 `authorId` 唯一;多收藏夹通过 `memberships` 表达,避免复制达人数据。
|
||||||
|
- `memberships` 以 `(folderId, authorId)` 唯一。
|
||||||
|
- 删除收藏夹只删除其成员关联;没有任何关联的达人记录可以一并清理。
|
||||||
|
- 导入时若存在 `coreUserId`,继续作为现有 payload 的 `authorUid` 发送。
|
||||||
|
- 读取缺失、格式错误或未知版本时视为未初始化状态,不应阻断市场页其他能力;写入失败必须向用户反馈。
|
||||||
|
|
||||||
|
## 模块边界
|
||||||
|
|
||||||
|
- 收藏数据仓库:读写、迁移、去重、收藏夹和成员关系规则;不依赖 DOM 或批次接口。
|
||||||
|
- 行内收藏装饰:从市场行读取最小达人身份,渲染书签和选择器;不负责抽屉列表。
|
||||||
|
- 收藏夹抽屉:呈现文件夹和达人,处理搜索、选择和管理操作;通过数据仓库获取状态。
|
||||||
|
- 收藏夹导入适配层:将收藏达人转换为最小 `MarketRecord[]`,调用现有批次提交流程;不直接读写浏览器存储。
|
||||||
|
- 市场控制器:组装这些模块并协调抽屉、行内状态与繁忙态。
|
||||||
|
|
||||||
|
## 状态与错误处理
|
||||||
|
|
||||||
|
- 收藏或取消收藏后,行内图标、选择器和已打开抽屉必须立刻同步。
|
||||||
|
- 新建、改名和删除收藏夹时,名称去除首尾空格;空名称不可保存。删除前确认。
|
||||||
|
- 导入执行期间,抽屉的导入和管理操作禁用,结束后恢复。
|
||||||
|
- 导入前没有有效达人时,不打开批次名称输入,也不调用提交接口。
|
||||||
|
- 对包含多个收藏夹成员的导入,提交前按 `authorId` 去重,避免发送重复作者。
|
||||||
|
- 读取或写入插件存储失败时,只提示收藏夹操作失败,不影响星图原生页面或既有导出/提交功能。
|
||||||
|
|
||||||
|
## 验收标准
|
||||||
|
|
||||||
|
1. 用户可创建、改名和删除收藏夹;删除收藏夹不删除其他收藏夹中相同达人。
|
||||||
|
2. 同一达人可加入多个收藏夹,但不会在同一收藏夹重复出现。
|
||||||
|
3. 每个有效达人行均有独立收藏图标,且不会影响星图原生 `下单` 等操作。
|
||||||
|
4. 行内图标可以打开多选收藏夹选择器,选择器可即时新建收藏夹并完成收藏。
|
||||||
|
5. 右侧入口不与星图原生右侧服务栏重叠;点击后抽屉能显示全部达人和具体收藏夹中的达人。
|
||||||
|
6. 抽屉的 `全部达人` 视图对跨收藏夹的同一达人去重;具体收藏夹视图只显示该收藏夹成员。
|
||||||
|
7. 用户可导入已选达人;用户也可导入当前收藏夹全部达人,但必须经过人数明确的二次确认。
|
||||||
|
8. 导入复用现有批次 payload 和提交接口,携带已有的 `authorId`、`authorName` 和可选 `authorUid`;成功后收藏不丢失。
|
||||||
|
9. 浏览器存储不可用、达人缺少 ID、空收藏夹、空选择和提交失败均有清晰反馈。
|
||||||
|
|
||||||
|
## 验证范围
|
||||||
|
|
||||||
|
- 收藏数据仓库的创建、改名、删除、成员去重、跨收藏夹关联、序列化错误恢复测试。
|
||||||
|
- 行内书签、选择器、新建收藏夹和状态同步的 DOM 测试。
|
||||||
|
- 抽屉的默认视图、文件夹切换、搜索、移除、选择和全量导入确认测试。
|
||||||
|
- 收藏达人到批次 payload 的映射、跨收藏夹去重、登录失败、提交成功/失败测试。
|
||||||
|
- 运行相关 Vitest 测试和 `npm run build`。
|
||||||
Reference in New Issue
Block a user