本文目录8 节

一开始,我以为主要工作是把移动端页面搬到 Web

移动端已经有自定义生图和生视频能力,Web 端要补上同样的入口。表面看,这像是把页面结构、表单和接口调用重新实现一遍。

真正开始梳理后,我发现两个项目的运行模型差异很大。移动端依赖 Ionic、Capacitor、原生保存与分享能力,Web 端使用 Vue 3、Vue Router、Pinia、Vue CLI 和 Webpack。页面生命周期、媒体能力、路由返回和资源处理都不能直接照搬。

因此我先把原功能拆成两类:

  • 可以复用的业务规则:配置加载、模板、参考图、提示词、任务状态、结果预览和历史记录;
  • 平台专属实现:原生保存、分享、App Bridge、Ionic 生命周期和移动端插件。

这一步决定了后续的边界。Web 页面需要保持用户目标一致,但不需要假装自己仍处在原生容器里。

先建立完整链路,再决定组件怎样拆

我把 Web 端能力画成一条完整流程:

进入图片或视频工作区
  -> 加载配置与快速模板
    -> 填写提示词或使用提示词辅助
      -> 上传参考图
        -> 选择模板、风格或画质
          -> 创建生成任务
            -> 持续查询任务状态
              -> 展示图片或视频结果
                -> 预览、查看历史或复用提示词

如果只按页面截图拆组件,很容易把最重要的任务状态散落在按钮、表单和结果列表里。链路画清后,组件职责才更容易确定:编辑器收集输入,上传器管理参考图,任务管理器负责异步状态,预览组件负责媒体展示和资源释放,历史页面只消费已经完成的结果。

图片和视频有公共外壳,但不是同一张表单

图片与视频都需要提示词、模板、参考图和生成按钮,看起来很适合完全复用。继续对比后,差异比共同点更影响状态设计:

  • 配置来源与模板结构不同;
  • 参考图数量不同;
  • 图片有风格、画质与分辨率价格;
  • 视频模板可能需要单图或首尾两图;
  • 并发任务数量和预览方式不同;
  • 请求参数与结果媒体类型不同。

最终我保留共享的提示词编辑、参考图上传和结果预览能力,让图片和视频工作区分别维护自己的配置与校验。这样没有把相似 UI 误认为相同业务状态,也避免在一个巨大的表单里堆叠大量类型判断。

异步生成不是一个 loading 布尔值

图片与视频都不是请求结束后立刻得到最终资源。页面先创建任务,再根据任务标识持续查询状态,最后才能拿到媒体结果。

这意味着任务可能跨过页面隐藏、网络中断和用户切换。旧请求也可能晚于新任务返回。如果只在组件里写一个 loading,页面重新进入后就不知道应该继续等待、重新请求还是清理状态。

我把任务流程集中到统一管理层,负责:

  • 创建任务并记录当前实例;
  • 查询进度和最终结果;
  • 区分生成失败与查询中断;
  • 页面隐藏时暂停,恢复后继续;
  • 网络中断后保留可恢复状态;
  • 用户切换后清理旧任务;
  • 丢弃已经失效的旧响应。

任务状态稳定后,页面只需要把结果交给图片缩放或视频预览,而不需要自己理解所有异步边界。

跨路由草稿是另一个状态所有权问题

角色创建页中,用户已经填写名称、性别、标签和介绍,然后点击“使用 AI 生成图片”。如果直接跳转到图片工作区,原页面没有持续挂载,返回后表单会恢复成默认状态。

简单把整个表单放进全局 store 也不够。用户可能在生成期间切换账号,或者开始新的草稿;旧图片结果不能覆盖当前内容。

最终流程是:

离开角色创建页
  -> 保存当前用户的草稿
    -> 生成一次性草稿令牌
      -> 进入图片工作区
        -> 生成并选择图片
          -> 返回角色创建页
            -> 校验用户与令牌
              -> 恢复表单并回填图片

用户标识解决跨账号污染,一次性令牌解决旧结果覆盖新草稿。它们都属于流程身份,不应该由组件是否还在 DOM 中决定。

账户余额、基础消耗和画质价格不能混用

页面同时展示账户余额和生成消耗。图片配置中还可能有基础价格与不同分辨率价格。如果都笼统地叫“站内额度”,很容易在模板或校验中拿错字段。

我把三种语义分开:用户账户中的真实余额、当前生成方案的基础消耗、具体画质选项的价格。余额不足时可以打开已有额度购买入口,但购买完成后不自动重新提交任务,避免重复生成或重复扣费。

这里让我再次意识到,字段值相同不代表语义相同。前端状态应该按照数据职责命名和传递,而不是只按照页面上显示的数字组织。

验证要诚实覆盖当前阶段

这一轮完成了页面结构、参考图、提示词辅助、模板选择、任务状态、预览、历史、跨路由草稿、多语言和响应式处理,也通过了定向检查与生产构建。

仍需要真实账号和后端环境继续验证:

  • 完整图片与视频生成;
  • 长时间任务、服务错误和查询恢复;
  • 余额不足与购买后的刷新;
  • 不同会员或活动下的动态价格;
  • Safari、Chrome 和移动端浏览器的视频差异;
  • 多语言真实排版与阿拉伯语 RTL;
  • 图片回填后的最终角色创建。

因此当前结论是“Web 端结构与任务链路已经建立”,而不是“所有生产场景已经完成联调”。

这次迁移留下的判断

跨端迁移的核心不是复制原平台的页面,而是识别哪些业务语义必须保留,哪些能力应该由目标平台重新表达。

以后再处理类似任务,我会先拆分业务规则、平台能力、异步状态和跨页面身份,再决定组件与 store。这样能够更早发现那些从截图里看不出来、却会在真实流程中丢失的状态。

Recommended

继续阅读

  1. 一个聊天 TTS 按钮,为什么要拆成三层边界前端与移动端 · 9 分钟
  2. 一个两行修复,为什么从 Vue 一直追到了 Android 原生插件?前端与移动端 · 9 分钟