From 24c6e6c0fd5a1d87a8b1230a0936f5e0d9cab275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Tue, 26 Aug 2025 18:53:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(invite):=20=E4=BC=98=E5=8C=96=E9=82=80?= =?UTF-8?q?=E8=AF=B7=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90=E5=92=8C=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构 invite 工具函数,增强参数解析能力 - 添加参数调试工具,便于排查问题 - 优化用户登录后的邀请关系处理流程- 调整 API调用,统一使用 dealerId替代 refereeId - 移除未使用的导入和冗余代码 --- config/env.ts | 2 +- src/admin/components/UserCard.tsx | 11 +- src/api/invite/index.ts | 7 +- src/app.ts | 20 ++- src/hooks/useUserData.ts | 4 + src/pages/index/Header.tsx | 12 +- src/pages/index/HeaderWithHook.tsx | 12 +- src/pages/index/Login.tsx | 12 +- src/pages/user/components/UserCard.tsx | 11 +- src/user/order/components/OrderList.tsx | 44 +++---- src/utils/invite.ts | 110 ++++++++++++++-- src/utils/test-invite.ts | 166 ++++++++++++++++++++++++ start-claude.sh | 11 -- 13 files changed, 358 insertions(+), 64 deletions(-) create mode 100644 src/utils/test-invite.ts delete mode 100755 start-claude.sh diff --git a/config/env.ts b/config/env.ts index 44ddb26..c92883b 100644 --- a/config/env.ts +++ b/config/env.ts @@ -2,7 +2,7 @@ export const ENV_CONFIG = { // 开发环境 development: { - API_BASE_URL: 'http://127.0.0.1:9200/api', + API_BASE_URL: 'https://cms-api.websoft.top/api', APP_NAME: '开发环境', DEBUG: 'true', }, diff --git a/src/admin/components/UserCard.tsx b/src/admin/components/UserCard.tsx index 132dc49..bb67aa2 100644 --- a/src/admin/components/UserCard.tsx +++ b/src/admin/components/UserCard.tsx @@ -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 }, diff --git a/src/api/invite/index.ts b/src/api/invite/index.ts index 9f973a1..ba38f75 100644 --- a/src/api/invite/index.ts +++ b/src/api/invite/index.ts @@ -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>( '/shop/shop-dealer-referee', { - refereeId: data.refereeId, + dealerId: data.dealerId, userId: data.userId, source: data.source || 'qrcode', scene: data.scene diff --git a/src/app.ts b/src/app.ts index 418ba66..9eba816 100644 --- a/src/app.ts +++ b/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) } diff --git a/src/hooks/useUserData.ts b/src/hooks/useUserData.ts index 33a1bef..fcc0423 100644 --- a/src/hooks/useUserData.ts +++ b/src/hooks/useUserData.ts @@ -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(), diff --git a/src/pages/index/Header.tsx b/src/pages/index/Header.tsx index be5a673..7abaffe 100644 --- a/src/pages/index/Header.tsx +++ b/src/pages/index/Header.tsx @@ -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 }, diff --git a/src/pages/index/HeaderWithHook.tsx b/src/pages/index/HeaderWithHook.tsx index da16113..7d41dd8 100644 --- a/src/pages/index/HeaderWithHook.tsx +++ b/src/pages/index/HeaderWithHook.tsx @@ -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 }, diff --git a/src/pages/index/Login.tsx b/src/pages/index/Login.tsx index f4a0e0d..090acaa 100644 --- a/src/pages/index/Login.tsx +++ b/src/pages/index/Login.tsx @@ -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 }, diff --git a/src/pages/user/components/UserCard.tsx b/src/pages/user/components/UserCard.tsx index 4ca426d..4cf4b89 100644 --- a/src/pages/user/components/UserCard.tsx +++ b/src/pages/user/components/UserCard.tsx @@ -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 }, diff --git a/src/user/order/components/OrderList.tsx b/src/user/order/components/OrderList.tsx index e00380c..9ec68e3 100644 --- a/src/user/order/components/OrderList.tsx +++ b/src/user/order/components/OrderList.tsx @@ -738,20 +738,20 @@ function OrderList(props: OrderListProps) { )} {/* 待发货状态:显示申请退款 */} - {item.payStatus && item.deliveryStatus === 10 && item.orderStatus !== 2 && item.orderStatus !== 4 && ( - - )} + {/*{item.payStatus && item.deliveryStatus === 10 && item.orderStatus !== 2 && item.orderStatus !== 4 && (*/} + {/* */} + {/*)}*/} {/* 待收货状态:显示查看物流和确认收货 */} {item.deliveryStatus === 20 && item.orderStatus !== 2 && ( - + {/**/} - - + {/**/} + {/**/} )} {/* 退款/售后状态:显示查看进度和撤销申请 */} {(item.orderStatus === 4 || item.orderStatus === 7) && ( - + {/**/} )} diff --git a/src/utils/invite.ts b/src/utils/invite.ts index f4c901d..be72ddb 100644 --- a/src/utils/invite.ts +++ b/src/utils/invite.ts @@ -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 { // 使用新的绑定推荐关系接口 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 { 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 diff --git a/src/utils/test-invite.ts b/src/utils/test-invite.ts new file mode 100644 index 0000000..f338161 --- /dev/null +++ b/src/utils/test-invite.ts @@ -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('🎉 所有测试完成') +} diff --git a/start-claude.sh b/start-claude.sh deleted file mode 100755 index ea4e719..0000000 --- a/start-claude.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -# 设置代理(根据你的 Clash Verge 配置) -export http_proxy=http://127.0.0.1:7897 -export https_proxy=http://127.0.0.1:7897 - -# 启动 Claude Code -echo "🚀 启动 Claude Code..." -echo "📡 使用代理: $http_proxy" - -npx @anthropic-ai/claude-code