Files
beige/plans/Clover前端逻辑诊断-数据流与交互.md
yangqianqian 6a2632da70 baseline: Clover 独立仓库首次基线提交
将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。
当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包),
M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 11:30:22 +08:00

108 lines
6.7 KiB
Markdown
Raw Permalink 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.
# Clover 前端逻辑诊断 · 数据流与交互(第一次扒·另一窗口改完需重扒)
> 你的直觉对了:"功能呈现和数据流转交互太弱"——但弱在**数据流架构**,不只在界面长相。
> 扒的是3个zustand store(generation/task/preference) + api.ts + useSse + sse.ts。
> ⚠️ 另一窗口正在改前端,本次结论是当前快照,改完重扒对比。
---
## 一、先画出前端真实的数据流
```
┌─ 进任务页 ─────────────────────────────────────────────┐
│ useSse(taskId) 启动 │
│ ① 立即 GET /tasks/{id} → hydrateFromTask (回填历史候选) │
│ ② 建 SSE: 先POST换ticket → EventSource连stream │
│ ③ SSE事件 → handleEvent → 写 generationStore │
└──────────────────────────────────────────────────────┘
↓ 组件从 store 订阅渲染
text/images页 读 generationStore.textCandidates 等
↓ 用户选择
taskStore.selectedTextIds (纯本地数组)
↓ 点"下一步"
for循环逐个 POST select → router.push 下一页
```
**三个store各管一摊**
- `generationStore`SSE进度+候选+飞轮注入(生成态)
- `taskStore`当前任务id+已选id数组选择态
- `preferenceStore`:飞轮偏好摘要(注入态)
<!-- 后续Edit补充二、数据流的7个弱点 / 三、交互弱的根因 / 四、对照俊达该补什么 / 五、待重扒清单 -->
---
## 二、数据流的7个弱点每条带代码证据
### 弱点1策略维度A/B/C在前端被彻底抹平 🔴最关键
- 后端生图按3套策略各N张`pipeline_io.py:201`SSE的`image_candidate`事件**带了strategy字段**(`useSse.ts:104`接收了)。
-`generationStore.imageCandidates` 是**一维平铺数组**(store注释明写"image_candidate无batch字段所以平铺")images页直接`grid`铺开。
- **后果**:后端辛苦做的"3个叙事方向×N张给你对比挑选"前端变成一堆看不出分组的散图。用户不知道哪些是同一策略、为什么有18张。这是"交互弱"最硬的证据——**信息结构在展示层塌掉了**。
### 弱点2文案五维分要二次请求补全且每条都重拉整个task 🔴
- `useSse.ts:75-94`SSE的`text_candidate`只推total分五维明细**靠再次 GET /tasks/{id} 补全**。
- 致命:**每来一条文案候选就GET一次整个task**(line88)8条文案=8次全量请求每次返回所有候选。N条候选→N次重复拉全量越往后越浪费。
- **后果**五维分有延迟跳变先0后补且网络浪费。交互上是"分数闪一下才出来"。
### 弱点3选择态是纯本地数组不落后端、刷新即丢 🟡
- `taskStore.selectedTextIds/selectedImageIds` 只在内存(line13)。
- 选文案时`toggleTextSelection`只改本地数组,**点"下一步"才 for循环逐个POST select**(`text/page.tsx:29-32`)。
- **后果**:①选到一半刷新页面,选择全没了 ②多选N条就发N个请求(不是批量) ③选中状态和后端`is_selected`字段不实时同步。
### 弱点4跳转用 router.push候选数据靠"重新拉" 🟡
- 每个环节(text→images→confirm)是独立页面,靠`router.push`跳转。
- 进每页 `useSse``store.reset()``hydrateFromTask`重新GET(`useSse.ts:21,30`)。
- **后果**:环节间无"连续流"感,每跳一页是一次重新加载+重连SSE。confirm页要的已选数据`generationStore`里还留着的候选`filter`出来(`confirm/page.tsx:22-23`)——**万一store被reset就空了**。
### 弱点5confirm页数据来源脆弱 🟡
- `confirm/page.tsx:22``textCandidates.filter(selectedTextIds.includes)`拿已选内容。
-`selectedTextIds`在taskStore、`textCandidates`在generationStore**两个store没绑定**。SSE的reset只清generationStoreselectedTextIds还在taskStore——两者生命周期不一致容易错位。
### 弱点6错误处理静默吞掉 🟡
- `useSse.ts:37,93` 多处`.catch(() => {})`空吞错误;`preferenceStore:31`无偏好"不阻塞流程"也静默。
- **后果**:数据没拉到时用户无感知,界面就是"空着",不知道是没数据还是出错了。这放大了"空"的感受。
### 弱点7SSE的task_done/error事件没驱动UI 🟡
- `useSse.ts:123-127``error`/`task_done`/`analyze_done`/`heartbeat`全部`break`空处理。
- **后果**:生成完成了(task_done)前端不弹提示、不自动跳转;出错了(error)也不显式告诉用户。状态机的关键节点在前端是哑的。
---
## 三、为什么"交互弱"——根因归纳
| 表象 | 数据流根因 |
|---|---|
| 图一堆看不出门道 | 策略维度被平铺抹平(弱点1) |
| 分数闪一下才出 | 五维分二次请求补全(弱点2) |
| 选着选着没了 | 选择态纯本地不持久(弱点3) |
| 翻页像重新加载 | 页面级跳转+每页重连重拉(弱点4) |
| 完成/出错没反馈 | 关键SSE事件空处理(弱点7)+错误静默(弱点6) |
> **本质**:前端是"**被动渲染后端推什么显示什么**"的薄层,没有自己的"数据组织能力"。后端给的多维数据(策略/评分/角色/理由),前端要么拍平、要么二次拉、要么不展示。**不是界面不好看,是数据进了前端没被'组织'成有结构的交互。**
---
## 四、对照俊达:他的前端为什么"饱满流畅"
俊达界面给人"饱满"感,本质是**数据被组织出了层次**
- 同一组图按策略/角色分组对比 → Clover平铺(弱点1)
- 每个产出带可见的评分/理由/标签 → Clover评分要补拉、理由没全显(弱点2)
- 操作即时反馈、状态流转有动效 → Clover关键事件空处理(弱点7)
- 进化页/复盘页是"数据看板" → Clover dashboard是3个按钮
> 借鉴点(不抄原文)**把"后端已有的多维数据"在前端组织成有结构的呈现**——分组、即时反馈、状态可见。这是纯前端重构不依赖后端加功能也不碰俊达的knowhow。
---
## 五、待重扒清单(另一窗口改完后)
本次基于当前快照。另一窗口改完前端后,重点复查这几项有没有变:
1. `generationStore` 的 imageCandidates 有没有改成按strategy分组
2. `useSse` 的五维分补全有没有改掉"每条拉全量task"
3. taskStore 选择态有没有改成持久化/批量提交
4. 关键SSE事件(task_done/error)有没有接UI反馈
5. dashboard 有没有加数据看板
6. images页有没有按A/B/C分组展示
> 重扒方法对这6个文件做 diff对照本文档逐条核实改了没。本文档是"改之前"的基线。