feat: 管理端聚合页、小程序/抖音埋点与统计、飞书线索 webhook、API 迁移与路由

- admin:OrdersHub/UsersHub、Commerce/Ops/Enterprise Hub、MpAnalytics、Feishu/小程序配置面板、鉴权存储
- api:Analytics、DataMigration、FeishuLeadWebhook、mp 事件迁移 SQL
- 微信/抖音小程序:analytics 上报与相关页面调整
- 开发文档与 scripts 补充

Made-with: Cursor
This commit is contained in:
卡若
2026-03-27 17:18:25 +08:00
parent 9601b6955b
commit aca2e263bb
188 changed files with 41937 additions and 27625 deletions

View File

@@ -0,0 +1,74 @@
/**
* 小程序埋点:批量上报 /api/analytics/events可选登录便于超管后台关联用户
*/
const { request } = require('./request.js')
const MAX_BATCH = 30
const queue = []
let lastPageReport = { path: '', t: 0 }
function getAppSafe() {
try {
return getApp()
} catch (e) {
return null
}
}
function getCurrentRoute() {
const pages = getCurrentPages()
const p = pages[pages.length - 1]
return p && p.route ? p.route : ''
}
function track(eventName, props) {
if (!eventName || typeof eventName !== 'string') return
const app = getAppSafe()
const openId =
app && app.globalData
? (app.globalData.openId || (app.globalData.userInfo && (app.globalData.userInfo.openid || app.globalData.userInfo.openId)) || '')
: ''
queue.push({
event_name: eventName,
page_path: getCurrentRoute(),
props: props && typeof props === 'object' ? props : {},
client_ts: Date.now(),
openid: openId || undefined
})
if (queue.length >= MAX_BATCH) {
flush()
}
}
/** 页面曝光(防抖:同路径 2 秒内只记一次) */
function reportPageView() {
const path = getCurrentRoute()
if (!path) return
const now = Date.now()
if (path === lastPageReport.path && now - lastPageReport.t < 2000) {
return
}
lastPageReport = { path, t: now }
track('page_view', { path })
}
function flush() {
if (queue.length === 0) return
const events = queue.splice(0, queue.length)
request({
url: '/api/analytics/events',
method: 'POST',
needAuth: true,
data: { events },
allow401: false,
success() {},
fail() {}
})
}
module.exports = {
track,
flush,
reportPageView,
getCurrentRoute
}