Files
lilishop-uniapp/utils/distributionBind.js
pikachu1995@126.com 4b1a09cbc3 feat(distribution): 增强分销功能与界面优化
- 新增银行卡管理页面,支持用户查看与管理银行卡。
- 实现添加、删除及设置默认银行卡功能。
- 优化邀请与加入页面,展示邀请人信息并改进用户提示。
- 更新海报与二维码生成逻辑,提升用户体验。
- 重构多个组件,提高可读性与可维护性。
2026-08-11 15:43:21 +08:00

191 lines
4.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 分销海报 / 商品分享扫码绑客(统一入口)
*/
import storage from '@/utils/storage.js'
import store from '@/store'
import { getGoodsDistribution } from '@/api/distribution.js'
import { getMpScene } from '@/api/goods.js'
const PENDING_KEY = 'pending_distribution_id'
/** 本次冷启动内已尝试绑定的分销员 ID避免重复请求 */
const launchBoundIds = new Set()
let flushing = false
export function clearPendingDistributionId() {
try {
uni.removeStorageSync(PENDING_KEY)
} catch (e) {
// ignore
}
}
export function setPendingDistributionId(distributionId) {
if (!distributionId) return
try {
uni.setStorageSync(PENDING_KEY, String(distributionId))
} catch (e) {
console.warn('set pending distributionId failed', e)
}
}
export function getPendingDistributionId() {
try {
return uni.getStorageSync(PENDING_KEY) || ''
} catch (e) {
return ''
}
}
export function resetLaunchBindCache() {
launchBoundIds.clear()
}
/**
* 解析葵花码 scene支持 shortLinkId 或明文 bind,{distributionId}
*/
export async function resolveDistributionIdFromScene(scene) {
if (!scene) return ''
const raw = decodeURIComponent(String(scene)).trim()
if (!raw) return ''
if (raw.startsWith('bind,')) {
const id = raw.split(',')[1]
return id ? String(id).trim() : ''
}
try {
const res = await getMpScene(raw)
const params = res?.data?.success ? String(res.data.result || '').trim() : ''
if (params.startsWith('bind,')) {
const id = params.split(',')[1]
return id ? String(id).trim() : ''
}
} catch (error) {
console.warn('resolve distribution scene failed', error)
}
return ''
}
function parseRecruitIdFromParams(params) {
if (!params) return ''
const text = String(params).trim()
if (text.startsWith('recruit_')) {
const id = text.substring('recruit_'.length)
return id ? String(id).trim() : ''
}
return ''
}
/**
* 解析图文邀请卡 scene支持 shortLinkId 或明文 recruit_{distributionId}
*/
export async function resolveRecruitDistributionIdFromScene(scene) {
if (!scene) return ''
const raw = decodeURIComponent(String(scene)).trim()
if (!raw) return ''
const direct = parseRecruitIdFromParams(raw)
if (direct) return direct
try {
const res = await getMpScene(raw)
const params = res?.data?.success ? String(res.data.result || '').trim() : ''
return parseRecruitIdFromParams(params)
} catch (error) {
console.warn('resolve recruit scene failed', error)
}
return ''
}
const CLEAR_PENDING_CODES = new Set([22000, 22001])
function shouldClearPendingOnFailure(res) {
const code = res?.data?.code
if (code != null && CLEAR_PENDING_CODES.has(Number(code))) {
return true
}
const message = String(res?.data?.message || '')
if (message.includes('分销员不存在') || message.includes('分销功能关闭')) {
return true
}
return false
}
/**
* 尝试绑定分销员:已登录直接请求;未登录写入 pending
*/
export async function tryBindDistribution(distributionId, options = {}) {
const id = String(distributionId || '').trim()
if (!id) return
const force = options.force === true
if (!force && launchBoundIds.has(id)) {
return
}
launchBoundIds.add(id)
if (!storage.getAccessToken()) {
setPendingDistributionId(id)
store.state.distributionId = id
return
}
try {
const res = await getGoodsDistribution(id)
if (res?.data?.success) {
clearPendingDistributionId()
store.state.distributionId = id
return
}
if (shouldClearPendingOnFailure(res)) {
clearPendingDistributionId()
}
} catch (error) {
console.warn('bind distribution failed', error)
const res = error?.data ? error : error?.response?.data ? { data: error.response.data } : null
if (res && shouldClearPendingOnFailure(res)) {
clearPendingDistributionId()
}
}
}
/**
* 登录成功后补绑 pending
*/
export async function flushPendingBind() {
if (flushing) return
const pendingId = getPendingDistributionId()
if (!pendingId || !storage.getAccessToken()) {
return
}
flushing = true
try {
launchBoundIds.delete(pendingId)
await tryBindDistribution(pendingId, { force: true })
} finally {
flushing = false
}
}
/**
* App onLaunch有 scene 则解析绑客;无 scene 清除 pending
*/
export async function handleAppLaunchScene(options) {
resetLaunchBindCache()
const scene = options?.query?.scene
if (!scene) {
clearPendingDistributionId()
return
}
const distributionId = await resolveDistributionIdFromScene(scene)
if (!distributionId) {
return
}
await tryBindDistribution(distributionId)
}