前端如何设计一个回溯用户操作的方案

发布于:2025-02-10 ⋅ 阅读:(65) ⋅ 点赞:(0)

同一个项目,为什么我本地无法复现,只有客户的设备才复现?

如何获取用户的操作路径呢?
两种方案:埋点和rrweb
埋点就很简单了,将所有可能操作的节点都进行预埋数据;但埋点简单并不省心(可能会漏掉某个场景)。接下来我们重点探讨rrweb方案。

rrweb

一、录制端(用户端)

1. 获取用户信息
import { getInstance } from "./instance"

let token = ''

export const getToken = () => {
  if (token) {
    return token
  }
  const tokenFromSession = sessionStorage.getItem('token')
  if (tokenFromSession) {
    token = tokenFromSession
    return tokenFromSession
  }
  const inst = getInstance()
  const tokenFromInst = inst.getToken()
  if (tokenFromInst) {
    token = tokenFromInst
    return tokenFromInst
  }
  const __options = inst.getOptions()
  const { token: tokenFromOption } = __options
  if (tokenFromOption) {
    token = tokenFromOption
    return tokenFromOption
  }
}

2. 用户信息换录制配置
a. 配置为空,退出录制,结束流程
b. 有配置数据,进行第3步
3. 从接口中解析配置数据(获取起始时间点,结束时间点,录制时长)
4. 当前时间点校验(【起始时间,结束时间】)
const { id, singleLength, startTime, endTime } = data
userConfig = { id, maxTime: singleLength, startTime, endTime }
const nowTime = Date.now()
if (nowTime < startTime || nowTime > endTime) {
  console.log('[未命中配置]-时间未生效')
  return
}
5.开始录制,并存储数据
function record() {
  return rrweb.record({
    checkoutEveryNth: 100,
    emit(event, isCheckout) {
      if (isCheckout) {
        // 保存数据
        saveEvents()
        events = []
      }
      // 临时存储
      events.push(event)
    },
  })
}

6. 超出录制时长,立刻停止,并上报数据

// 停止录播 - 时间限制
sumSecondTimeout = setTimeout(() => {
  // 停止录播
  stopRecord()
}, maxTime * 60 * 1000)
// 上报数据
http(
    'url',
    {
      jsonListObject: events, // 事件数据
    },
    {
      headers: {
        'X-Phone': userPhone,
      },
    }
  )

二、回溯端(B端)

1. 根据手机号获取用户的录制数据(events)
2. 引入rrweb播放端
import rrwebPlayer from 'rrweb-player';
import 'rrweb-player/dist/style.css';

new rrwebPlayer({
  target: videoRef.current, // 可以自定义 DOM 元素
  // 配置项
  props: {
    events,
  },
});

用户录制端之所以要设置这么多条件,在于C端设备复杂(性能好坏会影响录制);为了保证用户体验,需要在尽量不干扰用户操作的前提下去录制。