1、背景
做为客服域拜访量最大的页面之一,订单详情页在客服的平常工作中被用来查阅用户的订单信息,以此为进线的买卖家用户供给更好的购买服务,从而提高用户的满意度。无论是一二线客服还是客服管理者,都能在平常运用的系统中直接拜访到详情页,因此呢客服订单详情页的入口亦比较多,日前已然超过了10处。
随着得物业务的快速发展,客服订单详情页必须展示的信息越来越多,必须支持的操作亦越来越多,在页面改版前,一个页面首屏就必须展示80条订单信息,详细数量会按照订单类型、交易状态、物流状态等原因而改变。一个页面最多状况会有200条信息、60个按钮以及20个订单标签(不含用户标签、商品标签),因此会显现一个现象,一个1920*1080分辨率的表示器(客服常用的分辨率),鼠标滚轮必须滚2次才可从页面的最上方滑到最下方,详情页信息截图如下所示。
另一方面,贸然调节反而会降低客服朋友的工作效率。页面内容、交互变化太大对客服朋友亦存有不小的培训成本,因此呢秉持着变更影响最小化的原则,信息量始终保持着只增不减。
经过一段时间的沉淀与打磨,客服订单详情页无论是客服的运用体验,还是研发体验都得到了明显提高,订单关联的TS问题近半年始终保持清零状态。这时期做了非常多尝试和渐进式优化,本文重点从以下三点详细聊聊对客服订单详情页体验升级做的有些思考和优化。 这么信息全的页面,几乎所有客服域平台都要能直接拜访查阅,一个页面怎样多个系统运用,在保证客服朋友运用体验的同期,还能节省研发朋友守护成本。信息量大数据源多引起页面加载慢,客服朋友经常反馈卡顿,怎样对页面首屏进行秒开优化,进一步提高客服朋友的运用体验。简单的改动亦必须投入资源,信息模块复用率低,怎样建设信息自由编排、信息模块拔插的能力,最大程度解放产研运朋友生产力。
2、多入口的页面复用
1、多实例iframe
最早订单详情页只是客服工单系统中的一个页面,运用的是Vue2、ElementUI的技术栈。客服工单系统的定位是后台管理系统,运用门槛较高,更适合管理者运用,因此必须一个面向一二线客服的平台,章鱼工作台就诞生了。章鱼工作台是基于qiankun微应用搭建的,其子应用最起始运用Vue3、Vite和Ant Design,那时,倘若要在章鱼工作台中拜访客服订单详情页属于跨应用、跨技术栈通信,运用iframe是成本最小,亦是初期最合适的一种方式,这亦是页面复用的第1个周期:在子应用运用多个iframe容器嵌入工单系统中的订单详情页。
所有订单详情页的运用方只必须在本地创建iframe容器,而后在嵌入订单详情页的拜访位置时传有些必要的参数如订单号、求购单号就能够正常拜访了,非常方便。还能够支持有些高级配置供运用方选择,如支持经过url query传参的方式掌控页面样式,当用于外边嵌入时隐匿主应用的菜单和顶部tab栏等等。
这个周期,初步处理了页面复用的问题。但大众都晓得iframe的坏处端,一二线客服朋友的平常工作中会显现海量的页面切换,这般一来,iframe的内存占用高、加载缓慢的缺点就被放大开来,这个周期一二线客服经常会反馈页面卡顿,因此迫切必须进一步优化。
2、单实例iframe搭配MF远程组件
对客服工单系统、章鱼工作台两个平台的用户特点、作业行径进行分析,发掘章鱼工作台的用户对页面的体验需求更高,于是对详情页做了第1次优化,步入了第二个周期:将订单详情页迁移至章鱼工单工作台,其构建方式亦由Vite变更为Webpack5,子应用之间利用Webpack5的Module Federation特性经过远程组件的方式进行数据通信。另一方面,尽管iframe的缺点显著,但仍是跨技术栈应用间页面通信的不错选取,将iframe掌控在单实例容器中能够最大程度限制其对内存的占用。
这般一来,详情页的入口虽然有10多个,但通信方式都收拢成为了三种:远程组件、单实例iframe、本地组件。所有场景都能覆盖到,后续各个入口有繁杂交互的变更或自定义事件,都能够在页面主体做到监控和收口,不必须页面的运用方做额外研发。
3、技术实现
3.1、单实例iframe通信
内容供给方 详情接口响应后注册message事件。监听iframe父级携带数据变化,更新本地页面数据。本地页面交互事件被远端触发,发送当前的数据给远端做自定义交互。/** Vue3 */
/** 1. 详情接口响应后注册message事件 */
onMounted(() => {
/** 请求详情接口 */
fetchOrderDetail(() => {
/** query上打上iframe标签,用于确定注册机会 */
route.query.iframeRoute && watchParentMessage()
})
})
/** 2. 监听iframe父级携带数据变化,更新本地页面数据 */
const watchParentMessage = () => {
window.addEventListener(message, event => {
const orderNo = event.data.data.orderNo
if(event.data.type ===ORDER_CHANGE && orderNo) {
/** 更新订单信息*/
initStream(orderNo)
}
})
}
/** 3. 本地页面交互事件被远端触发,发送当前的数据给远端 */
window.parent.postMessage(
/** payload: 携带的数据*/
{
type: workbenchRoute,
params: {
/** 转退货详情页 */
name: refundDetail,
query: {
// 携带数据
},
},
},
/** orgin: 倘若想要传递给任意窗口,能够将这个参数设置为* ,为了安全起见,不意见设置为**/
*
)内容运用方 页面初始化时注册message事件。监听本地订单单号变化,将新的数据传给远端。监听远端交互和数据变化,按照交互类型做区别的本地处理。/** Vue2 */
/** 1. 页面初始化时注册message事件*/mounted() {
window.addEventListener(message, this.callBack, false)
},
/** 2. 监听本地订单单号变化,将新的数据传给远端*/
watch: {
orderNo(newOrderNo) {
/** 在iframe的contentWindow属性上挂载postMessage办法*/
detailIframeRef.contentWindow.postMessage(
/** payload: 携带的数据*/
{
type: ORDER_CHANGE,
data: {
orderNo:newOrderNo,
//其他数据},
},/** orgin: 倘若想要传递给任意窗口,能够将这个参数设置为* ,为了安全起见,不意见设置为**/
*,
)
},
},
/** 3. 监听远端交互和数据变化,按照交互类型做区别的本地处理 */
method: {
/** callBack: 远端事件被触发后,处理本地回调规律 */
callBack(event) {
try {
if (event.data.type === workbenchRoute) {
switch (event.data.params.name) {
case orderdetail:
//转订单详情的handler
break
case detail:
//跳转工单详情的handler
break
// 其他交互
default:
//兜底处理
}
}
} catch(error) {
//反常处理
}
}3.2、远程组件通信
内容供给方 配置webpack的MF插件,将全部订单详情页exposes出去守护详情页的props/** 配置webpack MF插件,将订单详情页exposes出去*/
new ModuleFederationPlugin({
filename: remoteEntry.js?[hash],
library: { type: window, name: app_ticket },
name: app_ticket,
shared: {
/** 需要共享的依赖 */
},
exposes: {
/** 供给订单详情远程组件*/
./OrderDetail: ./src/views/orderdetail/Index.tsx,
},
}),内容运用方 webpack配置必须意见通信的远端应用运用defineAsyncComponent注册组件像本地组件同样运用远程组件/** 1.webpack配置远端应用 */
remotes: {
app_ticket: getRemoteUrl(app_ticket),
},
/** 2. 运用defineAsyncComponent注册组件*/
OrderDetail: defineAsyncComponent(() => import(app_ticket/OrderDetail)),
/** 3. 像本地组件同样运用远程组件*/
<OrderDetail orderNo={orderNo} {...props} />4、总结
页面运用iframe的首屏耗时平均在7076ms,非首屏在2594ms,而MF的首屏只必须1279ms,非首屏更加是只需428ms,渲染时间降低了6倍。
单个页面的内存占用减少到了之前的1/10以内,关于模块联邦和远程组件的更加多细节能够查看Module Federation 在得物客服工单业务中的最佳实践。
3、首屏秒开优化
上一章节说到运用MF的方式处理了架构层面的卡顿问题,但无缓存下页面仍要2~3s乃至更久才可刷出订单信息,此时要怎么办?是的,能够改交互、拆接口。但倘若数据依赖了海量外域服务、无外域产研资源介入,且要在1星期时间做到有效的优化,那还能做些什么呢?
1、缓慢原由
因为有些历史原由,客服订单详情页必须同期展示100+的订单信息,所有的订单信息、订单操作触及的字段接近200个,而这么多字段其中90%都在一个http接口里面,这个大接口包括了36个dubbo接口,这些接口来自交易正向、逆向、供应链、商家、商品、用户以及其他BU。并行的调用必定会显现短板效应,只要有一个接口RT(Reaction Time,响应时间)慢,就会拉慢全部http接口的响应速度,同期显现Timeout的概率亦会提升,再加上页面本身对资源的渲染时间,无缓存下仍要2~3s乃至更久才可刷出订单信息。这个大接口的平均RT在500ms,P99线的RT达到了1.3s,下图便是生产环境下某一次的调用详情,耗时在782ms,降RT优化首屏渲染刻不容缓。
除了接口RT耗时高的问题,还有首屏接口并行调用的问题。90%的字段都在一个大接口里面,剩下10%都是在零零散散的有些小接口里,把这些小接口加起来页面首屏接口超过6个。咱们晓得一个Chrome页签最多并行处理6个http请求,倘若有第7个接口就会进入到Stalled(熄火)状态,等待前面的某一个接口响应完毕后再发起请求,下图是一个示例,getTrackTicketInfo接口是页面首屏的第7个接口,255.14ms便是必须等待的时间。
按照以上问题状况,初步的方法便是接口先聚合再拆分,把所有接口的数据聚合到一起,而后再按照信息模块拆分成若干个接口,前端再按照业务场景和用户行径,去对拆分出来的接口的调用机会进行优化。然则,理想很饱满,现实很骨感,数据量摆在这,很难在短期去做到这件事情。光把字段梳理全,数据源自理清楚就用掉了两天时间,再思虑到成本和收益后,咱们的最后方法便是新增快慢接口,快接口的RT要在200ms以内,所有拖慢RT的数据都放到慢接口中,前端再按照接口的特性将所有接口分为2个梯队在区别时间进行调用,最大程度的减少页面的首屏渲染时间。
2、接口调用优化
2.1、技术方法
为了掌控页面并行请求接口数量和页面数据渲染次数,将除了快慢接口之外,所有零散小接口分为如下两个梯队:不依赖详情大接口反参的首屏信息接口;依赖详情大接口反参的首屏信息接口、非首屏信息接口。
最后详情页首屏接口调用状况示意图如下,在能够聚合依赖大接口反参的首屏信息接口的状况下,页面只会渲染两次,第1次是在快详情接口和第1梯队接口请求回来之后(运用Promise.all掌控数据的渲染机会),第二次便是在慢详情接口请求回来之后。
运用Promise.all来保准快详情接口和第1梯队的接口信息同期渲染,减少页面渲染次数,从而减少页面抖动的状况。Promise.all有个缺点便是其中有一个Promise反常,全部就会抛出反常,因此必须对Promise.all包裹的Promise进行二次封装,保准有一个Promise报错不会干扰其他接口的请求,详细代码实现方式如下: /** 处理promise,保准promise.all运用时相互独立 */
export const handlerPromise = (api, params) => {
return new Promise(resolve => {
api(params)
.then(resolve)
.catch(() => resolve({ error: true}))
})
}/** 详情页首屏请求函数 */
const fetchOrderDetail = (callback?) => {
/** 运用handlerPromise封装过的promise,保准有一个报错不干扰其他接口请求 */
Promise.all([quickDetail(), firstLevel1(), firstLevel2()])
.then(([quickDetailData, firstLevelData1, firstLevelData2]) => {
// 快详情接口!quickDetailData?.error && quickDetailHandler(quickDetailData)// 第1梯队接口调用:不依赖详情反参的首屏信息接口!firstLevelData1?.error && firstLevelHandler1(firstLevelData1)
!firstLevelData2?.error && firstLevelHandler2(firstLevelData2)// 执行回调
nextTick(callback)
})
.then(() => {
// 第二梯队接口调用:依赖详情反参的首屏信息接口、非首屏接口
secondLevelHandler1()
secondLevelHandler2()
})
// 执行慢接口fetchSlowOrderDetail()
}接口调用次序确认后还有一点必须重视,由于慢接口响应耗时较高,在客服朋友快速查找的工作场景中,可能会在慢接口还在pending,就已然切换到下一个订单了,页面单实例的场景下,这个时候倘若不处理可能会将显现数据串台的状况,不属于该订单的数据表示了出来,关于这一点,必须在慢接口的handler上做如下处理。 /** 慢详情接口请求 */
const fetchSlowOrderDetail = () => {
slowLoading.value = true
orderApi
.getDetail(params)
.then(slowData => {/** 防止快速切换订单引起的数据串台问题 */
if (slowData?.topInfo?.orderNo === orderNo.value) {
orderDetail.value = slowData
}
slowLoading.value = false})
.catch(() => {
slowLoading.value = false
})
}2.2、最后效果
优化后的Waterfall图就如下所示,不会再显现灰色的stalled耗时了,况且在228ms后首屏的数据就已然请求回来了。
3、大接口优化
上面一点处理了首屏接口的调用问题,接下来是对大详情接口详细做的有些优化: 接口协议由POST改为GET请求,GET的总耗时是POST的三分之二;Chrome下倘若检测到GET请求的是静态资源,则会缓存,倘若两次传输的数据相同,第二次以后耗费的时间将在10ms以内。另一方面亦为后续工作台引入Service Worker技术打下基本。新增快详情接口,将大接口中的响应耗时较高的字段整理出来,快接口再也不包括这些字段。这些高耗时的字段新增字段级别的loading效果,为了避免快慢接口耗时差异很强,引起有些经验丰富的客服朋友误以为快接口没返回数据的字段是空数据,然则这个loading数量不会超过3处,保持页面的整洁易读。4、总结
经过以上优化,快详情接口RT只必须平均190ms,从之前大接口的470ms下降了41%,首屏渲染时间从873ms降至376ms,下降了57%,95分位567ms,下降了62%。
首屏优化效果显著,很难再看到反馈详情页加载缓慢的VOC了,必定程度地提高了客服的平台体验满意度。
4、信息编排、模版插拔能力建设
处理了页面卡顿和首屏加载慢的问题,但仍存在有些问题。这一次在产研运朋友的通力协作下,怎样进一步提高技术朋友的研发体验和客服朋友的运用体验呢。
1、仍面临的问题
虽然详情页中堆叠的字段已然多达200处,随着业务高速发展仍会存在部分信息缺失、不准确的状况,对客服平常作业产生了必定的负向影响。另一方面,在研发订单类需求中,约60%的都是协同外域或内部进行字段增删改,倘若创立了订单信息的编排能力,后续字段类需求将可配置,从而能够解放这部分需求的产研生产力,达到降本增效;同期若前端模块能够支持模块拔插能力,亦能为后续订单信息模块复用到坐席辅助及其他客服工作台供给技术支撑。
2、信息编排能力建设
将订单基本信息及相关信息经过统一Schema守护。大众晓得Schema(结构化的数据类型)只要约定的足够繁杂是能够用来描述所有场景的数据的,因此运用Schema第1步便是要掌控好这个边界,在能够覆盖大部分业务场景前提下不可太繁杂。首要可将订单信息做3层细分:信息块、信息组、信息元素。做到配置信息块、信息元素针对订单详情页的场景来讲都不太合适,因此这儿选取约定到信息组的格式。
2.1、Schema格式
上面图示中两组信息组可用下述Schema描述出来,利用数组的有序性,从左到右、从上到下对信息组进行渲染,实现订单信息的编排配置能力。 schemaData : [
{
label: 订单类型
text:普通现货
children: [
{
id: orderTypeDetail
text: 详情,
show: true,
toolType: linkBtn, /** linkBtn, primaryBtn, tag */
eventType: click, /** dbclick, hover*/
interactiveType: popover, /** modal, popover, message*/
children: [
//** popover弹出的内容 */
{ label: , text: , children: //..}]
{ label: , text: }
]
},
{
text: 晚到必赔,
show: truetoolType: tag,
},
{
text: 退运服务,
show: true
toolType: tag,
},
]
},
{
id: tradeStatus
label: 支付状态
text:已然支付
children: [
{
text: 七天风控,
show: truetoolType: tag,
},
]
}
],2.2高级配置
运用Schema能够满足大部分的字段渲染场景,然则针对有些繁杂的交互和自定义的样式仍必须前端去实现,这个时候每一个信息元素中的id就发挥了功效,前端能够按照id去绑定交互事件和自定义样式,详细实现如下: /** 信息元素枚举*/
enum INFO_ElEMENT_MAP {
/** 订单类型详情按钮 */
ORDERTYPE_DETAIL: orderTypeDetail
}
/** 信息元素*/
constinfoElementMap = {
INFO_ElEMENT_MAP.ORDERTYPE_DETAIL: {/** 绑定事件 */
onClick: () => {
orderTypeDetailClickHandler()
},
/** 绑定样式 */
className: [styles.marginLeft],
},
/** 其他必须添加繁杂交互和样式*/
}2.3、模版解析
约定好了Schema和规范,前端再编写对应模版解析代码去渲染页面,对应渲染图如下所示。
最外层的渲染器代码如下: const SchemaRender = () => {
//TODO 健壮性代码
return (
<div>
{schemaData.length ? (
<Row>{schemaTemplate.map(item => {
// 分隔符
if (item.key === TemplateKeyEnum.dividedLine) {
return<Divider />
}
return (
<Col span={12}>
<InfoItem
key={item.key}
label={item.label}
text={item.text}
infoList={item.children.map(child =>{
return {
text: popoverRender(child),
hide: !child.show,
}
})}
/></Col>
)
})}
</Row>
) : (
<Skeleton title={false} active paragraph={{ rows: 3 }} />
)}
</div>
)
}最后,Schema加上模版渲染就能渲染出订单详情页的信息,后续此类型的需求除了和外域约定字段,就再也不必须额外资源投入了。
3、模块插拔能力建设
实现了信息快速编排,还有信息模块高耦合的问题。并不同角色的客服朋友关注的信息是不同样的,因此新的订单详情页要按照客服的身份去展示区别的信息;况且随着屏幕体积的区别,所适合布局亦区别。另一方面,工单详情、坐席辅助都必须展示订单信息的某一个信息模块(全部页面展示就太重了),此时就必须订单信息模块有可插拔的能力了。
3.1、技术方法
初步方法是后端守护一个信息模块池,供给出一个接口,前端经过传一个标识,能够返回对应标识必须的模块组合,而后按照数据组合渲染数据。这个方法能够实现信息可拔插能力。
以上方法能够处理问题,亦比较简单,然则掌控数据的还是前端,这其实违背了最初建设信息编排能力的初衷。于是最后改为后端朋友从客服朋友的登录态拿到userId,按照id拿到其所在处理组,是买家处理组就返回买家版订单信息,卖家版就返回卖家版订单信息。另一方面,前端亦按照屏幕体积做布局的自适应。
3.2、最后效果大屏下页面布局:
小屏下页面布局(1440*900以下):
工单详情运用订单详情中的物流记录、服务记录订单信息模块:
从改版败兴近8个迭代的资源投入数据来看,订单需求研发成本降低了66.7%。
5、灰度和埋点方法
1、灰度方法
新版详情页改动很强必须按照客服所在处理组进行灰度,然则一线和二线的处理组分配又不太同样,因此必须按照入口源自判断运用哪套AB方法接口。另一方面,订单详情页的入口非常多,因此在每一个入口做灰度不太现实,改动很强,因此选取收口到详情页主页面区分新老页面。
1.1、技术方法按照源自区分运用一线AB方法还是二线AB方法,伪代码如下:/** 获取源自区分IM、工单灰度组信息 */watch(
() => props.platformCode,
code => {try {
switch (code) {
case PLATFORM_TYPE.IM:
/** 一线灰度走一线灰度接口 */
isGray.value = true
break
case PLATFORM_TYPE.TICKET:
/** 二线灰度走二线灰度接口 */
isGray.value = true
break
default:
isGray.value = false
} catch {
isGray.value = false
}
},
{
immediate: true,
}
)在主页面按照灰度状况渲染详情模版: return () => isGray.value ? (
<>
<Button type="link" onClick={clickHandler} >
返回{isOld.value ? 新版 : 老版}
</Button>
{isOld.value ? <OldDetail {...props} /> : <Detail {...props} />}
</>
) : <OldDetail {...props} />
1.2、总结
按照培训进度开放灰度名单给客服运用新版页面,同期对新老版页面的数据进行监控 。支持可监控、可灰度、可回滚,保证了在页面大改动状况下的系统质量稳定。
2、埋点方法
为了表现订单信息优化的收益和价值,必须对客服朋友在新老订单详情页的停留时间、跳出订单详情页次数进行比对。 订单详情页停留时间:有效的停留时间越长必定程度能说明页面的查阅费力度越高。订单详情页跳出率:跳出率越高说明当前订单详情信息不可满足客服的查阅需求,必须去其他页面查看。是信息不全、不清晰的一种表现。况且跳出页面会重新加载新的页面,等待时间会长于页面内获取信息,增多客服获取信息的时间。2.1、页面停留时间
运用监听路由的办法去计算页面停留时间。这儿只对其中一种做分析,其他两种类似。 确定路由:https://xxx-xxx.xxx/orderdetail/:id只必须思虑上一个路由是订单页面的状况数据过滤:少于3s,大于30min视为无效数据倘若近期的路由是订单页面,则重置时间/** 数据上报 */
const uplog = (current, last, constant, type) => {
/** b: 只用思虑上一个路由是订单页面的状况 */
if(constant === last) {const nowTime = getNowTime()
const stayTime = nowTime - stayOrderDetailTime.currentTime
/** c: 少于3s,大于30min视为无效数据 */
if (stayTime > 3000 && stayTime < 1000 * 60*30) {
orderDuLog(ORDER_STAY_TIME, {
orderNo: orderNo.value,
stayTime,
type,
})
}
stayOrderDetailTime.currentTime = nowTime
}/** d:倘若近期的路由是订单页面,则重置时间*/
if(constant === current) {
stayOrderDetailTime.currentTime = getNowTime()
}
}/** 监听路由 */
watch(
() => {
return { name: route.name, id: route.params?.id }
},
throttle(
(currentRoute, lastRoute) => {
/** 从工单出发:只用思虑上一个路由是订单页面的状况 */
uplog(currentRoute?.name, lastRoute?.name, `${globalConfig.backstageCode}_orderdetail`, routeChange)
},
100,
{ leading: true, trailing: false }
),
{
deep: true,
immediate: true,
}
)2.2、页面跳出次数
页面跳出次数就比较简单了,只必须在跳出事件的handler里加上数据上报办法,例如查看商品详情、退换货详情、用户分期信息、工单详情等等,最后计算跳出总量就可。
2.3、总结
老版页面平均停留时间15.6s,新版页面的平均停留时间8.5s,客服每次查找信息的时长缩短7.1s,可按照详情页PV换算日均可降低客服朋友工作时长。
同期,客服查找特定订单信息时必须跳到别的页面查找,这说明订单信息是有缺失和或客服是对信息准确性是有可疑的,老版页面跳出率11.4%(约8.7次拜访跳出1次),新版页面跳出率7.92%(约12.6次拜访跳出1次)。客服查看订单信息时跳出的率亦下降3.48pp。
6、总结&规划
1、总结
关于动态路由页面的多平台复用:跨技术栈运用单实例的iframe通信,协同双向的postMessage事件监听用户行径触发交互;微应用内运用Module Federation通信,在保证客服运用体验的同期,节省了研发守护成本。 MF的首屏必须1279ms,非首屏只需428ms,渲染时间降低了6倍。单个页面的内存占用减少到了之前的1/10以内。关于大数据量的页面首屏优化:基于业务优化接口调用机会,保准同期不超过6个接口请求,避免显现Stalled耗时,对大接口RT进行优化,场景准许的话可改为GET协议类型,降低首屏响应时间,提高客服体验。 首屏请求6个以上接口时再也不显现Stalled耗时,大接口改为GET后总耗时是POST的2/3。快详情接口RT只必须平均190ms,从之前大接口的470ms下降了41%,首屏渲染时间从873ms降至376ms,下降了57%,95分位567ms,下降了62%。关于信息编排、模块拔插能力建设:按照业务分析字段特点,约定合适的Schema格式使得信息内容可灵活配置;对用户的职能特点、设备状况进行分析,使得用户所拜访页面的布局、内容做到区分,做到给用户看到合适的内容,降低坐席的查找信息的费力度。 订单需求研发成本能够降低66.7%。老版页面平均停留时间15.6s,新版页面的平均停留时间8.5s,客服每次查找信息的时长缩短7.1s,按照订单详情页的PV可换算出每日可降低客服朋友的查找时长。老版页面跳出率11.4%(约8.7次拜访跳出1次),新版页面跳出率7.92%(约12.6次拜访跳出1次)。客服查看订单信息时跳出率下降了3.48pp。
2、后续规划
虽然客服订单详情页的运用体验已然得到提高,然则体验升级之路仍在继续: 模块联邦虽然火速,然则对公共依赖守护成本很强,亦会引起应用构建速度下降。后续会基于无界对订单子应用进行迁移,建设专门存放远程组件的应用容器,提高子应用的秒开和快速切换体验,同期亦能提高工单子应用构建速率,解耦横向订单功能的发布。可期待后续内容。
*文 / 昌禾
本文属得物技术原创,更加多精彩文案请看:得物技术
未经得物技术许可严禁转载,否则依法追究法律责任!
|