Commit 185027a0 by yuzhenWang

切换分支

parent cca1d392
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
import api from './api/api'; import api from './api/api';
import {hshare} from '@/util/fiveshare'; import {hshare} from '@/util/fiveshare';
import dataHandling from "@/util/dataHandling"; import dataHandling from "@/util/dataHandling";
import { useTracker, syncTrackerFromQuery } from '@/util/tracker/index.js'
export default { export default {
data() { data() {
return { return {
...@@ -14,8 +18,10 @@ ...@@ -14,8 +18,10 @@
loginType:'' loginType:''
} }
}, },
onLaunch: function() { onLaunch: function(options) {
console.log('App Launch'); console.log('App Launch');
//操作日志上传:宿主 webview 外链带过来的 trackerSessionId / trackerVisitorCode 优先
syncTrackerFromQuery((options && options.query) || {})
if(uni.getStorageSync('loginType')){ if(uni.getStorageSync('loginType')){
this.loginType = uni.getStorageSync('loginType') this.loginType = uni.getStorageSync('loginType')
} }
...@@ -85,6 +91,7 @@ ...@@ -85,6 +91,7 @@
}, },
onHide: function() { onHide: function() {
console.log('App Hide') console.log('App Hide')
useTracker()?.flush(true) // 切后台立即上报
}, },
methods: { methods: {
......
import App from './App'; import App from './App';
import { scrmUrl } from "./environments/environment";
import { initTracker, trackerMixin } from '@/util/tracker/index.js'
import pagesJson from '@/pages.json'
import {
EVENTS, FUNCTIONS, MODULES,
buildTrackParams
} from '@/util/tracker/track-events'
// ====== 构建期直接从 pages.json 生成模块映射(一次执行,运行时零开销)======
function buildModuleMap() {
const map = {}
// // #ifndef VUE3 function add(path, meta = {}, title = '') {
// import Vue from 'vue' if (!path) return
// App.mpType = 'app' const key = path[0] === '/' ? path : '/' + path
// const app = new Vue({ map[key] = {
// ...App moduleCode: meta.moduleCode || '',
// }) moduleName: meta.moduleName || meta.moduleCode || '',
title: title || ''
}
}
function processPages(pages, root = '') {
(pages || []).forEach((page) => {
const style = page.style || {}
const prefix = root ? (root.endsWith('/') ? root : root + '/') : ''
add(prefix + (page.path || ''), style.meta || {}, style.navigationBarTitleText)
})
}
try {
processPages(pagesJson.pages)
;(pagesJson.subPackages || []).forEach((sub) => {
processPages(sub.pages, sub.root || '')
})
} catch (e) {
console.warn('[Tracker] 构建页面模块映射失败:', e)
}
return map
}
// #ifndef VUE3
import Vue from 'vue'
App.mpType = 'app'
// Vue 2 全局挂载操作日志
const trackerVue2 = initTracker({
enabled: true,
projectCode: 'CFFP',
api: `${scrmUrl}/scrm-api/log/client/batch/save`,
pageMetaMap: buildModuleMap() // ← 注入 pages.json 映射表
})
// app.$mount() Vue.mixin(trackerMixin) // 三端通用:页面级自动采集
// // #endif // 业务统一入口:传 funcCode 即可
Vue.prototype.$trackFunc = (funcCode, extra = {}, overrides = {}) =>
trackerVue2.trackFunc(funcCode, extra, overrides)
// 完全自定义入口
Vue.prototype.$track = (eventCode, params = {}) =>
trackerVue2.track(Object.assign({ eventCode }, params))
// 常量暴露,业务代码免 import
Vue.prototype.$EVENTS = EVENTS
Vue.prototype.$FUNCTIONS = FUNCTIONS
Vue.prototype.$MODULES = MODULES
const app = new Vue({
...App
})
app.$mount()
// #endif
// #ifdef VUE3 // #ifdef VUE3
import { createSSRApp } from 'vue' import { createSSRApp } from 'vue'
export function createApp() { export function createApp() {
const app = createSSRApp(App) const app = createSSRApp(App)
const tracker = initTracker({
enabled: true, // 操作日志上报给后端的全局开关,
projectCode: 'CFFP',
api: `${scrmUrl}/scrm-api/log/client/batch/save`,
pageMetaMap: buildModuleMap() // ← 注入 pages.json 映射表
})
app.mixin(trackerMixin) // 三端通用:页面级自动采集
// 业务统一入口:传 funcCode 即可
app.config.globalProperties.$trackFunc = (funcCode, extra = {}, overrides = {}) =>
tracker.trackFunc(funcCode, extra, overrides)
// 完全自定义入口
app.config.globalProperties.$track = (eventCode, params = {}) =>
tracker.track(Object.assign({ eventCode }, params))
// 常量暴露,业务代码免 import
app.config.globalProperties.$EVENTS = EVENTS
app.config.globalProperties.$FUNCTIONS = FUNCTIONS
app.config.globalProperties.$MODULES = MODULES
return { return {
app app
} }
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
"path": "pages/index/index", "path": "pages/index/index",
"style": { "style": {
"topWindow": false, "topWindow": false,
"navigationBarTitleText": "银盾家办" "navigationBarTitleText": "银盾家办",
"meta": { "moduleCode": "home", "moduleName": "首页" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -12,7 +13,8 @@ ...@@ -12,7 +13,8 @@
"path": "components/login/login", "path": "components/login/login",
"style": { "style": {
"topWindow": false, "topWindow": false,
"navigationBarTitleText": "银盾家办" "navigationBarTitleText": "银盾家办",
"meta": { "moduleCode": "login", "moduleName": "登录" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -20,7 +22,8 @@ ...@@ -20,7 +22,8 @@
"path": "pages/courselist/courselist", "path": "pages/courselist/courselist",
"style": { "style": {
"topWindow": false, "topWindow": false,
"navigationBarTitleText": "银盾家办" "navigationBarTitleText": "银盾家办",
"meta": { "moduleCode": "product", "moduleName": "产品中心" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -29,9 +32,8 @@ ...@@ -29,9 +32,8 @@
"style": { "style": {
"navigationBarTitleText": "产品详情", "navigationBarTitleText": "产品详情",
"enablePullDownRefresh": false, "enablePullDownRefresh": false,
"app-plus": { "app-plus": { "softinputMode": "adjustResize" },
"softinputMode": "adjustResize" "meta": { "moduleCode": "product", "moduleName": "产品详情" }
}
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -39,7 +41,8 @@ ...@@ -39,7 +41,8 @@
"path": "pages/product/product", "path": "pages/product/product",
"style": { "style": {
"navigationBarTitleText": "SFP", "navigationBarTitleText": "SFP",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "tools", "moduleName": "金融工具" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -47,7 +50,8 @@ ...@@ -47,7 +50,8 @@
"path": "pages/shareFriend/shareFriend", "path": "pages/shareFriend/shareFriend",
"style": { "style": {
"navigationBarTitleText": "分享好友", "navigationBarTitleText": "分享好友",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "share", "moduleName": "分享好友" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -55,7 +59,8 @@ ...@@ -55,7 +59,8 @@
"path": "pages/personalCenter/personalCenter", "path": "pages/personalCenter/personalCenter",
"style": { "style": {
"navigationBarTitleText": "我的", "navigationBarTitleText": "我的",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "user", "moduleName": "个人中心" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -63,7 +68,8 @@ ...@@ -63,7 +68,8 @@
"path": "pages/announcement/announcement", "path": "pages/announcement/announcement",
"style": { "style": {
"navigationBarTitleText": "公告列表", "navigationBarTitleText": "公告列表",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "announcement", "moduleName": "公告列表" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -71,7 +77,8 @@ ...@@ -71,7 +77,8 @@
"path": "pages/announcement/announcement_detail", "path": "pages/announcement/announcement_detail",
"style": { "style": {
"navigationBarTitleText": "公告详情", "navigationBarTitleText": "公告详情",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "announcement", "moduleName": "公告详情" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -79,7 +86,8 @@ ...@@ -79,7 +86,8 @@
"path": "pages/systemMsg/system_msg", "path": "pages/systemMsg/system_msg",
"style": { "style": {
"navigationBarTitleText": "消息列表", "navigationBarTitleText": "消息列表",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "message", "moduleName": "消息列表" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -87,7 +95,8 @@ ...@@ -87,7 +95,8 @@
"path": "pages/systemMsg/system_msg_detail", "path": "pages/systemMsg/system_msg_detail",
"style": { "style": {
"navigationBarTitleText": "消息详情", "navigationBarTitleText": "消息详情",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "message", "moduleName": "消息详情" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -96,9 +105,8 @@ ...@@ -96,9 +105,8 @@
"style": { "style": {
"navigationBarTitleText": "申请加盟-基本资料", "navigationBarTitleText": "申请加盟-基本资料",
"enablePullDownRefresh": false, "enablePullDownRefresh": false,
"app-plus": { "app-plus": { "softinputMode": "adjustPan" },
"softinputMode": "adjustPan" "meta": { "moduleCode": "apply", "moduleName": "申请加盟-基本资料" }
}
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -106,7 +114,8 @@ ...@@ -106,7 +114,8 @@
"path": "pages/application-process/work-experience", "path": "pages/application-process/work-experience",
"style": { "style": {
"navigationBarTitleText": "从业经历", "navigationBarTitleText": "从业经历",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "apply", "moduleName": "从业经历" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -114,7 +123,8 @@ ...@@ -114,7 +123,8 @@
"path": "pages/myCertify/myCertify", "path": "pages/myCertify/myCertify",
"style": { "style": {
"navigationBarTitleText": "我的认证", "navigationBarTitleText": "我的认证",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "certify", "moduleName": "我的认证" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -122,7 +132,8 @@ ...@@ -122,7 +132,8 @@
"path": "pages/inviteJoin/inviteJoin", "path": "pages/inviteJoin/inviteJoin",
"style": { "style": {
"navigationBarTitleText": "邀请加盟", "navigationBarTitleText": "邀请加盟",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "invite", "moduleName": "邀请加盟" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -130,7 +141,8 @@ ...@@ -130,7 +141,8 @@
"path": "pages/orderConfirm/orderConfirm", "path": "pages/orderConfirm/orderConfirm",
"style": { "style": {
"navigationBarTitleText": "订单确认", "navigationBarTitleText": "订单确认",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "order", "moduleName": "订单确认" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -138,7 +150,8 @@ ...@@ -138,7 +150,8 @@
"path": "pages/learnCertify/learnCertify", "path": "pages/learnCertify/learnCertify",
"style": { "style": {
"navigationBarTitleText": "学习认证", "navigationBarTitleText": "学习认证",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "certify", "moduleName": "学习认证" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -146,7 +159,8 @@ ...@@ -146,7 +159,8 @@
"path": "pages/authentication-query/authentication-query", "path": "pages/authentication-query/authentication-query",
"style": { "style": {
"navigationBarTitleText": "认证查询", "navigationBarTitleText": "认证查询",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "certify", "moduleName": "认证查询" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -154,7 +168,8 @@ ...@@ -154,7 +168,8 @@
"path": "pages/authentication-query/authentication-result", "path": "pages/authentication-query/authentication-result",
"style": { "style": {
"navigationBarTitleText": "查询结果", "navigationBarTitleText": "查询结果",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "certify", "moduleName": "查询结果" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -162,22 +177,17 @@ ...@@ -162,22 +177,17 @@
"path": "pages/certifyDetail/certifyDetail", "path": "pages/certifyDetail/certifyDetail",
"style": { "style": {
"navigationBarTitleText": "认证详情", "navigationBarTitleText": "认证详情",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "certify", "moduleName": "认证详情" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
// {
// "path": "pages/myLearning/myLearning",
// "style": {
// "navigationBarTitleText": "我的学习",
// "enablePullDownRefresh": false
// }
// },
{ {
"path": "pages/personalCenter/myTeam", "path": "pages/personalCenter/myTeam",
"style": { "style": {
"navigationBarTitleText": "我的团队", "navigationBarTitleText": "我的团队",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "team", "moduleName": "我的团队" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -185,7 +195,8 @@ ...@@ -185,7 +195,8 @@
"path": "pages/personalCenter/myTeamIncubate", "path": "pages/personalCenter/myTeamIncubate",
"style": { "style": {
"navigationBarTitleText": "育成团队", "navigationBarTitleText": "育成团队",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "team", "moduleName": "育成团队" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -193,7 +204,8 @@ ...@@ -193,7 +204,8 @@
"path": "pages/personalCenter/helpCenter", "path": "pages/personalCenter/helpCenter",
"style": { "style": {
"navigationBarTitleText": "帮助中心", "navigationBarTitleText": "帮助中心",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "help", "moduleName": "帮助中心" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -201,7 +213,8 @@ ...@@ -201,7 +213,8 @@
"path": "pages/myShare/myShare", "path": "pages/myShare/myShare",
"style": { "style": {
"navigationBarTitleText": "分享数据", "navigationBarTitleText": "分享数据",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "share", "moduleName": "分享数据" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -209,7 +222,8 @@ ...@@ -209,7 +222,8 @@
"path": "pages/myPoints/myPoints", "path": "pages/myPoints/myPoints",
"style": { "style": {
"navigationBarTitleText": "我的积分", "navigationBarTitleText": "我的积分",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "points", "moduleName": "我的积分" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -217,7 +231,8 @@ ...@@ -217,7 +231,8 @@
"path": "pages/commonDetail/commonDetail", "path": "pages/commonDetail/commonDetail",
"style": { "style": {
"navigationBarTitleText": "明细", "navigationBarTitleText": "明细",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "points", "moduleName": "明细" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -225,7 +240,8 @@ ...@@ -225,7 +240,8 @@
"path": "pages/orderDetail/orderDetail", "path": "pages/orderDetail/orderDetail",
"style": { "style": {
"navigationBarTitleText": "订单详情", "navigationBarTitleText": "订单详情",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "order", "moduleName": "订单详情" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -233,7 +249,8 @@ ...@@ -233,7 +249,8 @@
"path": "pages/afterSales/afterSales", "path": "pages/afterSales/afterSales",
"style": { "style": {
"navigationBarTitleText": "我的售后", "navigationBarTitleText": "我的售后",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "after_sales", "moduleName": "我的售后" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -241,7 +258,8 @@ ...@@ -241,7 +258,8 @@
"path": "pages/afterSaleDetail/afterSaleDetail", "path": "pages/afterSaleDetail/afterSaleDetail",
"style": { "style": {
"navigationBarTitleText": "我的售后", "navigationBarTitleText": "我的售后",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "after_sales", "moduleName": "售后详情" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -249,7 +267,8 @@ ...@@ -249,7 +267,8 @@
"path": "pages/saleCourseLists/saleCourseLists", "path": "pages/saleCourseLists/saleCourseLists",
"style": { "style": {
"navigationBarTitleText": "成交订单", "navigationBarTitleText": "成交订单",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "order", "moduleName": "成交订单" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -257,7 +276,8 @@ ...@@ -257,7 +276,8 @@
"path": "pages/myPoints/pointsDetail", "path": "pages/myPoints/pointsDetail",
"style": { "style": {
"navigationBarTitleText": "积分明细", "navigationBarTitleText": "积分明细",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "points", "moduleName": "积分明细" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -265,7 +285,8 @@ ...@@ -265,7 +285,8 @@
"path": "pages/pointsExchange/pointsStatus", "path": "pages/pointsExchange/pointsStatus",
"style": { "style": {
"navigationBarTitleText": "佣金", "navigationBarTitleText": "佣金",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "commission", "moduleName": "佣金状态" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -273,7 +294,8 @@ ...@@ -273,7 +294,8 @@
"path": "pages/pointsExchange/pointsExchange", "path": "pages/pointsExchange/pointsExchange",
"style": { "style": {
"navigationBarTitleText": "佣金", "navigationBarTitleText": "佣金",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "commission", "moduleName": "佣金" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -281,7 +303,8 @@ ...@@ -281,7 +303,8 @@
"path": "pages/withdrawal/withdrawal", "path": "pages/withdrawal/withdrawal",
"style": { "style": {
"navigationBarTitleText": "兑换提现", "navigationBarTitleText": "兑换提现",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "withdrawal", "moduleName": "兑换提现" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -289,7 +312,8 @@ ...@@ -289,7 +312,8 @@
"path": "pages/exchangeRecord/exchangeRecord", "path": "pages/exchangeRecord/exchangeRecord",
"style": { "style": {
"navigationBarTitleText": "兑换记录", "navigationBarTitleText": "兑换记录",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "withdrawal", "moduleName": "兑换记录" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -297,7 +321,8 @@ ...@@ -297,7 +321,8 @@
"path": "pages/withdrawal/withdrawalDetail", "path": "pages/withdrawal/withdrawalDetail",
"style": { "style": {
"navigationBarTitleText": "提现详情", "navigationBarTitleText": "提现详情",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "withdrawal", "moduleName": "提现详情" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -305,7 +330,8 @@ ...@@ -305,7 +330,8 @@
"path": "pages/taxRules/taxRules", "path": "pages/taxRules/taxRules",
"style": { "style": {
"navigationBarTitleText": "纳税规则", "navigationBarTitleText": "纳税规则",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "tax", "moduleName": "纳税规则" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -313,7 +339,8 @@ ...@@ -313,7 +339,8 @@
"path": "pages/applyDropClass/applyDropClass", "path": "pages/applyDropClass/applyDropClass",
"style": { "style": {
"navigationBarTitleText": "申请退款", "navigationBarTitleText": "申请退款",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "refund", "moduleName": "申请退款" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -321,7 +348,8 @@ ...@@ -321,7 +348,8 @@
"path": "pages/application-process/id-card", "path": "pages/application-process/id-card",
"style": { "style": {
"navigationBarTitleText": "申请加盟-个人证件", "navigationBarTitleText": "申请加盟-个人证件",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "apply", "moduleName": "申请加盟-个人证件" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -329,7 +357,8 @@ ...@@ -329,7 +357,8 @@
"path": "pages/application-process/education", "path": "pages/application-process/education",
"style": { "style": {
"navigationBarTitleText": "申请加盟-学历信息", "navigationBarTitleText": "申请加盟-学历信息",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "apply", "moduleName": "申请加盟-学历信息" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -337,7 +366,8 @@ ...@@ -337,7 +366,8 @@
"path": "pages/application-process/bank-card", "path": "pages/application-process/bank-card",
"style": { "style": {
"navigationBarTitleText": "申请加盟-银行卡号", "navigationBarTitleText": "申请加盟-银行卡号",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "apply", "moduleName": "申请加盟-银行卡号" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -345,7 +375,8 @@ ...@@ -345,7 +375,8 @@
"path": "pages/application-process/personal-statement", "path": "pages/application-process/personal-statement",
"style": { "style": {
"navigationBarTitleText": "申请加盟-个人声明", "navigationBarTitleText": "申请加盟-个人声明",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "apply", "moduleName": "申请加盟-个人声明" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -353,7 +384,8 @@ ...@@ -353,7 +384,8 @@
"path": "pages/application-process/contract", "path": "pages/application-process/contract",
"style": { "style": {
"navigationBarTitleText": "申请加盟-合同文档", "navigationBarTitleText": "申请加盟-合同文档",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "apply", "moduleName": "申请加盟-合同文档" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -362,9 +394,8 @@ ...@@ -362,9 +394,8 @@
"style": { "style": {
"navigationBarTitleText": "申请加盟-电子签名", "navigationBarTitleText": "申请加盟-电子签名",
"enablePullDownRefresh": false, "enablePullDownRefresh": false,
"app-plus": { "app-plus": { "bounce": "none" },
"bounce": "none" "meta": { "moduleCode": "apply", "moduleName": "申请加盟-电子签名" }
}
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -372,7 +403,8 @@ ...@@ -372,7 +403,8 @@
"path": "pages/personalCenter/teamMembers/teamMembers", "path": "pages/personalCenter/teamMembers/teamMembers",
"style": { "style": {
"navigationBarTitleText": "团队成员", "navigationBarTitleText": "团队成员",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "team", "moduleName": "团队成员" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -380,7 +412,8 @@ ...@@ -380,7 +412,8 @@
"path": "pages/personalCenter/teamPerformance/teamPerformance", "path": "pages/personalCenter/teamPerformance/teamPerformance",
"style": { "style": {
"navigationBarTitleText": "团队业绩", "navigationBarTitleText": "团队业绩",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "team", "moduleName": "团队业绩" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -388,7 +421,8 @@ ...@@ -388,7 +421,8 @@
"path": "pages/personalCenter/user-information", "path": "pages/personalCenter/user-information",
"style": { "style": {
"navigationBarTitleText": "个人资料", "navigationBarTitleText": "个人资料",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "user", "moduleName": "个人资料" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -396,7 +430,8 @@ ...@@ -396,7 +430,8 @@
"path": "pages/personalCenter/system/settings", "path": "pages/personalCenter/system/settings",
"style": { "style": {
"navigationBarTitleText": "设置", "navigationBarTitleText": "设置",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "settings", "moduleName": "设置" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -404,7 +439,8 @@ ...@@ -404,7 +439,8 @@
"path": "pages/orderStatus/orderStatus", "path": "pages/orderStatus/orderStatus",
"style": { "style": {
"navigationBarTitleText": "订单支付", "navigationBarTitleText": "订单支付",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "order", "moduleName": "订单支付" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -412,22 +448,17 @@ ...@@ -412,22 +448,17 @@
"path": "pages/dropLists/dropLists", "path": "pages/dropLists/dropLists",
"style": { "style": {
"navigationBarTitleText": "已退课", "navigationBarTitleText": "已退课",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "refund", "moduleName": "已退课" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
// {
// "path": "pages/learningStatistics/learningStatistics",
// "style": {
// "navigationBarTitleText": "学习统计",
// "enablePullDownRefresh": false
// }
// },
{ {
"path": "pages/personalCenter/system/accontsetting", "path": "pages/personalCenter/system/accontsetting",
"style": { "style": {
"navigationBarTitleText": "账号绑定设置", "navigationBarTitleText": "账号绑定设置",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "settings", "moduleName": "账号绑定设置" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -435,7 +466,8 @@ ...@@ -435,7 +466,8 @@
"path": "pages/personalCenter/accountoperation/phonebinding", "path": "pages/personalCenter/accountoperation/phonebinding",
"style": { "style": {
"navigationBarTitleText": "手机号绑定", "navigationBarTitleText": "手机号绑定",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "settings", "moduleName": "手机号绑定" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -443,7 +475,8 @@ ...@@ -443,7 +475,8 @@
"path": "pages/personalCenter/accountoperation/resetpassword", "path": "pages/personalCenter/accountoperation/resetpassword",
"style": { "style": {
"navigationBarTitleText": "重置密码", "navigationBarTitleText": "重置密码",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "settings", "moduleName": "重置密码" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -451,7 +484,8 @@ ...@@ -451,7 +484,8 @@
"path": "pages/personalCenter/accountoperation/confirmResetpassword", "path": "pages/personalCenter/accountoperation/confirmResetpassword",
"style": { "style": {
"navigationBarTitleText": "重置密码", "navigationBarTitleText": "重置密码",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "settings", "moduleName": "确认重置密码" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -459,7 +493,8 @@ ...@@ -459,7 +493,8 @@
"path": "pages/personalCenter/accountoperation/aboutcffp", "path": "pages/personalCenter/accountoperation/aboutcffp",
"style": { "style": {
"navigationBarTitleText": "关于我", "navigationBarTitleText": "关于我",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "about", "moduleName": "关于我" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -467,7 +502,8 @@ ...@@ -467,7 +502,8 @@
"path": "pages/certifyDetail/uploadinformation", "path": "pages/certifyDetail/uploadinformation",
"style": { "style": {
"navigationBarTitleText": "上传信息", "navigationBarTitleText": "上传信息",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "certify", "moduleName": "上传信息" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -475,7 +511,8 @@ ...@@ -475,7 +511,8 @@
"path": "pages/receiptCycleDesc/receiptCycleDesc", "path": "pages/receiptCycleDesc/receiptCycleDesc",
"style": { "style": {
"navigationBarTitleText": "到账周期说明", "navigationBarTitleText": "到账周期说明",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "withdrawal", "moduleName": "到账周期说明" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -483,7 +520,8 @@ ...@@ -483,7 +520,8 @@
"path": "pages/invitationRegister/invitationRegister", "path": "pages/invitationRegister/invitationRegister",
"style": { "style": {
"navigationBarTitleText": "邀请注册", "navigationBarTitleText": "邀请注册",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "invite", "moduleName": "邀请注册" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -491,7 +529,8 @@ ...@@ -491,7 +529,8 @@
"path": "pages/invitationRegister/invitationlogin", "path": "pages/invitationRegister/invitationlogin",
"style": { "style": {
"navigationBarTitleText": "邀请登录", "navigationBarTitleText": "邀请登录",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "invite", "moduleName": "邀请登录" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -499,7 +538,8 @@ ...@@ -499,7 +538,8 @@
"path": "pages/application-process/application-result", "path": "pages/application-process/application-result",
"style": { "style": {
"navigationBarTitleText": "申请加盟-结果", "navigationBarTitleText": "申请加盟-结果",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "apply", "moduleName": "申请加盟-结果" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -507,7 +547,8 @@ ...@@ -507,7 +547,8 @@
"path": "pages/downloadApp/index", "path": "pages/downloadApp/index",
"style": { "style": {
"navigationBarTitleText": "下载", "navigationBarTitleText": "下载",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "download", "moduleName": "下载" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -515,33 +556,40 @@ ...@@ -515,33 +556,40 @@
"path": "pages/product/finance-calculator", "path": "pages/product/finance-calculator",
"style": { "style": {
"navigationBarTitleText": "pages/product/finance-calculator", "navigationBarTitleText": "pages/product/finance-calculator",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "tools", "moduleName": "理财计算器" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "components/webview", "path": "components/webview",
"style": {}, "style": {
"meta": { "moduleCode": "webview", "moduleName": "WebView" }
},
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "pages/personalCenter/system/cancellation", "path": "pages/personalCenter/system/cancellation",
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "settings", "moduleName": "注销" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "components/clause/clauseIOS", "path": "components/clause/clauseIOS",
"style": {}, "style": {
"meta": { "moduleCode": "clause", "moduleName": "协议" }
},
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "sfp/index/index", "path": "sfp/index/index",
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "sfp", "moduleName": "SFP首页" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -549,7 +597,8 @@ ...@@ -549,7 +597,8 @@
"path": "sfp/housePurchase/housePurchase", "path": "sfp/housePurchase/housePurchase",
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "sfp", "moduleName": "购房计算器" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -557,7 +606,8 @@ ...@@ -557,7 +606,8 @@
"path": "sfp/childEdu/childEdu", "path": "sfp/childEdu/childEdu",
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "sfp", "moduleName": "子女教育计算器" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -565,7 +615,8 @@ ...@@ -565,7 +615,8 @@
"path": "sfp/dataImport/data-import", "path": "sfp/dataImport/data-import",
"style": { "style": {
"topWindow": false, "topWindow": false,
"navigationBarTitleText": "批量数据计算" "navigationBarTitleText": "批量数据计算",
"meta": { "moduleCode": "sfp", "moduleName": "批量数据计算" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -581,7 +632,8 @@ ...@@ -581,7 +632,8 @@
"disableWebSecurity": true, "disableWebSecurity": true,
"allowNavigateToExternalPages": true, "allowNavigateToExternalPages": true,
"webviewDebug": true "webviewDebug": true
} },
"meta": { "moduleCode": "user", "moduleName": "个人详情" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
...@@ -589,10 +641,12 @@ ...@@ -589,10 +641,12 @@
"path": "pages/lanch/index", "path": "pages/lanch/index",
"style": { "style": {
"topWindow": false, "topWindow": false,
"navigationBarTitleText": "启动页" "navigationBarTitleText": "启动页",
"meta": { "moduleCode": "launch", "moduleName": "启动页" }
}, },
"lazyLoad": true "lazyLoad": true
} }
], ],
"subPackages": [ "subPackages": [
{ {
...@@ -601,158 +655,179 @@ ...@@ -601,158 +655,179 @@
{ {
"path": "lawManual/lawManual", "path": "lawManual/lawManual",
"style": { "style": {
"navigationBarTitleText": "CFFP法条摘要" "navigationBarTitleText": "CFFP法条摘要",
"meta": { "moduleCode": "law", "moduleName": "法条摘要" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "videoProject/login", "path": "videoProject/login",
"style": { "style": {
"navigationBarTitleText": "登录" "navigationBarTitleText": "登录",
"meta": { "moduleCode": "video", "moduleName": "视频登录" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "videoProject/videoDetail", "path": "videoProject/videoDetail",
"style": { "style": {
"navigationBarTitleText": "视频播放" "navigationBarTitleText": "视频播放",
"meta": { "moduleCode": "video", "moduleName": "视频播放" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "videoProject/wxLogin", "path": "videoProject/wxLogin",
"style": { "style": {
"navigationBarTitleText": "微信登录" "navigationBarTitleText": "微信登录",
"meta": { "moduleCode": "login", "moduleName": "微信登录" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "applyFranchise/applyFranchise", "path": "applyFranchise/applyFranchise",
"style": { "style": {
"navigationBarTitleText": "申请加盟" "navigationBarTitleText": "申请加盟",
"meta": { "moduleCode": "apply", "moduleName": "申请加盟" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "integralExchange/exchange", "path": "integralExchange/exchange",
"style": { "style": {
"navigationBarTitleText": "积分提现" "navigationBarTitleText": "积分提现",
"meta": { "moduleCode": "points", "moduleName": "积分提现" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "ruleAndContract/taxRules", "path": "ruleAndContract/taxRules",
"style": { "style": {
"navigationBarTitleText": "纳税规则" "navigationBarTitleText": "纳税规则",
"meta": { "moduleCode": "tax", "moduleName": "纳税规则" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "integralExchange/authenticaInfo", "path": "integralExchange/authenticaInfo",
"style": { "style": {
"navigationBarTitleText": "实名认证" "navigationBarTitleText": "实名认证",
"meta": { "moduleCode": "certify", "moduleName": "实名认证" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "setting/logOff", "path": "setting/logOff",
"style": { "style": {
"navigationBarTitleText": "合伙人解约" "navigationBarTitleText": "合伙人解约",
"meta": { "moduleCode": "settings", "moduleName": "合伙人解约" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "ruleAndContract/cancelProtocol", "path": "ruleAndContract/cancelProtocol",
"style": { "style": {
"navigationBarTitleText": "合伙人解约协议" "navigationBarTitleText": "合伙人解约协议",
"meta": { "moduleCode": "contract", "moduleName": "解约协议" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "login/login", "path": "login/login",
"style": { "style": {
"navigationBarTitleText": "银盾家办" "navigationBarTitleText": "银盾家办",
"meta": { "moduleCode": "login", "moduleName": "登录" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "ruleAndContract/clause", "path": "ruleAndContract/clause",
"style": { "style": {
"navigationBarTitleText": "协议" "navigationBarTitleText": "协议",
"meta": { "moduleCode": "contract", "moduleName": "协议" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "poster/poster", "path": "poster/poster",
"style": { "style": {
"navigationBarTitleText": "分销海报" "navigationBarTitleText": "分销海报",
"meta": { "moduleCode": "share", "moduleName": "分销海报" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "myTeam/myTeam", "path": "myTeam/myTeam",
"style": { "style": {
"navigationBarTitleText": "我的团队" "navigationBarTitleText": "我的团队",
"meta": { "moduleCode": "team", "moduleName": "我的团队" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "commission/withdrawalRecord", "path": "commission/withdrawalRecord",
"style": { "style": {
"navigationBarTitleText": "提现记录" "navigationBarTitleText": "提现记录",
"meta": { "moduleCode": "withdrawal", "moduleName": "提现记录" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "compare-result/compare-result", "path": "compare-result/compare-result",
"style": { "style": {
"navigationBarTitleText": "对比结果" "navigationBarTitleText": "对比结果",
"meta": { "moduleCode": "compare", "moduleName": "对比结果" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "product-list/product-list", "path": "product-list/product-list",
"style": { "style": {
"navigationBarTitleText": "产品对比" "navigationBarTitleText": "产品对比",
"meta": { "moduleCode": "product", "moduleName": "产品对比" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "product-list/product-commission", "path": "product-list/product-commission",
"style": { "style": {
"navigationBarTitleText": "产品佣率查询" "navigationBarTitleText": "产品佣率查询",
"meta": { "moduleCode": "commission", "moduleName": "产品佣率查询" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "product-list/commission-detail", "path": "product-list/commission-detail",
"style": { "style": {
"navigationBarTitleText": "佣金详情" "navigationBarTitleText": "佣金详情",
"meta": { "moduleCode": "commission", "moduleName": "佣金详情" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "businessCard/businessCard", "path": "businessCard/businessCard",
"style": { "style": {
"navigationBarTitleText": "我的名片" "navigationBarTitleText": "我的名片",
"meta": { "moduleCode": "card", "moduleName": "我的名片" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "noBusinessCard/noBusinessCard", "path": "noBusinessCard/noBusinessCard",
"style": { "style": {
"navigationBarTitleText": "我的名片" "navigationBarTitleText": "我的名片",
"meta": { "moduleCode": "card", "moduleName": "我的名片" }
}, },
"lazyLoad": true "lazyLoad": true
}, },
{ {
"path": "salary/salaryList", "path": "salary/salaryList",
"style": { "style": {
"navigationBarTitleText": "积分明细" "navigationBarTitleText": "积分明细",
"meta": { "moduleCode": "points", "moduleName": "积分明细" }
}, },
"lazyLoad": true "lazyLoad": true
} }
] ]
}, },
{ {
...@@ -762,7 +837,8 @@ ...@@ -762,7 +837,8 @@
"path": "memberQuery", "path": "memberQuery",
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"meta": { "moduleCode": "member", "moduleName": "会员查询" }
}, },
"lazyLoad": true "lazyLoad": true
} }
...@@ -828,4 +904,4 @@ ...@@ -828,4 +904,4 @@
} }
] ]
} }
} }
\ No newline at end of file
import { EVENTS, normalizeEventCode } from './track-events'
const DOM_EVENT_MAP = {
click: EVENTS.CLICK,
change: EVENTS.INPUT,
blur: EVENTS.INPUT
}
const MAX_NAME_LEN = 40 // 名称最大长度,超出截断
const MAX_CLIMB = 6 // 从 target 向上找可交互 / 有文案元素的最大层数
/** 判断是不是输入类元素 */
function isInputEl(el) {
if (!el) return false
const tag = (el.tagName || '').toLowerCase()
return tag === 'input' || tag === 'textarea' || el.isContentEditable === true
}
/** 是否携带埋点标注(dataset) */
const TRACK_DS_KEYS = ['trackId', 'trackName', 'trackType', 'trackEvent', 'trackExtra', 'func']
function hasTrackDs(el) {
const ds = el.dataset || {}
return TRACK_DS_KEYS.some(k => ds[k])
}
/** 文本归一化:压缩空白、去首尾空格 */
function normText(el) {
if (!el || typeof el.textContent !== 'string') return ''
return el.textContent.replace(/\s+/g, ' ').trim()
}
/** 元素自带的显式命名:data-track-name > aria-label > title */
function attrLabel(el) {
const ds = el.dataset || {}
if (ds.trackName) return ds.trackName
if (!el.getAttribute) return ''
return el.getAttribute('aria-label') || el.getAttribute('title') || ''
}
/** 该元素自身是否"可读"(有显式命名 / 是输入框 / 有短文案)
* 超过 MAX_NAME_LEN 的文本视为"整块内容容器",不作为点击对象,
* 否则会把整页文案拼成 actionTargetName */
function isReadable(el) {
if (!el || el.nodeType !== 1) return false
const tag = (el.tagName || '').toLowerCase()
if (tag === 'html' || tag === 'body') return false
if (isInputEl(el)) return true
if (attrLabel(el)) return true
const t = normText(el)
return !!t && t.length <= MAX_NAME_LEN
}
/** 取元素内第一个短文案后代(用于文案很长的卡片/容器,取标题当名称) */
function firstShortText(el, depth = 3) {
if (!el || depth < 0 || !el.children) return ''
for (const k of el.children) {
if (!k || k.nodeType !== 1) continue
const t = normText(k)
if (t && t.length <= MAX_NAME_LEN) return t
const sub = firstShortText(k, depth - 1)
if (sub) return sub
}
return ''
}
/**
* 可交互元素选择器:
* 覆盖原生标签 + uni-app H5 自定义元素 + vant 组件
*/
const INTERACTIVE_SELECTOR = [
'button', 'a', 'label',
'[role="button"]', '[role="tab"]', '[role="switch"]', '[role="checkbox"]', '[role="radio"]', '[role="option"]',
'uni-button', 'uni-a', 'uni-label', 'uni-checkbox', 'uni-radio', 'uni-switch', 'uni-picker', 'uni-ad',
'van-button', 'van-tab', 'van-cell', 'van-tag', 'van-checkbox', 'van-radio', 'van-switch', 'van-uploader'
].join(', ')
/** 噪音区域:不自动采集(tabbar 导航由 page_view 覆盖;toast / 遮罩无交互意义) */
const NOISE_SELECTOR = 'uni-tabbar, .uni-tabbar, uni-toast, .uni-toast, .uni-sample-toast, .uni-mask, .van-overlay, uni-modal, .uni-modal'
/**
* 从事件路径里找"值得上报"的元素:
* 1. 最内层带 data-track-* 标注的(手动标注优先)
* 2. 从 target 向上最多 6 层找可交互元素(按钮内的 icon/span 点上去归到按钮)
* 3. 兜底:target 自身无文案(纯图标 / 空容器)时,取最近一个有文案的祖先
* 都找不到 → 返回 null(这类点击没有业务含义,报了只会产生 module_uni-view 这种脏数据)
*/
function findTrackEl(e) {
const path = e.composedPath ? e.composedPath() : []
const nodes = path.filter(n => n && n.nodeType === 1)
if (!nodes.length && e.target && e.target.nodeType === 1) nodes.push(e.target)
if (!nodes.length) return null
// 1. 手动标注优先(路径由内向外,取最内层标注元素)
for (const node of nodes) {
if (hasTrackDs(node)) return node
if (node === document.body) break
}
// 2. 向上找可交互元素;同时记录最近一个"可读"元素做兜底
let el = e.target
let readable = null
for (let i = 0; el && el.nodeType === 1 && i < MAX_CLIMB; i++) {
const tag = (el.tagName || '').toLowerCase()
if (tag === 'html' || tag === 'body') break
if (el.matches && el.matches(INTERACTIVE_SELECTOR)) return el
if (!readable && isReadable(el)) readable = el
el = el.parentElement
}
// 3. 兜底:自身或最近有文案的祖先
return readable
}
/**
* 友好名称:data-track-name > placeholder > aria-label > name > 自身上下文 > 最近有文案的祖先
* 全部取不到时返回 '',由调用方丢弃该事件(禁止把标签名当名称上报)
*/
function resolveName(el, tag) {
const ds = el.dataset || {}
if (ds.trackName) return ds.trackName
if (tag === 'input' || tag === 'textarea') {
return el.placeholder
|| el.getAttribute('aria-label')
|| el.name
|| ds.trackId
|| (tag === 'textarea' ? '多行输入框' : '输入框')
}
const label = attrLabel(el)
if (label) return label.slice(0, MAX_NAME_LEN)
// 自身文案
const txt = normText(el)
if (txt && txt.length <= MAX_NAME_LEN) return txt
if (txt) {
// 文案过长(整块内容容器)→ 优先取内部第一个短文案(标题)当名称
const short = firstShortText(el)
if (short) return short
return txt.slice(0, MAX_NAME_LEN)
}
// 自身无文案(纯图标 / 空容器)→ 向上找最近的短文案祖先
let p = el.parentElement
for (let i = 0; p && p.nodeType === 1 && i < MAX_CLIMB; i++) {
const t = normText(p)
if (t && t.length <= MAX_NAME_LEN) return t
p = p.parentElement
}
return ''
}
function buildInfo(el, e) {
const ds = el.dataset || {}
const tag = (el.tagName || '').toLowerCase()
const inputEl = isInputEl(el)
// ---------- 1. actionTargetType ----------
let type = ds.trackType || ''
if (!type) {
if (inputEl) type = 'input'
else if (tag === 'button' || tag === 'uni-button' || (el.classList && el.classList.contains('van-button')) || el.getAttribute('role') === 'button') type = 'button'
else if (tag === 'a' || tag === 'uni-a') type = 'link'
else if (tag === 'img' || tag === 'uni-image') type = 'image'
else if (tag === 'uni-picker' || tag === 'uni-checkbox' || tag === 'uni-radio' || tag === 'uni-switch') type = 'button'
else type = 'module'
}
// ---------- 2. 名称 & ID ----------
const name = resolveName(el, tag)
const id = ds.trackId || el.id || (name ? `${type}_${name.slice(0, 20)}` : '')
// ---------- 3. extraParams ----------
let extraParams = {}
if (ds.trackExtra) {
try { extraParams = JSON.parse(ds.trackExtra) } catch (err) {}
}
if (inputEl) {
// 不采明文,除非显式 data-track-value="true"
if (ds.trackValue === 'true') {
extraParams.value = (el.value || '').slice(0, 200)
} else {
extraParams.valueLen = (el.value || '').length
}
}
// ---------- 4. eventCode ----------
let eventCode = ds.trackEvent || ''
if (!eventCode && !ds.func) {
// ★ 输入框统一走 INPUT 事件(不看 e.type)
eventCode = inputEl ? EVENTS.INPUT : (DOM_EVENT_MAP[e.type] || EVENTS.CLICK)
}
if (eventCode) eventCode = normalizeEventCode(eventCode)
return {
eventCode,
funcCode: ds.func || '',
moduleCode: ds.trackModule || '',
actionTarget: id,
actionTargetType: type,
actionTargetName: name,
extraParams
}
}
export function setupDomCollector(tracker) {
if (typeof document === 'undefined') return
const lastMap = new WeakMap() // 点击去重:元素 → 最后上报时间
const lastVal = new WeakMap() // 输入去重:元素 → 最后上报的值
const dedupe = tracker.cfg.dedupeWindow
// 自动采集未开启(APP/MP 手动模式):只挂页面离开时的兜底上报
if (tracker.cfg.autoClickCapture === false) {
// #ifdef H5
const onLeaveOnly = () => tracker.flushBeacon()
window.addEventListener('beforeunload', onLeaveOnly)
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') onLeaveOnly()
})
// #endif
return
}
const handler = (e) => {
if (!tracker.enabled) return
// ★ 业务显式标注 data-track-manual="true" 的元素/容器,自动采集直接跳过
const path = e.composedPath ? e.composedPath() : []
const isManual = path.some(n => n && n.nodeType === 1 && n.dataset && n.dataset.trackManual === 'true')
|| (e.target && e.target.closest && !!e.target.closest('[data-track-manual="true"]'))
if (isManual) return
// ★ 显式豁免:data-track-ignore="true" 的区域不进埋点
if (e.target && e.target.closest && e.target.closest('[data-track-ignore="true"]')) return
const el = findTrackEl(e)
if (!el) return
// 噪音区域不上报(tabbar 切换有 page_view 覆盖)
if (el.closest && el.closest(NOISE_SELECTOR)) return
const inputEl = isInputEl(el)
// ★★★ 输入框的 click 一律跳过(聚焦/点选不算"操作完成")★★★
if (e.type === 'click' && (inputEl || (el.closest && el.closest('uni-input, uni-textarea, .van-field')))) return
// ★★★ 密码框完全不采集(连长度都不采,避免泄露信息)★★★
if (inputEl && (el.type === 'password' || el.getAttribute('type') === 'password')) return
// ★★★ 输入框只在 blur / change 时上报,且值有变化才报 ★★★
if (inputEl && (e.type === 'blur' || e.type === 'change')) {
const nowVal = el.value || ''
const prevVal = lastVal.get(el)
if (prevVal === nowVal) return // 值没变,不报
lastVal.set(el, nowVal)
}
// 点击类去重窗口(非输入类)
if (!inputEl) {
const now = Date.now()
if (lastMap.get(el) && now - lastMap.get(el) < dedupe) return
lastMap.set(el, now)
}
const info = buildInfo(el, e)
// ★★★ 解析不出任何业务名称(纯装饰元素 / 空容器)→ 直接丢弃,
// 避免产生 actionTarget=module_uni-view 这类无意义数据 ★★★
if (!info.actionTargetName || !info.actionTarget) return
// ★ H5 自动模式防重复:点击延迟一拍上报,
// 若同一 tick 内业务代码调用了手动埋点(trackFunc),则放弃这条自动点击
if (e.type === 'click') {
const seq = tracker._manualSeq || 0
setTimeout(() => {
if (!tracker.enabled) return
if ((tracker._manualSeq || 0) !== seq) return
tracker.track(info)
}, 0)
return
}
tracker.track(info)
}
document.addEventListener('click', handler, true)
document.addEventListener('change', handler, true)
document.addEventListener('blur', handler, true)
// #ifdef H5
const onLeave = () => tracker.flushBeacon()
window.addEventListener('beforeunload', onLeave)
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') onLeave()
})
// #endif
}
import { resolvePageInfo } from './utils'
import { EVENTS, normalizeEventCode } from './track-events'
let _tracker = null
export function bindTracker(t) { _tracker = t }
const MP_EVENT_MAP = {
tap: EVENTS.CLICK,
longpress: EVENTS.CLICK,
change: EVENTS.INPUT,
blur: EVENTS.INPUT,
input: EVENTS.INPUT
}
/** 小程序里判断是不是输入框:靠 dataset 标记或占位符兜底 */
function isInputNode(node) {
if (!node || !node.dataset) return false
const ds = node.dataset
if (ds.trackType === 'input') return true
if (ds.trackInput === 'true') return true
// 兜底:没有 textContent、有 placeholder 的通常是 input
return !node.dataset.trackName && !node.dataset.trackId && false
}
function parseDataset(ds = {}, evtType = 'tap') {
let extraParams = {}
if (ds.trackExtra) {
try { extraParams = JSON.parse(ds.trackExtra) } catch (e) {}
}
let eventCode = ds.trackEvent || ''
if (!eventCode && !ds.func) {
eventCode = MP_EVENT_MAP[evtType] || EVENTS.CLICK
}
if (eventCode) eventCode = normalizeEventCode(eventCode)
return {
eventCode,
funcCode: ds.func || '',
moduleCode: ds.trackModule || '',
actionTargetType: ds.trackType || 'button',
actionTarget: ds.trackId || '',
actionTargetName: ds.trackName || '',
extraParams
}
}
export const trackerMixin = {
onShow() { _tracker && _tracker.enterPage() }, //this
onHide() { _tracker && _tracker.leavePage('hide') },
onUnload() { _tracker && _tracker.leavePage('unload') },
methods: {
__trackTap(e) {
const t = _tracker
if (!t || !t.enabled) return
const ds = (e.currentTarget && e.currentTarget.dataset) || {}
// ★★★ 关键:输入框的 tap 跳过,等 __trackBlur 再上报 ★★★
if (ds.trackType === 'input' || ds.trackInput === 'true') return
// 无任何标注的点击不采集
if (!ds.trackId && !ds.trackName && !ds.trackType && !ds.func) return
t.track(parseDataset(ds, 'tap'))
},
__trackBlur(e) {
const t = _tracker
if (!t || !t.enabled) return
const ds = (e.currentTarget && e.currentTarget.dataset) || {}
const val = (e.detail && e.detail.value) || ''
// ★ 值没变化不报(空点一下再离开)
const key = e.currentTarget
if (!key._trackLastVal === undefined) key._trackLastVal = undefined
if (key._trackLastVal === val) return
key._trackLastVal = val
const info = parseDataset(ds, 'blur')
info.eventCode = EVENTS.INPUT
info.actionTargetType = 'input'
info.actionTargetName = ds.trackName || ds.placeholder || '输入框'
info.extraParams.valueLen = val.length
t.track(info)
},
$trackFunc(funcCode, extra = {}, overrides = {}) {
_tracker && _tracker.trackFunc(funcCode, extra, overrides)
}
}
}
export function setupMpCollector(tracker) { bindTracker(tracker) }
\ No newline at end of file
export default {
enabled: false, // 全局开关(可由后端配置下发动态修改)
projectCode: 'CFFP',
api: '/api/log/batch',
batchSize: 10, // 攒多少条触发上报
maxBatch: 50, // 单次请求最多携带条数
flushInterval: 5000, // 定时上报间隔 ms
maxQueue: 200, // 队列上限
maxRetry: 3, // 失败重试次数
sessionTimeout: 30 * 60 * 1000, // 30 分钟无操作开新会话
sampleRate: 1, // 采样率 0~1
maxExtraSize: 2048, // extraParams 最大字节
dedupeWindow: 300, // 元素去重窗口 ms
initDelay: 800 ,// 延迟初始化 ms
reportPageLeave: false, // ← 是否上报 PAGE_LEAVE(默认 false = 不上报)
keepStayTime: true,// ← 关闭 LEAVE 时,是否把停留时长挂到下一次 PAGE_VIEW
// H5:全自动埋点(点击/输入由 DOM 采集器自动上报,页面无需写任何埋点代码)
// APP / 小程序:无可靠 DOM,维持手动埋点
// #ifdef H5
autoClickCapture: true,
// #endif
// #ifndef H5
autoClickCapture: false,
// #endif
}
\ No newline at end of file
import {
formatTime, getDeviceInfo, detectClientType,
getVisitorCode, genSessionId, safeStringify,
getUrlParam,
STORAGE_KEY_VISITOR, STORAGE_KEY_SESSION,
} from './utils'
// ↓↓↓ 业务事件字典(与 pages.json 模块一一对应)
import {
EVENTS,
getEventByFunction,
getModuleByFunction,
getEventName,
getEventCategory,
getModuleName,
getFunctionName,
normalizeEventCode,
isValidFunction
} from './track-events'
export default class Tracker {
constructor(cfg) {
this.cfg = cfg
this.pageMetaMap = cfg.pageMetaMap || {} // ← 持有映射表
this._enabled = !!cfg.enabled
this.queue = []
this._timer = null
this._flushing = false
this._retry = 0
// 手动埋点序号:每调一次 trackFunc 自增。
// H5 DOM 采集器用它实现「同一 tick 内有手动埋点则放弃自动点击」的去重
this._manualSeq = 0
this.currentPage = { url: '', title: '', moduleCode: '', moduleName: '' }
this.lastPageUrl = ''
this.pageEnterTime = 0 // ← 之前 enterPage 里用到的
// ★★★ 新增:暂存上一次页面停留统计(关闭 PAGE_LEAVE 时用) ★★★
this._lastPageStats = null
// 宿主(webview 外链)同时带入 trackerSessionId + trackerVisitorCode 时,视为宿主控制:
// 两个标识都用宿主的,sessionId 不因空闲超时重新生成
this._hostControlled = !!(getUrlParam('trackerSessionId') && getUrlParam('trackerVisitorCode'))
this.visitorCode = getVisitorCode()
this.sessionId = genSessionId()
this.clientType = detectClientType()
const d = getDeviceInfo()
this.device = d
this.screenResolution = `${d.screenWidth}x${d.screenHeight}`
this.lastActive = Date.now()
}
get enabled() { return this._enabled }
setEnabled(v) {
this._enabled = !!v
if (!this._enabled) this.queue.length = 0
}
/**
* 运行时同步身份标识。
* 用于宿主 webview 通过 URL 带入 trackerSessionId / trackerVisitorCode 的场景:
* 后续 flush 会使用新值(队列里已有的事件也会按新值上报,标识是请求级的)。
*/
setIdentity({ visitorCode = '', sessionId = '' } = {}) {
let changed = false
if (visitorCode && visitorCode !== this.visitorCode) {
this.visitorCode = visitorCode
uni.setStorageSync(STORAGE_KEY_VISITOR, visitorCode)
changed = true
}
if (sessionId && sessionId !== this.sessionId) {
this.sessionId = sessionId
uni.setStorageSync(STORAGE_KEY_SESSION, sessionId)
changed = true
}
// 两个标识同时由宿主传入,才视为宿主控制(与 URL 直读同样待遇)
if (visitorCode && sessionId) this._hostControlled = true
return changed
}
_touchSession() {
const now = Date.now()
// 宿主带入了 trackerSessionId 时会话由宿主控制,空闲超时也不重新生成
if (!this._hostControlled && now - this.lastActive > this.cfg.sessionTimeout) {
this.sessionId = genSessionId(true) // forceNew:强制换新会话,不能读到旧缓存
}
this.lastActive = now
}
setPage(page) {
this.currentPage = resolvePageInfo(page, this.pageMetaMap)
}
/** 兜底:若 mixin onShow 尚未触发(如冷启动立即点击),现场解析一次 */
_ensurePage() {
if (!this.currentPage.url) {
this.currentPage = resolvePageInfo(null, this.pageMetaMap)
}
}
// ============ 页面级:enterPage / leavePage ============
// enterPage(page) {
// if (!this.enabled) return
// this.setPage(page)
// const p = this.currentPage
// if (!p.url) return
// this.pageEnterTime = Date.now()
// this.track({
// eventCode: EVENTS.PAGE_VIEW,
// moduleCode: p.moduleCode, // 页面级用 pages.json meta
// pageUrl: p.url,
// pageTitle: p.title,
// actionTargetType: 'page',
// actionTarget: p.url,
// actionTargetName: p.moduleName || p.title,
// extraParams: {
// moduleName: p.moduleName,
// referrer: this.lastPageUrl || ''
// }
// })
// this.lastPageUrl = p.url
// }
enterPage(page) {
if (!this.enabled) return
this.setPage(page)
const p = this.currentPage
if (!p.url) return
this.pageEnterTime = Date.now()
const stats = this._lastPageStats || {}
this._lastPageStats = null
this.track({
eventCode: EVENTS.PAGE_VIEW,
moduleCode: p.moduleCode,
pageUrl: p.url,
pageTitle: p.title,
actionTargetType: 'page',
actionTarget: p.url,
actionTargetName: p.moduleName || p.title,
extraParams: {
moduleName: p.moduleName,
referrer: this.lastPageUrl || '',
// ③ 上一次页面的停留时长(若开启 keepStayTime)
prevUrl: stats.prevUrl || '',
prevStayMs: stats.prevStayMs || 0
}
})
this.lastPageUrl = p.url
}
// leavePage(reason = 'hide') {
// if (!this.enabled) return
// const p = this.currentPage
// if (p.url) {
// this.track({
// eventCode: EVENTS.PAGE_LEAVE,
// moduleCode: p.moduleCode,
// pageUrl: p.url,
// pageTitle: p.title,
// actionTargetType: 'page',
// actionTarget: p.url,
// actionTargetName: p.moduleName || p.title,
// extraParams: {
// moduleName: p.moduleName,
// stayMs: this.pageEnterTime ? Date.now() - this.pageEnterTime : 0,
// reason
// }
// })
// }
// this.flush(true)
// }
leavePage(reason = 'hide') {
if (!this.enabled) return
const p = this.currentPage
// ① 只有显式开启时才上报 PAGE_LEAVE
if (this.cfg.reportPageLeave && p.url) {
this.track({
eventCode: EVENTS.PAGE_LEAVE,
moduleCode: p.moduleCode,
pageUrl: p.url,
pageTitle: p.title,
actionTargetType: 'page',
actionTarget: p.url,
actionTargetName: p.moduleName || p.title,
extraParams: {
moduleName: p.moduleName,
stayMs: this.pageEnterTime ? Date.now() - this.pageEnterTime : 0,
reason
}
})
} else if (this.cfg.keepStayTime && this.pageEnterTime) {
// ② 不上报 LEAVE,但把停留时长暂存,下一次 PAGE_VIEW 带上
this._lastPageStats = {
prevUrl: p.url,
prevTitle: p.title,
prevStayMs: Date.now() - this.pageEnterTime
}
}
// ③ 无论是否上报 LEAVE,队列都要 flush(避免已采集的点击/输入丢)
this.flush(true)
}
// ============ 核心:track ============
/**
* @param {Object} data
* eventCode? 显式指定(不传则用 funcCode 从 FUNCTION_EVENT_MAP 推导)
* funcCode? FUNCTIONS.* 功能编码(推荐)
* moduleCode? 显式覆盖(不传则用 FUNCTION_MODULE_MAP 或页面 meta)
* actionTarget / actionTargetType / actionTargetName
* extraParams 业务扩展,自动注入 eventName / eventCategory / moduleName / functionName
*/
track(data = {}) {
if (!this._enabled) return
if (this.cfg.sampleRate < 1 && Math.random() > this.cfg.sampleRate) return
this._ensurePage()
this._touchSession()
const page = this.currentPage
const funcCode = data.funcCode || ''
// 开发期校验
// #ifdef H5
if (funcCode && !isValidFunction(funcCode)) {
console.warn('[Tracker] 未在 track-events.js 定义的 funcCode:', funcCode)
}
// 模块归属校验:功能编码与当前页面模块不匹配时告警(防埋点串页面)
const _funcModule = funcCode ? getModuleByFunction(funcCode) : ''
if (_funcModule && page.moduleCode && _funcModule !== page.moduleCode) {
console.warn(`[Tracker] funcCode「${funcCode}」属于模块 ${_funcModule},当前页面为 ${page.moduleCode}`)
}
// #endif
// ---- 1. eventCode:显式 > 功能推导 > 兜底 CLICK ----
let rawEvent = data.eventCode
if (!rawEvent && funcCode) rawEvent = getEventByFunction(funcCode)
const eventCode = normalizeEventCode(rawEvent)
// ---- 2. moduleCode:显式 > 功能推导 > 页面 meta(pages.json)----
let moduleCode = data.moduleCode || ''
if (!moduleCode && funcCode) moduleCode = getModuleByFunction(funcCode) || ''
if (!moduleCode) moduleCode = page.moduleCode || ''
// ---- 3. 名称类 ----
const eventName = getEventName(eventCode)
const eventCategory = getEventCategory(eventCode)
// ★ 页面级 moduleName(如「去风险-健康保障-规划后」)优先,
// 同一 moduleCode 下多页面才不会被模块级名称覆盖
const moduleName = (moduleCode === page.moduleCode && page.moduleName)
? page.moduleName
: (getModuleName(moduleCode) || page.moduleName || '')
const functionName = funcCode ? getFunctionName(funcCode) : ''
// ---- 4. extraParams:业务字段 + 名称注入 ----
let extra = Object.assign({}, data.extraParams || {})
if (eventName && !extra.eventName) extra.eventName = eventName
if (eventCategory&& !extra.eventCategory) extra.eventCategory = eventCategory
if (moduleName && !extra.moduleName) extra.moduleName = moduleName
if (functionName && !extra.functionName) extra.functionName = functionName
if (safeStringify(extra, this.cfg.maxExtraSize) === null) {
extra = { _dropped: 'extra_too_large', eventName, moduleName, functionName }
}
// ---- 5. 组装上报项(严格对齐后端接口字段)----
const item = {
projectCode: data.projectCode || this.cfg.projectCode,
clientCode: data.clientCode || this.clientType,
moduleCode, // ← 模块(pages.json meta.moduleCode)
funcCode, // ← 功能 FUNCTIONS.*
eventCode, // ← 事件 EVENTS.*
pageUrl: data.pageUrl || page.url || '',
pageTitle: data.pageTitle || page.title || moduleName || '',
actionTarget: data.actionTarget || '',
actionTargetType: data.actionTargetType || '',
actionTargetName: data.actionTargetName || functionName || '',
screenResolution: this.screenResolution,
extraParams: extra,
eventTime: formatTime(Date.now()),
remark: data.remark || ''
}
this.queue.push(item)
if (this.queue.length > this.cfg.maxQueue) this.queue.shift()
if (this.queue.length >= this.cfg.batchSize) this.flush()
else this._schedule()
}
/** 业务友好入口 */
trackFunc(funcCode, extra = {}, overrides = {}) {
this._manualSeq++ // 通知 DOM 采集器:这一 tick 有手动埋点
this.track(Object.assign({ funcCode, extraParams: extra }, overrides))
}
_schedule() {
if (this._timer) return
this._timer = setTimeout(() => {
this._timer = null
this.flush()
}, this.cfg.flushInterval)
}
async flush(force = false) {
if (this._flushing || !this.queue.length) return
this._flushing = true
if (this._timer) { clearTimeout(this._timer); this._timer = null }
const batch = this.queue.splice(0, this.cfg.maxBatch)
let ok = false
try {
await this._send(batch)
ok = true
this._retry = 0
} catch (e) {
this._retry++
if (this._retry <= this.cfg.maxRetry) {
// 回滚到队头,指数退避
this.queue.unshift(...batch)
if (this.queue.length > this.cfg.maxQueue) this.queue.length = this.cfg.maxQueue
const delay = Math.min(30000, 1000 * Math.pow(2, this._retry))
this._flushing = false
this._timer = setTimeout(() => { this._timer = null; this.flush() }, delay)
return
}
console.warn('[Tracker] 上报失败超过重试上限,丢弃', batch.length)
}
this._flushing = false
if (ok && this.queue.length) this._schedule()
}
_send(list) {
const payload = {
sessionId: this.sessionId,
visitorCode: this.visitorCode,
saveRequestList: list
}
return new Promise((resolve, reject) => {
uni.request({
url: this.cfg.api,
method: 'POST',
data: payload,
header: { 'Content-Type': 'application/json' },
timeout: 10000,
success: (res) => {
if (res.statusCode >= 200 && res.statusCode < 300) resolve()
else reject(new Error('HTTP ' + res.statusCode))
},
fail: reject
})
})
}
/** 页面卸载时的同步兜底上报 */
flushBeacon() {
if (!this.queue.length) return
const payload = {
sessionId: this.sessionId,
visitorCode: this.visitorCode,
saveRequestList: this.queue.splice(0)
}
// #ifdef H5
if (sendBeaconSafe(this.cfg.api, payload)) return
// #endif
this.queue.unshift(...payload.saveRequestList)
this.flush(true)
}
}
// 内部工具,避免循环依赖
import { resolvePageInfo } from './utils'
function resolvePageInfoSafe(page) { return resolvePageInfo(page) }
// #ifdef H5
import { sendBeacon } from './utils'
function sendBeaconSafe(url, payload) { return sendBeacon(url, payload) }
// #endif
import Tracker from './core'
import config from './config'
import { setupDomCollector } from './collector-dom'
import { setupMpCollector, trackerMixin, bindTracker } from './collector-mp'
import { syncTrackerIdentity } from './utils'
let _instance = null
export function initTracker(options = {}) {
if (_instance) return _instance
Object.assign(config, options)
_instance = new Tracker(config)
bindTracker(_instance)
// 延迟初始化,避免抢占首屏资源
setTimeout(() => {
// #ifdef H5 || APP-PLUS
setupDomCollector(_instance)
// #endif
// #ifdef MP
setupMpCollector(_instance)
// #endif
}, config.initDelay)
return _instance
}
/**
* 宿主(微信小程序 / APP 的 webview)通过 URL 带入 trackerSessionId / trackerVisitorCode 时调用。
* 优先级:入参 query > URL 参数。实例未初始化时先落缓存,初始化时自动读取。
* @param {Object} query 一般传 App.vue onLaunch 的 options.query
*/
export function syncTrackerFromQuery(query = {}) {
const { visitorCode, sessionId } = syncTrackerIdentity({
visitorCode: query.trackerVisitorCode || '',
sessionId: query.trackerSessionId || ''
})
if (!visitorCode && !sessionId) return false
if (_instance) _instance.setIdentity({ visitorCode, sessionId })
return true
}
export function useTracker() { return _instance }
export function setTrackerEnabled(v) { _instance && _instance.setEnabled(v) }
export { trackerMixin }
/**
* 手动埋点统一入口(业务页面唯一该调的埋点 API)
* ============================================================
* 定位:业务层 → 上报协议 的防腐层。这里只做三件事:
* 1. 收口参数(funcCode / eventCode / actionTarget* / remark 的组装规则)
* 2. 统一 try/catch —— 埋点异常绝不允许打断业务(跳转、赋值、请求)
* 3. 统一口径 —— 敏感值(金额/手机号等)只传长度,不传明文
*
* 不在这里做的事:队列、批量、重试、sendBeacon —— 那些在 core.js
*
* 用法:
* trackClick(FUNCTIONS.TOOLS_PENSION, 'pension_calc', '开始计算')
* trackField(FUNCTIONS.TOOLS_PENSION, 'monthPaymentWage', val, { fieldName: '本年月缴费工资', actionType: 'input' })
* trackView(FUNCTIONS.TOOLS_PENSION_DETAIL, 'pension_result', '养老金测算结果', { hasResult: '1' })
* trackEvent(FUNCTIONS.WECHAT_LOGIN, { target: 'login_phone_success', name: '手机号快捷登录成功' }) // eventCode 由 funcCode 推导
*/
import { useTracker } from './index'
import { EVENTS } from './track-events'
function _report(funcCode, extra, overrides) {
try {
const t = useTracker()
if (!t || !t.enabled) return
t.trackFunc(funcCode, extra, overrides)
} catch (e) {
console.warn('[Tracker] 手动埋点上报失败', e)
}
}
/**
* 底层入口:eventCode 不传时沿用 core 的推导规则(funcCode → FUNCTION_EVENT_MAP)
* @param {string} funcCode FUNCTIONS.xxx
* @param {Object} opts { target, name, targetType, eventCode, extra, remark }
*/
export function trackEvent(funcCode, opts = {}) {
try {
const { target = '', name = '', targetType = 'button', eventCode, extra = {}, remark } = opts
const overrides = {
actionTargetType: targetType,
actionTarget: target,
actionTargetName: name || target,
remark: remark || name
}
if (eventCode) overrides.eventCode = eventCode
_report(funcCode, Object.assign({ actionTarget: target }, extra), overrides)
} catch (e) {
console.warn('[Tracker] 手动埋点上报失败', e)
}
}
/**
* 点击类:按钮、图标、展开收起等
*/
export function trackClick(funcCode, target, name, extra = {}) {
trackEvent(funcCode, {
target,
name,
targetType: 'button',
eventCode: EVENTS.CLICK,
extra,
remark: `点击${name}`
})
}
/**
* 值变更类:下拉选中、输入框失焦
* @param {*} value 用户输入/选择的值(不会明文上报,只取长度)
* @param {Object} opts { fieldName, actionType: 'select'|'input', target, extra, includeValue }
* includeValue=true 时才把明文放进 extraParams.value(仅限非敏感字段)
*/
export function trackField(funcCode, field, value, opts = {}) {
try {
const { fieldName = field, actionType = 'select', target, extra = {}, includeValue = false } = opts
const v = value === undefined || value === null ? '' : String(value)
const payload = Object.assign({
field,
actionType,
valueLen: v.length,
hasValue: v ? '1' : '0'
}, includeValue ? { value: v } : {}, extra)
trackEvent(funcCode, {
target: target || `field_${field}`,
name: fieldName,
targetType: actionType === 'input' ? 'input' : 'picker',
eventCode: EVENTS.INPUT,
extra: payload,
remark: `${actionType === 'input' ? '编辑' : '选择'}${fieldName}`
})
} catch (e) {
console.warn('[Tracker] 手动埋点上报失败', e)
}
}
/**
* 曝光类:详情页/结果页展示
*/
export function trackView(funcCode, target, name, extra = {}, targetType = 'page') {
trackEvent(funcCode, {
target,
name,
targetType,
eventCode: EVENTS.VIEW_DETAIL,
extra,
remark: `查看${name}`
})
}
// track-events.js
/**
* ============================================================
* 业务事件定义
* 与数据字典保持一致,统一管理事件编码
* 基于:事件表、模块表、功能表
*
* 页面归属哪个模块,由 pages.json 里页面的 style.meta.moduleCode 决定
* (main.js 构建期生成 pageMetaMap),本文件不做页面路径映射。
* 新增页面时:pages.json 配上 meta.moduleCode 即可,无需改本文件;
* 只有新增「模块」或「功能」时才在这里补编码。
* ============================================================
*/
// ============================================================
// 一、事件编码常量(对应事件表 event_code)
// ============================================================
export const EVENTS = {
// ====== 页面级(自动采集) ======
PAGE_VIEW: 'page_view',
PAGE_LEAVE: 'page_leave',
STAY: 'stay',
// ====== 交互级(自动采集) ======
CLICK: 'click',
TAB_SWITCH: 'tab_switch',
INPUT: 'input',
// ====== 业务级 ======
VIEW_DETAIL: 'view_detail',
SUBMIT: 'submit',
APPLY: 'apply',
INVITE: 'invite',
SHARE: 'share',
SEARCH: 'search',
EDIT: 'edit',
DOWNLOAD: 'download',
CLEAR: 'clear',
LOGOUT: 'logout',
PURCHASE: 'purchase',
LOGIN: 'login',
REGISTER: 'register',
// ====== 风控级 ======
FRAUD_DETECT: 'fraud_detect',
ACCOUNT_LOCK: 'account_lock'
}
// ============================================================
// 二、事件分类映射(operCategory)
// ============================================================
export const EVENT_CATEGORIES = {
[EVENTS.PAGE_VIEW]: '页面级事件',
[EVENTS.PAGE_LEAVE]: '页面级事件',
[EVENTS.STAY]: '页面级事件',
[EVENTS.CLICK]: '交互级事件',
[EVENTS.TAB_SWITCH]: '交互级事件',
[EVENTS.INPUT]: '交互级事件',
[EVENTS.VIEW_DETAIL]: '业务级事件',
[EVENTS.SUBMIT]: '业务级事件',
[EVENTS.APPLY]: '业务级事件',
[EVENTS.INVITE]: '业务级事件',
[EVENTS.SHARE]: '业务级事件',
[EVENTS.SEARCH]: '业务级事件',
[EVENTS.EDIT]: '业务级事件',
[EVENTS.DOWNLOAD]: '业务级事件',
[EVENTS.CLEAR]: '业务级事件',
[EVENTS.LOGOUT]: '业务级事件',
[EVENTS.PURCHASE]: '业务级事件',
[EVENTS.LOGIN]: '业务级事件',
[EVENTS.REGISTER]: '业务级事件',
[EVENTS.FRAUD_DETECT]: '风控级事件',
[EVENTS.ACCOUNT_LOCK]: '风控级事件'
}
// ============================================================
// 三、事件名称映射(eventTypeName)
// ============================================================
export const EVENT_NAMES = {
[EVENTS.PAGE_VIEW]: '页面浏览',
[EVENTS.PAGE_LEAVE]: '页面离开',
[EVENTS.STAY]: '页面停留',
[EVENTS.CLICK]: '点击',
[EVENTS.TAB_SWITCH]: 'Tab切换',
[EVENTS.INPUT]: '输入',
[EVENTS.VIEW_DETAIL]: '查看详情',
[EVENTS.SUBMIT]: '提交',
[EVENTS.APPLY]: '申请',
[EVENTS.INVITE]: '邀请',
[EVENTS.SHARE]: '分享',
[EVENTS.SEARCH]: '搜索',
[EVENTS.EDIT]: '编辑',
[EVENTS.DOWNLOAD]: '下载',
[EVENTS.CLEAR]: '清除',
[EVENTS.LOGOUT]: '退出登录',
[EVENTS.PURCHASE]: '购买',
[EVENTS.LOGIN]: '登录',
[EVENTS.REGISTER]: '注册',
[EVENTS.FRAUD_DETECT]: '欺诈检测',
[EVENTS.ACCOUNT_LOCK]: '账号锁定'
}
// ============================================================
// 四、模块编码常量(对应模块表 module_code)
// 与 pages.json 中各页面 style.meta.moduleCode 一一对应
// 一个 moduleCode 可挂多个页面(如 certify 挂了认证相关 5 个页面)
// ============================================================
export const MODULES = {
HOME: 'home', // 首页
LOGIN: 'login', // 登录
PRODUCT: 'product', // 产品中心(列表/详情/对比)
TOOLS: 'tools', // 金融工具(理财计算器)
SHARE: 'share', // 分享(分享好友/分享数据/分销海报)
USER: 'user', // 个人中心
ANNOUNCEMENT: 'announcement', // 公告(列表/详情)
MESSAGE: 'message', // 消息(列表/详情)
APPLY: 'apply', // 申请加盟
CERTIFY: 'certify', // 认证(我的认证/认证查询/上传信息/实名认证)
INVITE: 'invite', // 邀请(邀请加盟/邀请注册/邀请登录)
ORDER: 'order', // 订单(确认/详情/成交/支付)
TEAM: 'team', // 团队(我的团队/育成团队/成员/业绩)
HELP: 'help', // 帮助中心
POINTS: 'points', // 积分
COMMISSION: 'commission', // 佣金
WITHDRAWAL: 'withdrawal', // 提现/兑换
TAX: 'tax', // 纳税规则
REFUND: 'refund', // 退款
AFTER_SALES: 'after_sales', // 售后
SETTINGS: 'settings', // 设置(绑定/密码/注销/解约)
ABOUT: 'about', // 关于我
DOWNLOAD: 'download', // 下载
WEBVIEW: 'webview', // 网页容器
CLAUSE: 'clause', // 协议
SFP: 'sfp', // SFP 金融工具
LAW: 'law', // 法条摘要
VIDEO: 'video', // 视频课程
CONTRACT: 'contract', // 合同/协议文档
CARD: 'card', // 名片
COMPARE: 'compare', // 对比
MEMBER: 'member', // 会员查询
LAUNCH: 'launch' // 启动页
}
// ============================================================
// 五、模块名称映射(moduleTypeName)
// 模块级名称;页面上报时若 pages.json 配了 meta.moduleName,
// 则优先使用页面级名称(如「产品详情」「分销海报」)
// ============================================================
export const MODULE_NAMES = {
[MODULES.HOME]: '首页',
[MODULES.LOGIN]: '登录',
[MODULES.PRODUCT]: '产品中心',
[MODULES.TOOLS]: '金融工具',
[MODULES.SHARE]: '分享',
[MODULES.USER]: '个人中心',
[MODULES.ANNOUNCEMENT]: '公告',
[MODULES.MESSAGE]: '消息',
[MODULES.APPLY]: '申请加盟',
[MODULES.CERTIFY]: '认证',
[MODULES.INVITE]: '邀请',
[MODULES.ORDER]: '订单',
[MODULES.TEAM]: '团队',
[MODULES.HELP]: '帮助中心',
[MODULES.POINTS]: '积分',
[MODULES.COMMISSION]: '佣金',
[MODULES.WITHDRAWAL]: '提现',
[MODULES.TAX]: '纳税规则',
[MODULES.REFUND]: '退款',
[MODULES.AFTER_SALES]: '售后',
[MODULES.SETTINGS]: '设置',
[MODULES.ABOUT]: '关于我',
[MODULES.DOWNLOAD]: '下载',
[MODULES.WEBVIEW]: '网页容器',
[MODULES.CLAUSE]: '协议',
[MODULES.SFP]: 'SFP金融工具',
[MODULES.LAW]: '法条摘要',
[MODULES.VIDEO]: '视频课程',
[MODULES.CONTRACT]: '合同协议',
[MODULES.CARD]: '名片',
[MODULES.COMPARE]: '产品对比',
[MODULES.MEMBER]: '会员查询',
[MODULES.LAUNCH]: '启动页'
}
// ============================================================
// 六、功能编码常量(对应功能表 function_code)
// ============================================================
export const FUNCTIONS = {
// ====== 首页模块 ======
HOME_TAB: 'home_tab', // 底部 Tab 切换
HOME_LOGIN: 'home_login', // 首页登录入口
// ====== 登录模块 ======
LOGIN_SEND_CODE: 'login_send_code', // 获取验证码
LOGIN_SUBMIT: 'login_submit', // 提交登录
LOGIN_WX: 'login_wx', // 微信登录
LOGIN_AGREE_RULE: 'login_agree_rule', // 勾选用户协议
LOGIN_AGREEMENT: 'login_agreement', // 查看用户协议
LOGIN_PRIVACY: 'login_privacy', // 查看隐私政策
// ====== 产品中心模块 ======
PRODUCT_LIST: 'product_list', // 产品列表
PRODUCT_VIEW_DETAIL: 'product_view_detail', // 查看产品详情
PRODUCT_SEARCH: 'product_search', // 搜索产品
PRODUCT_COMPARE: 'product_compare', // 产品对比
PRODUCT_BUY: 'product_buy', // 购买产品
// ====== 金融工具模块 ======
TOOLS_FINANCE_CALC: 'tools_finance_calc', // 打开理财计算器
TOOLS_CALC_SUBMIT: 'tools_calc_submit', // 提交计算
// ====== 分享模块 ======
SHARE_TO_FRIEND: 'share_to_friend', // 分享给好友
SHARE_POSTER: 'share_poster', // 生成/查看分销海报
SHARE_VIEW_DATA: 'share_view_data', // 查看分享数据
// ====== 个人中心模块 ======
USER_VIEW_INFO: 'user_view_info', // 查看个人资料
USER_EDIT_INFO: 'user_edit_info', // 编辑个人资料
USER_VIEW_DETAIL: 'user_view_detail', // 查看个人详情
USER_TEAM: 'user_team', // 查看我的团队
USER_POINTS: 'user_points', // 查看我的积分
USER_COMMISSION: 'user_commission', // 查看佣金
USER_ORDER: 'user_order', // 查看订单
USER_HELP: 'user_help', // 查看帮助中心
USER_SETTINGS: 'user_settings', // 打开设置
USER_LOGOUT: 'user_logout', // 退出登录
// ====== 公告模块 ======
ANNOUNCEMENT_VIEW_LIST: 'announcement_view_list', // 查看公告列表
ANNOUNCEMENT_VIEW_DETAIL: 'announcement_view_detail', // 查看公告详情
// ====== 消息模块 ======
MESSAGE_VIEW_LIST: 'message_view_list', // 查看消息列表
MESSAGE_VIEW_DETAIL: 'message_view_detail', // 查看消息详情
// ====== 申请加盟模块 ======
APPLY_BASIC_INFO: 'apply_basic_info', // 填写基本资料
APPLY_WORK_EXP: 'apply_work_exp', // 填写从业经历
APPLY_ID_CARD: 'apply_id_card', // 填写个人证件
APPLY_EDUCATION: 'apply_education', // 填写学历信息
APPLY_BANK_CARD: 'apply_bank_card', // 填写银行卡号
APPLY_STATEMENT: 'apply_statement', // 填写个人声明
APPLY_CONTRACT: 'apply_contract', // 查看合同文档
APPLY_SIGNATURE: 'apply_signature', // 电子签名
APPLY_SUBMIT: 'apply_submit', // 提交申请
APPLY_VIEW_RESULT: 'apply_view_result', // 查看申请结果
// ====== 认证模块 ======
CERTIFY_VIEW_LIST: 'certify_view_list', // 查看我的认证
CERTIFY_VIEW_DETAIL: 'certify_view_detail', // 查看认证详情
CERTIFY_UPLOAD: 'certify_upload', // 上传认证信息
CERTIFY_QUERY: 'certify_query', // 认证查询
CERTIFY_AUTH: 'certify_auth', // 实名认证
CERTIFY_LEARN: 'certify_learn', // 学习认证
// ====== 邀请模块 ======
INVITE_JOIN: 'invite_join', // 邀请加盟
INVITE_REGISTER: 'invite_register', // 邀请注册
INVITE_LOGIN: 'invite_login', // 邀请登录
// ====== 订单模块 ======
ORDER_CONFIRM: 'order_confirm', // 订单确认
ORDER_SUBMIT: 'order_submit', // 提交订单
ORDER_PAY: 'order_pay', // 订单支付
ORDER_VIEW_DETAIL: 'order_view_detail', // 查看订单详情
ORDER_VIEW_SALES: 'order_view_sales', // 查看成交订单
ORDER_REFUND: 'order_refund', // 申请退款
// ====== 团队模块 ======
TEAM_VIEW: 'team_view', // 查看我的团队
TEAM_INCUBATE: 'team_incubate', // 查看育成团队
TEAM_VIEW_MEMBERS: 'team_view_members', // 查看团队成员
TEAM_VIEW_PERFORMANCE: 'team_view_performance', // 查看团队业绩
// ====== 帮助中心模块 ======
HELP_VIEW: 'help_view', // 查看帮助中心
// ====== 积分模块 ======
POINTS_VIEW: 'points_view', // 查看我的积分
POINTS_VIEW_DETAIL: 'points_view_detail', // 查看积分明细
POINTS_EXCHANGE: 'points_exchange', // 积分兑换/提现
// ====== 佣金模块 ======
COMMISSION_VIEW: 'commission_view', // 查看佣金状态
COMMISSION_VIEW_DETAIL: 'commission_view_detail', // 查看佣金详情
COMMISSION_QUERY_RATE: 'commission_query_rate', // 产品佣率查询
// ====== 提现模块 ======
WITHDRAWAL_APPLY: 'withdrawal_apply', // 兑换提现申请
WITHDRAWAL_RECORDS: 'withdrawal_records', // 查看兑换/提现记录
WITHDRAWAL_DETAIL: 'withdrawal_detail', // 查看提现详情
WITHDRAWAL_TAX_RULES: 'withdrawal_tax_rules', // 查看纳税规则
// ====== 退款模块 ======
REFUND_APPLY: 'refund_apply', // 申请退款
REFUND_LIST: 'refund_list', // 查看已退课
// ====== 售后模块 ======
AFTER_SALES_VIEW: 'after_sales_view', // 查看我的售后
AFTER_SALES_DETAIL: 'after_sales_detail', // 查看售后详情
// ====== 设置模块 ======
SETTINGS_OPEN: 'settings_open', // 打开设置
SETTINGS_PHONE_BIND: 'settings_phone_bind', // 手机号绑定
SETTINGS_RESET_PWD: 'settings_reset_pwd', // 重置密码
SETTINGS_BIND_ACCOUNT: 'settings_bind_account', // 账号绑定设置
SETTINGS_CANCEL: 'settings_cancel', // 注销账号
SETTINGS_LOGOFF: 'settings_logoff', // 合伙人解约
SETTINGS_CONTRACT: 'settings_contract', // 查看解约协议/协议
// ====== 关于我模块 ======
ABOUT_VIEW: 'about_view', // 查看关于我
// ====== 下载模块 ======
DOWNLOAD_APP: 'download_app', // 下载 APP
// ====== 网页容器模块 ======
OPEN_WEBVIEW: 'open_webview', // 打开网页容器
// ====== 协议模块 ======
CLAUSE_VIEW: 'clause_view', // 查看协议
// ====== SFP 金融工具模块 ======
SFP_INDEX: 'sfp_index', // SFP 首页
SFP_HOUSE_CALC: 'sfp_house_calc', // 购房计算器
SFP_CHILD_EDU: 'sfp_child_edu', // 子女教育计算器
SFP_DATA_IMPORT: 'sfp_data_import', // 批量数据计算
SFP_CALC_SUBMIT: 'sfp_calc_submit', // 提交计算
// ====== 法条摘要模块 ======
LAW_VIEW: 'law_view', // 查看法条摘要
// ====== 视频课程模块 ======
VIDEO_LOGIN: 'video_login', // 视频登录
VIDEO_PLAY: 'video_play', // 播放视频
// ====== 名片模块 ======
CARD_VIEW: 'card_view', // 查看我的名片
// ====== 产品对比模块 ======
COMPARE_VIEW_RESULT: 'compare_view_result', // 查看对比结果
// ====== 会员查询模块 ======
MEMBER_QUERY: 'member_query', // 会员查询
// ====== 启动页模块 ======
LAUNCH_OPEN: 'launch_open' // 启动/中转
}
// ============================================================
// 七、功能 → 事件类型 映射
// ============================================================
export const FUNCTION_EVENT_MAP = {
// 首页
[FUNCTIONS.HOME_TAB]: EVENTS.TAB_SWITCH,
[FUNCTIONS.HOME_LOGIN]: EVENTS.LOGIN,
// 登录
[FUNCTIONS.LOGIN_SEND_CODE]: EVENTS.CLICK,
[FUNCTIONS.LOGIN_SUBMIT]: EVENTS.LOGIN,
[FUNCTIONS.LOGIN_WX]: EVENTS.LOGIN,
[FUNCTIONS.LOGIN_AGREE_RULE]: EVENTS.CLICK,
[FUNCTIONS.LOGIN_AGREEMENT]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.LOGIN_PRIVACY]: EVENTS.VIEW_DETAIL,
// 产品中心
[FUNCTIONS.PRODUCT_LIST]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.PRODUCT_VIEW_DETAIL]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.PRODUCT_SEARCH]: EVENTS.SEARCH,
[FUNCTIONS.PRODUCT_COMPARE]: EVENTS.CLICK,
[FUNCTIONS.PRODUCT_BUY]: EVENTS.PURCHASE,
// 金融工具
[FUNCTIONS.TOOLS_FINANCE_CALC]: EVENTS.CLICK,
[FUNCTIONS.TOOLS_CALC_SUBMIT]: EVENTS.SUBMIT,
// 分享
[FUNCTIONS.SHARE_TO_FRIEND]: EVENTS.SHARE,
[FUNCTIONS.SHARE_POSTER]: EVENTS.SHARE,
[FUNCTIONS.SHARE_VIEW_DATA]: EVENTS.VIEW_DETAIL,
// 个人中心
[FUNCTIONS.USER_VIEW_INFO]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.USER_EDIT_INFO]: EVENTS.EDIT,
[FUNCTIONS.USER_VIEW_DETAIL]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.USER_TEAM]: EVENTS.CLICK,
[FUNCTIONS.USER_POINTS]: EVENTS.CLICK,
[FUNCTIONS.USER_COMMISSION]: EVENTS.CLICK,
[FUNCTIONS.USER_ORDER]: EVENTS.CLICK,
[FUNCTIONS.USER_HELP]: EVENTS.CLICK,
[FUNCTIONS.USER_SETTINGS]: EVENTS.CLICK,
[FUNCTIONS.USER_LOGOUT]: EVENTS.LOGOUT,
// 公告
[FUNCTIONS.ANNOUNCEMENT_VIEW_LIST]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.ANNOUNCEMENT_VIEW_DETAIL]: EVENTS.VIEW_DETAIL,
// 消息
[FUNCTIONS.MESSAGE_VIEW_LIST]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.MESSAGE_VIEW_DETAIL]: EVENTS.VIEW_DETAIL,
// 申请加盟
[FUNCTIONS.APPLY_BASIC_INFO]: EVENTS.EDIT,
[FUNCTIONS.APPLY_WORK_EXP]: EVENTS.EDIT,
[FUNCTIONS.APPLY_ID_CARD]: EVENTS.EDIT,
[FUNCTIONS.APPLY_EDUCATION]: EVENTS.EDIT,
[FUNCTIONS.APPLY_BANK_CARD]: EVENTS.EDIT,
[FUNCTIONS.APPLY_STATEMENT]: EVENTS.EDIT,
[FUNCTIONS.APPLY_CONTRACT]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.APPLY_SIGNATURE]: EVENTS.SUBMIT,
[FUNCTIONS.APPLY_SUBMIT]: EVENTS.APPLY,
[FUNCTIONS.APPLY_VIEW_RESULT]: EVENTS.VIEW_DETAIL,
// 认证
[FUNCTIONS.CERTIFY_VIEW_LIST]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.CERTIFY_VIEW_DETAIL]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.CERTIFY_UPLOAD]: EVENTS.SUBMIT,
[FUNCTIONS.CERTIFY_QUERY]: EVENTS.SEARCH,
[FUNCTIONS.CERTIFY_AUTH]: EVENTS.SUBMIT,
[FUNCTIONS.CERTIFY_LEARN]: EVENTS.CLICK,
// 邀请
[FUNCTIONS.INVITE_JOIN]: EVENTS.INVITE,
[FUNCTIONS.INVITE_REGISTER]: EVENTS.REGISTER,
[FUNCTIONS.INVITE_LOGIN]: EVENTS.LOGIN,
// 订单
[FUNCTIONS.ORDER_CONFIRM]: EVENTS.CLICK,
[FUNCTIONS.ORDER_SUBMIT]: EVENTS.SUBMIT,
[FUNCTIONS.ORDER_PAY]: EVENTS.PURCHASE,
[FUNCTIONS.ORDER_VIEW_DETAIL]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.ORDER_VIEW_SALES]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.ORDER_REFUND]: EVENTS.CLICK,
// 团队
[FUNCTIONS.TEAM_VIEW]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.TEAM_INCUBATE]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.TEAM_VIEW_MEMBERS]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.TEAM_VIEW_PERFORMANCE]: EVENTS.VIEW_DETAIL,
// 帮助中心
[FUNCTIONS.HELP_VIEW]: EVENTS.VIEW_DETAIL,
// 积分
[FUNCTIONS.POINTS_VIEW]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.POINTS_VIEW_DETAIL]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.POINTS_EXCHANGE]: EVENTS.SUBMIT,
// 佣金
[FUNCTIONS.COMMISSION_VIEW]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.COMMISSION_VIEW_DETAIL]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.COMMISSION_QUERY_RATE]: EVENTS.SEARCH,
// 提现
[FUNCTIONS.WITHDRAWAL_APPLY]: EVENTS.SUBMIT,
[FUNCTIONS.WITHDRAWAL_RECORDS]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.WITHDRAWAL_DETAIL]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.WITHDRAWAL_TAX_RULES]: EVENTS.VIEW_DETAIL,
// 退款
[FUNCTIONS.REFUND_APPLY]: EVENTS.APPLY,
[FUNCTIONS.REFUND_LIST]: EVENTS.VIEW_DETAIL,
// 售后
[FUNCTIONS.AFTER_SALES_VIEW]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.AFTER_SALES_DETAIL]: EVENTS.VIEW_DETAIL,
// 设置
[FUNCTIONS.SETTINGS_OPEN]: EVENTS.CLICK,
[FUNCTIONS.SETTINGS_PHONE_BIND]: EVENTS.EDIT,
[FUNCTIONS.SETTINGS_RESET_PWD]: EVENTS.EDIT,
[FUNCTIONS.SETTINGS_BIND_ACCOUNT]: EVENTS.EDIT,
[FUNCTIONS.SETTINGS_CANCEL]: EVENTS.SUBMIT,
[FUNCTIONS.SETTINGS_LOGOFF]: EVENTS.SUBMIT,
[FUNCTIONS.SETTINGS_CONTRACT]: EVENTS.VIEW_DETAIL,
// 关于我
[FUNCTIONS.ABOUT_VIEW]: EVENTS.VIEW_DETAIL,
// 下载
[FUNCTIONS.DOWNLOAD_APP]: EVENTS.DOWNLOAD,
// 网页容器
[FUNCTIONS.OPEN_WEBVIEW]: EVENTS.VIEW_DETAIL,
// 协议
[FUNCTIONS.CLAUSE_VIEW]: EVENTS.VIEW_DETAIL,
// SFP 金融工具
[FUNCTIONS.SFP_INDEX]: EVENTS.VIEW_DETAIL,
[FUNCTIONS.SFP_HOUSE_CALC]: EVENTS.CLICK,
[FUNCTIONS.SFP_CHILD_EDU]: EVENTS.CLICK,
[FUNCTIONS.SFP_DATA_IMPORT]: EVENTS.CLICK,
[FUNCTIONS.SFP_CALC_SUBMIT]: EVENTS.SUBMIT,
// 法条摘要
[FUNCTIONS.LAW_VIEW]: EVENTS.VIEW_DETAIL,
// 视频课程
[FUNCTIONS.VIDEO_LOGIN]: EVENTS.LOGIN,
[FUNCTIONS.VIDEO_PLAY]: EVENTS.VIEW_DETAIL,
// 名片
[FUNCTIONS.CARD_VIEW]: EVENTS.VIEW_DETAIL,
// 产品对比
[FUNCTIONS.COMPARE_VIEW_RESULT]: EVENTS.VIEW_DETAIL,
// 会员查询
[FUNCTIONS.MEMBER_QUERY]: EVENTS.SEARCH,
// 启动页
[FUNCTIONS.LAUNCH_OPEN]: EVENTS.CLICK
}
// ============================================================
// 八、功能 → 模块 映射
// ============================================================
export const FUNCTION_MODULE_MAP = {
// 首页
[FUNCTIONS.HOME_TAB]: MODULES.HOME,
[FUNCTIONS.HOME_LOGIN]: MODULES.HOME,
// 登录
[FUNCTIONS.LOGIN_SEND_CODE]: MODULES.LOGIN,
[FUNCTIONS.LOGIN_SUBMIT]: MODULES.LOGIN,
[FUNCTIONS.LOGIN_WX]: MODULES.LOGIN,
[FUNCTIONS.LOGIN_AGREE_RULE]: MODULES.LOGIN,
[FUNCTIONS.LOGIN_AGREEMENT]: MODULES.LOGIN,
[FUNCTIONS.LOGIN_PRIVACY]: MODULES.LOGIN,
// 产品中心
[FUNCTIONS.PRODUCT_LIST]: MODULES.PRODUCT,
[FUNCTIONS.PRODUCT_VIEW_DETAIL]: MODULES.PRODUCT,
[FUNCTIONS.PRODUCT_SEARCH]: MODULES.PRODUCT,
[FUNCTIONS.PRODUCT_COMPARE]: MODULES.PRODUCT,
[FUNCTIONS.PRODUCT_BUY]: MODULES.PRODUCT,
// 金融工具
[FUNCTIONS.TOOLS_FINANCE_CALC]: MODULES.TOOLS,
[FUNCTIONS.TOOLS_CALC_SUBMIT]: MODULES.TOOLS,
// 分享
[FUNCTIONS.SHARE_TO_FRIEND]: MODULES.SHARE,
[FUNCTIONS.SHARE_POSTER]: MODULES.SHARE,
[FUNCTIONS.SHARE_VIEW_DATA]: MODULES.SHARE,
// 个人中心
[FUNCTIONS.USER_VIEW_INFO]: MODULES.USER,
[FUNCTIONS.USER_EDIT_INFO]: MODULES.USER,
[FUNCTIONS.USER_VIEW_DETAIL]: MODULES.USER,
[FUNCTIONS.USER_TEAM]: MODULES.USER,
[FUNCTIONS.USER_POINTS]: MODULES.USER,
[FUNCTIONS.USER_COMMISSION]: MODULES.USER,
[FUNCTIONS.USER_ORDER]: MODULES.USER,
[FUNCTIONS.USER_HELP]: MODULES.USER,
[FUNCTIONS.USER_SETTINGS]: MODULES.USER,
[FUNCTIONS.USER_LOGOUT]: MODULES.USER,
// 公告
[FUNCTIONS.ANNOUNCEMENT_VIEW_LIST]: MODULES.ANNOUNCEMENT,
[FUNCTIONS.ANNOUNCEMENT_VIEW_DETAIL]: MODULES.ANNOUNCEMENT,
// 消息
[FUNCTIONS.MESSAGE_VIEW_LIST]: MODULES.MESSAGE,
[FUNCTIONS.MESSAGE_VIEW_DETAIL]: MODULES.MESSAGE,
// 申请加盟
[FUNCTIONS.APPLY_BASIC_INFO]: MODULES.APPLY,
[FUNCTIONS.APPLY_WORK_EXP]: MODULES.APPLY,
[FUNCTIONS.APPLY_ID_CARD]: MODULES.APPLY,
[FUNCTIONS.APPLY_EDUCATION]: MODULES.APPLY,
[FUNCTIONS.APPLY_BANK_CARD]: MODULES.APPLY,
[FUNCTIONS.APPLY_STATEMENT]: MODULES.APPLY,
[FUNCTIONS.APPLY_CONTRACT]: MODULES.APPLY,
[FUNCTIONS.APPLY_SIGNATURE]: MODULES.APPLY,
[FUNCTIONS.APPLY_SUBMIT]: MODULES.APPLY,
[FUNCTIONS.APPLY_VIEW_RESULT]: MODULES.APPLY,
// 认证
[FUNCTIONS.CERTIFY_VIEW_LIST]: MODULES.CERTIFY,
[FUNCTIONS.CERTIFY_VIEW_DETAIL]: MODULES.CERTIFY,
[FUNCTIONS.CERTIFY_UPLOAD]: MODULES.CERTIFY,
[FUNCTIONS.CERTIFY_QUERY]: MODULES.CERTIFY,
[FUNCTIONS.CERTIFY_AUTH]: MODULES.CERTIFY,
[FUNCTIONS.CERTIFY_LEARN]: MODULES.CERTIFY,
// 邀请
[FUNCTIONS.INVITE_JOIN]: MODULES.INVITE,
[FUNCTIONS.INVITE_REGISTER]: MODULES.INVITE,
[FUNCTIONS.INVITE_LOGIN]: MODULES.INVITE,
// 订单
[FUNCTIONS.ORDER_CONFIRM]: MODULES.ORDER,
[FUNCTIONS.ORDER_SUBMIT]: MODULES.ORDER,
[FUNCTIONS.ORDER_PAY]: MODULES.ORDER,
[FUNCTIONS.ORDER_VIEW_DETAIL]: MODULES.ORDER,
[FUNCTIONS.ORDER_VIEW_SALES]: MODULES.ORDER,
[FUNCTIONS.ORDER_REFUND]: MODULES.ORDER,
// 团队
[FUNCTIONS.TEAM_VIEW]: MODULES.TEAM,
[FUNCTIONS.TEAM_INCUBATE]: MODULES.TEAM,
[FUNCTIONS.TEAM_VIEW_MEMBERS]: MODULES.TEAM,
[FUNCTIONS.TEAM_VIEW_PERFORMANCE]: MODULES.TEAM,
// 帮助中心
[FUNCTIONS.HELP_VIEW]: MODULES.HELP,
// 积分
[FUNCTIONS.POINTS_VIEW]: MODULES.POINTS,
[FUNCTIONS.POINTS_VIEW_DETAIL]: MODULES.POINTS,
[FUNCTIONS.POINTS_EXCHANGE]: MODULES.POINTS,
// 佣金
[FUNCTIONS.COMMISSION_VIEW]: MODULES.COMMISSION,
[FUNCTIONS.COMMISSION_VIEW_DETAIL]: MODULES.COMMISSION,
[FUNCTIONS.COMMISSION_QUERY_RATE]: MODULES.COMMISSION,
// 提现
[FUNCTIONS.WITHDRAWAL_APPLY]: MODULES.WITHDRAWAL,
[FUNCTIONS.WITHDRAWAL_RECORDS]: MODULES.WITHDRAWAL,
[FUNCTIONS.WITHDRAWAL_DETAIL]: MODULES.WITHDRAWAL,
[FUNCTIONS.WITHDRAWAL_TAX_RULES]: MODULES.WITHDRAWAL,
// 退款
[FUNCTIONS.REFUND_APPLY]: MODULES.REFUND,
[FUNCTIONS.REFUND_LIST]: MODULES.REFUND,
// 售后
[FUNCTIONS.AFTER_SALES_VIEW]: MODULES.AFTER_SALES,
[FUNCTIONS.AFTER_SALES_DETAIL]: MODULES.AFTER_SALES,
// 设置
[FUNCTIONS.SETTINGS_OPEN]: MODULES.SETTINGS,
[FUNCTIONS.SETTINGS_PHONE_BIND]: MODULES.SETTINGS,
[FUNCTIONS.SETTINGS_RESET_PWD]: MODULES.SETTINGS,
[FUNCTIONS.SETTINGS_BIND_ACCOUNT]: MODULES.SETTINGS,
[FUNCTIONS.SETTINGS_CANCEL]: MODULES.SETTINGS,
[FUNCTIONS.SETTINGS_LOGOFF]: MODULES.SETTINGS,
[FUNCTIONS.SETTINGS_CONTRACT]: MODULES.SETTINGS,
// 关于我
[FUNCTIONS.ABOUT_VIEW]: MODULES.ABOUT,
// 下载
[FUNCTIONS.DOWNLOAD_APP]: MODULES.DOWNLOAD,
// 网页容器
[FUNCTIONS.OPEN_WEBVIEW]: MODULES.WEBVIEW,
// 协议
[FUNCTIONS.CLAUSE_VIEW]: MODULES.CLAUSE,
// SFP 金融工具
[FUNCTIONS.SFP_INDEX]: MODULES.SFP,
[FUNCTIONS.SFP_HOUSE_CALC]: MODULES.SFP,
[FUNCTIONS.SFP_CHILD_EDU]: MODULES.SFP,
[FUNCTIONS.SFP_DATA_IMPORT]: MODULES.SFP,
[FUNCTIONS.SFP_CALC_SUBMIT]: MODULES.SFP,
// 法条摘要
[FUNCTIONS.LAW_VIEW]: MODULES.LAW,
// 视频课程
[FUNCTIONS.VIDEO_LOGIN]: MODULES.VIDEO,
[FUNCTIONS.VIDEO_PLAY]: MODULES.VIDEO,
// 名片
[FUNCTIONS.CARD_VIEW]: MODULES.CARD,
// 产品对比
[FUNCTIONS.COMPARE_VIEW_RESULT]: MODULES.COMPARE,
// 会员查询
[FUNCTIONS.MEMBER_QUERY]: MODULES.MEMBER,
// 启动页
[FUNCTIONS.LAUNCH_OPEN]: MODULES.LAUNCH
}
// ============================================================
// 九、功能名称映射(functionName)
// ============================================================
export const FUNCTION_NAMES = {
// 首页
[FUNCTIONS.HOME_TAB]: '切换底部Tab',
[FUNCTIONS.HOME_LOGIN]: '首页登录入口',
// 登录
[FUNCTIONS.LOGIN_SEND_CODE]: '获取验证码',
[FUNCTIONS.LOGIN_SUBMIT]: '提交登录',
[FUNCTIONS.LOGIN_WX]: '微信登录',
[FUNCTIONS.LOGIN_AGREE_RULE]: '勾选用户协议',
[FUNCTIONS.LOGIN_AGREEMENT]: '查看用户协议',
[FUNCTIONS.LOGIN_PRIVACY]: '查看隐私政策',
// 产品中心
[FUNCTIONS.PRODUCT_LIST]: '查看产品列表',
[FUNCTIONS.PRODUCT_VIEW_DETAIL]: '查看产品详情',
[FUNCTIONS.PRODUCT_SEARCH]: '搜索产品',
[FUNCTIONS.PRODUCT_COMPARE]: '产品对比',
[FUNCTIONS.PRODUCT_BUY]: '购买产品',
// 金融工具
[FUNCTIONS.TOOLS_FINANCE_CALC]: '打开理财计算器',
[FUNCTIONS.TOOLS_CALC_SUBMIT]: '提交理财计算',
// 分享
[FUNCTIONS.SHARE_TO_FRIEND]: '分享给好友',
[FUNCTIONS.SHARE_POSTER]: '查看分销海报',
[FUNCTIONS.SHARE_VIEW_DATA]: '查看分享数据',
// 个人中心
[FUNCTIONS.USER_VIEW_INFO]: '查看个人资料',
[FUNCTIONS.USER_EDIT_INFO]: '编辑个人资料',
[FUNCTIONS.USER_VIEW_DETAIL]: '查看个人详情',
[FUNCTIONS.USER_TEAM]: '查看我的团队',
[FUNCTIONS.USER_POINTS]: '查看我的积分',
[FUNCTIONS.USER_COMMISSION]: '查看佣金',
[FUNCTIONS.USER_ORDER]: '查看订单',
[FUNCTIONS.USER_HELP]: '查看帮助中心',
[FUNCTIONS.USER_SETTINGS]: '打开设置',
[FUNCTIONS.USER_LOGOUT]: '退出登录',
// 公告
[FUNCTIONS.ANNOUNCEMENT_VIEW_LIST]: '查看公告列表',
[FUNCTIONS.ANNOUNCEMENT_VIEW_DETAIL]: '查看公告详情',
// 消息
[FUNCTIONS.MESSAGE_VIEW_LIST]: '查看消息列表',
[FUNCTIONS.MESSAGE_VIEW_DETAIL]: '查看消息详情',
// 申请加盟
[FUNCTIONS.APPLY_BASIC_INFO]: '填写基本资料',
[FUNCTIONS.APPLY_WORK_EXP]: '填写从业经历',
[FUNCTIONS.APPLY_ID_CARD]: '填写个人证件',
[FUNCTIONS.APPLY_EDUCATION]: '填写学历信息',
[FUNCTIONS.APPLY_BANK_CARD]: '填写银行卡号',
[FUNCTIONS.APPLY_STATEMENT]: '填写个人声明',
[FUNCTIONS.APPLY_CONTRACT]: '查看合同文档',
[FUNCTIONS.APPLY_SIGNATURE]: '电子签名',
[FUNCTIONS.APPLY_SUBMIT]: '提交加盟申请',
[FUNCTIONS.APPLY_VIEW_RESULT]: '查看申请结果',
// 认证
[FUNCTIONS.CERTIFY_VIEW_LIST]: '查看我的认证',
[FUNCTIONS.CERTIFY_VIEW_DETAIL]: '查看认证详情',
[FUNCTIONS.CERTIFY_UPLOAD]: '上传认证信息',
[FUNCTIONS.CERTIFY_QUERY]: '认证查询',
[FUNCTIONS.CERTIFY_AUTH]: '实名认证',
[FUNCTIONS.CERTIFY_LEARN]: '学习认证',
// 邀请
[FUNCTIONS.INVITE_JOIN]: '邀请加盟',
[FUNCTIONS.INVITE_REGISTER]: '邀请注册',
[FUNCTIONS.INVITE_LOGIN]: '邀请登录',
// 订单
[FUNCTIONS.ORDER_CONFIRM]: '订单确认',
[FUNCTIONS.ORDER_SUBMIT]: '提交订单',
[FUNCTIONS.ORDER_PAY]: '订单支付',
[FUNCTIONS.ORDER_VIEW_DETAIL]: '查看订单详情',
[FUNCTIONS.ORDER_VIEW_SALES]: '查看成交订单',
[FUNCTIONS.ORDER_REFUND]: '申请退款入口',
// 团队
[FUNCTIONS.TEAM_VIEW]: '查看我的团队',
[FUNCTIONS.TEAM_INCUBATE]: '查看育成团队',
[FUNCTIONS.TEAM_VIEW_MEMBERS]: '查看团队成员',
[FUNCTIONS.TEAM_VIEW_PERFORMANCE]: '查看团队业绩',
// 帮助中心
[FUNCTIONS.HELP_VIEW]: '查看帮助中心',
// 积分
[FUNCTIONS.POINTS_VIEW]: '查看我的积分',
[FUNCTIONS.POINTS_VIEW_DETAIL]: '查看积分明细',
[FUNCTIONS.POINTS_EXCHANGE]: '积分兑换/提现',
// 佣金
[FUNCTIONS.COMMISSION_VIEW]: '查看佣金状态',
[FUNCTIONS.COMMISSION_VIEW_DETAIL]: '查看佣金详情',
[FUNCTIONS.COMMISSION_QUERY_RATE]: '产品佣率查询',
// 提现
[FUNCTIONS.WITHDRAWAL_APPLY]: '兑换提现申请',
[FUNCTIONS.WITHDRAWAL_RECORDS]: '查看兑换/提现记录',
[FUNCTIONS.WITHDRAWAL_DETAIL]: '查看提现详情',
[FUNCTIONS.WITHDRAWAL_TAX_RULES]: '查看纳税规则',
// 退款
[FUNCTIONS.REFUND_APPLY]: '申请退款',
[FUNCTIONS.REFUND_LIST]: '查看已退课',
// 售后
[FUNCTIONS.AFTER_SALES_VIEW]: '查看我的售后',
[FUNCTIONS.AFTER_SALES_DETAIL]: '查看售后详情',
// 设置
[FUNCTIONS.SETTINGS_OPEN]: '打开设置',
[FUNCTIONS.SETTINGS_PHONE_BIND]: '手机号绑定',
[FUNCTIONS.SETTINGS_RESET_PWD]: '重置密码',
[FUNCTIONS.SETTINGS_BIND_ACCOUNT]: '账号绑定设置',
[FUNCTIONS.SETTINGS_CANCEL]: '注销账号',
[FUNCTIONS.SETTINGS_LOGOFF]: '合伙人解约',
[FUNCTIONS.SETTINGS_CONTRACT]: '查看解约协议/协议',
// 关于我
[FUNCTIONS.ABOUT_VIEW]: '查看关于我',
// 下载
[FUNCTIONS.DOWNLOAD_APP]: '下载APP',
// 网页容器
[FUNCTIONS.OPEN_WEBVIEW]: '打开网页容器',
// 协议
[FUNCTIONS.CLAUSE_VIEW]: '查看协议',
// SFP 金融工具
[FUNCTIONS.SFP_INDEX]: '查看SFP首页',
[FUNCTIONS.SFP_HOUSE_CALC]: '购房计算器',
[FUNCTIONS.SFP_CHILD_EDU]: '子女教育计算器',
[FUNCTIONS.SFP_DATA_IMPORT]: '批量数据计算',
[FUNCTIONS.SFP_CALC_SUBMIT]: '提交SFP计算',
// 法条摘要
[FUNCTIONS.LAW_VIEW]: '查看法条摘要',
// 视频课程
[FUNCTIONS.VIDEO_LOGIN]: '视频登录',
[FUNCTIONS.VIDEO_PLAY]: '播放视频',
// 名片
[FUNCTIONS.CARD_VIEW]: '查看我的名片',
// 产品对比
[FUNCTIONS.COMPARE_VIEW_RESULT]: '查看对比结果',
// 会员查询
[FUNCTIONS.MEMBER_QUERY]: '会员查询',
// 启动页
[FUNCTIONS.LAUNCH_OPEN]: '启动/中转'
}
// ============================================================
// 十、辅助函数
// ============================================================
/**
* 获取事件分类
*/
export function getEventCategory(eventCode) {
return EVENT_CATEGORIES[eventCode] || '业务级事件'
}
/**
* 获取事件名称
*/
export function getEventName(eventCode) {
return EVENT_NAMES[eventCode] || eventCode
}
/**
* 获取功能对应的事件类型
*/
export function getEventByFunction(functionCode) {
return FUNCTION_EVENT_MAP[functionCode] || EVENTS.CLICK
}
/**
* 获取功能对应的模块
* 未登记的功能返回 '',由 core.js 取当前页面 pages.json 的 moduleCode 兜底
*/
export function getModuleByFunction(functionCode) {
return FUNCTION_MODULE_MAP[functionCode] || ''
}
/**
* 获取模块名称
*/
export function getModuleName(moduleCode) {
return MODULE_NAMES[moduleCode] || moduleCode || ''
}
/**
* 获取功能名称
*/
export function getFunctionName(functionCode) {
return FUNCTION_NAMES[functionCode] || functionCode
}
/**
* 构建标准埋点参数(适配后端入参格式)
*/
export function buildTrackParams(functionCode, extra = {}) {
const eventCode = getEventByFunction(functionCode)
const moduleCode = getModuleByFunction(functionCode)
return {
eventCode: eventCode,
eventName: getEventName(eventCode),
eventCategory: getEventCategory(eventCode),
moduleType: moduleCode,
moduleTypeName: getModuleName(moduleCode),
functionCode: functionCode,
functionName: getFunctionName(functionCode),
extra: extra
}
}
// ============================================================
// 十一、归一化工具(供 tracker 使用)
// ============================================================
const _EVENT_VALUES = new Set(Object.values(EVENTS))
/** 原生事件 / 旧值 / 大小写 → EVENTS 字典值 */
const _EVENT_ALIASES = {
tap: EVENTS.CLICK,
click: EVENTS.CLICK,
longpress: EVENTS.CLICK,
change: EVENTS.INPUT,
blur: EVENTS.INPUT,
input: EVENTS.INPUT,
page_show: EVENTS.PAGE_VIEW,
page_hide: EVENTS.PAGE_LEAVE,
page_view: EVENTS.PAGE_VIEW,
page_leave: EVENTS.PAGE_LEAVE,
tab_switch: EVENTS.TAB_SWITCH
}
export function normalizeEventCode(code) {
if (!code) return EVENTS.CLICK
const lc = String(code).toLowerCase()
if (_EVENT_VALUES.has(lc)) return lc
if (_EVENT_ALIASES[lc]) return _EVENT_ALIASES[lc]
return EVENTS.CLICK
}
const _FUNC_VALUES = new Set(Object.values(FUNCTIONS))
export function isValidFunction(funcCode) {
return _FUNC_VALUES.has(funcCode)
}
export function isValidModule(moduleCode) {
return Object.values(MODULES).includes(moduleCode)
}
let _device = null
let _clientType = null
export function formatTime(ts = Date.now()) {
const d = new Date(ts)
const p = (n, l = 2) => String(n).padStart(l, '0')
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ` +
`${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`
}
/** 设备信息只取一次,同步 API 不重复调用 */
export function getDeviceInfo() {
if (_device) return _device
const info = { platform: '', osVersion: '', brand: '', model: '', screenWidth: 0, screenHeight: 0 }
try {
const s = uni.getSystemInfoSync()
info.platform = s.platform || ''
info.osVersion = s.osVersion || ''
info.brand = s.brand || ''
info.model = s.model || ''
info.screenWidth = s.screenWidth || 0
info.screenHeight = s.screenHeight || 0
} catch (e) {
console.warn('[Tracker] 获取设备信息失败:', e)
}
_device = info
return info
}
export function detectClientType() {
if (_clientType) return _clientType
let type = 'UNKNOWN'
// #ifdef APP-PLUS
try {
type = 'APP_' + (plus.os.name === 'iOS' ? 'IOS' : 'ANDROID')
} catch (e) { type = 'APP' }
// #endif
// #ifdef MP-WEIXIN
type = 'MP'
// #endif
// #ifdef H5
const ua = (navigator.userAgent || '').toLowerCase()
if (ua.includes('micromessenger')) {
type = 'MP'
} else {
const isMobile = /android|iphone|ipad|ipod|blackberry|windows phone/i.test(ua)
type = isMobile ? 'H5' : 'PC'
}
// #endif
_clientType = type
return type
}
export const STORAGE_KEY_VISITOR = 'tracker_visitor_code'
export const STORAGE_KEY_SESSION = 'tracker_sessionId'
/**
* 读取 URL 上的 query 参数(宿主 webview 内嵌时由外部传入)
* 同时兼容 hash 路由:/#/pages/index?a=1 与 /?a=1#/pages/index
*/
export function getUrlParam(name) {
// #ifdef H5
try {
const raws = []
const search = (typeof window !== 'undefined' && window.location.search) || ''
const hash = (typeof window !== 'undefined' && window.location.hash) || ''
if (search) raws.push(search)
const i = hash.indexOf('?')
if (i > -1) raws.push(hash.slice(i))
const reg = new RegExp('[?&]' + name + '=([^&]*)')
for (let k = 0; k < raws.length; k++) {
const m = raws[k].match(reg)
if (m && m[1]) return decodeURIComponent(m[1])
}
} catch (e) {}
// #endif
// #ifdef APP-PLUS
try {
const wv = typeof plus !== 'undefined' && plus.webview && plus.webview.currentWebview()
const q = (wv && wv.query) || {}
if (q[name]) return String(q[name])
} catch (e) {}
// #endif
return ''
}
/**
* 运行时同步身份标识(优先级:显式入参 > URL 参数)
* @returns {Object} 最终生效的 { visitorCode, sessionId }(未变更的字段为 '')
*/
export function syncTrackerIdentity({ visitorCode = '', sessionId = '' } = {}) {
const code = visitorCode || getUrlParam('trackerVisitorCode')
const sess = sessionId || getUrlParam('trackerSessionId')
if (code) uni.setStorageSync(STORAGE_KEY_VISITOR, code)
if (sess) uni.setStorageSync(STORAGE_KEY_SESSION, sess)
return { visitorCode: code, sessionId: sess }
}
export function getVisitorCode() {
// URL 参数优先,且必须覆盖旧缓存(宿主每次外链都会带最新值)
let code = getUrlParam('trackerVisitorCode') || uni.getStorageSync(STORAGE_KEY_VISITOR)
if (!code) code = 'vis_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8)
uni.setStorageSync(STORAGE_KEY_VISITOR, code)
return code
}
/**
* 生成/读取 sessionId
* @param {boolean} forceNew true = 强制生成新会话(空闲超时续期用,忽略 URL/缓存)
* false = URL 参数 > 缓存 > 生成
*/
export function genSessionId(forceNew = false) {
if (!forceNew) {
const fromUrl = getUrlParam('trackerSessionId')
if (fromUrl) {
uni.setStorageSync(STORAGE_KEY_SESSION, fromUrl)
return fromUrl
}
const stored = uni.getStorageSync(STORAGE_KEY_SESSION)
if (stored) return stored
}
const sessionId = 'sess_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6)
uni.setStorageSync(STORAGE_KEY_SESSION, sessionId)
return sessionId
}
/**
* 三端通用:解析当前页面的 route / title / moduleCode / moduleName
* @param {Object} page 可选,页面实例
* @param {Object} pageMetaMap 可选,main.js 注入的 pages.json 映射表
*/
export function resolvePageInfo(page, pageMetaMap = {}) {
let route = ''
let pageInstance = page
try {
const pages = getCurrentPages()
const p = page || pages[pages.length - 1]
if (p) {
pageInstance = p
route = p.route || (p.$page && p.$page.path) || ''
}
} catch (e) {}
if (!route) return { url: '', title: '', moduleCode: '', moduleName: '' }
const key = route[0] === '/' ? route : '/' + route
// 1. 运行时 $page.meta(部分端/场景可用,作为覆盖)
let runtimeMeta = {}
try {
runtimeMeta = (pageInstance && pageInstance.$page && pageInstance.$page.meta) || {}
} catch (e) {}
// 2. main.js 注入的 pages.json 映射
const cfg = pageMetaMap[key] || {}
return {
url: key,
title: runtimeMeta.navigationBarTitleText || cfg.title || '',
moduleCode: runtimeMeta.moduleCode || cfg.moduleCode || '',
moduleName: runtimeMeta.moduleName || cfg.moduleName || ''
}
}
/** 安全 JSON 序列化(带大小校验) */
export function safeStringify(obj, maxSize) {
try {
const s = JSON.stringify(obj || {})
return s.length > maxSize ? null : s
} catch (e) {
return null
}
}
// #ifdef H5
export function sendBeacon(url, payload) {
try {
if (navigator.sendBeacon) {
const blob = new Blob([JSON.stringify(payload)], { type: 'application/json' })
return navigator.sendBeacon(url, blob)
}
} catch (e) {}
return false
}
// #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment