import Taro from '@tarojs/taro' import { bindRefereeRelation } from '@/api/invite' /** * 邀请参数接口 */ export interface InviteParams { inviter?: string; source?: string; t?: string; } /** * 解析小程序启动参数中的邀请信息 */ export function parseInviteParams(options: any): InviteParams | null { try { // 从 scene 参数中解析邀请信息 if (options.scene) { // 确保 scene 是字符串类型 const sceneStr = typeof options.scene === 'string' ? options.scene : String(options.scene) console.log('解析scene参数:', sceneStr) // 处理 uid_xxx 格式的邀请码 if (sceneStr.startsWith('uid_')) { const inviterId = sceneStr.replace('uid_', '') if (inviterId && !isNaN(parseInt(inviterId))) { console.log('检测到uid格式邀请码:', inviterId) return { inviter: inviterId, source: 'qrcode', t: Date.now().toString() } } } // 处理传统的 key=value&key=value 格式 const params: InviteParams = {} const pairs = sceneStr.split('&') pairs.forEach((pair: string) => { const [key, value] = pair.split('=') if (key && value) { switch (key) { case 'inviter': params.inviter = decodeURIComponent(value) break case 'source': params.source = decodeURIComponent(value) break case 't': params.t = decodeURIComponent(value) break } } }) if (params.inviter) { console.log('检测到传统格式邀请码:', params) return params } } // 从 query 参数中解析邀请信息(兼容旧版本) if (options.referrer) { return { inviter: options.referrer, source: 'link' } } return null } catch (error) { console.error('解析邀请参数失败:', error) return null } } /** * 保存邀请信息到本地存储 */ export function saveInviteParams(params: InviteParams) { try { Taro.setStorageSync('invite_params', { ...params, timestamp: Date.now() }) console.log('邀请参数已保存:', params) } catch (error) { console.error('保存邀请参数失败:', error) } } /** * 获取本地存储的邀请信息 */ export function getStoredInviteParams(): InviteParams | null { try { const stored = Taro.getStorageSync('invite_params') if (stored && stored.inviter) { // 检查是否过期(24小时) const now = Date.now() const expireTime = 24 * 60 * 60 * 1000 // 24小时 if (now - stored.timestamp < expireTime) { return { inviter: stored.inviter, source: stored.source || 'unknown', t: stored.t } } else { // 过期则清除 clearInviteParams() } } return null } catch (error) { console.error('获取邀请参数失败:', error) return null } } /** * 清除本地存储的邀请信息 */ export function clearInviteParams() { try { Taro.removeStorageSync('invite_params') console.log('邀请参数已清除') } catch (error) { console.error('清除邀请参数失败:', error) } } /** * 处理邀请关系建立 */ export async function handleInviteRelation(userId: number): Promise { try { console.log('开始处理邀请关系,当前用户ID:', userId) const inviteParams = getStoredInviteParams() if (!inviteParams || !inviteParams.inviter) { console.log('没有找到邀请参数,跳过邀请关系建立') return false } console.log('找到邀请参数:', inviteParams) const inviterId = parseInt(inviteParams.inviter) if (isNaN(inviterId) || inviterId === userId) { // 邀请人ID无效或自己邀请自己 console.log('邀请人ID无效或自己邀请自己,清除邀请参数') clearInviteParams() return false } console.log(`准备建立邀请关系: ${inviterId} -> ${userId}`) // 使用新的绑定推荐关系接口 await bindRefereeRelation({ refereeId: inviterId, userId: userId, source: inviteParams.source || 'qrcode', scene: inviteParams.source === 'qrcode' ? `uid_${inviterId}` : `inviter=${inviterId}&source=${inviteParams.source}&t=${inviteParams.t}` }) // 清除本地存储的邀请参数 clearInviteParams() console.log(`邀请关系建立成功: ${inviterId} -> ${userId}`) // 显示成功提示 setTimeout(() => { Taro.showToast({ title: '邀请关系建立成功', icon: 'success', duration: 2000 }) }, 500) return true } catch (error) { console.error('建立邀请关系失败:', error) // 显示错误提示 setTimeout(() => { Taro.showToast({ title: '邀请关系建立失败', icon: 'error', duration: 2000 }) }, 500) return false } } /** * 检查是否有待处理的邀请 */ export function hasPendingInvite(): boolean { const params = getStoredInviteParams() return !!(params && params.inviter) } /** * 获取邀请来源的显示名称 */ export function getSourceDisplayName(source: string): string { const sourceMap: Record = { 'qrcode': '小程序码', 'link': '分享链接', 'share': '好友分享', 'poster': '海报分享', 'unknown': '未知来源' } return sourceMap[source] || source } /** * 验证邀请码格式 */ export function validateInviteCode(scene: string): boolean { try { if (!scene) return false // 检查是否包含必要的参数 const hasInviter = scene.includes('inviter=') const hasSource = scene.includes('source=') return hasInviter && hasSource } catch (error) { return false } } /** * 生成邀请场景值 */ export function generateInviteScene(inviterId: number, source: string): string { const timestamp = Date.now() return `inviter=${inviterId}&source=${source}&t=${timestamp}` } /** * 统计邀请来源 */ export function trackInviteSource(source: string, inviterId?: number) { try { // 记录邀请来源统计 const trackData = { source, inviterId, timestamp: Date.now(), userAgent: Taro.getSystemInfoSync() } // 可以发送到统计服务 console.log('邀请来源统计:', trackData) // 暂存到本地,后续可批量上报 const existingTracks = Taro.getStorageSync('invite_tracks') || [] existingTracks.push(trackData) // 只保留最近100条记录 if (existingTracks.length > 100) { existingTracks.splice(0, existingTracks.length - 100) } Taro.setStorageSync('invite_tracks', existingTracks) } catch (error) { console.error('统计邀请来源失败:', error) } } /** * 检查并处理当前用户的邀请关系 * 用于在用户登录后立即检查是否需要建立邀请关系 */ export async function checkAndHandleInviteRelation(): Promise { try { // 获取当前用户信息 const userInfo = Taro.getStorageSync('userInfo') if (!userInfo || !userInfo.userId) { console.log('用户未登录,无法处理邀请关系') return false } return await handleInviteRelation(userInfo.userId) } catch (error) { console.error('检查邀请关系失败:', error) return false } } /** * 手动触发邀请关系建立 * 用于在特定页面或时机手动建立邀请关系 */ export async function manualHandleInviteRelation(userId: number): Promise { try { console.log('手动触发邀请关系建立,用户ID:', userId) const inviteParams = getStoredInviteParams() if (!inviteParams || !inviteParams.inviter) { console.log('没有待处理的邀请参数') return false } const result = await handleInviteRelation(userId) if (result) { // 显示成功提示 Taro.showModal({ title: '邀请成功', content: '您已成功加入邀请人的团队!', showCancel: false, confirmText: '知道了' }) } return result } catch (error) { console.error('手动处理邀请关系失败:', error) return false } } /** * 直接绑定推荐关系 * 用于直接调用绑定推荐关系接口 */ export async function bindReferee(refereeId: number, userId?: number, source: string = 'qrcode'): Promise { try { console.log('直接绑定推荐关系:', { refereeId, userId, source }) // 如果没有传入userId,尝试从本地存储获取 let targetUserId = userId if (!targetUserId) { const userInfo = Taro.getStorageSync('userInfo') if (userInfo && userInfo.userId) { targetUserId = userInfo.userId } else { throw new Error('无法获取用户ID') } } // 防止自己推荐自己 if (refereeId === targetUserId) { throw new Error('不能推荐自己') } await bindRefereeRelation({ refereeId: refereeId, userId: targetUserId, source: source, scene: source === 'qrcode' ? `uid_${refereeId}` : undefined }) console.log(`推荐关系绑定成功: ${refereeId} -> ${targetUserId}`) // 显示成功提示 Taro.showToast({ title: '推荐关系绑定成功', icon: 'success', duration: 2000 }) return true } catch (error: any) { console.error('绑定推荐关系失败:', error) // 显示错误提示 Taro.showToast({ title: error.message || '绑定推荐关系失败', icon: 'error', duration: 2000 }) return false } }