0


vue项目前端通用埋点方案

埋点方案主要流程

1、 在 main.js 文件中生成 capol-log-uuid 埋点会话唯一id,并存入sessionStorage

router.afterEach((to, from, next)=>{//优先取url上面携带的埋点idconst uuid = to.query.logId ? to.query.logId : Utils.uuid()
    console.log('进入页面,生成回话id')
    sessionStorage.setItem('capol-log-uuid',uuid)})

2、在 utils 文件夹下添加 commonLog.js 公共埋点方法类,提供3个方法:

  1. 添加埋点函数:CapolLog.pointAdd(dynamicInfo, el)
  2. 更新埋点函数:CapolLog.pointUpdate(id, type,updateData)
  3. 更新埋点辅助函数:CapolLog.pointUpdateHelper(event,operateResultBool)

3、封装v-capol-log指令,监听元素点击事件,触发埋点

//通用按钮埋点指令
Vue.directive('capol-log', {
    inserted(el, binding) {
        //按钮点击执行事件
        const handleClick = (el, binding) => {
            //修饰符
            const idFlag = binding.modifiers.idFlag ? 1 : 0;
            //绑定值
            const data = binding.value
            //埋点外部传参对象
            const dynamicInfo = { idFlag, ...data }
            CapolLog.pointAdd(dynamicInfo,el)
        }
        const wrappedClickEvent = function (event) {
            handleClick(el, binding, event)
        }
        el.addEventListener('click', Utils.debounce(wrappedClickEvent, 300))
        el.handleClick = handleClick
    },
    unbind(el, binding) {
        const handleClick = el.handleClick
        el.removeEventListener('click', handleClick)
        delete el.handleClick
    },
})

4、将埋点公共方法添加到Vue.prototype原型对象中,手动调用,触发埋点

        startTask(event) {
            //模拟接口响应时间2s
            setTimeout(() => {
                this.$CapolLog
                    .pointUpdateHelper(event, true)
                    .then((res) => {
                        console.log(res)
                    })
                    .catch((error) => {
                        console.error(error)
                    })
            }, 2000)
            this.getMajorData()
            this.showStartTaskDialog = true
        },

埋点接口传参说明

添加埋点参数

字段是否必填备注说明source是来源端functionType是功能类型logType是日志类型info是埋点基本信息uuid是回话唯一值menuCode否菜单编码buttonName否(点击按钮为必填)按钮名称(应该带上下文)privateData是私有参数json字符串idFlag是id值是否需要返回,后续用于更新

更新埋点参数

字段是否必填备注说明functionType是功能类型(和添加埋点时传参保持一致)updateData是更新埋点参数json字符串(必须包含id字段,其他为更新参数)

部分参数枚举说明
functionType(功能类型)

功能类型key功能类型val0按钮点击1页面初始2文件下载3文件浏览4文件分享5文件上传6选择模板7进度浏览8管控事件9图模关联10问题导出

logType(日志类型)

功能类型key功能类型val0工具埋点点击1框架埋点初始2文件项目文件下载3文件分享文件下载4管控文件下载5项目文件浏览6分享文件浏览7管控文件浏览8图纸文件浏览9项目文件分享10项目文件上传11管控文件上传12选择模板埋点13进度浏览埋点14进度管控埋点15图模关联埋点16问题导出埋点

source(来源端)

来源key来源Val0pc1android2ios3wx4Capol3D5Capol2D

指令埋点详细说明

实现方案

1、在需要埋点的元素上绑定 v-capol-log 指令,监听元素点击事件,当元素点击时,自动触发添加埋点方法,如果 v-capol-log 修饰符idFlag为true,在添加埋点成功后,在该点击元素上添加capol-log-element 类名、data-id(记录此次埋点id)、data-type(记录此次埋点类型)

<buttontype="button"class="el-button el-button--default el-button--small is-plain capol-log-element"data-id="1929582931271722"data-type="按钮点击">发起审批任务</span></button>

2、在点击事件相关业务执行完毕后,通过点击事件的event对象拿到元素上记录的埋点id、埋点类型type,将操作结果(‘“操作成功” || “操作失败”)作为更新参数作为updateData参数,调用CapolLog.pointUpdate(id, type,updateData)更新埋点方法实现埋点更新。后台将根据初次埋点时间、更新埋点时间,计算出****此次点击事件的响应时间responseTime

使用方案

1、绑定指令

            <el-button
                v-capol-log.idFlag="{
                    functionType: 0,
                    logType: 0,
                    buttonName: '发起审批任务-成功审查',
                    privateData: { functionName: '发起审批任务', menuName: '成果审查',projectId:123,enterpriseId:456 },
                }"
                plain
                @click="startTask"
                >发起审批任务
            </el-button>

指令传参说明:
字段是否必填备注说明idFlag否指令修饰符,后续需要更新埋点必传functionType是功能类型,根据枚举说明表传对应下标即可(eg:按钮点击传0)logType是日志类型,根据枚举说明表传对应下标即可(eg:工具埋点点击传0)buttonName是按钮名称,需要带上下文(eg:发起审批任务-成功审查)privateData是私有参数对象,functionName(按钮名称)、menuName(菜单名称)这两个字段必传,其他字段按需传递即可menuCode否菜单编码,不传优先取左侧导航栏高亮菜单code,取不到取当前路由code
2、点击事件业务执行完毕后,调用this.$CapolLog.pointUpdateHelper(event,operateResultBool)更新埋点(如果需要)

        startTask(event) {
            //模拟接口响应时间2s
            setTimeout(() => {
                this.$CapolLog
                    .pointUpdateHelper(event, true)
                    .then((res) => {
                        console.log(res)
                    })
                    .catch((error) => {
                        console.error(error)
                    })
            }, 2000)
            this.getMajorData()
            this.showStartTaskDialog = true
        },

页面初始埋点详细说明

待后续更新…

主要实现代码

commonLog.js(通用埋点方法)
import API from '../api'
import router from '../router'
import Utils from './utils'
import store from '../store'
import { getDeviceInfo } from './getDeviceInfo'

// 获取功能类型
function getFunctionType(val) {
    const List = {
        0: '按钮点击',
        1: '页面初始',
        2: '文件下载',
        3: '文件浏览',
        4: '文件分享',
        5: '文件上传',
        6: '选择模板',
        7: '进度浏览',
        8: '管控事件',
        9: '图模关联',
        10: '问题导出',
    }
    return List[val] || ''
}

// 获取日志类型
function getLogType(val) {
    const List = {
        0: '工具埋点点击',
        1: '框架埋点初始',
        2: '项目文件下载',
        3: '分享文件下载',
        4: '管控文件下载',
        5: '项目文件浏览',
        6: '分享文件浏览',
        7: '管控文件浏览',
        8: '图纸文件浏览',
        9: '项目文件分享',
        10: '项目文件上传',
        11: '管控文件上传',
        12: '选择模板埋点',
        13: '进度浏览埋点',
        14: '进度管控埋点',
        15: '图模关联埋点',
        16: '问题导出埋点',
    }
    return List[val] || ''
}

// 获取来源端
// function getScource(val) {
//     const List = {
//         0: 'pc', //WEB端
//         1: 'android', //安卓端
//         2: 'ios', //苹果端
//         3: 'wx', //小程序端
//         4: 'Capol3D', //速建端
//         5: 'Capol2D', //速绘端
//     }
//     return List[val] || ''
// }

// 获取基本埋点信息
function getBasicInfo() {
    const basicInfo = getDeviceInfo(null, router.history.current)
    console.log(basicInfo, 'basicInfo')
    return basicInfo
}

//获取回话唯一id
function getUUID() {
    let uuid = sessionStorage.getItem('capol-log-uuid')
    if (!uuid) {
        uuid = Utils.uuid()
        sessionStorage.setItem('capol-log-uuid', uuid)
    }
    return uuid
}

//按照后台要求 将对象转成json字符串
function getJSONObj(obj) {
    if (typeof obj === 'object' && obj !== null) {
        return JSON.stringify(obj).replace(/"/g, "'")
    } else {
        return ''
    }
}

// 扁平化系统菜单数组
function flatterArray(arr, finalArr = []) {
    if (arr.length === 0) return finalArr
    for (let i = 0; i < arr.length; i++) {
        const item = arr[i]
        if (item.children && item.children.length) {
            flatterArray(item.children, finalArr)
        } else {
            finalArr.push(item)
        }
    }
    return finalArr
}

//获取菜单code
function getMenuCode() {
    //默认取路由名称
    let code = router.currentRoute.name || ''
    let menuList = store.getters.menuList || []
    if (menuList.length === 0) {
        const queryObj = Utils.getURLParameters(decodeURIComponent(window.location.href))
        const { proId, enterpriseId } = queryObj
        menuList = JSON.parse(localStorage.getItem('pro_menu_list_' + proId + '_' + enterpriseId))
    }
    //从系统菜单列表中取code
    if (menuList.length) {
        const flatterMenuList = flatterArray(menuList)
        const activeMenuText = document.querySelector(
            '.sidebar-el-menu .el-menu-item.is-active .item span'
        )?.innerHTML
        const activeMenu = flatterMenuList.find((el) => el.title === activeMenuText)
        if (activeMenu) {
            code = activeMenu.code
        }
    }
    return code
}

//埋点方法类
export default class CapolLog {
    /**
     * 通用添加埋点函数
     * @param dynamicInfo 添加埋点的参数 (必填)
     * @param dynamicInfo 必填项说明:functionType(功能类型);logType(日志类型);privateData(埋点私有参数);idFlag(是否需要后台返回此次埋点id,用于后续更新)
     * @param el dom元素,如果有传,将往dom元素上添加埋点信息 (非必填)
     * @returns {Promise} 添加埋点的状态
     */
    static pointAdd = (dynamicInfo, el) => {
        let { functionType, source, logType, menuCode, buttonName, privateData, idFlag } =
            dynamicInfo
        const params = {
            source: source || 'pc', //来源端
            functionType: getFunctionType(functionType), //功能类型
            logType: getLogType(logType), //日志类型
            info: getJSONObj(getBasicInfo()), //埋点基本信息
            uuid: getUUID(), //回话唯一值
            menuCode: menuCode || getMenuCode(), //菜单编码 (非必填)
            buttonName, //按钮名称
            //私有参数json字符串
            privateData: getJSONObj(privateData),
            idFlag: idFlag || 0, //id值是否需要返回
        }
        return new Promise((resolve, reject) => {
            API.log
                .capolAddLog(params)
                .then((res) => {
                    if (res.status === 200) {
                        if (res.data && el) {
                            el.classList.add('capol-log-element')
                            el.setAttribute('data-id', res.data)
                            el.setAttribute('data-type', getFunctionType(functionType))
                        }
                        resolve(res)
                    } else {
                        reject(res)
                    }
                })
                .catch((error) => {
                    reject(error)
                })
        })
    }
    /**
     * 更新埋点通用函数
     * @param id 此次需要更新的埋点id (必填)
     * @param type 功能类型 eg('按钮点击') (必填)
     * @param updateData 更新的私有参数 (必填)
     * @returns {Promise} 返回更新埋点的状态
     */
    static pointUpdate = (id, type, updateData) => {
        const params = {
            functionType: type,
            updateData: getJSONObj({
                id,
                ...updateData,
            }),
        }
        return new Promise((resolve, reject) => {
            API.log
                .capolUpdateLog(params)
                .then((res) => {
                    if (res.status === 200) {
                        resolve(res)
                    } else {
                        reject(res)
                    }
                })
                .catch((error) => {
                    reject(error)
                })
        })
    }
    /**
     * 按钮点击更新埋点辅助函数
     * @param event 点击事件的 event 对象 (必填)
     * @param operateResultBool 点击事件的操作结果 true || false (必填)
     * @returns {updatePromise} 返回更新埋点的状态
     */
    static pointUpdateHelper = async (event, operateResultBool) => {
        if (!event || operateResultBool === undefined) {
            return Promise.reject(new Error('更新埋点参数缺失'))
        }
        const updateData = {
            operateResult: operateResultBool ? '操作成功' : '操作失败',
        }
        console.log(event?.target.closest('.capol-log-element'))
        const targetBtn = event?.target.closest('.capol-log-element')
        //返回更新埋点的状态
        let updatePromise
        if (targetBtn) {
            const id = targetBtn.dataset.id
            const type = targetBtn.dataset.type
            updatePromise = await this.pointUpdate(id, type, updateData)
        } else {
            updatePromise = Promise.reject(new Error('获取不到更新埋点id'))
        }
        return updatePromise
    }
}

本文转载自: https://blog.csdn.net/Y_seaboy/article/details/134839137
版权归原作者 UpUp_seaboy 所有, 如有侵权,请联系我们删除。

“vue项目前端通用埋点方案”的评论:

还没有评论