2225 字
11 分钟
开发日志 2026-09-28:上传的时机、进度的真话与常驻页面的状态卫生

开发日志 2026-09-28:上传的时机、进度的真话与常驻页面的状态卫生#

前言#

今天的所有改动都落在这条链路上:用户在社区小程序里发一个作品——选图、上传、填标签、保存。打磨到最后发现,四件事其实是同一件事:让界面说的每一句话都是真的。进度是真的在涨,成功是真的完成了,空表单是真的空的,已选中是真的选中了。界面一旦开始「说客气话」,用户就要开始猜,而猜的下一步往往就是重复提交或者直接放弃。

一、把上传前置到选图:交互的时机问题#

原来的流程是教科书式的:选图 → 填表单 → 点保存 → 保存时才开始上传。用户在最后一步盯着一个转圈的保存按钮,等所有图片传完才得到回应。改造思路很直接:把上传挪到用户本来就在等的动作里——封面裁剪完成的那一刻、内容图选入的那一刻,立即开始上传;等用户填完表单点保存时,只剩一个纯表单提交请求,速度就是提交本身的速度。

但「前置」真正的功夫在配套设计,不在挪位置:

  • 代际号丢弃旧回调:封面可以连续重新裁剪,上一轮还在途的上传回调回来时,用代际号判断是否已过期,过期即丢弃——连续快速重裁不会把旧图串写进新数据。
  • 删除与重排的错位防护:图片列表在上传期间还允许删除和拖动排序,上传完成回写时按身份匹配,列表里已经找不到的就直接丢弃,避免错位回写污染数据。
  • 保存兜底补传:选图时自动上传失败的本地路径仍会在保存时补传一次——快不能以丢图为代价,兜底补传是「前置」方案敢上线的安全网。
  • 上传中的软拦截:还有图片在传时点保存,toast 提示稍候而不是放行一个必然缺图的提交。

这轮改造的心得是:交互优化的本质是重新安排等待,而不是消灭等待。上传总量一秒都没少,只是每一段等待都被安置在了用户本来就没有别的诉求的时间窗里。而所有「乐观前置」的方案,可靠性都取决于兜底路径是否完整。

二、进度与成功的可见性:让界面说真话#

上传前置之后,新的问题立刻出现:上传发生在用户选图的时候,如果没有任何反馈,用户不知道图传没传、传到哪了。于是给封面上传加了进度显示——图片上方叠加半透明遮罩,白色文字显示当前百分比,到 100% 自动消失。

这里有个小而有意思的口径问题:封面是裁剪图和原图两张并发上传,进度条显示哪个?答案是把两者的进度取平均值,且任意一张完成即整体记 100%——因为对用户而言「封面」是一个整体,单独显示任何一张都是误导。多文件并发上传的合并进度没有万能公式,但必须有一个明确的、对用户语义正确的口径。

另一个「真话」问题更隐蔽:内容图上传成功后,页面层的数据已经更新成 CDN 地址了,但图片选择器组件的显示列表没有同步,界面上图片的来源一直停留在本地临时路径——功能上一切正常,就是用户(和调试的我们)从界面上永远无法确认上传真的成功了。修复方式是上传成功后主动调用组件暴露的同步方法,把显示值一并替换。

心得记两条:其一,进度条的真正价值不是动画,是让等待有据可依——用户焦虑的从来不是慢,是不知道还要等多久、以及刚才那下到底成没成。其二,页面和组件分离维护同一份数据时,数据更新必须双端同步;组件提供了更新方法,就意味着它不承诺自动跟随页面数据,这个方法就必须被调用。

三、常驻页面的状态卫生:tabBar 页的生命周期课#

这一单的症状很经典:发布一个作品保存成功后,切走再点发布 tab 进入新建页,表单里残留着上一次的图片和标签——对用户来说,「新建」就该是空的。

根因在 tabBar 页面的特殊性:实例常驻内存,状态跨次保留。页面不会销毁重建,onLoad 里那套初始化只走一次,之后全靠保存回调里手动清态。而清态代码有两处失灵:

  • 图片清不掉:清图是靠给组件传一个布尔信号、组件用 observer 监听的。问题在于 observer 只在值变化时触发——第一次保存设置 true 之后它就恒为 true,后面每次再设置 true 都不会触发 observer,图片从此永远清不掉。修复是把信号改成翻转值,保证每次保存都构成一次变化。
  • 标签清不掉:保存回调里只清了页面层的标签数组,从未调用标签组件的重置方法,组件内部的选中态原封不动。修复是显式调用组件的重置方法——和上一节是同一个教训:组件内部状态要用组件的方法清,页面层清得再干净也传不进去。

最后加了一道兜底:在 onShow 里检测「编辑标记已清除但页面仍处于编辑态」的异常路径(上次未保存直接切走),自动重置为新建表单。状态卫生的原则就此完整:常驻实例的每一个状态都要有明确的清理时机,且要假设清理本身可能失败——兜底分支不是防御式编程的装饰,是状态机的最后一根撑杆。

四、两套 id 的账:标签回显的口径课#

编辑作品时,已选标签无法回显选中状态。排查下来是两笔账对不上:前端混用了两套标签 id 体系——候选列表用一套,已选记录用另一套,回显时拿着 B 体系的 id 去 A 体系里找选中态,自然永远找不到;服务端还存在重复的标签记录,同一个名字两条 id,进一步搅浑了对账。

修复没有动交互,只是把口径对齐:全链路统一一套 id,查重逻辑同步修正。心得是:「显示层修不好」的问题,根因往往在数据口径。多端共存的项目里(这套功能网页端、H5、小程序三端都有),同一份标签数据在两端各自的实现里很容易长出两套主键——只要有一次「先跑起来再说」的临时代码混进主干,回显、去重、统计这些所有依赖「同一个东西有同一个 id」的功能都会慢性失血。口径问题越早还账越便宜。

五、界面一致性杂记#

另有几件小事一并记下:全站主题色从默认蓝统一成品牌黑,含组件库的默认色覆盖;封面展示框比例改成 1:1,与裁剪输出比例一致,从此 1:1 封面不再被横框二次裁切;H5 端把旧版两步向导布局改成单页、字段顺序对齐小程序,三端的发布表单从此是同一张表单;移动端标签输入的占位文案删掉了「回车添加」——手机上没有回车,还给小程序补了个「添加」按钮。都是不起眼的活,但多端一致性就是由这些小事构成的:同一份功能在三个端长得不一样,用户会认为每一个都是 bug。

结语#

回看这一天:时机前移换来速度,进度可见换来信任,状态卫生换来确定性,口径对齐换来一致性——四件事的验收标准其实是同一句话:界面陈述的每一个事实,都要经得起对账。用户对界面的信任是按次结算的,一次「明明说成功了其实没有」的扣款,比十次「慢一点」更贵。让界面说真话,是交互设计里最便宜也最值钱的工程。

开发日志 2026-09-28:上传的时机、进度的真话与常驻页面的状态卫生
https://shenhuanjie.github.io/posts/2026-09-28-daily-devlog-upload-timing-honest-progress-and-state-hygiene/
作者
沈焕杰
发布于
2026-09-28
许可协议
CC BY-NC-SA 4.0