LobeHub UX 审计实战范例:视频/图像创作(Create)界面的三层审计与发现回灌
本文以 LobeHub 仓库中 ux-audit 技能的一个真实审计范例为主体,完整讲解对桌面端视频创作与图像创作两个「生成类(generation)」界面执行 L1 静态审计的全过程:从界面类基准(surface-class benchmark)、模式(pattern)盘点表、✅ 亮点到 7 个分级体验缺口(experience gaps),以及发现如何「回灌(feedback loop)」到 ux 检查清单。读完本文,你可以掌握一套可重复执行的标准化 UX 审计方法——先命名界面类别、再逐模式取证、最后把可泛化的缺口沉淀为团队级检查规则,并且知道每条结论应落在源码的哪个 file:line 上。
1. 审计背景:这份文档在 ux-audit 技能中的定位
这份范例是 .agents/skills/ux-audit/references/example/create.md —— 2026 年 7 月针对两个桌面端生成界面的真实审计记录(对应内部工单 LOBE-11151,隶属于桌面主区域审计 LOBE-11098)。文档开头明确声明了自己的用法:它是「输出形状」的模板,不是当前状态的事实(代码在变,引用前要重新验证)。
要理解这份范例,需要先理解它所属的 ux-audit 技能 的框架:
- 基准是两套东西:一是 Jenifer Tidwell《Designing Interfaces》的模式语言(见 pattern-catalog.md),回答「好界面由什么构成」;二是 LobeHub 自己的 ux 技能执行检查清单,回答「一个流程应该怎么表现」。
- 三层审计(L1/L2/L3)各管各的:L1 读代码,抓缺失的空态/错误分支、无草稿持久化、缺失的模式(便宜、离线、每次必跑);L2 截屏看渲染结果,抓真实视觉层级、间距、截断、暗色模式;L3 驱动真实用户旅程并测量,抓进行中状态、强制触发的错误态、CLS/LCP/INP 等量化指标。核心规则是:结论必须来自「看得到」它的层——不能从代码里的
variant属性去勾「只有一个主按钮」这种视觉结论。 - 证据规则(evidence, not vibes):每条发现都要引用证据——L1 是
file:line,L2 是 Read 工具验证过的截屏,L3 是捕获值/快照。错误的「它缺失了」比没有发现更糟。 - 表面类别基准(surface-class benchmark):只读自家代码天然只能暴露「已经建了的东西」里的缺陷,对「完全没建的能力」结构性失明。因此审计要先命名界面的类别(本例是生成类:Midjourney / DALL·E / Ideogram / Leonardo / Runway / Kling / Sora),写出这类产品公认应具备的能力清单,再逐条对照——否则审计只会打磨已存在的路径,对缺失的能力「默许通过」。
- 回灌闭环(mandatory):审计的完成标准不是「写完了发现」,而是发现被落地:具体 bug 修掉或建单;可泛化缺口必须新增/强化 ux 检查清单条目(规则 + ✅/❌ 示例 + 镜像到 Quick review),并以被审计界面作为 ❌ 示例;优秀案例则反向 sharpen 规则的 ✅ 一侧——目标是让规则文本本身变锋利,而不只是装饰。审计本身存为
references/example/<page>.md,供下一次运行当模板。
本次运行实际执行的层:L1(静态/代码)✅ 完成,下文全部结论来自 L1;L2(视觉)/ L3(动态 + CLS + 离开页面行为)⏳ 未执行(见第 6 节)。
2. 被审计对象:两个近乎同构的创作界面
审计对象是 src/routes/(main)/(create)/video 与 src/routes/(main)/(create)/image 两个路由。两者近乎同构:都组合同一个共享外壳 features//(create)/features/)(CreateGenerationPage → GenerationWorkspace → Content / EmptyState,外加 GenerationLayout 侧边栏),再叠加各自按媒介划分的 store(src/store/video 与 src/store/image),两个 store 拥有相同的四个 slice:generationConfig / generationTopic / generationBatch / create{Video,Image}。
这带来两个审计推论:
- 多数发现是「共享代码 → 同时命中两个界面」,且因为活在共享外壳里,任何未来基于该外壳新建的生成界面都会直接继承这些问题;
- 验证成本被摊薄——修一处,两个界面对齐。
界面结构可概括为一条主链路:左侧主题(topic)侧边栏 → 中央工作区(骨架屏 → 空态(内含 composer)→ 生成批次的 feed 流)→ PromptInput 输入器(提示词 + 内联参考图上传 + ConfigPanel 弹出面板)。这些路径在当前仓库中均可直接查看,例如 GenerationWorkspace/Content.tsx/(create)/features/GenerationWorkspace/Content.tsx)、GenerationLayout//(create)/features/GenerationLayout/)、video/features/ConfigPanel//(create)/video/features/ConfigPanel/) 与 image/features/ConfigPanel//(create)/image/features/ConfigPanel/)(含 ImageUpload.tsx/(create)/image/features/ConfigPanel/components/ImageUpload.tsx)、SeedNumberInput.tsx/(create)/image/features/ConfigPanel/components/SeedNumberInput.tsx) 等参数控件)。
按「表面类别基准」先列出生成类界面应具备的能力,对照结果如下(✅ 具备 / ⚠️ 部分 / ❌ 缺失 / ⏳ 待验证):
| 类别惯例 | 审计结论 | 对应实现 |
|---|---|---|
| 提示词历史/复用 | ✅ | 持久批次 feed + Reuse Settings / Copy Prompt |
| 批量 + 变体 | ⚠️ | 只能「复用设置后重新生成」,没有 "vary" |
| seed 可复现 | ✅ | Copy/Apply Seed |
| 持久画廊 | ✅ | 服务端批次(server-side batches) |
| 参考图/帧上传 | ✅ | ImageUpload / FrameUpload 内联上传 |
| 能力门槛(capability gate) | ✅ | 审计时点为 image/NotSupportClient.tsx |
| 取消进行中的任务 | ❌ | 缺口 ② |
| 结果 → 输入复用 | ❌ | 缺口 ⑤ |
| 长视频任务的异步完成信号 | ⏳ | 待 L3 验证 |
| 生成前展示成本/配额 | ⏳ | 未呈现;超出 L1 范围 |
3. 模式盘点(Patterns in use)
L1 逐模式读码后得到的盘点表——这是审计报告的第一节,要求按模式家族分组、每行带一句判读,且亮点行必须配真实证据而不是一词打勾:
| 模式(家族) | 位置 | 评级 | 说明 |
|---|---|---|---|
| 全局导航(nav) | GenerationLayout/Sidebar 主题列表 |
✅ | 持久、按媒介划分 |
| 中心舞台(layout) | 空态时 composer 居中;有内容时 feed + 底部 composer | ✅ | 教科书级的创作工具形态 |
| 卡片堆叠/网格(data) | GenerationFeed 批次条目;图像 N-up 网格 |
✅ | — |
| 总览 + 详情(data) | 批次 → 单项 success/loading/error | ✅ | — |
| 骨架屏加载(feedback) | !isCurrentGenerationTopicLoaded 时显示 SkeletonList |
⚠️ | 仅成功态门控 → 出错时永久卡骨架(缺口 ①) |
| 进度指示(feedback) | VideoLoadingItem 环形百分比 + ElapsedTime(sessionStorage 支撑) |
✅ | 耗时跨重挂载存活 |
| 可取消性(action) | — | — | 缺失但预期存在:无停止/中止,只有删除(缺口 ②) |
| 失败 + 重试(feedback) | VideoErrorItem / ErrorState 展示原因 + Copy Error |
⚠️ | 无原地 Retry——只能删除后重建(缺口 ②/③) |
| 好的/智能默认值(input) | 模型/供应商从 globalStore.status 恢复;seed 随机器 |
✅ | 上次模型持久化(配置参数不持久——缺口 ⑥) |
| 按钮组(action) | hover 行:Reuse Settings / Copy Prompt / Delete | ✅ | — |
| 显著的「完成」按钮(action) | Generate 按钮 | ✅ | 唯一主按钮(待 L2 确认) |
| 能力门槛(feedback) | image/NotSupportClient.tsx(CLI / 自托管升级引导) |
✅ | 类别惯例门槛存在 |
| 空态即入门引导 | EmptyState = 居中 composer,无示例/展示 |
⚠️ | 首次运行过于素(缺口 ④) |
判读(Read):导航、feed、进度与默认值都很扎实;弱点集中在 Feedback(失败路径)——这正是该代码库反复薄弱的同一个模式家族——外加生成类惯例中两个缺失的入口(取消、结果→输入)。
4. 亮点 / 优秀案例(不要回退)
审计的第二节是专门的「✅ 亮点」区——它是回灌闭环的 ✅ 半边,也是下次重构的「don't regress」清单。范例给出 5 条,全部落在共享外壳或生成 feed 中:
-
✅ 亮点 — 持久批次 feed 即持久画廊。 已提交批次在服务端,刷新后仍在,所以
GenerationFeed是真正的画廊而非会话内草稿板。它承载了类别惯例「提示词历史/持久画廊」这一代码阅读通常以为缺失的能力。之所以「承重」,是因为整个结果→复用故事(Copy Prompt / Reuse Settings / seed)都依赖刷新后结果依然存在。 -
✅ 亮点 — 每一行都具备生成级可复现性。 hover 行动作行暴露 Copy / Apply Seed + Reuse Settings + Copy Prompt(Button Groups 模式),任何历史生成都可复现或微调。seed 可复现 + 设置复用是生成类惯例,且存在于每一个批次行上,而不是藏在详情视图里。当前仓库中这一行为链可在 video/features/GenerationFeed/BatchItem.tsx/(create)/video/features/GenerationFeed/BatchItem.tsx)(
handleReuseSettings、handleCopyPrompt)与 image/features/GenerationFeed/GenerationItem/index.tsx/(create)/image/features/GenerationFeed/GenerationItem/index.tsx)(handleCopySeed在模型支持时直接reuseSeed回灌配置、否则复制到剪贴板)中逐行核对。 -
✅ 亮点 — 参考图/视频帧可内联上传。
ImageUpload/FrameUpload让 composer 直接接受参考图和视频帧——参考上传惯例达成。它之所以承重,恰恰因为缺口 ⑤ 讲的是缺失的反向桥:接收侧已经建好,结果→输入复用只是接线缺口,不是从零建功能。 -
✅ 亮点 — 能力门槛存在(→ 已回灌为 ux Feedback §4.3 ✅)。
NotSupportClient在客户端构建缺少生成后端时渲染整面 CLI / 自托管说明,并附带补救措施(自托管 DB + 托管应用链接),而不是一个坏掉的 composer。它把 §4.3 的规则 sharpen 了:原规则「软内联警告、绝不硬阻断」默认了这是用户当场可修(模型/配置)的缺口;而这里是平台/部署缺口,用户在界面上无法翻转开关,因此「整面门槛 + 附带补救」才是正确形态——这是 §4.3 此前没画出的分界线。注:文档自述「代码在变,引用前需重新验证」。从当前仓库结构看,该文件已不在
image/目录下以原名出现,正体现了范例文档的这一定位——引用其结论时应回到当时代码核实。 -
✅ 亮点 — 耗时跨组件重挂载存活(→ 已回灌为 ux Feedback §4.1 ✅)。 ElapsedTime.tsx/(create)/image/features/GenerationFeed/GenerationItem/ElapsedTime.tsx) 挂载时读取 sessionStorage 的
generation_start_time_{generationId},任务离开 active 时removeItem清理,于是单项计时器跨重挂载恢复真实时长而不是归零。这条从实现里提炼出了一条 §4.1 原本没写明的潜在子规则:长时操作的耗时/进度读数必须派生自按任务 id 持久化的起始时间戳(跨重挂载存活),并在完成时清理——绝不能是重挂载即归零的本地计数器。
5. 体验缺口(按严重度排序)
第三节是排序后的 7 个缺口,每条都给出违反的 ux 检查清单条目/目录模式、层级 + 证据、以及一行补救方向。以下按原文顺序完整继承,并补充当前仓库中的源码级印证。
① 批次列表获取失败 → 永久骨架屏(ux Feedback §4.2 + Read §1.1)🔴
useFetchGenerationBatches 审计时点只注册 onSuccess、没有 onError(store/video/slices/generationBatch/action.ts,store/image/…/action.ts 同形),且只在成功时写 generationBatchesMap[topicId]。而「loaded」门控是 isCurrentGenerationTopicLoaded = Array.isArray(map[topicId])(selectors.ts#L23-27)——一个披着 Array.isArray 外衣的「仅成功初始化」标志位。共享外壳随后执行 !loaded → <SkeletonList/>、!hasGenerations → <EmptyState/>、否则 feed(Content.tsx/(create)/features/GenerationWorkspace/Content.tsx)),没有错误分支。于是批次获取失败/超时永远不会翻标志位 → 永久骨架、无重试,且同时命中两个界面及任何未来基于外壳的界面。侧边栏 useFetchGenerationTopics 是同样的仅成功形态,主题列表有同样风险。
源码演进印证:当前仓库的 Content.tsx/(create)/features/GenerationWorkspace/Content.tsx) 中已经出现针对该缺口的修复痕迹——
useFetchGenerationBatches现在解构出error/mutate(源码注释直言:「loaded flag isArray.isArray(map[topicId]), written only on success, so a failed batch fetch would otherwise stick on the skeleton forever with no retry」),并在骨架分支之前插入if (error && !isCurrentGenerationTopicLoaded)→ 渲染AsyncError+onRetry={() => mutate()}。这正是「范例文档是模板而非当前事实」的活例。
② 进行中的生成无法取消(ux Act §3.1 + Cancelability 模式)🟠
两个 store 中不存在 cancel / abort / stop 动作(对 store/{video,image} 全量 grep 为空);停止一个运行中任务的唯一办法是删除批次(BatchItem 的 delete → 仅 console.error,即缺口 ③)。视频任务跑起来是分钟级且消耗 token;Cancelability 是生成类惯例(Runway / Kling / Sora 都能取消排队中/运行中的任务),Act §3.1 的异步状态机预期一个可被取消的进行中锁定态,而不是事后删除。此外错误项上没有原地 Retry——恢复路径是手工「Reuse Settings → 再生成」。
③ 下载与删除的失败是静默的,而同级复制动作却有 toast(ux Act §3.1)🟠
同一文件内,handleCopyPrompt / handleCopyError / handleCopySeed 失败时 message.error(...) 提示,而 handleDelete / handleDeleteBatch / handleDownload 只 console.error(video/…/GenerationFeed/BatchItem.tsx 中各 handler 的 catch 分支;image/…/GenerationItem/index.tsx 的 handleDeleteGeneration 同形),图像侧 handleDownloadImage 甚至完全没有 try/catch。下载失败(大视频、网络抖动)给用户零反馈——一个死按钮。同一界面内错误反馈不一致,本身就是味道(smell)。当前 BatchItem.tsx/(create)/video/features/GenerationFeed/BatchItem.tsx) 中这一不对称依然可逐行核对:handleCopyPrompt/handleCopyError catch 里 toast.error,而 handleDelete(L96)、handleDeleteBatch(L128)、handleDownload(L144)仅 console.error。
④ 首次运行的空态过于素(ux Read §1.1)🟡
EmptyState 只渲染居中的 PromptInput(EmptyState.tsx/(create)/features/GenerationWorkspace/EmptyState.tsx) 中仅一个 Center + PromptInput),无示例提示词、无模型展示、无「这里能做什么」。生成类工具习惯用示例画廊做首次引导(Midjourney explore、DALL·E / Ideogram 示例)。由于 composer 本身是可辩护的空态,此项偏轻——待 L2 确认它实际看起来有多素。
⑤ 生成结果无法复用为输入(ux Act §3.1 前进动量 / Grow)🟡
成功项提供下载/删除/copy-seed/reuse-settings,但没有「用这张图/视频作为参考 / 编辑 / vary」——产物是终端态(SuccessState / VideoSuccessItem)。两个界面都接受参考图上传,却不提供从结果回到 composer 的一键桥(img2img 续作、"vary"、视频帧复用——都是生成类惯例)。前进路径死在「下载」上。
⑥ 草稿(提示词 + 配置)仅存内存(ux Edit §2.1)🟡
两个 store 均未使用 persist(grep 为空):提示词文本和所有配置参数(模型/比例/尺寸/seed/steps)都在内存里,刷新/崩溃即失。降低严重度的细枝末节:已提交生成是服务端持久的(feed 持久),且提示词在提交后被有意清空,所以丢失窗口仅限未提交草稿——但一份写长的提示词 + 调好的 ConfigPanel 被一次误刷新抹掉,是真实损失。这是 §2.1 的第二个验证实例(继首页 composer 之后)。
⑦ 状态轮询失败不可见(ux Read §1.7)🟡
useCheckGenerationStatus 的 onError 只做 console.error + 加倍退避;条目继续显示 loading 转圈,没有「检查失败/仍在重试」提示,于是持续失败的轮询与慢生成无法区分。重试成功即自愈,故列次要——但「刷新失败 ≠ 仍在进行中」正是 §1.7 规则。这条在当前 action.ts 中仍清晰可读:onError 仅置 isErrorRef 并打印(L164-167),refreshInterval 基于 Math.pow(2, backoffMultiplier) 从 1s 指数退避到 30s 上限,出错时再乘 2(L216-236)——退避策略本身是好的,缺的只是把「轮询已失败」这个事实呈现给用户。
6. 回灌(Skill feedback)与待执行层
审计的第四节回答「这次运行让检查清单变锋利了什么」,分四档:
- 验证了既有规则(现在可被 ux 引用为真实 ❌ 实例):Feedback §4.2(缺口 ①——永久骨架,以及新的「
Array.isArray(map[id])当初始化标志位」形态);Act §3.1(缺口 ③——动作失败必须呈现,以及「同级动作有 toast、这些没有」的不一致);Edit §2.1(缺口 ⑥,第二实例)。 - 从缺口 ❌ 落地为新/强化 ux 条目:Act §3.1——长时/耗费的异步操作(生成、导出、上传)需要 Cancel 入口,而不是事后删除(缺口 ②);并镜像进 Quick review。这是本次最具泛化性的一条——任何有分钟级、计费后台任务的界面都会复现。
- 从优秀案例 ✅ 落地(回灌的另一半——每条都 sharpen 了规则,而非装饰):
- Feedback §4.1——从
ElapsedTime提炼潜在子规则:长时操作耗时/进度读数必须派生自按任务 id 持久化的起始时间戳(跨重挂载存活)并在完成时清理,而非归零重来的本地计数器。旧 §4.1 文本只谈骨架/CLS,从未写明这一点。 - Feedback §4.3——
NotSupportClient把能力门槛规则一分为二:既有「软内联警告、绝不硬阻断」默认的是用户当场可修(模型/配置)缺口;平台/部署缺口(用户无法在界面上翻转)应改为整面门槛 + 附带补救。§4.3 此前未做此区分。
- Feedback §4.1——从
- 记录在案、尚未落地(若第二个界面复现则升级):生成界面结果→输入复用(缺口 ⑤);创作工具首启示例画廊(缺口 ④)。
第五节是待执行清单——L1 完成后明确列出的 L2/L3 议程:
- L2(视觉):Generate 按钮是否是 composer 上唯一主导控件(对应「pending L2」的评级);空态实际看起来多素(缺口 ④);feed 卡片在 loading→success 图/视频切换时的 CLS;窄宽下 N-up 图像网格;环形进度 loading 项与已加载视频的高度匹配。
- L3(动态):
- 强制批次获取离线,实锤缺口 ①(永久骨架、无重试)——价值最高的确认项;
- 发起一个长视频生成,离开页面再回来,检查是否有任何完成信号(轮询按已挂载条目进行,分钟级任务可能根本没有异步完成通知——这是生成类惯例的期望);
- 让删除/下载离线,实锤缺口 ③(静默失败);
- 跨骨架→feed、loading 项→结果切换,测量创建工作区的 CLS。
7. 从这份范例中可以带走的方法论
把 .agents/skills/ux-audit/references/example/create.md 当作模板使用时,值得记住的五件事:
- 先命名类别,再读代码。生成类的基准清单(历史/复用、batch+variations、seed、持久画廊、参考上传、能力门槛、取消、结果→输入、异步完成信号、成本前置)让「完全没建的能力」也能被检出——这是纯代码阅读做不到的。
- 每条结论标注来源层。本例严格区分「L1 已证实」与「pending L2/L3」,绝不用 L1 的
variantprop 去下视觉结论。 - 模式盘点表 + 专门亮点区是报告的骨骼:✅ 行必须带
file:line证据与「为什么承重」,亮点区是独立章节而不是表格脚注——它同时是回灌的 ✅ 素材和重构的防回归清单。 - 缺口条目四要素:违反哪条 ux 规则/目录模式、来自哪一层、
file:line证据、一行补救。像缺口 ① 这种「仅成功初始化标志位 + 共享外壳放大」的结构性发现,比单点 bug 更有价值,因为它预言了未来所有基于同外壳的界面都会继承它。 - 审计在回灌后才算完成:可泛化缺口必须成为 ux 检查清单的新规则(引用本界面为 ❌ 实例),优秀案例必须让规则文本变锋利(引用本界面为 ✅ 实例)——
.agents/skills/ux-audit/SKILL.md明确把回灌标为 mandatory,「没有可泛化缺口」也要在 Skill-feedback 节显式声明。
8. 延伸阅读(仓库内路径)
- 技能与流程:ux-audit SKILL.md、L1 静态层流程、L2 视觉层流程、L3 动态层流程、模式目录
- 同一批范例中的兄弟审计:home.md、chat.md、settings.md、fleet.md
- 被审计源码:共享外壳/(create)/features/GenerationWorkspace/Content.tsx)、空态/(create)/features/GenerationWorkspace/EmptyState.tsx)、图像 ConfigPanel/(create)/image/features/ConfigPanel/index.ts)、视频批次行/(create)/video/features/GenerationFeed/BatchItem.tsx)、视频批次 store 动作、loaded 门控 selector、耗时组件/(create)/image/features/GenerationFeed/GenerationItem/ElapsedTime.tsx)
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00