scanCheckin.js
4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
* @description 解析小程序码进入扫码打卡详情页时的 scene 参数
* @param {string} rawScene - scene 原始值,兼容 `detailId,activityId` 和 querystring 两种格式
* @returns {{activityId:string, detailId:string, rawScene:string}}
*/
export const parseScanCheckinSceneParams = (rawScene = '') => {
const normalizedScene = safeDecodeURIComponent(String(rawScene || '').trim())
if (!normalizedScene) {
return {
activityId: '',
detailId: '',
rawScene: '',
}
}
if (!normalizedScene.includes('=') && normalizedScene.includes(',')) {
const [detailId = '', activityId = ''] = normalizedScene.split(',').map(item => item.trim())
return {
activityId,
detailId,
rawScene: normalizedScene,
}
}
const rawParams = parseQueryString(normalizedScene)
return {
activityId: pickFirstAvailableValue(rawParams, ['activity_id', 'activityId', 'id']),
detailId: pickFirstAvailableValue(rawParams, ['detail_id', 'detailId', 'stage_id', 'stageId']),
rawScene: normalizedScene,
}
}
/**
* @description 从扫码结果中提取打卡接口所需参数
* @param {string} rawScanResult - 微信扫码返回的原始结果,可能是 path、完整URL,也可能是纯查询串
* @returns {{activityId:string, detailId:string, rawParams:Object, rawScene:string}}
*/
export const parseScanCheckinParams = (rawScanResult = '') => {
const normalized = String(rawScanResult || '').trim()
if (!normalized) {
return {
activityId: '',
detailId: '',
rawParams: {},
rawScene: '',
}
}
const querySource = extractQuerySource(normalized)
const rawParams = parseQueryString(querySource)
// 兼容 `pages/xxx?scene=detailId,activityId` 这种太阳码 path 场景。
const sceneParams = parseScanCheckinSceneParams(rawParams.scene || '')
return {
activityId:
sceneParams.activityId ||
pickFirstAvailableValue(rawParams, ['activity_id', 'activityId', 'id']),
detailId:
sceneParams.detailId ||
pickFirstAvailableValue(rawParams, ['detail_id', 'detailId', 'stage_id', 'stageId']),
rawParams,
rawScene: sceneParams.rawScene,
}
}
/**
* @description 判断当前详情页和扫码结果是否指向同一个打卡点
* @param {{activityId:string|number, detailId:string|number}} currentTarget
* @param {{activityId:string|number, detailId:string|number}} scannedTarget
* @returns {boolean}
*/
export const isSameScanCheckinTarget = (currentTarget = {}, scannedTarget = {}) => {
const currentActivityId = normalizeTargetValue(currentTarget.activityId)
const currentDetailId = normalizeTargetValue(currentTarget.detailId)
const scannedActivityId = normalizeTargetValue(scannedTarget.activityId)
const scannedDetailId = normalizeTargetValue(scannedTarget.detailId)
if (!currentActivityId || !currentDetailId || !scannedActivityId || !scannedDetailId) {
return false
}
return currentActivityId === scannedActivityId && currentDetailId === scannedDetailId
}
const extractQuerySource = input => {
const questionMarkIndex = input.indexOf('?')
if (questionMarkIndex >= 0) {
return input.slice(questionMarkIndex + 1)
}
return input
}
const parseQueryString = (queryString = '') => {
const hashRemoved = String(queryString || '').split('#')[0]
const pairs = hashRemoved.split('&').filter(Boolean)
return pairs.reduce((result, pair) => {
const [rawKey, ...rest] = pair.split('=')
const rawValue = rest.join('=')
const key = safeDecodeURIComponent(rawKey)
const value = safeDecodeURIComponent(rawValue)
if (key) {
result[key] = value
}
return result
}, {})
}
const pickFirstAvailableValue = (params, keys = []) => {
for (const key of keys) {
const value = params?.[key]
if (value !== '' && value !== undefined && value !== null) {
return String(value)
}
}
return ''
}
const normalizeTargetValue = value => String(value || '').trim()
const safeDecodeURIComponent = (value = '') => {
try {
return decodeURIComponent(String(value || '').replace(/\+/g, '%20'))
} catch (error) {
return String(value || '')
}
}