feat(invite): 优化邀请参数解析和处理逻辑
- 重构 invite 工具函数,增强参数解析能力 - 添加参数调试工具,便于排查问题 - 优化用户登录后的邀请关系处理流程- 调整 API调用,统一使用 dealerId替代 refereeId - 移除未使用的导入和冗余代码
This commit is contained in:
@@ -8,6 +8,7 @@ import navTo from "@/utils/common";
|
||||
import {TenantId} from "@/config/app";
|
||||
import {getMyAvailableCoupons} from "@/api/shop/shopUserCoupon";
|
||||
import {useUser} from "@/hooks/useUser";
|
||||
import {getStoredInviteParams} from "@/utils/invite";
|
||||
|
||||
function UserCard() {
|
||||
const {getDisplayName, getRoleName} = useUser();
|
||||
@@ -134,6 +135,14 @@ function UserCard() {
|
||||
/* 获取用户手机号 */
|
||||
const handleGetPhoneNumber = ({detail}: {detail: {code?: string, encryptedData?: string, iv?: string}}) => {
|
||||
const {code, encryptedData, iv} = detail
|
||||
|
||||
// 获取存储的邀请参数
|
||||
const inviteParams = getStoredInviteParams()
|
||||
const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter) : 0
|
||||
|
||||
console.log('Admin UserCard组件登录时检测到的邀请参数:', inviteParams)
|
||||
console.log('Admin UserCard组件推荐人ID:', refereeId)
|
||||
|
||||
Taro.login({
|
||||
success: function () {
|
||||
if (code) {
|
||||
@@ -145,7 +154,7 @@ function UserCard() {
|
||||
encryptedData,
|
||||
iv,
|
||||
notVerifyPhone: true,
|
||||
refereeId: 0,
|
||||
refereeId: refereeId, // 使用解析出的推荐人ID
|
||||
sceneType: 'save_referee',
|
||||
tenantId: TenantId
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import request from '@/utils/request';
|
||||
import type { ApiResult, PageResult } from '@/api';
|
||||
import { BaseUrl } from '@/config/app';
|
||||
|
||||
/**
|
||||
* 小程序码生成参数
|
||||
@@ -38,7 +39,7 @@ export interface InviteRelationParam {
|
||||
*/
|
||||
export interface BindRefereeParam {
|
||||
// 推荐人ID
|
||||
refereeId: number;
|
||||
dealerId: number;
|
||||
// 被推荐人ID (可选,如果不传则使用当前登录用户)
|
||||
userId?: number;
|
||||
// 推荐来源
|
||||
@@ -112,7 +113,7 @@ export async function generateMiniProgramCode(data: MiniProgramCodeParam) {
|
||||
try {
|
||||
const url = '/wx-login/getOrderQRCodeUnlimited/' + data.scene;
|
||||
// 由于接口直接返回图片buffer,我们直接构建完整的URL
|
||||
return `${API_BASE_URL}${url}`;
|
||||
return `${BaseUrl}${url}`;
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message || '生成小程序码失败');
|
||||
}
|
||||
@@ -155,7 +156,7 @@ export async function bindRefereeRelation(data: BindRefereeParam) {
|
||||
const res = await request.post<ApiResult<unknown>>(
|
||||
'/shop/shop-dealer-referee',
|
||||
{
|
||||
refereeId: data.refereeId,
|
||||
dealerId: data.dealerId,
|
||||
userId: data.userId,
|
||||
source: data.source || 'qrcode',
|
||||
scene: data.scene
|
||||
|
||||
20
src/app.ts
20
src/app.ts
@@ -6,7 +6,7 @@ import './app.scss'
|
||||
import {loginByOpenId} from "@/api/layout";
|
||||
import {TenantId} from "@/config/app";
|
||||
import {saveStorageByLoginUser} from "@/utils/server";
|
||||
import {parseInviteParams, saveInviteParams, trackInviteSource, handleInviteRelation} from "@/utils/invite";
|
||||
import {parseInviteParams, saveInviteParams, trackInviteSource, handleInviteRelation, debugInviteInfo} from "@/utils/invite";
|
||||
|
||||
function App(props: { children: any; }) {
|
||||
const reload = () => {
|
||||
@@ -57,12 +57,13 @@ function App(props: { children: any; }) {
|
||||
// 处理启动参数
|
||||
const handleLaunchOptions = (options: any) => {
|
||||
try {
|
||||
console.log('小程序启动参数:', options)
|
||||
console.log('=== 小程序启动参数处理开始 ===')
|
||||
console.log('完整启动参数:', JSON.stringify(options, null, 2))
|
||||
|
||||
// 解析邀请参数
|
||||
const inviteParams = parseInviteParams(options)
|
||||
if (inviteParams) {
|
||||
console.log('检测到邀请参数:', inviteParams)
|
||||
console.log('✅ 成功检测到邀请参数:', inviteParams)
|
||||
|
||||
// 保存邀请参数到本地存储
|
||||
saveInviteParams(inviteParams)
|
||||
@@ -73,12 +74,21 @@ function App(props: { children: any; }) {
|
||||
// 显示邀请提示
|
||||
setTimeout(() => {
|
||||
Taro.showToast({
|
||||
title: '检测到邀请信息',
|
||||
title: `检测到邀请信息 ID:${inviteParams.inviter}`,
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
duration: 3000
|
||||
})
|
||||
}, 1000)
|
||||
|
||||
// 打印调试信息
|
||||
setTimeout(() => {
|
||||
debugInviteInfo()
|
||||
}, 2000)
|
||||
} else {
|
||||
console.log('❌ 未检测到邀请参数')
|
||||
}
|
||||
|
||||
console.log('=== 小程序启动参数处理结束 ===')
|
||||
} catch (error) {
|
||||
console.error('处理启动参数失败:', error)
|
||||
}
|
||||
|
||||
@@ -39,6 +39,10 @@ export const useUserData = (): UseUserDataReturn => {
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
|
||||
if(!Taro.getStorageSync('UserId')){
|
||||
return;
|
||||
}
|
||||
|
||||
// 并发请求所有数据
|
||||
const [userDataRes, couponsRes, giftCardsRes] = await Promise.all([
|
||||
getUserInfo(),
|
||||
|
||||
@@ -8,7 +8,7 @@ import {TenantId} from "@/config/app";
|
||||
import {getOrganization} from "@/api/system/organization";
|
||||
import {myUserVerify} from "@/api/system/userVerify";
|
||||
import { useShopInfo } from '@/hooks/useShopInfo';
|
||||
import {handleInviteRelation} from "@/utils/invite";
|
||||
import {handleInviteRelation, getStoredInviteParams} from "@/utils/invite";
|
||||
import {View,Text} from '@tarojs/components'
|
||||
import MySearch from "./MySearch";
|
||||
import './Header.scss';
|
||||
@@ -88,6 +88,14 @@ const Header = (props: any) => {
|
||||
/* 获取用户手机号 */
|
||||
const handleGetPhoneNumber = ({detail}: {detail: {code?: string, encryptedData?: string, iv?: string}}) => {
|
||||
const {code, encryptedData, iv} = detail
|
||||
|
||||
// 获取存储的邀请参数
|
||||
const inviteParams = getStoredInviteParams()
|
||||
const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter) : 0
|
||||
|
||||
console.log('登录时检测到的邀请参数:', inviteParams)
|
||||
console.log('推荐人ID:', refereeId)
|
||||
|
||||
Taro.login({
|
||||
success: function () {
|
||||
if (code) {
|
||||
@@ -99,7 +107,7 @@ const Header = (props: any) => {
|
||||
encryptedData,
|
||||
iv,
|
||||
notVerifyPhone: true,
|
||||
refereeId: 0,
|
||||
refereeId: refereeId, // 使用解析出的推荐人ID
|
||||
sceneType: 'save_referee',
|
||||
tenantId: TenantId
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ import {myUserVerify} from "@/api/system/userVerify";
|
||||
import {User} from "@/api/system/user/model";
|
||||
import { useShopInfo } from '@/hooks/useShopInfo';
|
||||
import { useUser } from '@/hooks/useUser';
|
||||
import {handleInviteRelation} from "@/utils/invite";
|
||||
import {handleInviteRelation, getStoredInviteParams} from "@/utils/invite";
|
||||
import MySearch from "./MySearch";
|
||||
import './Header.scss';
|
||||
|
||||
@@ -74,6 +74,14 @@ const Header = (props: any) => {
|
||||
// 获取手机号授权
|
||||
const handleGetPhoneNumber = ({detail}: {detail: {code?: string, encryptedData?: string, iv?: string}}) => {
|
||||
const {code, encryptedData, iv} = detail
|
||||
|
||||
// 获取存储的邀请参数
|
||||
const inviteParams = getStoredInviteParams()
|
||||
const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter) : 0
|
||||
|
||||
console.log('HeaderWithHook组件登录时检测到的邀请参数:', inviteParams)
|
||||
console.log('HeaderWithHook组件推荐人ID:', refereeId)
|
||||
|
||||
Taro.login({
|
||||
success: function () {
|
||||
if (code) {
|
||||
@@ -85,7 +93,7 @@ const Header = (props: any) => {
|
||||
encryptedData,
|
||||
iv,
|
||||
notVerifyPhone: true,
|
||||
refereeId: 0,
|
||||
refereeId: refereeId, // 使用解析出的推荐人ID
|
||||
sceneType: 'save_referee',
|
||||
tenantId: TenantId
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ import {Input, Radio, Button} from '@nutui/nutui-react-taro'
|
||||
import {TenantId} from "@/config/app";
|
||||
import './login.scss';
|
||||
import {saveStorageByLoginUser} from "@/utils/server";
|
||||
import {handleInviteRelation} from "@/utils/invite";
|
||||
import {handleInviteRelation, getStoredInviteParams} from "@/utils/invite";
|
||||
|
||||
// 微信获取手机号回调参数类型
|
||||
interface GetPhoneNumberDetail {
|
||||
@@ -40,6 +40,14 @@ const Login = (props: LoginProps) => {
|
||||
/* 获取用户手机号 */
|
||||
const handleGetPhoneNumber = ({detail}: GetPhoneNumberEvent) => {
|
||||
const {code, encryptedData, iv} = detail
|
||||
|
||||
// 获取存储的邀请参数
|
||||
const inviteParams = getStoredInviteParams()
|
||||
const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter) : 0
|
||||
|
||||
console.log('Login组件登录时检测到的邀请参数:', inviteParams)
|
||||
console.log('Login组件推荐人ID:', refereeId)
|
||||
|
||||
Taro.login({
|
||||
success: function () {
|
||||
if (code) {
|
||||
@@ -51,7 +59,7 @@ const Login = (props: LoginProps) => {
|
||||
encryptedData,
|
||||
iv,
|
||||
notVerifyPhone: true,
|
||||
refereeId: 0,
|
||||
refereeId: refereeId, // 使用解析出的推荐人ID
|
||||
sceneType: 'save_referee',
|
||||
tenantId: TenantId
|
||||
},
|
||||
|
||||
@@ -11,6 +11,7 @@ import {TenantId} from "@/config/app";
|
||||
import {getMyAvailableCoupons} from "@/api/shop/shopUserCoupon";
|
||||
import {useUser} from "@/hooks/useUser";
|
||||
import {useUserData} from "@/hooks/useUserData";
|
||||
import {getStoredInviteParams} from "@/utils/invite";
|
||||
|
||||
function UserCard() {
|
||||
const {
|
||||
@@ -151,6 +152,14 @@ function UserCard() {
|
||||
/* 获取用户手机号 */
|
||||
const handleGetPhoneNumber = ({detail}: {detail: {code?: string, encryptedData?: string, iv?: string}}) => {
|
||||
const {code, encryptedData, iv} = detail
|
||||
|
||||
// 获取存储的邀请参数
|
||||
const inviteParams = getStoredInviteParams()
|
||||
const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter) : 0
|
||||
|
||||
console.log('UserCard组件登录时检测到的邀请参数:', inviteParams)
|
||||
console.log('UserCard组件推荐人ID:', refereeId)
|
||||
|
||||
Taro.login({
|
||||
success: function () {
|
||||
if (code) {
|
||||
@@ -162,7 +171,7 @@ function UserCard() {
|
||||
encryptedData,
|
||||
iv,
|
||||
notVerifyPhone: true,
|
||||
refereeId: 0,
|
||||
refereeId: refereeId, // 使用解析出的推荐人ID
|
||||
sceneType: 'save_referee',
|
||||
tenantId: TenantId
|
||||
},
|
||||
|
||||
@@ -738,20 +738,20 @@ function OrderList(props: OrderListProps) {
|
||||
)}
|
||||
|
||||
{/* 待发货状态:显示申请退款 */}
|
||||
{item.payStatus && item.deliveryStatus === 10 && item.orderStatus !== 2 && item.orderStatus !== 4 && (
|
||||
<Button size={'small'} onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
applyRefund(item);
|
||||
}}>申请退款</Button>
|
||||
)}
|
||||
{/*{item.payStatus && item.deliveryStatus === 10 && item.orderStatus !== 2 && item.orderStatus !== 4 && (*/}
|
||||
{/* <Button size={'small'} onClick={(e) => {*/}
|
||||
{/* e.stopPropagation();*/}
|
||||
{/* applyRefund(item);*/}
|
||||
{/* }}>申请退款</Button>*/}
|
||||
{/*)}*/}
|
||||
|
||||
{/* 待收货状态:显示查看物流和确认收货 */}
|
||||
{item.deliveryStatus === 20 && item.orderStatus !== 2 && (
|
||||
<Space>
|
||||
<Button size={'small'} onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
viewLogistics(item);
|
||||
}}>查看物流</Button>
|
||||
{/*<Button size={'small'} onClick={(e) => {*/}
|
||||
{/* e.stopPropagation();*/}
|
||||
{/* viewLogistics(item);*/}
|
||||
{/*}}>查看物流</Button>*/}
|
||||
<Button size={'small'} type="primary" onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
confirmReceive(item);
|
||||
@@ -766,24 +766,24 @@ function OrderList(props: OrderListProps) {
|
||||
e.stopPropagation();
|
||||
buyAgain(item);
|
||||
}}>再次购买</Button>
|
||||
<Button size={'small'} onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
evaluateGoods(item);
|
||||
}}>评价商品</Button>
|
||||
<Button size={'small'} onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
applyRefund(item);
|
||||
}}>申请退款</Button>
|
||||
{/*<Button size={'small'} onClick={(e) => {*/}
|
||||
{/* e.stopPropagation();*/}
|
||||
{/* evaluateGoods(item);*/}
|
||||
{/*}}>评价商品</Button>*/}
|
||||
{/*<Button size={'small'} onClick={(e) => {*/}
|
||||
{/* e.stopPropagation();*/}
|
||||
{/* applyRefund(item);*/}
|
||||
{/*}}>申请退款</Button>*/}
|
||||
</Space>
|
||||
)}
|
||||
|
||||
{/* 退款/售后状态:显示查看进度和撤销申请 */}
|
||||
{(item.orderStatus === 4 || item.orderStatus === 7) && (
|
||||
<Space>
|
||||
<Button size={'small'} onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
viewProgress(item);
|
||||
}}>查看进度</Button>
|
||||
{/*<Button size={'small'} onClick={(e) => {*/}
|
||||
{/* e.stopPropagation();*/}
|
||||
{/* viewProgress(item);*/}
|
||||
{/*}}>查看进度</Button>*/}
|
||||
</Space>
|
||||
)}
|
||||
|
||||
|
||||
@@ -15,22 +15,41 @@ export interface InviteParams {
|
||||
*/
|
||||
export function parseInviteParams(options: any): InviteParams | null {
|
||||
try {
|
||||
console.log('开始解析邀请参数,完整options:', JSON.stringify(options))
|
||||
|
||||
// 优先从 query.scene 参数中解析邀请信息
|
||||
let sceneStr = null
|
||||
if (options.query && options.query.scene) {
|
||||
sceneStr = typeof options.query.scene === 'string' ? options.query.scene : String(options.query.scene)
|
||||
console.log('从query.scene解析参数:', sceneStr, '类型:', typeof sceneStr)
|
||||
} else if (options.scene) {
|
||||
// 兼容直接从 scene 参数解析
|
||||
sceneStr = typeof options.scene === 'string' ? options.scene : String(options.scene)
|
||||
console.log('从options.scene解析参数:', sceneStr, '类型:', typeof sceneStr)
|
||||
}
|
||||
|
||||
// 从 scene 参数中解析邀请信息
|
||||
if (options.scene) {
|
||||
// 确保 scene 是字符串类型
|
||||
const sceneStr = typeof options.scene === 'string' ? options.scene : String(options.scene)
|
||||
console.log('解析scene参数:', sceneStr)
|
||||
if (sceneStr) {
|
||||
|
||||
// 处理 uid_xxx 格式的邀请码
|
||||
if (sceneStr.startsWith('uid_')) {
|
||||
const inviterId = sceneStr.replace('uid_', '')
|
||||
console.log('提取的邀请人ID:', inviterId)
|
||||
|
||||
if (inviterId && !isNaN(parseInt(inviterId))) {
|
||||
console.log('检测到uid格式邀请码:', inviterId)
|
||||
return {
|
||||
const parsedInviterId = parseInt(inviterId)
|
||||
console.log('检测到uid格式邀请码,邀请人ID:', parsedInviterId)
|
||||
|
||||
const inviteParams = {
|
||||
inviter: inviterId,
|
||||
source: 'qrcode',
|
||||
t: Date.now().toString()
|
||||
}
|
||||
console.log('返回的邀请参数:', inviteParams)
|
||||
|
||||
return inviteParams
|
||||
} else {
|
||||
console.log('邀请人ID无效:', inviterId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +78,8 @@ export function parseInviteParams(options: any): InviteParams | null {
|
||||
console.log('检测到传统格式邀请码:', params)
|
||||
return params
|
||||
}
|
||||
} else {
|
||||
console.log('options中没有scene参数或query.scene参数')
|
||||
}
|
||||
|
||||
// 从 query 参数中解析邀请信息(兼容旧版本)
|
||||
@@ -81,11 +102,17 @@ export function parseInviteParams(options: any): InviteParams | null {
|
||||
*/
|
||||
export function saveInviteParams(params: InviteParams) {
|
||||
try {
|
||||
Taro.setStorageSync('invite_params', {
|
||||
const saveData = {
|
||||
...params,
|
||||
timestamp: Date.now()
|
||||
})
|
||||
console.log('邀请参数已保存:', params)
|
||||
}
|
||||
|
||||
Taro.setStorageSync('invite_params', saveData)
|
||||
console.log('邀请参数已保存到本地存储:', saveData)
|
||||
|
||||
// 验证保存是否成功
|
||||
const saved = Taro.getStorageSync('invite_params')
|
||||
console.log('验证保存结果:', saved)
|
||||
} catch (error) {
|
||||
console.error('保存邀请参数失败:', error)
|
||||
}
|
||||
@@ -97,21 +124,28 @@ export function saveInviteParams(params: InviteParams) {
|
||||
export function getStoredInviteParams(): InviteParams | null {
|
||||
try {
|
||||
const stored = Taro.getStorageSync('invite_params')
|
||||
console.log('从本地存储获取的邀请参数:', stored)
|
||||
|
||||
if (stored && stored.inviter) {
|
||||
// 检查是否过期(24小时)
|
||||
const now = Date.now()
|
||||
const expireTime = 24 * 60 * 60 * 1000 // 24小时
|
||||
|
||||
if (now - stored.timestamp < expireTime) {
|
||||
return {
|
||||
const result = {
|
||||
inviter: stored.inviter,
|
||||
source: stored.source || 'unknown',
|
||||
t: stored.t
|
||||
}
|
||||
console.log('返回有效的邀请参数:', result)
|
||||
return result
|
||||
} else {
|
||||
console.log('邀请参数已过期,清除本地存储')
|
||||
// 过期则清除
|
||||
clearInviteParams()
|
||||
}
|
||||
} else {
|
||||
console.log('本地存储中没有有效的邀请参数')
|
||||
}
|
||||
return null
|
||||
} catch (error) {
|
||||
@@ -159,7 +193,7 @@ export async function handleInviteRelation(userId: number): Promise<boolean> {
|
||||
|
||||
// 使用新的绑定推荐关系接口
|
||||
await bindRefereeRelation({
|
||||
refereeId: inviterId,
|
||||
dealerId: inviterId,
|
||||
userId: userId,
|
||||
source: inviteParams.source || 'qrcode',
|
||||
scene: inviteParams.source === 'qrcode' ? `uid_${inviterId}` : `inviter=${inviterId}&source=${inviteParams.source}&t=${inviteParams.t}`
|
||||
@@ -275,20 +309,68 @@ export function trackInviteSource(source: string, inviterId?: number) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调试工具:打印所有邀请相关的存储信息
|
||||
*/
|
||||
export function debugInviteInfo() {
|
||||
try {
|
||||
console.log('=== 邀请参数调试信息 ===')
|
||||
|
||||
// 获取启动参数
|
||||
const launchOptions = Taro.getLaunchOptionsSync()
|
||||
console.log('启动参数:', JSON.stringify(launchOptions, null, 2))
|
||||
|
||||
// 获取存储的邀请参数
|
||||
const storedParams = Taro.getStorageSync('invite_params')
|
||||
console.log('存储的邀请参数:', JSON.stringify(storedParams, null, 2))
|
||||
|
||||
// 获取用户信息
|
||||
const userId = Taro.getStorageSync('UserId')
|
||||
const userInfo = Taro.getStorageSync('userInfo')
|
||||
console.log('用户ID:', userId)
|
||||
console.log('用户信息:', JSON.stringify(userInfo, null, 2))
|
||||
|
||||
// 获取邀请统计
|
||||
const inviteTracks = Taro.getStorageSync('invite_tracks')
|
||||
console.log('邀请统计:', JSON.stringify(inviteTracks, null, 2))
|
||||
|
||||
console.log('=== 调试信息结束 ===')
|
||||
|
||||
return {
|
||||
launchOptions,
|
||||
storedParams,
|
||||
userId,
|
||||
userInfo,
|
||||
inviteTracks
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取调试信息失败:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并处理当前用户的邀请关系
|
||||
* 用于在用户登录后立即检查是否需要建立邀请关系
|
||||
*/
|
||||
export async function checkAndHandleInviteRelation(): Promise<boolean> {
|
||||
try {
|
||||
// 打印调试信息
|
||||
debugInviteInfo()
|
||||
|
||||
// 获取当前用户信息
|
||||
const userInfo = Taro.getStorageSync('userInfo')
|
||||
if (!userInfo || !userInfo.userId) {
|
||||
const userId = Taro.getStorageSync('UserId')
|
||||
|
||||
const finalUserId = userId || userInfo?.userId
|
||||
|
||||
if (!finalUserId) {
|
||||
console.log('用户未登录,无法处理邀请关系')
|
||||
return false
|
||||
}
|
||||
|
||||
return await handleInviteRelation(userInfo.userId)
|
||||
console.log('使用用户ID处理邀请关系:', finalUserId)
|
||||
return await handleInviteRelation(parseInt(finalUserId))
|
||||
} catch (error) {
|
||||
console.error('检查邀请关系失败:', error)
|
||||
return false
|
||||
@@ -353,7 +435,7 @@ export async function bindReferee(refereeId: number, userId?: number, source: st
|
||||
}
|
||||
|
||||
await bindRefereeRelation({
|
||||
refereeId: refereeId,
|
||||
dealerId: refereeId,
|
||||
userId: targetUserId,
|
||||
source: source,
|
||||
scene: source === 'qrcode' ? `uid_${refereeId}` : undefined
|
||||
|
||||
166
src/utils/test-invite.ts
Normal file
166
src/utils/test-invite.ts
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* 邀请参数解析测试工具
|
||||
*/
|
||||
|
||||
import { parseInviteParams } from './invite'
|
||||
|
||||
/**
|
||||
* 测试不同格式的邀请参数解析
|
||||
*/
|
||||
export function testInviteParamsParsing() {
|
||||
console.log('=== 开始测试邀请参数解析 ===')
|
||||
|
||||
// 测试用例1: uid_格式
|
||||
const testCase1 = {
|
||||
scene: 'uid_33103',
|
||||
path: 'pages/index/index'
|
||||
}
|
||||
console.log('测试用例1 - uid格式:')
|
||||
console.log('输入:', testCase1)
|
||||
const result1 = parseInviteParams(testCase1)
|
||||
console.log('输出:', result1)
|
||||
console.log('预期: { inviter: "33103", source: "qrcode", t: "..." }')
|
||||
console.log('结果:', result1?.inviter === '33103' && result1?.source === 'qrcode' ? '✅ 通过' : '❌ 失败')
|
||||
console.log('')
|
||||
|
||||
// 测试用例2: 传统格式
|
||||
const testCase2 = {
|
||||
scene: 'inviter=12345&source=share&t=1640995200000',
|
||||
path: 'pages/index/index'
|
||||
}
|
||||
console.log('测试用例2 - 传统格式:')
|
||||
console.log('输入:', testCase2)
|
||||
const result2 = parseInviteParams(testCase2)
|
||||
console.log('输出:', result2)
|
||||
console.log('预期: { inviter: "12345", source: "share", t: "1640995200000" }')
|
||||
console.log('结果:', result2?.inviter === '12345' && result2?.source === 'share' ? '✅ 通过' : '❌ 失败')
|
||||
console.log('')
|
||||
|
||||
// 测试用例3: 数字类型的scene
|
||||
const testCase3 = {
|
||||
scene: 1047, // 数字类型
|
||||
path: 'pages/index/index'
|
||||
}
|
||||
console.log('测试用例3 - 数字类型scene:')
|
||||
console.log('输入:', testCase3)
|
||||
const result3 = parseInviteParams(testCase3)
|
||||
console.log('输出:', result3)
|
||||
console.log('预期: null (因为不是uid_格式)')
|
||||
console.log('结果:', result3 === null ? '✅ 通过' : '❌ 失败')
|
||||
console.log('')
|
||||
|
||||
// 测试用例4: 空参数
|
||||
const testCase4 = {}
|
||||
console.log('测试用例4 - 空参数:')
|
||||
console.log('输入:', testCase4)
|
||||
const result4 = parseInviteParams(testCase4)
|
||||
console.log('输出:', result4)
|
||||
console.log('预期: null')
|
||||
console.log('结果:', result4 === null ? '✅ 通过' : '❌ 失败')
|
||||
console.log('')
|
||||
|
||||
// 测试用例5: 无效的uid格式
|
||||
const testCase5 = {
|
||||
scene: 'uid_abc',
|
||||
path: 'pages/index/index'
|
||||
}
|
||||
console.log('测试用例5 - 无效uid格式:')
|
||||
console.log('输入:', testCase5)
|
||||
const result5 = parseInviteParams(testCase5)
|
||||
console.log('输出:', result5)
|
||||
console.log('预期: null (因为abc不是数字)')
|
||||
console.log('结果:', result5 === null ? '✅ 通过' : '❌ 失败')
|
||||
console.log('')
|
||||
|
||||
// 测试用例6: referrer参数
|
||||
const testCase6 = {
|
||||
referrer: '99999',
|
||||
path: 'pages/index/index'
|
||||
}
|
||||
console.log('测试用例6 - referrer参数:')
|
||||
console.log('输入:', testCase6)
|
||||
const result6 = parseInviteParams(testCase6)
|
||||
console.log('输出:', result6)
|
||||
console.log('预期: { inviter: "99999", source: "link" }')
|
||||
console.log('结果:', result6?.inviter === '99999' && result6?.source === 'link' ? '✅ 通过' : '❌ 失败')
|
||||
console.log('')
|
||||
|
||||
console.log('=== 邀请参数解析测试完成 ===')
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟小程序启动场景测试
|
||||
*/
|
||||
export function simulateMiniProgramLaunch() {
|
||||
console.log('=== 模拟小程序启动场景 ===')
|
||||
|
||||
// 模拟通过小程序码启动
|
||||
const qrcodeOptions = {
|
||||
path: 'pages/index/index',
|
||||
scene: 'uid_33103',
|
||||
shareTicket: undefined,
|
||||
referrerInfo: {}
|
||||
}
|
||||
|
||||
console.log('模拟小程序码启动:')
|
||||
console.log('启动参数:', qrcodeOptions)
|
||||
|
||||
const qrcodeResult = parseInviteParams(qrcodeOptions)
|
||||
console.log('解析结果:', qrcodeResult)
|
||||
|
||||
if (qrcodeResult && qrcodeResult.inviter === '33103') {
|
||||
console.log('✅ 小程序码邀请解析成功')
|
||||
return qrcodeResult
|
||||
} else {
|
||||
console.log('❌ 小程序码邀请解析失败')
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证邀请参数格式
|
||||
*/
|
||||
export function validateInviteParams(params: any) {
|
||||
console.log('=== 验证邀请参数格式 ===')
|
||||
console.log('参数:', params)
|
||||
|
||||
if (!params) {
|
||||
console.log('❌ 参数为空')
|
||||
return false
|
||||
}
|
||||
|
||||
if (!params.inviter) {
|
||||
console.log('❌ 缺少inviter字段')
|
||||
return false
|
||||
}
|
||||
|
||||
if (isNaN(parseInt(params.inviter))) {
|
||||
console.log('❌ inviter不是有效数字')
|
||||
return false
|
||||
}
|
||||
|
||||
if (!params.source) {
|
||||
console.log('❌ 缺少source字段')
|
||||
return false
|
||||
}
|
||||
|
||||
console.log('✅ 邀请参数格式验证通过')
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行所有测试
|
||||
*/
|
||||
export function runAllTests() {
|
||||
console.log('🚀 开始运行所有邀请参数测试')
|
||||
|
||||
testInviteParamsParsing()
|
||||
|
||||
const simulationResult = simulateMiniProgramLaunch()
|
||||
|
||||
if (simulationResult) {
|
||||
validateInviteParams(simulationResult)
|
||||
}
|
||||
|
||||
console.log('🎉 所有测试完成')
|
||||
}
|
||||
Reference in New Issue
Block a user