refactor(qr-confirm): 简化二维码确认登录页面逻辑

- 移除未使用的组件和图标导入,减少包大小
- 注释掉登录卡片相关样式和元素,隐藏界面内容
- 删除手动确认登录函数及相关按钮渲染逻辑
- 去除状态图标、标题、描述和用户信息的渲染函数
- 删除所有操作按钮和安全提示组件渲染
- 取消整体页面布局,仅直接渲染授权页面部分
- 修改品牌文本首字母小写,统一风格
This commit is contained in:
2026-04-11 08:35:31 +08:00
parent 2fd6f073c3
commit ad6fb13ec1
2 changed files with 187 additions and 568 deletions

View File

@@ -30,10 +30,10 @@
"profession": "高级开发工程师", "profession": "高级开发工程师",
"avatarUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/avatars/02-Engineering/SeniorDeveloper/SeniorDeveloper.png", "avatarUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/avatars/02-Engineering/SeniorDeveloper/SeniorDeveloper.png",
"promptUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/experts/02-Engineering/SeniorDeveloper/SeniorDeveloper_zh.md", "promptUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/experts/02-Engineering/SeniorDeveloper/SeniorDeveloper_zh.md",
"usedAt": 1775819465726, "usedAt": 1775866025894,
"industryId": "all" "industryId": "all"
} }
] ]
}, },
"lastUpdated": 1775819525128 "lastUpdated": 1775867452878
} }

View File

@@ -1,31 +1,13 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text } from '@tarojs/components'; import { View, Text, Button } from '@tarojs/components';
import { Button } from '@nutui/nutui-react-taro';
import Taro, { useRouter } from '@tarojs/taro'; import Taro, { useRouter } from '@tarojs/taro';
import { confirmQRLogin } from '@/api/passport/qr-login';
import { loginByOpenId } from '@/api/passport/wx-login';
import { TenantId } from "@/config/app";
import { saveStorageByLoginUser, SERVER_API_URL } from "@/utils/server"; import { saveStorageByLoginUser, SERVER_API_URL } from "@/utils/server";
import { checkAndHandleInviteRelation, hasPendingInvite, getStoredInviteParams } from "@/utils/invite"; import { checkAndHandleInviteRelation, hasPendingInvite, getStoredInviteParams } from "@/utils/invite";
/** /**
* 扫码登录确认页面 * 扫码登录确认页面 - 科技风格授权页
* *
* 支持两种场景: * 用户扫描 PC 端二维码后,打开此小程序页面进行微信手机号授权登录
* 1. 主动扫码:用户点击按钮调用微信扫码,扫描 PC 端二维码
* 2. URL 扫码(小程序码):用户扫描小程序码后,微信自动打开此页面
*
* URL 扫码场景:
* - 微信「扫普通链接二维码打开小程序」配置的二维码规则:`https://websopy.websoft.top/wx-scan/`
* - 扫码后 URL`https://websopy.websoft.top/wx-scan?token=xxx`
* - 小程序接收到参数后自动确认登录
*
* 登录流程2026-04-08 更新):
* 1. 用户扫码 → 进入 qr-confirm 页面
* 2. 页面立即调用 wx.login() 获取 code
* 3. 用 code 调用 /api/wx-login/loginByOpenId 获取/验证用户身份
* 4. 如果用户不存在 → 显示微信手机号授权按钮(一键注册登录)
* 5. 如果用户存在 → 自动调用 confirmQRLogin 确认登录
*/ */
// 微信获取手机号回调参数类型 // 微信获取手机号回调参数类型
@@ -51,91 +33,33 @@ interface LoginResponse {
} }
// 协议类型 // 协议类型
type AgreementType = 'service' | 'privacy' | null; type AgreementType = 'service' | 'privacy';
const QRConfirmPage: React.FC = () => { const QRConfirmPage: React.FC = () => {
const router = useRouter(); const router = useRouter();
const [loading, setLoading] = useState(false);
const [confirmed, setConfirmed] = useState(false);
const [error, setError] = useState<string>('');
const [token, setToken] = useState<string>('');
const [loginMethod, setLoginMethod] = useState<'scan' | 'url'>('url');
const [userInfo, setUserInfo] = useState<any>(null);
const [needAuth, setNeedAuth] = useState(false); // 是否需要手机号授权
const [authLoading, setAuthLoading] = useState(false); // 授权中状态 const [authLoading, setAuthLoading] = useState(false); // 授权中状态
const [agreementChecked, setAgreementChecked] = useState(false); // 协议勾选状态 const [agreementChecked, setAgreementChecked] = useState(false); // 协议勾选状态
const [token, setToken] = useState<string>(''); // 登录 token
useEffect(() => { useEffect(() => {
// 从 URL 参数中获取 token // 从 URL 参数中获取 token
const params = router.params; const params = router.params;
// 兼容多种参数名
let loginToken = params.scene || params.token || params.qrCodeKey || ''; let loginToken = params.scene || params.token || params.qrCodeKey || '';
// 如果是 q 参数URL 编码的完整 URL,需要解析 // 兼容 q 参数URL 编码的完整 URL
if (params.q && !loginToken) { if (params.q && !loginToken) {
try { try {
const decodedUrl = decodeURIComponent(params.q); const decodedUrl = decodeURIComponent(params.q);
console.log('[QRConfirm] 解码后的 URL:', decodedUrl);
const url = new URL(decodedUrl); const url = new URL(decodedUrl);
loginToken = url.searchParams.get('token') || loginToken = url.searchParams.get('token') || url.searchParams.get('qrCodeKey') || '';
url.searchParams.get('qrCodeKey') ||
'';
setLoginMethod('url');
} catch (e) { } catch (e) {
console.error('[QRConfirm] 解析 q 参数失败:', e);
loginToken = decodeURIComponent(params.q); loginToken = decodeURIComponent(params.q);
setLoginMethod('url');
} }
} else if (loginToken) {
setLoginMethod('url');
} }
// 扫码场景:直接显示授权登录界面
console.log('[QRConfirm] 显示授权登录界面');
setToken(loginToken); setToken(loginToken);
setNeedAuth(true);
}, [router.params]); }, [router.params]);
/**
* 自动确认登录URL 扫码场景)
*/
const handleAutoConfirm = async (_: string) => {
try {
setLoading(true);
// 1. 调用微信登录获取 code
console.log('[QRConfirm] 调用 wx.login() 获取 code...');
const loginResult = await Taro.login();
if (!loginResult.code) {
throw new Error('获取微信登录凭证失败');
}
console.log('[QRConfirm] 获取到 code:', loginResult.code);
// 2. 用 code 调用后端接口验证用户身份
console.log('[QRConfirm] 调用后端 loginByOpenId...');
const wxLoginResult = await loginByOpenId({
code: loginResult.code,
tenantId: 5
});
console.log('[QRConfirm] loginByOpenId 结果:', wxLoginResult);
// 3. 统一显示授权登录界面,让用户一键授权完成登录
// 无论用户是否注册、是否绑定手机号,都走授权登录流程
console.log('[QRConfirm] 显示手机号授权登录界面');
setNeedAuth(true);
setLoading(false);
} catch (err: any) {
console.error('[QRConfirm] 自动确认登录失败:', err);
setError(err.message || '自动确认登录失败');
setLoading(false);
}
};
/** /**
* 处理微信手机号授权 * 处理微信手机号授权
*/ */
@@ -144,42 +68,32 @@ const QRConfirmPage: React.FC = () => {
// 检查协议是否勾选 // 检查协议是否勾选
if (!agreementChecked) { if (!agreementChecked) {
Taro.showToast({ Taro.showToast({ title: '请先同意服务协议和隐私政策', icon: 'none' });
title: '请先同意服务协议和隐私政策',
icon: 'none'
});
return; return;
} }
// 用户拒绝授权 // 用户拒绝授权
if (errMsg && errMsg.includes('fail')) { if (errMsg && errMsg.includes('fail')) {
Taro.showToast({ Taro.showToast({ title: '需要授权手机号才能完成登录', icon: 'none' });
title: '需要授权手机号才能完成登录',
icon: 'none'
});
return; return;
} }
if (!code) { if (!code) {
Taro.showToast({ Taro.showToast({ title: '获取授权信息失败,请重试', icon: 'none' });
title: '获取授权信息失败,请重试',
icon: 'none'
});
return; return;
} }
// 执行授权登录
await handleAuthLogin(code, encryptedData, iv); await handleAuthLogin(code, encryptedData, iv);
}; };
/** /**
* 授权登录(未注册用户) * 授权登录
*/ */
const handleAuthLogin = async (phoneCode: string, encryptedData?: string, iv?: string) => { const handleAuthLogin = async (phoneCode: string, encryptedData?: string, iv?: string) => {
try { try {
setAuthLoading(true); setAuthLoading(true);
// 获取存储的邀请参数 // 获取邀请参数
const inviteParams = getStoredInviteParams(); const inviteParams = getStoredInviteParams();
const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter) : 0; const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter) : 0;
@@ -190,133 +104,82 @@ const QRConfirmPage: React.FC = () => {
code: phoneCode, code: phoneCode,
encryptedData, encryptedData,
iv, iv,
tenantId: TenantId, tenantId: 5,
notVerifyPhone: true, notVerifyPhone: true,
refereeId: refereeId, refereeId,
sceneType: 'save_referee' sceneType: 'save_referee'
}, },
header: { header: { 'content-type': 'application/json', 'TenantId': 5 }
'content-type': 'application/json',
'TenantId': TenantId
}
}); });
if (res.data.code !== 0) { if (res.data.code !== 0) {
throw new Error(res.data.message || '登录失败'); throw new Error(res.data.message || '登录失败');
} }
// 保存登录信息
if (res.data.data?.user) { if (res.data.data?.user) {
saveStorageByLoginUser(res.data.data.access_token, res.data.data.user); saveStorageByLoginUser(res.data.data.access_token, res.data.data.user);
setUserInfo(res.data.data.user);
// 处理邀请关系 // 处理邀请关系
if (hasPendingInvite()) { if (hasPendingInvite()) {
try { try {
await checkAndHandleInviteRelation(); await checkAndHandleInviteRelation();
} catch (e) { } catch (e) {
console.error('授权登录后处理邀请关系失败:', e); console.error('处理邀请关系失败:', e);
} }
} }
Taro.showToast({ Taro.showToast({ title: '授权成功,正在确认登录...', icon: 'success' });
title: '授权成功,正在确认登录...',
icon: 'success'
});
// 延迟后自动确认扫码登录 // 延迟确认扫码登录
setTimeout(() => { setTimeout(() => handleConfirmQRLogin(res.data.data.user), 1500);
handleConfirmLogin(token, res.data.data.user);
}, 1500);
} }
} catch (error: any) { } catch (error: any) {
Taro.showToast({ Taro.showToast({ title: error.message || '授权失败', icon: 'error' });
title: error.message || '授权失败',
icon: 'error'
});
} finally { } finally {
setAuthLoading(false); setAuthLoading(false);
} }
}; };
/** /**
* 确认登录 * 确认扫码登录
*/ */
const handleConfirmLogin = async (loginToken?: string, wxUserInfo?: any) => { const handleConfirmQRLogin = async (userInfo: any) => {
const confirmToken = loginToken || token; if (!token) {
Taro.showToast({ title: '缺少登录token', icon: 'none' });
if (!confirmToken) {
setError('缺少登录token');
return; return;
} }
const currentUser = wxUserInfo || userInfo;
if (!currentUser?.userId) {
const userId = Taro.getStorageSync('UserId');
if (!userId) {
setError('请先登录小程序');
setNeedAuth(true);
return;
}
currentUser && (currentUser.userId = Number(userId));
}
try { try {
setLoading(true); const res = await Taro.request({
setError(''); url: `${SERVER_API_URL}/qr-login/confirm`,
method: 'POST',
const result = await confirmQRLogin({ data: {
token: confirmToken, token,
userId: currentUser.userId, userId: userInfo.userId,
platform: 'wechat', platform: 'wechat',
wechatInfo: { wechatInfo: {
nickname: currentUser.nickname || currentUser.username, nickname: userInfo.nickname || userInfo.username,
avatar: currentUser.avatar avatar: userInfo.avatar
} }
},
header: { 'content-type': 'application/json', 'TenantId': 5 }
}); });
const isConfirmed = result.status === 'confirmed' || result.success === true; if (res.data.success || res.data.status === 'confirmed') {
Taro.showToast({ title: '登录确认成功', icon: 'success', duration: 2000 });
if (isConfirmed) {
setConfirmed(true);
setNeedAuth(false);
Taro.showToast({
title: result.successMessage || result.message || '登录确认成功',
icon: 'success',
duration: 2000
});
setTimeout(() => { setTimeout(() => {
const pages = Taro.getCurrentPages();
if (pages.length > 1) {
Taro.navigateBack();
} else {
Taro.showModal({ Taro.showModal({
title: '登录成功', title: '登录成功',
content: '请回到电脑端刷新页面', content: '请回到电脑端刷新页面',
showCancel: false, showCancel: false,
confirmText: '我知道了' confirmText: '我知道了'
}); });
} }, 2000);
}, 3000);
} else if (result.status === 'bind_phone' || result.needBindPhone) {
Taro.showToast({
title: '请先绑定手机号',
icon: 'none'
});
setTimeout(() => {
Taro.redirectTo({ url: '/passport/sms-login' });
}, 1500);
} else { } else {
setError(result.message || '登录确认失败'); Taro.showToast({ title: res.data.message || '登录确认失败', icon: 'none' });
} }
} catch (err: any) { } catch (err: any) {
console.error('[QRConfirm] 确认登录失败:', err); Taro.showToast({ title: err.message || '确认登录失败', icon: 'error' });
setError(err.message || '登录确认失败');
} finally {
setLoading(false);
} }
}; };
@@ -328,133 +191,47 @@ const QRConfirmPage: React.FC = () => {
if (pages.length > 1) { if (pages.length > 1) {
Taro.navigateBack(); Taro.navigateBack();
} else { } else {
Taro.switchTab({ Taro.switchTab({ url: '/pages/user/user' });
url: '/pages/user/user'
});
} }
}; };
/** // 打开协议页面
* 重试
*/
const handleRetry = () => {
setError('');
setConfirmed(false);
setNeedAuth(false);
if (token) {
handleAutoConfirm(token);
}
};
/**
* 打开微信扫码
*/
const handleScan = () => {
Taro.scanCode({
success: async (res) => {
console.log('[QRConfirm] 扫码成功:', res);
let scanToken = '';
const qrContent = res.result;
try {
if (qrContent.includes('http')) {
const url = new URL(qrContent);
scanToken = url.searchParams.get('token') ||
url.searchParams.get('qrCodeKey') ||
'';
}
if (!scanToken && qrContent.startsWith('{')) {
const parsed = JSON.parse(qrContent);
scanToken = parsed.token || parsed.qrCodeKey || '';
}
if (!scanToken && qrContent.length >= 32) {
scanToken = qrContent;
}
if (scanToken) {
setToken(scanToken);
setLoginMethod('scan');
setNeedAuth(false);
setError('');
handleConfirmLogin(scanToken);
} else {
setError('无效的二维码内容');
}
} catch (e) {
console.error('[QRConfirm] 解析二维码失败:', e);
setError('二维码解析失败');
}
},
fail: (err) => {
console.error('[QRConfirm] 扫码失败:', err);
if (err.errMsg !== 'scanCode:fail cancel') {
setError('扫码失败,请重试');
}
}
});
};
// 打开协议页面(使用网页版)
const openAgreement = (type: AgreementType) => { const openAgreement = (type: AgreementType) => {
const urlMap = { const urlMap = {
service: 'https://websopy.websoft.top/agreement', service: 'https://websopy.websoft.top/agreement',
privacy: 'https://websopy.websoft.top/privacy', privacy: 'https://websopy.websoft.top/privacy',
}; };
if (!type) return;
const targetUrl = encodeURIComponent(urlMap[type]); const targetUrl = encodeURIComponent(urlMap[type]);
Taro.navigateTo({ Taro.navigateTo({ url: `/passport/webview/index?url=${targetUrl}` });
url: `/passport/webview/index?url=${targetUrl}`
});
}; };
// 授权登录页面 - 科技风格 // 科技风格授权页面
const renderAuthPage = () => {
return ( return (
<View className="min-h-screen relative overflow-hidden" style={{ background: 'linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%)' }}> <View className="min-h-screen relative overflow-hidden" style={{ background: 'linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%)' }}>
{/* 背景科技元素 */} {/* 背景科技元素 */}
{/* 网格背景 */}
{/* 1. 网格背景 */}
<View style={{ <View style={{
position: 'absolute', position: 'absolute', top: 0, left: 0, right: 0, bottom: 0,
top: 0, backgroundImage: `linear-gradient(rgba(138, 43, 226, 0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(138, 43, 226, 0.1) 1px, transparent 1px)`,
left: 0, backgroundSize: '50px 50px', opacity: 0.5,
right: 0,
bottom: 0,
backgroundImage: `
linear-gradient(rgba(138, 43, 226, 0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(138, 43, 226, 0.1) 1px, transparent 1px)
`,
backgroundSize: '50px 50px',
opacity: 0.5,
}} /> }} />
{/* 2. 渐变光晕 - 左上 */} {/* 渐变光晕 - 左上 */}
<View style={{ <View style={{
position: 'absolute', position: 'absolute', top: '-30%', left: '-20%', width: '60%', height: '60%',
top: '-30%',
left: '-20%',
width: '60%',
height: '60%',
background: 'radial-gradient(circle, rgba(147, 51, 234, 0.3) 0%, transparent 70%)', background: 'radial-gradient(circle, rgba(147, 51, 234, 0.3) 0%, transparent 70%)',
filter: 'blur(40px)', filter: 'blur(40px)',
}} /> }} />
{/* 3. 渐变光晕 - 右下 */} {/* 渐变光晕 - 右下 */}
<View style={{ <View style={{
position: 'absolute', position: 'absolute', bottom: '-20%', right: '-20%', width: '50%', height: '50%',
bottom: '-20%',
right: '-20%',
width: '50%',
height: '50%',
background: 'radial-gradient(circle, rgba(59, 130, 246, 0.25) 0%, transparent 70%)', background: 'radial-gradient(circle, rgba(59, 130, 246, 0.25) 0%, transparent 70%)',
filter: 'blur(50px)', filter: 'blur(50px)',
}} /> }} />
{/* 4. 动态粒子光点 */} {/* 动态粒子光点 */}
{[ {[
{ top: '15%', left: '20%', size: 4, delay: '0s' }, { top: '15%', left: '20%', size: 4, delay: '0s' },
{ top: '25%', left: '80%', size: 3, delay: '0.5s' }, { top: '25%', left: '80%', size: 3, delay: '0.5s' },
@@ -465,32 +242,20 @@ const QRConfirmPage: React.FC = () => {
{ top: '75%', left: '25%', size: 4, delay: '1.2s' }, { top: '75%', left: '25%', size: 4, delay: '1.2s' },
{ top: '80%', left: '75%', size: 5, delay: '0.8s' }, { top: '80%', left: '75%', size: 5, delay: '0.8s' },
].map((particle, index) => ( ].map((particle, index) => (
<View <View key={index} className="particle" style={{
key={index} position: 'absolute', top: particle.top, left: particle.left,
className="particle" width: particle.size, height: particle.size, borderRadius: '50%',
style={{
position: 'absolute',
top: particle.top,
left: particle.left,
width: particle.size,
height: particle.size,
borderRadius: '50%',
background: index % 2 === 0 ? '#a855f7' : '#3b82f6', background: index % 2 === 0 ? '#a855f7' : '#3b82f6',
boxShadow: index % 2 === 0 boxShadow: index % 2 === 0
? '0 0 10px rgba(168, 85, 247, 0.8), 0 0 20px rgba(168, 85, 247, 0.4)' ? '0 0 10px rgba(168, 85, 247, 0.8), 0 0 20px rgba(168, 85, 247, 0.4)'
: '0 0 10px rgba(59, 130, 246, 0.8), 0 0 20px rgba(59, 130, 246, 0.4)', : '0 0 10px rgba(59, 130, 246, 0.8), 0 0 20px rgba(59, 130, 246, 0.4)',
animationDelay: particle.delay, animationDelay: particle.delay,
}} }} />
/>
))} ))}
{/* 5. 扫描线效果 */} {/* 扫描线效果 */}
<View style={{ <View style={{
position: 'absolute', position: 'absolute', top: 0, left: 0, right: 0, height: '2px',
top: 0,
left: 0,
right: 0,
height: '2px',
background: 'linear-gradient(90deg, transparent, rgba(168, 85, 247, 0.6), transparent)', background: 'linear-gradient(90deg, transparent, rgba(168, 85, 247, 0.6), transparent)',
animation: 'scanline 3s ease-in-out infinite', animation: 'scanline 3s ease-in-out infinite',
}} /> }} />
@@ -500,142 +265,55 @@ const QRConfirmPage: React.FC = () => {
{/* Logo 区域 */} {/* Logo 区域 */}
<View className="flex flex-col items-center mb-12"> <View className="flex flex-col items-center mb-12">
{/* 科技感 Logo 容器 */}
<View style={{ <View style={{
width: '100px', width: '100px', height: '100px', borderRadius: '24px',
height: '100px', background: 'linear-gradient(135deg, rgba(168, 85, 247, 0.2), rgba(59, 130, 246, 0.2))',
borderRadius: '24px',
background: 'linear-gradient(135deg, rgba(168, 85, 247, 0.2) 0%, rgba(59, 130, 246, 0.2) 100%)',
border: '1px solid rgba(168, 85, 247, 0.3)', border: '1px solid rgba(168, 85, 247, 0.3)',
display: 'flex', display: 'flex', alignItems: 'center', justifyContent: 'center',
alignItems: 'center', marginBottom: '20px', position: 'relative', overflow: 'hidden',
justifyContent: 'center',
marginBottom: '20px',
position: 'relative',
overflow: 'hidden',
}}> }}>
{/* Logo 内光效 */} {/* Logo 内光效 */}
<View style={{ <View style={{
position: 'absolute', position: 'absolute', top: '-50%', left: '-50%', width: '200%', height: '200%',
top: '-50%',
left: '-50%',
width: '200%',
height: '200%',
background: 'conic-gradient(from 0deg, transparent, rgba(168, 85, 247, 0.1), transparent, rgba(59, 130, 246, 0.1), transparent)', background: 'conic-gradient(from 0deg, transparent, rgba(168, 85, 247, 0.1), transparent, rgba(59, 130, 246, 0.1), transparent)',
animation: 'rotate 4s linear infinite', animation: 'rotate 4s linear infinite',
}} /> }} />
{/* Logo 图标 */}
<Text style={{ fontSize: '48px', position: 'relative', zIndex: 1 }}>🔐</Text> <Text style={{ fontSize: '48px', position: 'relative', zIndex: 1 }}>🔐</Text>
</View> </View>
{/* 品牌名 - 渐变文字 */}
<Text style={{ <Text style={{
fontSize: '28px', fontSize: '28px', fontWeight: '700',
fontWeight: '700',
background: 'linear-gradient(90deg, #a855f7, #6366f1, #3b82f6)', background: 'linear-gradient(90deg, #a855f7, #6366f1, #3b82f6)',
WebkitBackgroundClip: 'text', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent',
WebkitTextFillColor: 'transparent', backgroundClip: 'text', marginBottom: '8px',
backgroundClip: 'text',
marginBottom: '8px',
}}>websopy</Text> }}>websopy</Text>
{/* 标语 */} <Text style={{ fontSize: '14px', color: 'rgba(255, 255, 255, 0.6)', letterSpacing: '2px' }}>
<Text style={{ ·
fontSize: '14px', </Text>
color: 'rgba(255, 255, 255, 0.6)',
letterSpacing: '2px',
}}> · </Text>
{/* 分割线 */}
<View style={{ <View style={{
width: '60px', width: '60px', height: '3px',
height: '3px',
background: 'linear-gradient(90deg, transparent, #a855f7, transparent)', background: 'linear-gradient(90deg, transparent, #a855f7, transparent)',
marginTop: '20px', marginTop: '20px', borderRadius: '2px',
borderRadius: '2px',
}} /> }} />
</View> </View>
{/* 登录卡片 */}
{/*<View style={{*/}
{/* width: '100%',*/}
{/* maxWidth: '320px',*/}
{/* background: 'rgba(255, 255, 255, 0.05)',*/}
{/* backdropFilter: 'blur(20px)',*/}
{/* WebkitBackdropFilter: 'blur(20px)',*/}
{/* borderRadius: '20px',*/}
{/* border: '1px solid rgba(255, 255, 255, 0.1)',*/}
{/* padding: '24px',*/}
{/* marginBottom: '24px',*/}
{/*}}>*/}
{/* /!* 提示图标 *!/*/}
{/* <View style={{*/}
{/* display: 'flex',*/}
{/* alignItems: 'center',*/}
{/* justifyContent: 'center',*/}
{/* marginBottom: '16px',*/}
{/* }}>*/}
{/* <View style={{*/}
{/* width: '48px',*/}
{/* height: '48px',*/}
{/* borderRadius: '50%',*/}
{/* background: 'linear-gradient(135deg, rgba(168, 85, 247, 0.3), rgba(59, 130, 246, 0.3))',*/}
{/* display: 'flex',*/}
{/* alignItems: 'center',*/}
{/* justifyContent: 'center',*/}
{/* border: '1px solid rgba(168, 85, 247, 0.4)',*/}
{/* }}>*/}
{/* <Text style={{ fontSize: '24px' }}>📱</Text>*/}
{/* </View>*/}
{/* </View>*/}
{/* /!* 标题 *!/*/}
{/* <Text style={{*/}
{/* textAlign: 'center',*/}
{/* color: '#fff',*/}
{/* fontSize: '18px',*/}
{/* fontWeight: '600',*/}
{/* marginBottom: '8px',*/}
{/* }}>授权登录</Text>*/}
{/* /!* 描述 *!/*/}
{/* <Text style={{*/}
{/* textAlign: 'center',*/}
{/* color: 'rgba(255, 255, 255, 0.6)',*/}
{/* fontSize: '13px',*/}
{/* lineHeight: '1.5',*/}
{/* }}>点击下方按钮,使用微信手机号快速登录</Text>*/}
{/*</View>*/}
{/* 主按钮 - 渐变发光按钮 */} {/* 主按钮 - 渐变发光按钮 */}
<View <View style={{
style={{ width: '100%', maxWidth: '320px',
width: '100%',
maxWidth: '320px',
background: 'linear-gradient(135deg, #7c3aed 0%, #a855f7 50%, #6366f1 100%)', background: 'linear-gradient(135deg, #7c3aed 0%, #a855f7 50%, #6366f1 100%)',
borderRadius: '30px', borderRadius: '30px', padding: '2px',
padding: '2px',
boxShadow: '0 0 30px rgba(168, 85, 247, 0.4), 0 0 60px rgba(168, 85, 247, 0.2)', boxShadow: '0 0 30px rgba(168, 85, 247, 0.4), 0 0 60px rgba(168, 85, 247, 0.2)',
}} }}>
>
<Button <Button
className="authorize-btn"
open-type="getPhoneNumber" open-type="getPhoneNumber"
onGetPhoneNumber={handleGetPhoneNumber} onGetPhoneNumber={handleGetPhoneNumber}
disabled={authLoading} disabled={authLoading}
style={{ style={{
width: '100%', width: '100%', height: '52px', fontSize: '17px', fontWeight: '600',
height: '52px', color: '#fff', background: 'transparent', borderRadius: '28px',
fontSize: '17px', border: 'none', padding: '0', boxSizing: 'border-box', lineHeight: '52px',
fontWeight: '600',
color: '#fff',
background: authLoading ? 'rgba(255, 255, 255, 0.1)' : 'transparent',
borderRadius: '28px',
border: 'none',
padding: '0',
boxSizing: 'border-box',
lineHeight: '52px',
textAlign: 'center',
}} }}
> >
{authLoading ? '授权中...' : '微信手机号登录'} {authLoading ? '授权中...' : '微信手机号登录'}
@@ -643,96 +321,37 @@ const QRConfirmPage: React.FC = () => {
</View> </View>
{/* 取消按钮 */} {/* 取消按钮 */}
<View <View style={{ width: '100%', maxWidth: '320px', height: '44px', display: 'flex', alignItems: 'center', justifyContent: 'center', marginTop: '16px' }} onClick={handleCancel}>
className="w-full max-w-80 flex items-center justify-center mt-4 cursor-pointer"
style={{ height: '44px' }}
onClick={handleCancel}
>
<Text style={{ color: 'rgba(255, 255, 255, 0.5)', fontSize: '14px' }}></Text> <Text style={{ color: 'rgba(255, 255, 255, 0.5)', fontSize: '14px' }}></Text>
</View> </View>
{/* 协议勾选 */} {/* 协议勾选 */}
<View className="flex items-center justify-center mt-6"> <View className="flex items-center justify-center mt-6">
<View <View style={{ padding: '8px', marginRight: '4px' }} onClick={() => setAgreementChecked(!agreementChecked)}>
style={{ padding: '8px', marginRight: '4px' }} <View style={{
onClick={() => setAgreementChecked(!agreementChecked)} width: '18px', height: '18px', borderRadius: '4px',
>
<View
style={{
width: '18px',
height: '18px',
borderRadius: '4px',
border: agreementChecked ? 'none' : '1px solid rgba(255, 255, 255, 0.3)', border: agreementChecked ? 'none' : '1px solid rgba(255, 255, 255, 0.3)',
background: agreementChecked ? 'linear-gradient(135deg, #7c3aed, #a855f7)' : 'transparent', background: agreementChecked ? 'linear-gradient(135deg, #7c3aed, #a855f7)' : 'transparent',
display: 'flex', display: 'flex', alignItems: 'center', justifyContent: 'center',
alignItems: 'center', }}>
justifyContent: 'center', {agreementChecked && <Text style={{ color: '#fff', fontSize: '12px' }}></Text>}
}}
>
{agreementChecked && (
<Text style={{ color: '#fff', fontSize: '12px' }}></Text>
)}
</View> </View>
</View> </View>
<Text style={{ color: 'rgba(255, 255, 255, 0.5)', fontSize: '12px' }}> <Text style={{ color: 'rgba(255, 255, 255, 0.5)', fontSize: '12px' }}></Text>
<Text style={{ color: '#a855f7', fontSize: '12px', padding: '4px 2px' }} onClick={() => openAgreement('service')}></Text>
</Text>
<Text
style={{ color: '#a855f7', fontSize: '12px', padding: '4px 2px' }}
onClick={(e) => {
e.stopPropagation();
openAgreement('service');
}}
>
</Text>
<Text style={{ color: 'rgba(255, 255, 255, 0.5)', fontSize: '12px' }}></Text> <Text style={{ color: 'rgba(255, 255, 255, 0.5)', fontSize: '12px' }}></Text>
<Text <Text style={{ color: '#a855f7', fontSize: '12px', padding: '4px 2px' }} onClick={() => openAgreement('privacy')}></Text>
style={{ color: '#a855f7', fontSize: '12px', padding: '4px 2px' }}
onClick={(e) => {
e.stopPropagation();
openAgreement('privacy');
}}
>
</Text>
</View> </View>
{/* 底部装饰 */} {/* 底部装饰 */}
<View style={{ <View style={{ position: 'absolute', bottom: '40px', display: 'flex', alignItems: 'center', gap: '8px' }}>
position: 'absolute', <View style={{ width: '6px', height: '6px', borderRadius: '50%', background: '#a855f7', boxShadow: '0 0 10px rgba(168, 85, 247, 0.8)' }} />
bottom: '40px', <Text style={{ color: 'rgba(255, 255, 255, 0.3)', fontSize: '11px' }}></Text>
display: 'flex', <View style={{ width: '6px', height: '6px', borderRadius: '50%', background: '#3b82f6', boxShadow: '0 0 10px rgba(59, 130, 246, 0.8)' }} />
alignItems: 'center',
gap: '8px',
}}>
<View style={{
width: '6px',
height: '6px',
borderRadius: '50%',
background: '#a855f7',
boxShadow: '0 0 10px rgba(168, 85, 247, 0.8)',
}} />
<Text style={{ color: 'rgba(255, 255, 255, 0.3)', fontSize: '11px' }}>
</Text>
<View style={{
width: '6px',
height: '6px',
borderRadius: '50%',
background: '#3b82f6',
boxShadow: '0 0 10px rgba(59, 130, 246, 0.8)',
}} />
</View> </View>
</View> </View>
</View> </View>
); );
}; };
// 如果是授权页面,直接返回授权页面
return renderAuthPage();
};
export default QRConfirmPage; export default QRConfirmPage;