资质提交页第一版是一个长表单:十几个字段加五六张图片,一次填完提交。在我的开发机上完全正常,商家侧的反馈全是问题,四类。
一是上传经常失败,而且他不知道失败了。证照都是手机直接拍的原图,一张两三兆;商家用的是店里的网络(很多是共用的无线网络,上传带宽很低)。一张图要传半分钟,中途失败的比例很高。而我的实现只有一个整体的「上传中」提示,某一张失败了他看不出来,以为都传好了就点提交,然后提交接口报「材料不完整」,他不知道是哪张缺了。
二是失败要整套重来。五张图传了四张,第五张失败,他刷新页面重新开始,前四张也白传了。在他那个网速下,这意味着又要花好几分钟。
三是驳回之后不知道改哪。后端返回的驳回原因是结构化的(定位到字段),但我在前端只是把原因文字显示在页面顶部。商家看到「营业执照照片模糊」,但页面上有五个上传框,他不确定哪个是营业执照(我用的标签是内部叫法),于是把五张全重拍了。
四是中途被打断就得重填。门店老板填表时随时会被客人叫走,回来发现页面被刷新了、或者他自己点了别的地方,填的十几个字段全没了。有个商家连着重填三次,最后打电话让客服帮他填。
所以四个改动:前端压缩加单张进度与状态、失败单张重传、驳回定位到字段并高亮、自动保存草稿加离开拦截,另外加了上传前的类型尺寸校验与示例图对照。
这个模块最想说的一句话是:功能在我的机器上正常,不等于在使用者的处境下正常。我的开发机是有线网络、图片是我自己截的小图、我知道每个上传框对应什么材料、我填表时不会被人叫走。而商家的每一个条件都和我相反——所以我做的不是「上传功能」,是「一个只在理想条件下可用的上传功能」。
选前端压缩而不是让服务端处理大图。服务端压缩的好处是不损失原始质量、前端逻辑简单,但它解决不了核心问题——上传本身就慢、就容易失败。问题出在传输环节,就必须在传输之前解决。代价是要在前端处理压缩(有兼容性和性能考虑)、并且原图不再保留。判据是「瓶颈在哪」:瓶颈是商家的上行带宽,那就只能减少要传的数据量。
压缩参数的取舍是「体积」和「可辨认度」。压得越狠上传越快,但证照上的小字(统一社会信用代码、有效期)会模糊到审核看不清,结果被驳回——那就白优化了。我的做法是拿真实的证照照片试参数,以「审核同学能看清关键字段」为验收标准,而不是拿一个通用的压缩比。这一条我觉得很关键:优化不能优化到把功能本身破坏掉。
分步表单 vs 长表单。长表单的好处是能看到全貌、实现简单;分步的好处是每步校验、错误暴露得早、心理负担小。代价是看不到全貌(用最后一步汇总回显来补)、以及步骤间的状态管理复杂一些。判据是「字段数量和错误的暴露时机」——十几个字段加六张图,长表单会导致「提交时一次报五个错」,那种体验会直接把人劝退。
草稿存本地而不是存服务端。存服务端能跨设备恢复,但资质材料是敏感信息,未提交的草稿存到服务端会带来额外的存储与合规责任;而且商家基本是在同一台电脑上完成的。取舍依据是「跨设备的需求很弱、而敏感数据的责任很实在」。
踩过的坑一:整体一个「上传中」,某张失败商家看不出来。他以为都传好了点提交,接口报「材料不完整」,而这个报错没告诉他缺哪张。他打电话给客服,客服也不知道。教训是:批量操作的每一项都要有自己的状态显示,汇总状态会掩盖个别失败——这和后端「批量操作要逐条回显结果」是同一个道理,只是发生在前端。
踩过的坑二:驳回原因只在页面顶部显示文字。后端已经给了结构化的字段定位,是我在前端没用上。商家看到「营业执照照片模糊」,但页面上五个上传框用的是内部叫法,他对不上,于是五张全重拍了。教训是:后端给了结构化信息,前端要真的用它来定位,而不是把它当文案显示——这个浪费很典型。
踩过的坑三:没做草稿,商家中途被叫走回来全部重填。有个商家连着重填三次最后让客服帮他填。这件事让我理解了「使用者的处境」有多重要:我填表时不会被人叫走,所以我完全没想到这个场景。后来我养成的习惯是先问「这个人在什么环境下、用什么设备、会被什么打断」,再决定要做哪些兜底。
没做的部分:没做大文件的分片续传。压缩之后单张图只有几百 KB,分片续传的收益很小、复杂度不低。取舍依据是「压缩已经把问题解决到了不需要续传的程度」——先用便宜的办法把问题规模缩小,往往比直接上复杂方案更划算。
压缩效果要报三个数:原图体积、压缩后体积、以及关键字段是否仍可辨认。第三个是定性的但必须报——只报压缩比不报可辨认度,等于没说清这个优化有没有副作用。我的做法是让审核同学在压缩后的图上确认能看清哪些字段。
上传成功率与耗时必须在限速环境下测。用弱网工具模拟商家的上行带宽,报「压缩前后的单张上传耗时与失败率」。在办公室网络下测这个指标毫无意义——那里什么都能成功。
失败重传要用断言型用例:让第三张上传失败,断言前两张保留成功状态、只有第三张显示失败与重传按钮、重传后不影响其他张。
驳回定位:构造一个带字段级驳回原因的回流,断言对应表单项被高亮、页面自动滚动到它、其余材料保留为已通过状态。
草稿恢复:填一半后关闭页面,重新进入,断言提示存在草稿、恢复后文本字段与已上传图片都在。第二部分容易漏。
客服咨询量的报法要谨慎:可以报「资质提交相关的客服工单数下降」,但必须说明同期是否有其他变更(比如审核标准调整、商家培训),不能把全部功劳归给这个改动。
驳回率的报法同理:示例图对照理论上能降低驳回率,但驳回率也受审核松紧影响。要说清这一点。
不要报什么:不要报「上传成功率 100%」——弱网下不可能。该报的是「限速环境下压缩前后的失败率对比」「关键字段压缩后仍可辨认(经审核确认)」「单张失败只需重传该张」「驳回原因能定位到具体表单项」这几件可核对的事。
评价管理页第一版就是一个按时间倒序的评价列表,每条下面一个「回复」按钮。功能上什么都不缺,但商家几乎不用它,四个问题。
一是默认视图不对,最该处理的评价被淹了。按时间倒序意味着最新的评价在最前面,而其中绝大多数是好评(不需要回复)。一条三天前的差评已经翻到第二页了,而它正是最影响门店的那条。商家每天登录后台是为了处理订单,他不会有耐心翻页找差评。
二是每条都要手写回复,商家嫌麻烦干脆不回。他一天可能有十几条评价,逐条手写没有精力。所以他的实际选择是全都不回。
三是我做了模板之后,出现了新问题:所有回复变成一模一样的模板原文。用户在门店页面看到十条评价下面十条完全相同的「感谢您的光临,欢迎再次品尝」,观感比不回复更差——那是明显的敷衍。我做了个优化,结果制造了一个新问题。
四是申诉提交之后没有任何反馈。商家点了申诉,然后就什么都看不到了——不知道有没有收到、审核到哪一步、结果是什么。他会反复提交同一条申诉,或者打电话问客服。
所以四个改动:默认视图改成待回复的低分优先、提供模板但强制编辑(不允许原文直接发布)、回复前给公开性提示、申诉状态全程可跟踪。
这个模块最想说的一句话是:默认值决定了功能会不会被用。回复功能一直都在,但因为默认视图把差评埋在了第二页,商家实际上用不到它。我没有加任何新功能,只是把默认排序从「按时间」改成「待回复的低分优先」,低分评价的回复率就明显上来了。这件事让我明白:「功能有没有」和「功能会不会被用到」是两回事,而后者往往由默认值决定。
不做批量回复,这是有意的取舍。批量回复技术上很简单,商家也提过这个需求(「能不能一键回复全部好评」)。但我认为它会直接破坏功能的目的——评价回复的价值在于「商家真的看到了并且回应了」,批量回复出来的内容必然是模板原文,用户一眼就能看出是批量的。而这比不回复更伤门店形象。所以我的处理是拒绝批量,但用「分场景模板 + 变量填充 + 强制编辑」把单条回复的成本降到足够低。判据是「这个效率优化会不会破坏功能本身的目的」——会的话就不该做,而应该去降低正确做法的成本。
模板强制编辑而不是完全自由。完全自由的结果我们实测过——商家会直接发模板原文,十条评价下十条一模一样。强制编辑的代价是多一个约束、商家可能觉得麻烦。但这个约束保护的是他自己的门店形象,而他当时意识不到。这类「用户短期觉得麻烦但长期对他有利」的约束要不要加,我的判据是:这个后果他自己能不能及时看到——看不到(用户不会告诉他「你的回复很敷衍」),那就该由系统来兜。
情绪化用词选「提示」而不是「拦截」。拦截的问题有两个:一是判断本身有误差会误伤(有些词在特定语境下是正常的);二是商家会觉得被管太多而产生抵触,甚至绕过(换个说法表达同样的情绪)。提示的代价是有些不当回复还是会发出去。但我们有事后手段(回复也过内容检测、有可编辑窗口、平台可下架),所以前置环节不必做硬拦。这一条和敏感词分级处置是同一个思路:机器判不准的事,给人提示而不是替人决定。
踩过的坑一:默认按时间倒序,导致回复功能形同虚设。功能一直都在,但差评被新的好评顶到第二页,商家不会翻页去找。我改的只是一个默认排序,低分评价的回复率就明显上来了。这件事对我的影响很大:「功能有没有」和「功能会不会被用到」是两回事,而后者往往由默认值决定。后来我做任何列表页都会先问「用户打开这个页面最想先看到什么」,而不是默认按时间排。
踩过的坑二:加了模板功能,结果制造了「千篇一律的回复」这个新问题。这是我第一次真切体会到「一个优化可能带来比原问题更糟的新问题」。原问题是「商家嫌麻烦不回复」,我用模板降低了成本;但我没想到成本降到零之后,他会选择完全不加工。修法是强制编辑。教训是:做效率优化时要想一步——成本降低之后,用户的行为会怎么变?
踩过的坑三:申诉提交后没有任何状态反馈。商家反复提交同一条申诉,客服接到很多「我的申诉怎么样了」的电话。教训是:任何「提交后由别人处理」的流程,都必须给提交方一个可查询的状态——否则他唯一的办法就是反复提交或者找人问。这个成本一定会回到我们身上,只是换了个部门承担。
没做的部分:没做回复内容的智能生成(根据评价内容自动写回复)。它能进一步降低成本,但会把「千篇一律」的问题变成「看起来不一样但同样没有诚意」,而且生成内容的质量与合规都需要额外把控。我认为在没有解决「怎么保证生成内容真的针对了用户的具体问题」之前,它的风险大于收益。
回复率是这个模块的核心指标,但要按星级分开报。总体回复率会被好评稀释。报法是「低分评价的回复率从 X 提升到 Y」并说明统计区间——因为改动的目标就是让差评被处理。
回复及时性报「从评价发布到商家回复的中位时长」。用中位数而不是平均值,因为少数几条很久之后才回复的会把平均值拉得很离谱。
模板的效果要报两个数,不能只报一个:「使用模板的回复占比」和「模板回复中被实际编辑的比例」。第二个才说明「强制编辑」这个约束有没有起作用——只报第一个会掩盖「全是模板原文」这个问题。
回复内容的差异度可以做一个简单的抽样检查:取同一门店的若干条回复,看是否存在大量完全相同的文本。这是「千篇一律」问题的直接回归验证。
默认视图改动的效果验证要注意归因:回复率上升可能同时受到「运营培训商家」等因素影响。我的处理是同时报「待处理计数被清零的天数占比」——这个指标更直接对应默认视图的改动。
申诉状态跟踪的效果用「重复申诉次数」和「申诉相关客服工单数」衡量,两者都应下降。
草稿保留:断言写了一半切换评价再切回、或刷新页面后内容仍在。
不要报什么:不要报「门店评分提升」——评分主要由服务质量决定,不是回复功能的功劳。该报的是「低分评价回复率与回复中位时长」「模板回复中被实际编辑的比例」「重复申诉次数下降」「草稿在切换与刷新后保留」这几件可核对的事。
门店信息编辑页第一版是一个平铺的表单:店名、地址、电话、品类、营业时间、简介、门头照,全部放在一起,一个「保存」按钮。四个问题都不是功能 bug,全是「商家不知道发生了什么」。
一是不知道哪些改动需要审核。店名、地址、品类这些改了要重新审核(审核期间用户看到的还是旧值);营业时间、电话、简介改了立即生效。而我的表单对这两类字段没有任何区分。商家改了店名点保存,看到「保存成功」,他以为立刻生效了,去用户端一看还是旧名字,于是打电话说「你们系统有 bug」。
二是不知道改完在用户端是什么样。他填了一段简介,不知道会不会被截断、门头照会不会被裁掉重点、店名太长会不会显示不全。他只能保存了之后自己去 App 上找自己的店看一眼——而如果需要审核,他还得等审核通过才能看到。
三是营业时间根本表达不了他的真实情况。我做的是一个「开始时间 - 结束时间」的单时段控件。但很多门店是中午晚上两个时段、有的周末和平日不同、夜宵店是晚上十点到次日凌晨两点。跨天的情况在我的控件里填不进去——结束时间比开始时间小,校验直接报错。他的处理是填一个错的时间,然后在简介里写「实际营业时间见店内告示」。
四是改动的影响面他不知道。地址改了会影响配送范围(原来能送到的小区可能送不到了)、品类改了会影响搜索归类。他改地址只是因为「门牌号写错了想修正」,完全没想到会影响配送。
所以四个改动:字段按生效方式分组并明确标注、加顾客视角实时预览、营业时间支持按周、多时段、跨天、高影响字段改动时提示影响面,另外补了未保存离开拦截。
这个模块最想说的一句话是:表单的设计要把「系统内部的差异」显式呈现给用户,而不是隐藏起来。「需要审核」和「立即生效」在我们内部是很清楚的两类字段,但我把它们混在一个表单里、用同一个「保存成功」提示,就等于把这个差异藏起来了——而用户会用他自己的理解去填补这个空白,通常是错的。
预览选「前端复用顾客端样式约束」而不是「调顾客端接口渲染真实页面」。后者最真实,但需审核的字段在审核通过前拿不到新值,所以真实渲染只能看到旧值——那就完全达不到预览的目的。前端渲染的代价是样式约束要在两边各维护一份,顾客端改了样式预览可能不同步。缓解办法是把关键约束(截断字数、行数、裁剪比例)抽成共享配置,而不是在预览里写死。判据是「预览要解决的核心问题是什么」——是让他在提交前看到效果,那就必须不依赖保存。
营业时间控件选自己实现而不是用现成组件拼。现成的时间选择器解决不了「按周 + 多时段 + 跨天 + 特殊日期」这个组合。自己实现的代价是要处理很多边界(重叠、跨天、时长为零)。但这些边界本身就是业务需求,用现成组件也躲不掉,只是把复杂度挪到了外面。我的判断是:当一个控件的核心复杂度来自业务规则而不是交互形式时,自己实现更清楚。
影响面提示选「说明后果」而不是「要求二次确认」。二次确认会让每次改地址都多一步,而改地址是低频操作、且大多数改动是正当的(修正门牌号)。说明后果让他自己判断,成本更低。判据是「误操作的代价是否不可逆」——配送范围变化是可逆的(改回来就行),所以不需要强确认;而如果是不可逆的操作,我会加二次确认。
踩过的坑一:需审核的字段没有任何标注,商家改完店名以为立刻生效。他看到「保存成功」,去用户端一看还是旧名字,打电话说「你们系统有 bug」。根因是我把系统内部的差异(两类字段)藏起来了,用同一个提示覆盖了两种完全不同的结果。教训是:用户会用他自己的理解去填补你没说清的空白,而那个理解通常是错的——「保存成功」在他的理解里就是「已经生效了」。
踩过的坑二:营业时间只支持单时段,夜宵店填不进去。结束时间比开始时间小,我的校验直接报错。商家的处理是填一个错的时间,然后在简介里写「实际营业时间见店内告示」——这意味着这个字段的数据完全不可信,而下游(是否接单、是否显示营业中)都依赖它。教训是:当用户开始用「变通办法」绕过你的字段时,说明这个字段的设计和真实业务不匹配,而且它已经污染了下游数据。我是从简介内容里发现这个问题的,不是从工单里。
踩过的坑三:门头照预览没有显示裁剪框。商家上传了一张居中构图的照片,实际展示时按比例裁剪,主体被裁掉了一半。他反复换图也不明白为什么。教训是:预览如果不真实反映约束,它比没有预览更糟——因为它给了用户错误的确信。
没做的部分:没做改动的历史版本与回滚(改错了能恢复到上一版)。它有价值,但需要存储每次变更的完整快照,而且「回滚」在有审核环节的字段上语义复杂(回滚到一个待审核的版本是什么意思)。我记录了变更日志(谁在什么时候改了什么),这已经能解决「查是谁改的」这个主要需求,回滚留给后续。
「以为已生效」这类问题最好的指标是客服工单分类:报「门店信息生效相关的咨询工单数下降」。要说明工单是怎么分类的(人工标注还是关键词),以及同期有没有其他变更影响。
预览的价值用「保存后又立即再次修改的比例」衡量。这个指标很有意思——它代表「保存后才发现效果不对」的情况。有了预览之后这个比例应该下降。要说清统计窗口(多长时间内的再次修改算)。
营业时间控件的正确性要用断言型用例覆盖全部边界:单时段、多时段、时段重叠(应报错)、跨天、跨天与次日首段冲突、时长为零、按周批量应用。其中「跨天与次日首段冲突」最容易漏,要专门写。
营业时间数据质量可以直接查:统计「简介里包含营业时间描述的门店数」——这个数字反映了有多少商家在用变通办法绕过营业时间字段。控件改造后这个数字应该下降。这是我发现原问题的方式,也是最直接的验证。
预览与实际的一致性验证:取若干真实门店数据,对比预览渲染与顾客端实际渲染的截断位置、行数、裁剪区域是否一致。这条必须做——预览不准比没有预览更糟。
离开拦截:断言有变更时拦截、无变更时不拦、保存成功后不再拦。第三条最容易漏。
不要报什么:不要报「门店信息完整度提升」——那主要靠运营催促。该报的是「简介里写营业时间的门店数下降」「保存后立即再次修改的比例下降」「营业时间边界用例全部通过」「预览与顾客端渲染一致」这几件可核对的事。
没有匹配的内容,换个关键词试试。
项目拆解 · 商家后台常用页(Vue · 实习级)· 共 3 个模块 · 数字均为示例,需替换成自己项目的真实数据