腾讯亿级用户规模自研业务的上云实践解读,立即报名 了解详情
写点什么

针对多状态订单详情的前端 mock 方案

  • 2021-08-05
  • 本文字数:4689 字

    阅读完需:约 15 分钟

针对多状态订单详情的前端mock方案

背景

闲鱼作为国内最大的二手交易电商平台,有着验货宝/省心卖/优品等有着闲鱼特色的交易链路,而作为交易链路的闭环,一旦形成有效订单,就会有对应的订单详情页,订单详情页往往承载着复杂的交易状态的变化。以验货宝为例, 验货宝是闲鱼推出针对二手商品存在的质量/真伪的不确定性,提出的先验货后交易模式。 


作为交易订单节点:买家拍下->付款->卖家发货->鉴定方收货->鉴定为真->发货给买家->买家收货等多个交易节点,一个订单详情页在不同流转状态下可能存在数十种细分状态,每种状态之间存在着有着文案/操作按钮/进度条等视觉交互上的差别, 如下图所示:


null

存在问题

订单详情页的不同的状态视图流转,依赖于接口返回的字段的改变,存在和服务端的沟通成本;


前端的直接 mock 的方式,像集团内的山海关,dummy 更多是通用的 mock 数据映射,本质还是要手动修改 mock 数据的 status 值;


在真机调试时,依赖的 Charles 的 pc 代理,单次修改成本高;


除了开发同学外,测试同学测试回归的成本高. UI 同学在视觉走查中难以覆盖全部,容易带问题到线上,引起线上舆情。


总结来说,面对此类订单的订单详情页的前端开发测试,我们现有的 mock 存在着以下问题:


•开发联调周期长,自测难以充分;

•测试/视觉回归成本高;

•线上样式问题定位还原周期长;

需求分析

针对以上的问题,能否让订单状态页面的 mock 方式更为易用,我们通过真实的开发体验,提出了针对此类页面的 mock 方式要达到好用,应该具备以下特点:


1.调试方便

mock 方式应该在本地 pc 端调试和真机调试都能够方便使用;


2.业务语义

不同状态的切换交互应该带有业务语义,能够方便开发和测试快速找到想要的订单状态,而不只是简单的修改接口的某个字段值;


3.代码解耦

mock 的方式本身应该和业务代码尽量解耦,即不会将 mock 的逻辑引入线上环境;


4.mock 数据精简

订单页面状态虽多,但是接口往往统一,接口字段,对 mock 数据的维护不应该每一种状态都是单独一份 mock 数据而是应该在一份主的 mock 数据上针对产生变化的字段进行单独 mock;

技术方案

方案总揽

基于以上需求,我们尝试设计开发更为贴近此类业务的 mock 方案。先别看广告,看疗效, 此方案的真实效果如下图所示:

null


从效果图可以看出我们通过按钮点击实现了状态视图的变更,也就实现了目标一、二,而这个按钮本身不会在线上环境所带入也就不实现了代码解耦;那么这套方案是如何实现的呢?如下图所示,我们将整体方案设计为三大模块:


null


胶水层:是整个方案的编译层基座,负责在编译层将视图层插件和 mock 层插件按照生产环境状态加载进入业务层,实现在本地和预发环境下具有 mock 能力,并负责在视图层进行状态切换时按照状态码重新生成对应 mock.json,利用胶水层的打包逻辑做到了与业务解耦的目标; 


mock 层:负责将前端发起的 mtop 请求拦截,根据路由映射到本地 webserver 下的 mock.json 并模拟返回对应结果,利用 mock 层方式实现了 mock 数据精简,调试方便的目标 


视图层:负责页面处的整体 mock 状态切换的交互逻辑,我们将交互入口设计为类似于 eruda 调试工具的唤起方式,在需要的订单页面侧植入, 点击会唤起弹层,弹层展示所有可枚举的订单状态文案以及其他可枚举会影响订单视图的变量条件,点击对应状态进行页面重载展示对应状态的视觉; 视图层负责实现了业务语义的目标。

胶水层实现

在具体实现过程中,由于闲鱼前端开发使用集团提供的 rax 的前端方案,rax-app 也提供了在编译层可以定制的插件机制, rax-app 基于工程构建工具 build-scripts 封装,因此在插件能力上也完整继承了 build-scripts。除了通过插件定制工程能力以外,rax-app 还为插件扩展了运行时定制的能力, 我们定制了 @ali/build-plugin-rax-mock 和本地的 selfBuild 两个编译插件,分别对应 mock 层和胶水层的设计需求,以如下方式在项目的 build.json 里进行引入,很好地实现与业务层代码的解耦。


{  "plugins": [    [      "build-plugin-rax-app",      {        "targets": [          "web"        ],        "type": "mpa"      }    ],    "@ali/build-plugin-rax-mock",    "./selfBuild"  ]}
复制代码


rax-app 的插件机制提供的针对 webpack 打包方案所提供的 onGetWebpackConfig api 将视图层组件植入业务页面, 如下方代码所示,会在打包过程中根据根据指定页面文件路径选择性地注入,并且判断编译环境在真实生产环境中不做任何 mock 模块的打包。


if (api.context.command === 'build') return;    api.onGetWebpackConfig('web', (config) => {      config.entryPoints.values().forEach(entry => {        const entrys = entry.values();        const entryName = entrys[1];        // 只对订单页面注入        if (!/pages\/Order\/index$/.test(entryName)) {          return;        }
const prefixLoader = __filename; const debugOrderPath = path.resolve(__dirname, 'src/components/DebugOrder'); const newOrderPage = `${prefixLoader}?debugOrderPath=${debugOrderPath}!${entryName}`;
entry.clear(); // 视图层组件 entry.add(entrys[0]); entry.add(newOrderPage); }); }); }
复制代码


因此通过胶水层,我们可以快速将 mock 模块和视图层模块快速引入到工程方案中,并能按需引入,不对业务造成明显侵入痕迹。

mock 层实现

首先我们会根据状态合集所需订单详情接口生成一份 mock.json 数据的合集,这样就能涵盖所有状态下所需消费字段,一般接口格式如下所示:


{    "api": "mtop.a.order.info",    "data": {      "status": 0,      "orderStatus": 1001,        ...      "trade": {        "actions": [],          ....        "amount": "2189.00",        "attributes": {          "consis": "10",            ...          "ultronPP": "a_3_0@c",         }       }     },     "ret": [      "SUCCESS::调用成功"        ],        "v": "1.0"}
复制代码


如下图所示,mock 层既要更新视图层切换状态而组成新的 mock.json, 也要拦截页面侧发起的 mtop 网络请求定向到对应的 mock.json 文件;


null


为了真实能够把接口请求到本地,需要对 h5 页面侧发起的 mtop 请求进行拦截,这里利用了淘宝 mtop 库的运行机制会将 mtop 对象加载到页面全局的 window.lib 对象上,利用 Proxy 的代理机制监听 window.lib 对象的挂载 mtop 时机 set 进行 hook, 并根据所处的生产环境判断是否使用发送请求到本地的自定义 request 请求, 实现代码如下:


lib = window.lib;// 拦截Mtop对象的request方法挂载const getMtop = (originValue) => new Proxy(originValue, {  set(target, p, v, r) {    if (p === 'request'     || p === 'H5Request') {      Reflect.set(target, p, getRequest(v), r);    } else {      Reflect.set(target, p, v, r);    }
return true; }});
// 拦截window.lib对象挂载mtopif (!lib) { lib = new Proxy({}, { set(target, p, v, r) { if (p.toLowerCase() === 'mtop') { Reflect.set(target, p, v,r); } else { Reflect.set(target, p, v, r); } return true; } });} else if (!lib.mtop) {lib.mtop = getMtop({});} else {lib.mtop.request = getRequest(lib.mtop.request);lib.mtop.H5Request = getRequest(lib.mtop.H5Request);}
// 根据运行环境选择加载对应的request请求function getRequest(originRequest) { return async function () { if (getMockSwitch()) { // }
return originRequest(); }}
复制代码


当挂载完成即可实现接口的 mock 功能:


  1. 当本地页面发起 mtop 请求,如:mtop.com.test.one;

  2. 请求被注入的插件代码 hold 住,当判断是在本地开发环境或者链接带上 mock query 时, 用本地的 mtopRquest 替换,请求以 http://127.0.0.1/_mtop_mock_/com.test.one 格式重新发起请求;

  3. 请求打到本地 webpack-dev-server 上,server 再去本地 mock 目录上找 com.test.one.js4.如果找到就执行 com.test.one.js 文件,将执行结果返回 5.如果未找到,则走原有的 mtop 请求;

视图层实现

视图层 UI 由页面侧直接可见的切换 icon 和弹层构成,icon 设置为 dragable 方便用户随时拖动, 弹层的渲染考虑到扩展性由树状节点组成。目前根据真实的业务需要,将节点层级分为 2 层(可扩展),一级节点代表:已下单,已验货等核心节点, 二级节点代表在一级节点下可能存在的正负向交易细节节点, 如:在已下单环节下存在取消订单的副状态;


单点数据结构为如下代码所示,包含有每个枚举状态的语义文案,每种状态对应接口字段的主副状态码,状态枚举值,子节点。


// 状态数据结构export interface ClassifyDataItem {  [key: string]: any;  /**   * 节点名称   */  nodeName: string;  /**   * 节点枚举值   */  node?: StatusEnum;  /**   * 对应的协议主状态   */  status?: string;  /**   * 对应的协议副状态   */  subStatus?: string;  childNode?: ClassifyDataItem[];}
// 真实的状态数据枚举export const classifyData: ClassifyDataItem[] = [ { nodeName: '已下单,等待顺丰上门取件', status: '1', subStatus: '10', node: StatusEnum.BUYER_CREATE, childNode: [ ...classifyData ] } ...];
复制代码


每个节点在渲染过程中采用树状递归渲染,视觉层展示 nodeName, 同时绑定点击回调 onItemChange。当弹窗的某一状态结点发生点击行为时,设置节点选中态样式,同时通过 Modal 组件通过 props 传入的函数方法向外层传递绑定在结点上的 status 和 subStatus 值,从而实现了点击单个选项能够修改对应的 mock.json 文件, 同时会触发页面的 window.reload()功能重新加载页面发起 mtop 请求,因此此时接口返回的数据已经是切换后的状态数据,因此页面也会呈现对应状态的视图。

业务应用

当将以上所述的整套方案串联完成后,业务侧开发只需要定义好属于自己订单详情的状态枚举数据结构,并将视图层组件和 mock 层插件引入项目工程,即可接入 mock 的能力,实现所选即所得的订单状态变更。

目前该方案已经在闲鱼验货宝、奢侈品寄卖等交易链路场景下接入, 从真实使用过程中,能够有效提升开发联调的效率,单次状态的切换时间成本从分钟级别下降到秒级, 并能帮助测试和视觉同学快速回归业务场景,定位线上问题,简单的视觉问题不再依赖于后端接口的状态切换,约能节省 30%以上的联调沟通成本。另外带来的彩蛋是该方案的切换语义特点, 在项目开发人员出现流动时,新承接人能够通过这一 mock 方式快速地理解业务,上手开发。上手快,所见即所得,算是针对此类页面维护开发的一门利器。


null

总结与展望

本章节主要介绍了闲鱼在前端开发典型交易场景-订单详情页时,面对多状态模式切换页面的一种开发体验提升的一种尝试,通过上述的方案设计基本实现了开篇所定义的业务 mock 的 4 个目标:调试方便、业务语义、代码解耦、mock 数据精简,不仅提升了在开发/测试同学的体验,通过语义化的方式也能帮助项目更好地进行维护升级。 


伴随着业务系统的复杂度提升和功能迭代,如何能如何更低成本地去维护 mock 项目给我们提出了更高的要求,能否在比如状态码伴随业务升级,变更,增减的功能迭代过程中,联动式地快速变更枚举状态值配置,减少业务侧开发的维护成本是我们继续升级迭代该方案的方向。目前页面只针对单页面 mock, 如何去覆盖整体交易链路的 mock,比如一个完整订单链路的状态一致性,也是值得探索的方向。


本文转载自:闲鱼技术(ID:XYtech_Alibaba)

原文链接:针对多状态订单详情的前端mock方案

2021-08-05 13:001477

评论 1 条评论

发布
用户头像
mock应该作为微服务的一部分
2021-08-06 11:06
回复
没有更多了
发现更多内容

自助洗车市场悄然兴起你准备好了吗

车白兔自助洗车机加盟

自助洗车 自助洗车加盟

FutureTask

周杰伦本人

6月月更

【Java Web 系列】Session的原理分析和使用细节

倔强的牛角

Java javaWeb session 6月月更

KubeVela 1.4:让应用交付更安全、上手更简单、过程更透明

孙健波

Kubernetes OAM KubeVela 云原生应用 K8s 多集群管理

IDM短信发送接口设计说明

agileai

数据安全 集成底座 企业服务总线 统一身份管理平台 主数据管理平台

直播app源码,充值提现模板的设计看似简单却不简单

开源直播系统源码

软件开发 直播源码 app定制开发

24H共享便民自助洗车加盟怎么样

车白兔自助洗车机加盟

共享自助洗车 自助洗车加盟 24小时自助洗车 便民自助洗车

自助洗车机洗车怎么收费和付费

车白兔自助洗车机加盟

自助洗车加盟 自助洗车收费 自助洗车付费

IT采购专家指导 联想百应618 IT运维软硬服一站集采

Geek_2d6073

SRE,了解一下?35+岁程序员新选择

华为云开发者联盟

SRE 华为云

“互联网+”大学生创新创业大赛来了,欢迎报名龙蜥社区赛题!

OpenAnolis小助手

开源 操作系统 互联网+ 龙蜥社区 大学生创新创业大赛

云GPU的618,拿捏了

恒源云

人工智能 深度学习 GPU服务器

【LeetCode】找到一个数字的 K 美丽值Java题解

Albert

LeetCode 6月月更

共享自助洗车机让你告别传统洗车

车白兔自助洗车机加盟

共享自助洗车 自助洗车加盟

开启全方位安全巡检

观测云

7 月亚马逊云科技培训与认证课程,精彩不容错过!

亚马逊云科技 (Amazon Web Services)

架构师 培训 认证

Jupyter Notebook,太强大了!

Jackpop

首批 | 腾讯云完成国内首个云原生安全成熟度评估

腾讯安全云鼎实验室

云原生

Apache Dolphinscheduler3.0.0-beta-1 版本发布,新增FlinkSQL、Zeppelin任务类型

Apache DolphinScheduler

Apache 大数据 开源 Apache DolphinScheduler 消息队列 workflow

要想自助洗车加盟赚钱记住这几点

车白兔自助洗车机加盟

自助洗车加盟 自助洗车品牌

10段实用Python代码,帮我省了几万块钱!

Jackpop

JDK7 HashMap如何实现?

源字节1号

软件开发 前端开发 后端开发 小程序开发

写代码过程中最忌讳什么?

Jackpop

低代码开发:企业应用构建新模式

力软低代码开发平台

vue-表单输入绑定

小恺

6月月更

如何系统地学习 C++ 语言?太全面了!

Jackpop

API工具--Apifox和Postman对比(区别)

Liam

Java 后端 Postman API API接口管理

SQL和Python 哪个更容易自学?

Jackpop

测试进阶必备,这5款http接口自动化测试工具不要太香~

伤心的辣条

Python 程序人生 软件测试 自动化测试 接口自动化测试

使用 Amazon EC2 降低 DeepRacer 的训练成本 DeepRacer-for-cloud 的实践操作

亚马逊云科技 (Amazon Web Services)

Amazon EC2 EC2

针对多状态订单详情的前端mock方案_语言 & 开发_闲鱼技术_InfoQ精选文章