首页
/ LobeHub UX 审计实战范例:视频/图像创作(Create)界面的三层审计与发现回灌

LobeHub UX 审计实战范例:视频/图像创作(Create)界面的三层审计与发现回灌

2026-09-06 15:49:37作者:平淮齐Percy

本文以 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)/videosrc/routes/(main)/(create)/image 两个路由。两者近乎同构:都组合同一个共享外壳 features//(create)/features/)(CreateGenerationPageGenerationWorkspaceContent / EmptyState,外加 GenerationLayout 侧边栏),再叠加各自按媒介划分的 store(src/store/videosrc/store/image),两个 store 拥有相同的四个 slice:generationConfig / generationTopic / generationBatch / create{Video,Image}

这带来两个审计推论:

  1. 多数发现是「共享代码 → 同时命中两个界面」,且因为活在共享外壳里,任何未来基于该外壳新建的生成界面都会直接继承这些问题;
  2. 验证成本被摊薄——修一处,两个界面对齐。

界面结构可概括为一条主链路:左侧主题(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 中:

  1. ✅ 亮点 — 持久批次 feed 即持久画廊。 已提交批次在服务端,刷新后仍在,所以 GenerationFeed 是真正的画廊而非会话内草稿板。它承载了类别惯例「提示词历史/持久画廊」这一代码阅读通常以为缺失的能力。之所以「承重」,是因为整个结果→复用故事(Copy Prompt / Reuse Settings / seed)都依赖刷新后结果依然存在。

  2. ✅ 亮点 — 每一行都具备生成级可复现性。 hover 行动作行暴露 Copy / Apply Seed + Reuse Settings + Copy Prompt(Button Groups 模式),任何历史生成都可复现或微调。seed 可复现 + 设置复用是生成类惯例,且存在于每一个批次行上,而不是藏在详情视图里。当前仓库中这一行为链可在 video/features/GenerationFeed/BatchItem.tsx/(create)/video/features/GenerationFeed/BatchItem.tsx)(handleReuseSettingshandleCopyPrompt)与 image/features/GenerationFeed/GenerationItem/index.tsx/(create)/image/features/GenerationFeed/GenerationItem/index.tsx)(handleCopySeed 在模型支持时直接 reuseSeed 回灌配置、否则复制到剪贴板)中逐行核对。

  3. ✅ 亮点 — 参考图/视频帧可内联上传。 ImageUpload / FrameUpload 让 composer 直接接受参考图和视频帧——参考上传惯例达成。它之所以承重,恰恰因为缺口 ⑤ 讲的是缺失的反向桥:接收侧已经建好,结果→输入复用只是接线缺口,不是从零建功能。

  4. ✅ 亮点 — 能力门槛存在(→ 已回灌为 ux Feedback §4.3 ✅)。 NotSupportClient 在客户端构建缺少生成后端时渲染整面 CLI / 自托管说明,并附带补救措施(自托管 DB + 托管应用链接),而不是一个坏掉的 composer。它把 §4.3 的规则 sharpen 了:原规则「软内联警告、绝不硬阻断」默认了这是用户当场可修(模型/配置)的缺口;而这里是平台/部署缺口,用户在界面上无法翻转开关,因此「整面门槛 + 附带补救」才是正确形态——这是 §4.3 此前没画出的分界线。

    注:文档自述「代码在变,引用前需重新验证」。从当前仓库结构看,该文件已不在 image/ 目录下以原名出现,正体现了范例文档的这一定位——引用其结论时应回到当时代码核实。

  5. ✅ 亮点 — 耗时跨组件重挂载存活(→ 已回灌为 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、没有 onErrorstore/video/slices/generationBatch/action.tsstore/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 is Array.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 / handleDownloadconsole.errorvideo/…/GenerationFeed/BatchItem.tsx 中各 handler 的 catch 分支;image/…/GenerationItem/index.tsxhandleDeleteGeneration 同形),图像侧 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)🟡 useCheckGenerationStatusonError 只做 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 此前未做此区分。
  • 记录在案、尚未落地(若第二个界面复现则升级):生成界面结果→输入复用(缺口 ⑤);创作工具首启示例画廊(缺口 ④)。

第五节是待执行清单——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 当作模板使用时,值得记住的五件事:

  1. 先命名类别,再读代码。生成类的基准清单(历史/复用、batch+variations、seed、持久画廊、参考上传、能力门槛、取消、结果→输入、异步完成信号、成本前置)让「完全没建的能力」也能被检出——这是纯代码阅读做不到的。
  2. 每条结论标注来源层。本例严格区分「L1 已证实」与「pending L2/L3」,绝不用 L1 的 variant prop 去下视觉结论。
  3. 模式盘点表 + 专门亮点区是报告的骨骼:✅ 行必须带 file:line 证据与「为什么承重」,亮点区是独立章节而不是表格脚注——它同时是回灌的 ✅ 素材和重构的防回归清单。
  4. 缺口条目四要素:违反哪条 ux 规则/目录模式、来自哪一层、file:line 证据、一行补救。像缺口 ① 这种「仅成功初始化标志位 + 共享外壳放大」的结构性发现,比单点 bug 更有价值,因为它预言了未来所有基于同外壳的界面都会继承它。
  5. 审计在回灌后才算完成:可泛化缺口必须成为 ux 检查清单的新规则(引用本界面为 ❌ 实例),优秀案例必须让规则文本变锋利(引用本界面为 ✅ 实例)——.agents/skills/ux-audit/SKILL.md 明确把回灌标为 mandatory,「没有可泛化缺口」也要在 Skill-feedback 节显式声明。

8. 延伸阅读(仓库内路径)

登录后查看全文
热门项目推荐
相关项目推荐