Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
CFFP-HB
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chao Sun
CFFP-HB
Commits
658e8104
Commit
658e8104
authored
Nov 13, 2026
by
yuzhenWang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
实现分享上报发布测试
parent
829addd4
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
288 additions
and
28 deletions
+288
-28
index.html
+83
-0
myPackageA/businessCard/businessCard.vue
+7
-1
pages/courseDetail/courseDetail.vue
+18
-0
pages/courselist/courselist.vue
+19
-9
pages/inviteJoin/inviteJoin.vue
+9
-0
static/js/vconsole.min.js
+0
-0
util/fiveshare.ts
+9
-1
util/interceptor.ts
+16
-14
util/tracker/collector-dom.js
+14
-0
util/tracker/config.js
+1
-0
util/tracker/core.js
+46
-2
util/tracker/index.js
+35
-0
util/tracker/manual.js
+31
-1
No files found.
index.html
View file @
658e8104
...
...
@@ -3,6 +3,89 @@
<head>
<meta
charset=
"UTF-8"
/>
<script>
// ============ 真机调试:vConsole 控制台 ============
// 默认开启:公众号/微信里打开 CFFP 即出现右下角绿色 vConsole 按钮,无需带参数
// 关闭:URL 追加 ?vconsole=0(本机记住,之后不再自动开);恢复:?vconsole=1
// 上线前如需全量关闭:把下面 VCONSOLE_DEFAULT_ON 改成 false
(
function
()
{
try
{
var
VCONSOLE_DEFAULT_ON
=
false
;
var
qs
=
(
location
.
search
||
''
)
+
'&'
+
(
location
.
hash
||
''
);
var
m
=
qs
.
match
(
/
[
?&
]
vconsole=
(
1|true|0|false
)
/i
);
var
offFlag
=
localStorage
.
getItem
(
'__vconsole_off'
)
===
'1'
;
var
on
=
false
;
if
(
m
)
{
// URL 显式指定优先级最高
if
(
/^
(
1|true
)
$/i
.
test
(
m
[
1
]))
{
on
=
true
;
localStorage
.
removeItem
(
'__vconsole_off'
);
}
else
{
on
=
false
;
localStorage
.
setItem
(
'__vconsole_off'
,
'1'
);
}
}
else
{
// 无参数:默认开启,但尊重本机上次的手动关闭
on
=
VCONSOLE_DEFAULT_ON
&&
!
offFlag
;
}
if
(
!
on
)
return
;
// vConsole 加载前的日志先缓存,就绪后补打出来
var
buf
=
[],
MAX
=
300
,
replayed
=
false
;
var
methods
=
[
'log'
,
'info'
,
'warn'
,
'error'
];
methods
.
forEach
(
function
(
name
)
{
var
orig
=
console
[
name
]
?
console
[
name
].
bind
(
console
)
:
function
()
{};
console
[
name
]
=
function
()
{
try
{
if
(
!
replayed
&&
buf
.
length
<
MAX
)
{
buf
.
push
([
name
,
Array
.
prototype
.
slice
.
call
(
arguments
)]);
}
}
catch
(
e
)
{}
orig
.
apply
(
null
,
arguments
);
};
});
function
replay
()
{
try
{
var
list
=
buf
;
buf
=
[];
replayed
=
true
;
list
.
forEach
(
function
(
it
)
{
(
console
[
it
[
0
]]
||
console
.
log
).
apply
(
console
,
it
[
1
]);
});
}
catch
(
e
)
{}
}
function
boot
()
{
try
{
window
.
vConsole
=
new
window
.
VConsole
({
theme
:
'light'
,
maxLogNumber
:
1000
,
onReady
:
function
()
{
replay
();
console
.
log
(
'%c[vConsole] 已就绪 → 分享后在 Log 里看 [Tracker] 日志'
,
'color:#1565c0;font-weight:bold'
);
}
});
}
catch
(
e
)
{
console
.
error
(
'[vConsole] 初始化失败'
,
e
);
}
}
function
load
(
src
,
onError
)
{
var
s
=
document
.
createElement
(
'script'
);
s
.
src
=
src
;
s
.
onload
=
boot
;
s
.
onerror
=
onError
||
function
()
{
console
.
warn
(
'[vConsole] 脚本加载失败: '
+
src
);
};
document
.
head
.
appendChild
(
s
);
}
// 本地优先(微信内更稳),失败回退 CDN
load
(
'./static/js/vconsole.min.js'
,
function
()
{
load
(
'https://cdn.jsdelivr.net/npm/vconsole@3.15.1/dist/vconsole.min.js'
);
});
}
catch
(
e
)
{
console
.
warn
(
'[vConsole] 加载器异常'
,
e
);
}
})();
// ============ vConsole 结束 ============
</script>
<script>
// ============ 新增:解析 URL 参数并设置状态栏占位 ============
//解决项目以h5的方式内嵌到app的webview中,手机状态栏和页面顶部内容重叠的问题
(
function
()
{
...
...
myPackageA/businessCard/businessCard.vue
View file @
658e8104
...
...
@@ -319,7 +319,8 @@
import
customSegmentedControl
from
'@/components/customSegmentedControl/customSegmentedControl.vue'
;
import
wx
from
'weixin-js-sdk'
import
{
previewImages
}
from
'@/util/previewImage.js'
;
import
{
trackShare
}
from
'@/util/tracker/manual.js'
;
export
default
{
name
:
'businessCard'
,
components
:
{
...
...
@@ -835,6 +836,11 @@
cardId
:
this
.
cardId
,
commonId
:
this
.
userId
}
// 手动埋点:上报用户分享操作
trackShare
(
shareInfo
.
title
,
''
,
{
sharePage
:
shareInfo
.
sharePage
,
channel
:
'wechat-miniprogram'
})
wx
.
miniProgram
.
postMessage
({
data
:
{
type
:
'share'
,
...
...
pages/courseDetail/courseDetail.vue
View file @
658e8104
...
...
@@ -270,6 +270,10 @@
import
ShareGuide
from
'@/components/ShareGuide/ShareGuide.vue'
;
import
wx
from
'weixin-js-sdk'
import
{
previewImages
}
from
'@/util/previewImage.js'
;
import
{
trackShare
}
from
'@/util/tracker/manual.js'
;
export
default
{
components
:
{
UniShareWx
,
...
...
@@ -493,6 +497,20 @@
shareCode
:
shareCode
,
isSaveShare
:
'1'
,
//是否存贮分享便于统计分享数据
}
// 手动埋点:上报用户分享操作
trackShare
(
shareInfo
.
title
,
''
,
{
shareCode
:
shareInfo
.
shareCode
,
fileId
:
shareInfo
.
fileId
,
sharePage
:
shareInfo
.
sharePage
,
channel
:
'wechat-miniprogram'
})
// 手动埋点:上报用户分享操作
trackShare
(
shareInfo
.
title
,
''
,
{
shareCode
:
shareInfo
.
shareCode
,
fileId
:
shareInfo
.
fileId
,
sharePage
:
shareInfo
.
sharePage
,
channel
:
'wechat-miniprogram'
})
wx
.
miniProgram
.
postMessage
({
data
:
{
type
:
'share'
,
...
...
pages/courselist/courselist.vue
View file @
658e8104
...
...
@@ -158,6 +158,8 @@
import
UQRCode
from
'uqrcodejs'
;
import
wx
from
'weixin-js-sdk'
import
{
elementToImage
}
from
'@/util/htmlToImage'
;
import
{
trackShare
}
from
'@/util/tracker/manual.js'
;
export
default
{
name
:
'courselist'
,
props
:
{
...
...
@@ -405,16 +407,24 @@
shareCode
:
shareCode
,
isSaveShare
:
'1'
,
//是否存贮分享便于统计分享数据
}
wx
.
miniProgram
.
postMessage
({
data
:
{
type
:
'share'
,
shareData
:
JSON
.
stringify
(
shareInfo
),
messageId
:
nanoid
()
// 唯一消息ID
}
// 手动埋点:上报用户分享操作
trackShare
(
shareInfo
.
title
,
''
,
{
shareCode
:
shareInfo
.
shareCode
,
fileId
:
shareInfo
.
fileId
,
sharePage
:
shareInfo
.
sharePage
,
channel
:
'wechat-miniprogram'
})
return
wx
.
miniProgram
.
postMessage
({
data
:
{
type
:
'share'
,
shareData
:
JSON
.
stringify
(
shareInfo
),
messageId
:
nanoid
()
// 唯一消息ID
}
})
return
}
this
.
getshareData2
(
shareCode
,
jumptime
,
this
.
shareItem
)
// #endif
...
...
pages/inviteJoin/inviteJoin.vue
View file @
658e8104
...
...
@@ -127,6 +127,7 @@
import
wx
from
'weixin-js-sdk'
import
restrictedTip
from
'@/components/commonPopup/restrictedTip.vue'
;
import
{
nanoid
}
from
'nanoid'
;
import
{
trackShare
}
from
'@/util/tracker/manual.js'
;
export
default
{
components
:
{
sharePosterPop
,
...
...
@@ -369,6 +370,14 @@
sharePage
:
'applyFranchise'
,
//分享出去得页面,
}
// 手动埋点:上报用户分享操作
trackShare
(
shareInfo
.
title
,
''
,
{
invitationCode
:
this
.
invitationCode
,
inviteUserId
:
this
.
inviteUserId
,
shareId
:
this
.
shareId
,
sharePage
:
shareInfo
.
sharePage
,
channel
:
'wechat-miniprogram'
})
wx
.
miniProgram
.
postMessage
({
data
:
{
type
:
'share'
,
...
...
static/js/vconsole.min.js
0 → 100644
View file @
658e8104
This source diff could not be displayed because it is too large. You can
view the blob
instead.
util/fiveshare.ts
View file @
658e8104
// fiveshare.ts
import
api
from
"../api/api"
;
import
{
shareURL
}
from
"@/environments/environment"
;
import
{
trackShare
}
from
"./tracker/manual.js"
;
let
userInfo
=
{
name
:
''
};
if
(
uni
.
getStorageSync
(
'cffp_userInfo'
))
{
...
...
@@ -147,7 +148,13 @@ export function setWechatShare(data: any) {
// 在微信浏览器中执行
if
(
isWechatBrowser
())
{
const
shareData
=
getShareData
(
data
);
// 手动埋点:仅在传入真实分享数据时上报(无参调用属于重置默认分享配置,不计分享行为)
if
(
data
)
{
trackShare
(
shareData
.
title
,
''
,
{
channel
:
'h5-wechat'
});
}
// 确保 SDK 已加载
ensureWechatSDK
().
then
(()
=>
{
// @ts-ignore
...
...
@@ -212,6 +219,7 @@ export function hshare(data: any, url: string) {
// ===== 降级方案 =====
function
fallbackShare
(
data
:
any
)
{
console
.
log
(
'📋 降级方案:复制链接'
,
data
.
link
);
try
{
// @ts-ignore
if
(
typeof
uni
!==
'undefined'
&&
uni
.
setClipboardData
)
{
...
...
util/interceptor.ts
View file @
658e8104
...
...
@@ -97,20 +97,22 @@
// 旧版的拦截器
import
{
apiURL
,
cffpURL
,
sfpUrl
}
from
"../environments/environment"
;
import
{
apiURL
,
cffpURL
,
sfpUrl
,
scrmUrl
}
from
"../environments/environment"
;
import
api
from
"@/api/api"
;
// 白名单,不需要携带token就允许被访问的接口
const
whiteApiList
=
[
`
${
apiURL
}
/authorize/obtainToken`
,
`
${
apiURL
}
/authorize/checkToken`
,
`
${
cffpURL
}
/user/loginVerification`
,
`
${
apiURL
}
/appVersion/checkIsUpdate`
,
`
${
cffpURL
}
/accessLog/accessLogSave`
,
`
${
cffpURL
}
/user/powerQuery`
,
`
${
cffpURL
}
/user/wxLogin`
,
`
${
cffpURL
}
/certificate/officialWebsiteDetail`
,
`
${
apiURL
}
/verificationCode`
,
`
${
sfpUrl
}
/sfp/sfpMain/pocessTracking`
,
`
${
cffpURL
}
/partner/queryById`
,
];
const
whiteApiList
=
[
`
${
scrmUrl
}
/scrm-api/log/client/batch/save`
,
`
${
apiURL
}
/authorize/obtainToken`
,
`
${
apiURL
}
/authorize/checkToken`
,
`
${
cffpURL
}
/user/loginVerification`
,
`
${
apiURL
}
/appVersion/checkIsUpdate`
,
`
${
cffpURL
}
/accessLog/accessLogSave`
,
`
${
cffpURL
}
/user/powerQuery`
,
`
${
cffpURL
}
/user/wxLogin`
,
`
${
cffpURL
}
/certificate/officialWebsiteDetail`
,
`
${
apiURL
}
/verificationCode`
,
`
${
sfpUrl
}
/sfp/sfpMain/pocessTracking`
,
`
${
cffpURL
}
/partner/queryById`
,
];
export
const
interceptor
=
()
=>
{
uni
.
addInterceptor
(
'request'
,
{
// 请求拦截器
...
...
@@ -136,8 +138,8 @@ export const interceptor = () => {
success
:
(
res
)
=>
{
if
(
res
.
statusCode
===
200
)
{
uni
.
setStorageSync
(
'uni-token'
,
res
.
data
[
'data'
][
'token'
]);
let
isHas
=
window
.
location
.
href
.
indexOf
(
'?'
)
==-
1
?
'?'
:
'&'
;
window
.
location
.
href
=
window
.
location
.
href
+
isHas
+
't_reload='
+
new
Date
().
getTime
();
//
let isHas = window.location.href.indexOf('?')==-1?'?':'&';
//
window.location.href = window.location.href + isHas + 't_reload=' + new Date().getTime();
}
}
})
...
...
util/tracker/collector-dom.js
View file @
658e8104
...
...
@@ -203,6 +203,16 @@ function buildInfo(el, e) {
}
}
/** 输入元素是否已脱离文档或不可见(页面切换时旧页输入框失焦、临时复制元素等) */
function
isDetachedOrHidden
(
el
)
{
if
(
!
el
.
isConnected
)
return
true
if
(
el
.
getClientRects
&&
el
.
getClientRects
().
length
===
0
)
return
true
// uni-app H5:隐藏页面的 uni-page 容器为 display:none
const
page
=
el
.
closest
&&
el
.
closest
(
'uni-page'
)
if
(
page
&&
page
.
getClientRects
&&
page
.
getClientRects
().
length
===
0
)
return
true
return
false
}
export
function
setupDomCollector
(
tracker
)
{
if
(
typeof
document
===
'undefined'
)
return
...
...
@@ -242,6 +252,10 @@ export function setupDomCollector(tracker) {
const
inputEl
=
isInputEl
(
el
)
// ★★ 输入元素不可见/已脱离文档时不算用户操作:
// 页面切换瞬间旧页输入框失焦会晚于新页 onShow,不拦会错误归因到新页面
if
(
inputEl
&&
isDetachedOrHidden
(
el
))
return
// ★★★ 输入框的 click 一律跳过(聚焦/点选不算"操作完成")★★★
if
(
e
.
type
===
'click'
&&
(
inputEl
||
(
el
.
closest
&&
el
.
closest
(
'uni-input, uni-textarea, .van-field'
))))
return
...
...
util/tracker/config.js
View file @
658e8104
export
default
{
enabled
:
false
,
// 全局开关(可由后端配置下发动态修改)
debug
:
true
,
// 控制台输出上报明细(排查用;确认无误后可关闭)
projectCode
:
'CFFP'
,
api
:
'/api/log/batch'
,
batchSize
:
10
,
// 攒多少条触发上报
...
...
util/tracker/core.js
View file @
658e8104
...
...
@@ -24,6 +24,8 @@ import {
export
default
class
Tracker
{
constructor
(
cfg
)
{
this
.
cfg
=
cfg
this
.
debug
=
cfg
.
debug
!==
false
// ← 控制台输出上报明细
this
.
_lastPayload
=
null
// ← 最近一次请求体(供控制台排查)
this
.
pageMetaMap
=
cfg
.
pageMetaMap
||
{}
// ← 持有映射表
this
.
_enabled
=
!!
cfg
.
enabled
this
.
queue
=
[]
...
...
@@ -298,7 +300,21 @@ export default class Tracker {
this
.
queue
.
push
(
item
)
if
(
this
.
queue
.
length
>
this
.
cfg
.
maxQueue
)
this
.
queue
.
shift
()
if
(
this
.
debug
)
{
console
.
log
(
`%c[Tracker] 入队
${
eventCode
}
|
${
item
.
actionTargetName
}
`
,
'color:#2e7d32;font-weight:bold'
,
{
funcCode
,
moduleCode
,
pageUrl
:
item
.
pageUrl
,
actionTargetType
:
item
.
actionTargetType
,
actionTarget
:
item
.
actionTarget
,
extraParams
:
extra
,
queue
:
this
.
queue
.
length
}
)
}
if
(
this
.
queue
.
length
>=
this
.
cfg
.
batchSize
)
this
.
flush
()
else
this
.
_schedule
()
}
...
...
@@ -325,12 +341,20 @@ export default class Tracker {
const
batch
=
this
.
queue
.
splice
(
0
,
this
.
cfg
.
maxBatch
)
let
ok
=
false
if
(
this
.
debug
)
{
console
.
log
(
`%c[Tracker] 上报
${
batch
.
length
}
条 →
${
this
.
cfg
.
api
}
`
,
'color:#1565c0;font-weight:bold'
,
batch
.
map
(
i
=>
({
event
:
i
.
eventCode
,
func
:
i
.
funcCode
,
target
:
i
.
actionTargetName
}))
)
}
try
{
await
this
.
_send
(
batch
)
ok
=
true
this
.
_retry
=
0
}
catch
(
e
)
{
this
.
_retry
++
if
(
this
.
debug
)
console
.
warn
(
`[Tracker] 上报异常,第
${
this
.
_retry
}
次重试`
,
e
&&
e
.
message
)
if
(
this
.
_retry
<=
this
.
cfg
.
maxRetry
)
{
// 回滚到队头,指数退避
this
.
queue
.
unshift
(...
batch
)
...
...
@@ -353,6 +377,10 @@ export default class Tracker {
visitorCode
:
this
.
visitorCode
,
saveRequestList
:
list
}
this
.
_lastPayload
=
payload
if
(
this
.
debug
)
{
console
.
log
(
'%c[Tracker] 请求体'
,
'color:#1565c0'
,
JSON
.
parse
(
JSON
.
stringify
(
payload
)))
}
return
new
Promise
((
resolve
,
reject
)
=>
{
uni
.
request
({
url
:
this
.
cfg
.
api
,
...
...
@@ -361,10 +389,23 @@ export default class Tracker {
header
:
{
'Content-Type'
:
'application/json'
},
timeout
:
10000
,
success
:
(
res
)
=>
{
if
(
this
.
debug
)
{
const
pass
=
res
.
statusCode
>=
200
&&
res
.
statusCode
<
300
console
.
log
(
`%c[Tracker]
${
pass
?
'✅ 上报成功'
:
'❌ 上报失败'
}
HTTP
${
res
.
statusCode
}
`
,
`color:
${
pass
?
'#2e7d32'
:
'#c62828'
}
;font-weight:bold`
,
res
.
data
)
}
if
(
res
.
statusCode
>=
200
&&
res
.
statusCode
<
300
)
resolve
()
else
reject
(
new
Error
(
'HTTP '
+
res
.
statusCode
))
},
fail
:
reject
fail
:
(
err
)
=>
{
if
(
this
.
debug
)
{
console
.
error
(
'[Tracker] ❌ 请求发送失败(接口地址/跨域/网络问题)'
,
this
.
cfg
.
api
,
err
)
}
reject
(
err
)
}
})
})
}
...
...
@@ -377,6 +418,9 @@ export default class Tracker {
visitorCode
:
this
.
visitorCode
,
saveRequestList
:
this
.
queue
.
splice
(
0
)
}
if
(
this
.
debug
)
{
console
.
warn
(
'[Tracker] 页面隐藏,走 sendBeacon 兜底上报(控制台看不到响应,属正常)'
,
payload
.
saveRequestList
.
length
,
'条'
)
}
// #ifdef H5
if
(
sendBeaconSafe
(
this
.
cfg
.
api
,
payload
))
return
// #endif
...
...
util/tracker/index.js
View file @
658e8104
...
...
@@ -13,6 +13,41 @@ export function initTracker(options = {}) {
_instance
=
new
Tracker
(
config
)
bindTracker
(
_instance
)
// #ifdef H5
// 控制台调试入口:__tracker.info() / queue() / last() / flush() / debug(false)
if
(
typeof
window
!==
'undefined'
)
{
window
.
__tracker
=
{
instance
:
_instance
,
info
:
()
=>
({
enabled
:
_instance
.
enabled
,
api
:
config
.
api
,
sessionId
:
_instance
.
sessionId
,
visitorCode
:
_instance
.
visitorCode
,
queue
:
_instance
.
queue
.
length
,
clientType
:
_instance
.
clientType
,
page
:
_instance
.
currentPage
}),
queue
:
()
=>
JSON
.
parse
(
JSON
.
stringify
(
_instance
.
queue
)),
last
:
()
=>
(
_instance
.
_lastPayload
?
JSON
.
parse
(
JSON
.
stringify
(
_instance
.
_lastPayload
))
:
null
),
flush
:
()
=>
{
_instance
.
flush
(
true
);
return
'已触发立即上报,看下方 [Tracker] 日志'
},
// 不点分享也能验证「前端→后端」链路是否通
testShare
:
(
title
=
'调试分享'
,
link
=
location
.
href
)
=>
{
_instance
.
trackFunc
(
'share_to_friend'
,
{
shareTitle
:
title
,
shareLink
:
link
},
{
eventCode
:
'share'
,
actionTargetType
:
'button'
,
actionTarget
:
'share'
,
actionTargetName
:
`(分销)
${
title
}
-->
${
link
}
`
,
remark
:
'分销分享'
})
_instance
.
flush
(
true
)
return
'已发送一条 share 测试事件'
},
debug
:
(
on
=
true
)
=>
{
_instance
.
debug
=
!!
on
;
return
`debug =
${
_instance
.
debug
}
`
}
}
console
.
log
(
'%c[Tracker] 控制台入口已就绪 → __tracker.info() / __tracker.queue() / __tracker.last() / __tracker.flush()'
,
'color:#1565c0'
)
}
// #endif
// 延迟初始化,避免抢占首屏资源
setTimeout
(()
=>
{
// #ifdef H5 || APP-PLUS
...
...
util/tracker/manual.js
View file @
658e8104
...
...
@@ -15,7 +15,7 @@
* trackEvent(FUNCTIONS.WECHAT_LOGIN, { target: 'login_phone_success', name: '手机号快捷登录成功' }) // eventCode 由 funcCode 推导
*/
import
{
useTracker
}
from
'./index'
import
{
EVENTS
}
from
'./track-events'
import
{
EVENTS
,
FUNCTIONS
}
from
'./track-events'
function
_report
(
funcCode
,
extra
,
overrides
)
{
try
{
...
...
@@ -105,3 +105,33 @@ export function trackView(funcCode, target, name, extra = {}, targetType = 'page
remark
:
`查看
${
name
}
`
})
}
/**
* 分享类:拉起分享(小程序 postMessage / H5 jssdk 分享 / 降级复制链接)
* actionTargetName 口径:(分销)标题(链接不拼进名称,只在 extraParams.shareLink 里)
* @param {*} title 分享标题(shareInfo.title)
* @param {*} link 分享链接(shareInfo.link)
* @param {Object} extra 额外扩展字段(如 shareCode / fileId / sharePage)
*/
export
function
trackShare
(
title
,
link
,
extra
=
{})
{
const
t
=
title
===
undefined
||
title
===
null
?
''
:
String
(
title
)
const
l
=
link
===
undefined
||
link
===
null
?
''
:
String
(
link
)
trackEvent
(
FUNCTIONS
.
SHARE_TO_FRIEND
,
{
target
:
'share'
,
name
:
`(分销)
${
t
}
`
,
targetType
:
'button'
,
eventCode
:
EVENTS
.
SHARE
,
extra
:
Object
.
assign
({
shareTitle
:
t
},
l
?
{
shareLink
:
l
}
:
{},
extra
),
remark
:
'分销分享'
})
// 分享是关键事件:立即上报,不等 5s 批量窗口
try
{
const
inst
=
useTracker
()
if
(
inst
&&
inst
.
enabled
)
{
console
.
log
(
'%c[Tracker] 分享事件 → 立即上报'
,
'color:#2e7d32;font-weight:bold'
,
{
title
:
t
,
link
:
l
,
extra
})
inst
.
flush
(
true
)
}
}
catch
(
e
)
{
console
.
warn
(
'[Tracker] 分享事件立即上报失败'
,
e
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment