Files
template-10579/src/utils/invite.ts
赵忠林 ec252beb4b feat(pages): 添加管理页面功能和配置
- 创建 .editorconfig 文件统一代码风格配置
- 配置 .eslintrc 使用 taro/react 规则集
- 完善 .gitignore 忽略编译产物和敏感文件
- 添加 admin/article/add 页面实现文章管理功能
- 添加 dealer/apply/add 页面实现经销商申请功能
- 添加 dealer/bank/add 页面实现银行卡管理功能
- 添加 dealer/customer/add 页面实现客户管理功能
- 添加 user/address/add 页面实现用户地址管理功能
- 添加 user/chat/message/add 页面实现消息功能
- 添加 user/gift/add 页面实现礼品管理功能
- 配置各页面导航栏标题和样式
- 实现表单验证和数据提交功能
- 集成图片上传和头像选择功能
- 添加日期选择和数据校验逻辑
- 实现编辑和新增模式切换
- 集成用户权限和角色管理功能
2026-02-08 12:15:31 +08:00

297 lines
7.3 KiB
TypeScript
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 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 {
console.log('解析邀请参数:', options)
// 优先从 query.scene 中解析邀请信息
if (options.query && options.query.scene) {
const sceneStr = typeof options.query.scene === 'string' ? options.query.scene : String(options.query.scene)
console.log('从 query.scene 解析:', sceneStr)
// 处理 uid_xxxxx 格式的参数
if (sceneStr.startsWith('uid_')) {
const uid = sceneStr.replace('uid_', '')
if (uid) {
return {
inviter: uid,
source: 'qrcode',
t: String(Date.now())
}
}
}
// 处理 key=value&key=value 格式的参数
if (sceneStr.includes('=')) {
const params: InviteParams = {}
const pairs = sceneStr.split('&')
pairs.forEach((pair: string) => {
const [key, value] = pair.split('=')
if (key && value) {
switch (key) {
case 'inviter':
case 'uid':
params.inviter = decodeURIComponent(value)
break
case 'source':
params.source = decodeURIComponent(value)
break
case 't':
params.t = decodeURIComponent(value)
break
}
}
})
if (params.inviter) {
return params
}
}
}
// 从 scene 参数中解析邀请信息(兼容旧版本)
if (options.scene) {
const sceneStr = typeof options.scene === 'string' ? options.scene : String(options.scene)
console.log('从 scene 解析:', sceneStr)
// 处理 uid_xxxxx 格式的参数
if (sceneStr.startsWith('uid_')) {
const uid = sceneStr.replace('uid_', '')
if (uid) {
return {
inviter: uid,
source: 'qrcode',
t: String(Date.now())
}
}
}
// 处理 key=value&key=value 格式的参数
if (sceneStr.includes('=')) {
const params: InviteParams = {}
const pairs = sceneStr.split('&')
pairs.forEach((pair: string) => {
const [key, value] = pair.split('=')
if (key && value) {
switch (key) {
case 'inviter':
case 'uid':
params.inviter = decodeURIComponent(value)
break
case 'source':
params.source = decodeURIComponent(value)
break
case 't':
params.t = decodeURIComponent(value)
break
}
}
})
if (params.inviter) {
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<boolean> {
try {
const inviteParams = getStoredInviteParams()
if (!inviteParams || !inviteParams.inviter) {
return false
}
const inviterId = parseInt(inviteParams.inviter)
if (isNaN(inviterId) || inviterId === userId) {
// 邀请人ID无效或自己邀请自己
clearInviteParams()
return false
}
// 建立邀请关系
await bindRefereeRelation({
dealerId: inviterId,
userId: userId,
source: inviteParams.source || 'unknown',
scene: `inviter=${inviterId}&source=${inviteParams.source}&t=${inviteParams.t}`
})
// 清除本地存储的邀请参数
clearInviteParams()
console.log(`邀请关系建立成功: ${inviterId} -> ${userId}`)
return true
} catch (error) {
console.error('建立邀请关系失败:', error)
return false
}
}
/**
* 检查是否有待处理的邀请
*/
export function hasPendingInvite(): boolean {
const params = getStoredInviteParams()
return !!(params && params.inviter)
}
/**
* 获取邀请来源的显示名称
*/
export function getSourceDisplayName(source: string): string {
const sourceMap: Record<string, string> = {
'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)
}
}