const INVITE_CONTEXT_KEY = 'inviteShareContext' const INVITE_DEVICE_KEY = 'inviteDeviceId' function isBlank(value) { return value === undefined || value === null || String(value).trim() === '' } function readCurrentRegionId() { try { const area = uni.getStorageSync('area') if (!area) return '' const data = typeof area === 'string' ? JSON.parse(area) : area return data && data.id ? String(data.id) : '' } catch (e) { return '' } } function appendParam(query, key, value) { if (isBlank(value)) return query.push(key + '=' + encodeURIComponent(String(value))) } export function getInviteDeviceId() { let deviceId = '' try { deviceId = uni.getStorageSync(INVITE_DEVICE_KEY) || '' } catch (e) {} if (deviceId) return deviceId deviceId = 'dev_' + Date.now() + '_' + Math.random().toString(36).slice(2, 12) try { uni.setStorageSync(INVITE_DEVICE_KEY, deviceId) } catch (e) {} return deviceId } export function getCurrentInviteParams() { return { inviterId: uni.getStorageSync('id') || '', regionId: readCurrentRegionId() } } export function normalizeInviteParams(params) { params = params || {} const inviterId = params.inviterId || params.inviteUserId || '' const regionId = params.regionId || params.inviteRegionId || '' return { inviterId: isBlank(inviterId) ? '' : String(inviterId), regionId: isBlank(regionId) ? '' : String(regionId) } } function resolveInviteParams(params, useCurrentFallback) { const invite = normalizeInviteParams(params) if ((!invite.inviterId || !invite.regionId) && useCurrentFallback) { const current = getCurrentInviteParams() if (!invite.inviterId) invite.inviterId = current.inviterId if (!invite.regionId) invite.regionId = current.regionId } return invite } function appendInviteParams(query, params, useCurrentFallback) { const invite = resolveInviteParams(params, useCurrentFallback) appendParam(query, 'inviterId', invite.inviterId) appendParam(query, 'regionId', invite.regionId) } export function rememberInviteParams(params) { const invite = normalizeInviteParams(params) if (!invite.inviterId || !invite.regionId) return invite try { uni.setStorageSync(INVITE_CONTEXT_KEY, invite) } catch (e) {} return invite } export function getStoredInviteParams() { try { const stored = uni.getStorageSync(INVITE_CONTEXT_KEY) if (!stored) return { inviterId: '', regionId: '' } return normalizeInviteParams(typeof stored === 'string' ? JSON.parse(stored) : stored) } catch (e) { return { inviterId: '', regionId: '' } } } export function parseQueryString(queryString) { const result = {} String(queryString || '').split('&').forEach((item) => { if (!item) return const pair = item.split('=') const key = pair[0] if (!key) return const value = pair.slice(1).join('=') try { result[key] = decodeURIComponent(value || '') } catch (e) { result[key] = value || '' } }) return result } export function extractInviteParamsFromUrl(url) { const value = String(url || '') const queryIndex = value.indexOf('?') if (queryIndex === -1) return { inviterId: '', regionId: '' } return normalizeInviteParams(parseQueryString(value.slice(queryIndex + 1))) } export function buildInviteHomeSharePath(params) { params = params || {} const query = ['shareType=invite'] if (!isBlank(params.tabIndex)) { appendParam(query, 'tabIndex', params.tabIndex) } appendInviteParams(query, params, true) return '/pages/index/index?' + query.join('&') } export function buildHomeSharePath(targetPath, params) { const inviteQuery = [] appendInviteParams(inviteQuery, params || {}, true) if (!targetPath) { return inviteQuery.length > 0 ? '/pages/index/index?' + inviteQuery.join('&') : '/pages/index/index' } let finalTargetPath = targetPath if (inviteQuery.length > 0) { finalTargetPath += (finalTargetPath.indexOf('?') === -1 ? '?' : '&') + inviteQuery.join('&') } return '/pages/index/index?targetPath=' + encodeURIComponent(finalTargetPath) } export function buildGroupHomeSharePath(params) { params = params || {} const query = [ 'shareType=group', 'type=shop', 'shopId=' + encodeURIComponent(params.shopId || ''), 'groupId=' + encodeURIComponent(params.groupId || ''), 'targetMembers=' + encodeURIComponent(params.targetMembers || 2), 'isFaceToFace=' + encodeURIComponent(params.isFaceToFace || 0) ] if (params.orderScene) { query.push('orderScene=' + encodeURIComponent(params.orderScene)) } appendInviteParams(query, params, true) return '/pages/index/index?' + query.join('&') } export function buildGroupTargetPath(params) { params = params || {} if (!params.shopId || !params.groupId) return '' let targetPath = '/package2/group/groupBuySingle?type=shop' + '&shopId=' + encodeURIComponent(params.shopId) + '&groupId=' + encodeURIComponent(params.groupId) + '&targetMembers=' + encodeURIComponent(params.targetMembers || 2) + '&isFaceToFace=' + encodeURIComponent(params.isFaceToFace || 0) if (params.orderScene) { targetPath += '&orderScene=' + encodeURIComponent(params.orderScene) } const inviteQuery = [] appendInviteParams(inviteQuery, params, false) if (inviteQuery.length > 0) { targetPath += '&' + inviteQuery.join('&') } return targetPath } export function buildGroupShopTargetPath(shopId) { if (!shopId) return '' return '/package2/group/groupBuySingle?type=shop&shopId=' + encodeURIComponent(shopId) } export function resolveMiniCodeSceneTarget(scene) { let value = String(scene || '').trim() if (!value) return '' try { value = decodeURIComponent(value) } catch (e) {} if (!value) return '' if (value.indexOf('groupShop:') === 0) { return buildGroupShopTargetPath(value.replace('groupShop:', '')) } if (/^s[A-Za-z0-9_-]{1,31}$/.test(value)) { return buildGroupShopTargetPath(value.slice(1)) } return '' } export function normalizeShareTargetPath(value) { let targetPath = String(value || '') if (targetPath.indexOf('%2F') === 0 || targetPath.indexOf('%2f') === 0) { try { targetPath = decodeURIComponent(targetPath) } catch (e) {} } if (!targetPath || targetPath.charAt(0) !== '/') return '' if (targetPath.indexOf('/pages/index/index') === 0) return '' return targetPath } export function resolveHomeShareTarget(query) { query = query || {} rememberInviteParams(query) if (query.shareType === 'group') { return buildGroupTargetPath(query) } if (query.targetPath) { return normalizeShareTargetPath(query.targetPath) } return '' } export function isShareEnterScene(options) { if (!options || options.scene == null) return false const scene = Number(options.scene) return scene === 1007 || scene === 1008 || scene === 1044 || scene === 1154 } export function getEnterShareTarget(options) { if (!options) { try { if (uni.getEnterOptionsSync) { options = uni.getEnterOptionsSync() } else if (uni.getLaunchOptionsSync) { options = uni.getLaunchOptionsSync() } } catch (e) {} } if (!isShareEnterScene(options)) return '' return resolveHomeShareTarget(options && options.query) } // 同一次分享进入只跳转一次。小程序切回前台、关闭图片预览都会再次触发 onShow, // 且 App.onShow 仍可能带上最初的分享参数。 const handledShareTargets = Object.create(null) export function stageShareEnter(options) { rememberInviteParams(options && options.query) const targetPath = resolveMiniCodeSceneTarget(options && options.query && options.query.scene) || getEnterShareTarget(options) if (!targetPath) return { targetPath: '', alreadyHandled: false } if (handledShareTargets[targetPath]) return { targetPath: '', alreadyHandled: true } return { targetPath: targetPath, alreadyHandled: false } } export function isShareTargetHandled(targetPath) { return !!(targetPath && handledShareTargets[targetPath]) } export function completeShareEnter(targetPath) { if (targetPath) handledShareTargets[targetPath] = true } export function reopenShareEnter(targetPath) { if (targetPath) delete handledShareTargets[targetPath] } let suppressShareRedirectOnce = false export function suppressNextShareRedirect() { suppressShareRedirectOnce = true } export function consumeShareRedirectSuppression() { if (!suppressShareRedirectOnce) return false suppressShareRedirectOnce = false return true } export function getCurrentEnterShareTarget() { let options = null try { if (uni.getEnterOptionsSync) { options = uni.getEnterOptionsSync() } else if (uni.getLaunchOptionsSync) { options = uni.getLaunchOptionsSync() } } catch (e) {} return getEnterShareTarget(options) }