退款流程包含多个独立步骤
申请页先根据订单号查询退款金额,用户选择原因并可添加图片凭证。图片从相册选择后上传,控制器把服务端返回的文件路径保存到证据列表;提交时将原因、订单号和凭证路径列表交给退款接口。
上传和提交使用独立状态,上传过程中不能删除凭证或重复提交。页面关闭时会释放“其他原因”输入框。成功后根据来源页面刷新订单详情或订单列表,再返回上一页。
进度页并行取回两组数据
退款进度控制器用 Future.wait 并行请求订单详情与退款金额,再根据订单中的退款模型展示当前阶段。业务方处理期限由服务端截止时间换算成秒数,页面用周期定时器更新处理期限的倒计时。
Future<List<Object?>> loadRefundData(String orderId) {
return Future.wait<Object?>([
loadOrderDetails(orderId),
loadRefundEstimate(orderId),
]);
}
并行请求可以避免两次接口串行等待,但任意一个失败都会让 Future.wait 抛错。当前页面会统一进入错误处理;如果产品希望部分数据仍可展示,可以考虑分别承接成功和失败状态。
协商记录是单独的时间线
退款协商历史页使用订单号请求记录列表,再根据日志类型映射“用户申请”“对方处理”“金额调整”等事件。它把历史当作不可编辑的时间线展示,避免把当前进度和历史操作混在一个状态字段里。
订单号来自路由参数,接口结果还要验证 code 并转换为模型。空订单号时页面给出错误提示。读取服务端数据时要继续考虑错误状态与空列表状态,避免将解析失败显示成“没有协商记录”。
售后流程可重点验证什么
- 图片选择取消时不进入上传态。
- 上传失败后允许重新选择,已有证据不会丢失。
- 达到证据数量上限后阻止继续添加。
- 提交过程中重复点击不会产生重复退款请求。
- 退款成功后正确刷新来源页。
- 订单已经取消、退款已完成或服务端状态变化时,按钮状态与可执行操作一致。
- 倒计时格式错误、截止时间已过、页面离开时定时器正确停止。
经验总结
Future.wait 并行取订单详情和退款金额,我摘出来跑过:两个都成功时返回,任一失败即抛错——这正是示例应用里”统一进入错误处理”的行为。但产品上要想清楚:金额接口挂了,订单详情是不是也看不了?如果希望部分展示,就别用 Future.wait 裸调,给每个 future 单独 catch 后再合并。倒计时那块提醒一句:服务端给的截止时间先校验格式,过期了直接显示”已过期”,别让 Timer 去算负数。退款我没在自己的项目里做过,真实售后链路的坑建议按文中的检查表逐条在真机上点一遍。
小结
退款流程把金额查询、用户输入、文件上传、申请提交和订单状态刷新串成了一条链。每个异步步骤都有自己的失败和重试边界;把当前状态与操作历史分开建模,页面会更容易理解。
