fix(api): 替换所有接口请求的域名为 guilixu-api.websoft.top

- 将获取 STS Token 的接口地址由 paopao-api 改为 guilixu-api
- 更新图片上传接口地址为新的 guilixu-api 域名
- 修改用户推广页面中邀请码链接和二维码接口的域名
- 更改注册页微信登录接口请求的域名为 guilixu-api
This commit is contained in:
2026-06-16 17:15:59 +08:00
commit f3886664f7
617 changed files with 77059 additions and 0 deletions

269
src/passport/sms-login.tsx Normal file
View File

@@ -0,0 +1,269 @@
import {useEffect, useState} from "react";
import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'
import {Input, Button} from '@nutui/nutui-react-taro'
import {loginBySms, sendSmsCaptcha} from "@/api/passport/login";
import {LoginParam} from "@/api/passport/login/model";
import {checkAndHandleInviteRelation, hasPendingInvite, parseInviteParams, saveInviteParams, trackInviteSource} from "@/utils/invite";
const SmsLogin = () => {
const [loading, setLoading] = useState<boolean>(false)
const [sendingCode, setSendingCode] = useState<boolean>(false)
const [countdown, setCountdown] = useState<number>(0)
const [formData, setFormData] = useState<LoginParam>({
phone: '',
code: ''
})
const router = Taro.getCurrentInstance().router
const redirectParam = (router?.params as any)?.redirect as string | undefined
const safeDecodeMaybeEncoded = (input?: string) => {
if (!input) return ''
try {
return decodeURIComponent(input)
} catch (_e) {
return input
}
}
const redirectUrl = (() => {
const decoded = safeDecodeMaybeEncoded(redirectParam)
if (!decoded) return ''
return decoded.startsWith('/') ? decoded : `/${decoded}`
})()
const isTabBarUrl = (url: string) => {
const pure = url.split('?')[0]
return (
pure === '/pages/index/index' ||
pure === '/pages/cart/cart' ||
pure === '/pages/user/user' ||
pure === '/pages/category/index'
)
}
const navigateAfterLogin = async () => {
if (!redirectUrl) {
await Taro.reLaunch({ url: '/pages/index/index' })
return
}
if (isTabBarUrl(redirectUrl)) {
await Taro.switchTab({ url: redirectUrl.split('?')[0] })
return
}
await Taro.redirectTo({ url: redirectUrl })
}
const reload = () => {
// sms-login 页面不是 tabBar 页面,无需调用 hideTabBar
}
useEffect(() => {
reload()
}, [])
// 如果从分享/二维码链接进入短信登录页,先暂存邀请信息
useEffect(() => {
try {
const inviteParams = parseInviteParams({ query: router?.params })
if (inviteParams?.inviter) {
saveInviteParams(inviteParams)
trackInviteSource(inviteParams.source || 'share', parseInt(inviteParams.inviter, 10))
}
} catch (e) {
console.error('短信登录页处理邀请参数失败:', e)
}
}, [router?.params])
// 倒计时效果
useEffect(() => {
let timer: NodeJS.Timeout
if (countdown > 0) {
timer = setTimeout(() => {
setCountdown(countdown - 1)
}, 1000)
}
return () => {
if (timer) clearTimeout(timer)
}
}, [countdown])
// 验证手机号格式
const validatePhone = (phone: string): boolean => {
const phoneRegex = /^1[3-9]\d{9}$/
return phoneRegex.test(phone)
}
// 发送短信验证码
const handleSendCode = async () => {
if (!formData.phone) {
Taro.showToast({
title: '请输入手机号码',
icon: 'none'
})
return
}
if (!validatePhone(formData.phone)) {
Taro.showToast({
title: '请输入正确的手机号码',
icon: 'none'
})
return
}
if (sendingCode || countdown > 0) {
return
}
try {
setSendingCode(true)
await sendSmsCaptcha({ phone: formData.phone })
Taro.showToast({
title: '验证码已发送',
icon: 'success'
})
// 开始60秒倒计时
setCountdown(60)
} catch (error: any) {
Taro.showToast({
title: error.message || '发送失败',
icon: 'error'
})
} finally {
setSendingCode(false)
}
}
// 处理登录
const handleLogin = async () => {
// 防止重复提交
if (loading) {
return
}
// 表单验证
if (!formData.phone) {
Taro.showToast({
title: '请输入手机号码',
icon: 'none'
})
return
}
if (!validatePhone(formData.phone)) {
Taro.showToast({
title: '请输入正确的手机号码',
icon: 'none'
})
return
}
if (!formData.code) {
Taro.showToast({
title: '请输入验证码',
icon: 'none'
})
return
}
if (formData.code.length !== 6) {
Taro.showToast({
title: '请输入6位验证码',
icon: 'none'
})
return
}
try {
setLoading(true)
await loginBySms({
phone: formData.phone,
code: formData.code
})
// 登录成功后(可能是新注册用户),检查是否存在待处理的邀请关系并尝试绑定
if (hasPendingInvite()) {
try {
await checkAndHandleInviteRelation()
} catch (e) {
console.error('短信登录后处理邀请关系失败:', e)
}
}
Taro.showToast({
title: '登录成功',
icon: 'success'
})
// 延迟跳转到首页
setTimeout(() => {
navigateAfterLogin().catch((e) => {
console.error('短信登录后跳转失败:', e)
Taro.reLaunch({ url: '/pages/index/index' })
})
}, 1500)
} catch (error: any) {
Taro.showToast({
title: error.message || '登录失败',
icon: 'error'
})
} finally {
setLoading(false)
}
}
return (
<>
<View className='flex flex-col justify-center px-5 pt-3'>
<View className='flex flex-col justify-between items-center my-2'>
<Input
type='number'
placeholder='请输入手机号码'
maxLength={11}
value={formData.phone}
onChange={(value) => setFormData({...formData, phone: value})}
style={{backgroundColor: '#ffffff', borderRadius: '8px'}}
/>
</View>
<View className='flex justify-between items-center bg-white rounded-lg my-2 pr-2'>
<Input
type='number'
placeholder='请输入6位验证码'
maxLength={6}
value={formData.code}
onChange={(value) => setFormData({...formData, code: value})}
style={{ backgroundColor: '#ffffff', borderRadius: '8px'}}
/>
<Button
size='small'
type={countdown > 0 ? "default" : "primary"}
loading={sendingCode}
disabled={sendingCode || countdown > 0}
onClick={handleSendCode}
>
{countdown > 0 ? `${countdown}s` : sendingCode ? '发送中...' : '获取验证码'}
</Button>
</View>
<View className='flex justify-center my-5'>
<Button
type='info'
size='large'
className='w-full rounded-lg p-2'
loading={loading}
disabled={loading}
onClick={handleLogin}
>
{loading ? '登录中...' : '登录'}
</Button>
</View>
</View>
</>
)
}
export default SmsLogin