rrweb记录用户操作(转为txt文档上传阿里云)前端代码

需求:保险购买页面新需求: 为了避免纠纷,需要记录用户操作。
使用rrweb插件记录用户操作的events,并转为txt文档上传阿里云指定文件夹。

目录

  1. rrweb简单介绍
  2. rrweb引入
  3. rrweb记录行为
  4. 保存录制内容,转为txt文档并上传阿里云
  5. rrweb回放
  6. 踩坑的地方

一、rrweb 简单介绍

官方介绍:rrweb – record and replay the web,利用现代浏览器所提供的强大 API 录制并回放任意 web 界面中的用户操作。
rrweb是前端js,可以将⻚⾯中的 DOM 以及⽤户操作保存为可序列化的数据,以实现远程回放的一款实用插件。常用于记录用户操作行为,起到监控、回溯、用户行为分析的作用。
项目官网 https://github.com/rrweb-io/rrweb

二、rrweb引入

  • 直接通过script引入
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.css"
/>
// 或者
<script src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"></script>
  • npm安装
npm install --save rrweb

三、rrweb记录行为

// 引入record
    <script src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/record/rrweb-record.min.js"></script>
let events = [];
// 页面刷新开始录制
$(window).ready(function () {
startRecord() 
})
// 开始录制
function startRecord() {
            let self = this;
            // 这里是连接两个页面存在本地的,如果只有一个页面可以忽略这里的判断
            if(!window.sessionStorage.getItem('events') || window.sessionStorage.getItem('events')=='') {
                events = []
            } else {
                events = JSON.parse(window.sessionStorage.getItem('events'));
            }
            window.sessionStorage.removeItem('events');
            // 开始录制
            rrweb.record({
                emit(event) {
                    events.push(event);
                },
                sampling: {
                    // 定义不录制的鼠标交互事件类型,可以细粒度的开启或关闭对应交互录制
                    mouseInteraction: false,
                    mousemove: true,
                    scroll: 150, // 每 150ms 最多触发一次
                    // 设置输入事件的录制时机
                    input: 'last' // 连续输入时,只录制最终值
                },
            });
        }

// 停止录制(实际上没用到 ,因为提交订单之后页面跳转了)
let stopFn = rrweb.record({
  emit(event) {
    if (events.length > 100) {
      // 当事件数量大于 100 时停止录制
      stopFn();
    }
  },
});

四、保存录制内容,转为txt文档并上传阿里云

// 保存功能(在提交订单的时候触发)
function saveMyrecord(callback) {
            if(!events || events.length == 0){return;}
            const body = JSON.stringify(events);
            events = [];
            var url = '';
            var credit = {!! json_encode($sts_info->Credentials) !!};
            webUploadTxt(body,credit,function(res) {
            // 获取到阿里云txt储存地址(链接)
                url = res;
                callback(url)
            });
        }
// 在调用的时候,异步使用url ,上传至后台储存订单信息的接口。

/*
 * 上传txt
 * */
function webUploadTxt(_this, cred,successCallback) {
    let files = _this;
    webUpTxtToAli(files, cred,function (data) {
        if (successCallback && (typeof successCallback) === 'function') {
            successCallback(data);
        }
    });

}

/*
 * 上传TXT到阿里云
 * */
function webUpTxtToAli(file, cred,callbackFuc) {
    let bucket = $('meta[name="bucket_id"]').attr('content'),
        date = new Date(),
        _token = $('meta[name="csrf-token"]').attr('content'),
        client = void 0;
   // 生成随机链接
    let storeAs = '储存地址/' + date.format('yyyy-MM-dd_hh.mm.ss') + '-' + Math.round(Math.random()*1000000) + '-' + hex_md5(_token) + '.txt' ;
    if (localStorage.Credentials && new Date(JSON.parse(localStorage.Credentials).Expiration).getTime() > new Date().getTime()) { // Credentials.Expiration 过期时间
        let Credentials = JSON.parse(localStorage.Credentials);
        client = new OSS({
            accessKeyId: Credentials.AccessKeyId,
            accessKeySecret: Credentials.AccessKeySecret,
            stsToken: Credentials.SecurityToken,
            region: 'oss-cn-hangzhou',
            bucket: bucket
        });
    } else {
        localStorage.Credentials = JSON.stringify(cred);
        client = new OSS({
            accessKeyId: cred.AccessKeyId,
            accessKeySecret: cred.AccessKeySecret,
            stsToken: cred.SecurityToken,
            region: 'oss-cn-hangzhou',
            bucket: bucket
        });
    }
    var fileArr = [];
    fileArr.push(file);
    // 转为blob对象储存
    var result = new Blob(fileArr, {type: 'text/plain'});
    client
        .put(storeAs, result)
        .then(function (res) {
            if (callbackFuc && (typeof callbackFuc) === 'function') {
                callbackFuc(res.url)
            }
        })
        .catch(function (err) {
            console.log(err);
        });

}
// 这样我们就可以根据订单号获取用户操作记录的url地址。

五、rrweb回放

  • 引入rrweb回放插件
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/style.css"/>
   <script src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"></script>
   <script src="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/index.js"></script>
  • 获取events
var events = [];
    let url = {!! json_encode($data_path) !!};  // 获取后台返回的储存的url地址。
    // 将地址转为内容,地址是 http://blablabla.txt
    function urlToBlob() {
        let xhr = new XMLHttpRequest();
        xhr.open("get", url, true);
        xhr.responseType = "blob";
        xhr.onload = function () {
            if (this.status == 200) {
                console.log(this.response);
                const reader = new FileReader();
                reader.onload = function () {
                    events = JSON.parse(reader.result);
                    // 回放
                    new rrwebPlayer({
                        target: document.body, // 可以自定义 DOM 元素
                        data: {
                            events,
                        }
                    });
                };
                reader.readAsText(this.response);
            }
        };
        xhr.send();
    }
    urlToBlob();

六、踩坑的地方

  • 使用定时器?
    在接到新需求的时候,查阅了很多博客,里面关于rrweb记录的代码很简洁,很多提到了使用定时器进行储存。例如:
    在这里插入图片描述
    这里作者尝试之后,踩雷。发现这样每隔多少秒存一次的方法,会造成大量数据冗余。因为rrweb记录的时候,会首先记录页面内容,而不是操作。页面的dom元素很多,很复杂的情况下,定时记录,会产生大量数据。
    解决方法是:一个页面一次记录就可以,页面跳转的时候就会结束录制,保存的数据会小很多。

  • 跳转多个页面?
    需求里面页面跳转了三个页面,记录的时候也是需要记录下来多个页面的操作记录。例如(第一个页面选择保险方案,跳转到填写投保人被保险人信息页面提交订单。)
    解决方法:
    在跳转之前可以本地储存events数据,另一个页面记录之前先将events赋值。但是这里还是有个bug,,如果是跳转到提交订单页面的时候,需要返回上一个页面,这样记录的话,由于最后一个页面操作数据过多,本地储存不了,会报错。(也可以跳转回前一个页面的时候重新开始记录。)

  • 储存方式?
    储存方式,刚开始想的是直接将数据存在后台数据库,尝试了几次,发现数据量过大,数据字段过长,因此放弃。
    解决方法:
    查阅其他码哥做法之后,采用先将这些数据转为txt文档之后储存在阿里云。获取的时候直接根据阿里云返回的txt地址,获取到文档内容,进而进行播放。

  • 回放报错?
    当events数据只有两条的时候会报错,数据不能低于两条。
    当浏览器地址是https开头的时候会跨域报错,改成http就行。(因为服务器没有配置SSL证书,只能通过http请求,这里看服务器配置的是哪个。)
    在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
rrweb可以通过以下步骤记录canvas: 1. 在页面中引入rrweb库。 2. 对canvas进行事件监听,例如鼠标点击、移动等事件。 3. 在监听到事件时,使用rrweb提供的API记录事件信息。 4. 当需要回放记录的canvas时,使用rrweb提供的回放功能,将记录的事件逐一播放。 以下是一个基本的示例代码: ```javascript import { addCustomEvent } from 'rrweb'; const canvas = document.querySelector('canvas'); let isRecording = false; let events = []; function startRecording() { isRecording = true; addCustomEvent(canvas, 'mousedown', (e) => { events.push({ type: 'mousedown', timestamp: Date.now(), x: e.clientX, y: e.clientY, }); }); addCustomEvent(canvas, 'mousemove', (e) => { events.push({ type: 'mousemove', timestamp: Date.now(), x: e.clientX, y: e.clientY, }); }); } function stopRecording() { isRecording = false; } function playRecording() { let i = 0; const intervalId = setInterval(() => { const event = events[i]; if (event) { const { type, x, y } = event; switch (type) { case 'mousedown': // 在canvas上模拟鼠标点击事件 break; case 'mousemove': // 在canvas上模拟鼠标移动事件 break; default: break; } i++; } else { clearInterval(intervalId); } }, 10); } ``` 在该示例中,我们使用addCustomEvent函数为canvas添加了mousedown和mousemove事件的监听器,并在监听到事件时记录了事件的类型、时间戳、鼠标位置等信息。当需要回放记录时,我们遍历记录的事件数组,并模拟对应的鼠标事件。需要注意的是,由于canvas的绘制是依靠JavaScript代码实现的,因此需要根据具体的业务逻辑进行模拟。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值