diff --git a/config/index.ts b/config/index.ts
index e36b8e5..c77a458 100644
--- a/config/index.ts
+++ b/config/index.ts
@@ -10,12 +10,13 @@ export default defineConfig<'webpack5'>(async (merge, { command, mode }) => {
const baseConfig: UserConfigExport<'webpack5'> = {
projectName: 'playBallTogether',
date: '2025-8-9',
- designWidth: 375,
+ designWidth: 390,
deviceRatio: {
640: 2.34 / 2,
750: 1,
375: 2,
- 828: 1.81 / 2
+ 828: 1.81 / 2,
+ 390: 1.92
},
sourceRoot: 'src',
outputRoot: 'dist',
diff --git a/src/pages/login/verification/index.scss b/src/pages/login/verification/index.scss
index c19131f..7bf0be3 100644
--- a/src/pages/login/verification/index.scss
+++ b/src/pages/login/verification/index.scss
@@ -273,6 +273,16 @@
font-size: 14px;
line-height: 1.714;
color: rgba(60, 60, 67, 0.3);
+
+ .count_number {
+ color: rgba(60, 60, 67, 0.3);
+ transition: color 0.3s ease;
+
+ &.active {
+ color: #000000;
+ font-weight: 500;
+ }
+ }
}
}
}
@@ -321,6 +331,16 @@
font-size: 14px;
line-height: 1.714;
color: rgba(60, 60, 67, 0.3);
+
+ .count_number {
+ color: rgba(60, 60, 67, 0.3);
+ transition: color 0.3s ease;
+
+ &.active {
+ color: #000000;
+ font-weight: 500;
+ }
+ }
}
}
diff --git a/src/pages/login/verification/index.tsx b/src/pages/login/verification/index.tsx
index f34e5f6..cd3e35d 100644
--- a/src/pages/login/verification/index.tsx
+++ b/src/pages/login/verification/index.tsx
@@ -10,11 +10,11 @@ const VerificationPage: React.FC = () => {
const [countdown, setCountdown] = useState(0);
const [can_send_code, setCanSendCode] = useState(true);
const [is_loading, setIsLoading] = useState(false);
+ const [code_input_focus, setCodeInputFocus] = useState(false);
+
+ // 计算登录按钮是否应该启用
+ const can_login = phone.length === 11 && verification_code.length === 6 && !is_loading;
- // 返回上一页
- const handle_go_back = () => {
- Taro.navigateBack();
- };
// 发送验证码
const handle_send_code = async () => {
@@ -30,10 +30,16 @@ const VerificationPage: React.FC = () => {
if (!can_send_code) return;
try {
+ console.log('开始发送验证码,手机号:', phone);
+
// 调用发送短信接口
const result = await send_sms_code(phone);
+ console.log('发送验证码结果:', result);
+
if (result.success) {
+ console.log('验证码发送成功,开始倒计时');
+
Taro.showToast({
title: '验证码已发送',
icon: 'success',
@@ -43,7 +49,19 @@ const VerificationPage: React.FC = () => {
// 开始倒计时
setCanSendCode(false);
setCountdown(60);
+
+ console.log('设置状态: can_send_code = false, countdown = 60');
+
+ // 发送验证码成功后,让验证码输入框获得焦点并调用系统键盘
+ setTimeout(() => {
+ // 设置验证码输入框聚焦状态
+ setCodeInputFocus(true);
+ // 清空验证码,让用户重新输入
+ setVerificationCode('');
+ console.log('设置验证码输入框聚焦');
+ }, 500); // 延迟500ms确保Toast显示完成后再聚焦
} else {
+ console.log('验证码发送失败:', result.message);
Taro.showToast({
title: result.message || '发送失败',
icon: 'none',
@@ -51,6 +69,7 @@ const VerificationPage: React.FC = () => {
});
}
} catch (error) {
+ console.error('发送验证码异常:', error);
Taro.showToast({
title: '发送失败,请重试',
icon: 'none',
@@ -61,15 +80,19 @@ const VerificationPage: React.FC = () => {
// 倒计时效果
useEffect(() => {
+ console.log('倒计时 useEffect 触发,countdown:', countdown);
+
if (countdown > 0) {
const timer = setTimeout(() => {
+ console.log('倒计时减少,从', countdown, '到', countdown - 1);
setCountdown(countdown - 1);
}, 1000);
return () => clearTimeout(timer);
- } else {
+ } else if (countdown === 0 && !can_send_code) {
+ console.log('倒计时结束,重新启用发送按钮');
setCanSendCode(true);
}
- }, [countdown]);
+ }, [countdown, can_send_code]);
// 手机号登录
const handle_phone_login = async () => {
@@ -96,7 +119,7 @@ const VerificationPage: React.FC = () => {
try {
// 调用登录服务
const result = await phone_auth_login({ phone, verification_code });
-
+
if (result.success) {
setTimeout(() => {
@@ -122,12 +145,6 @@ const VerificationPage: React.FC = () => {
}
};
- // 查看条款
- const handle_view_terms = (type: string = 'terms') => {
- Taro.navigateTo({
- url: `/pages/login/terms/index?type=${type}`
- });
- };
return (
@@ -159,7 +176,12 @@ const VerificationPage: React.FC = () => {
onInput={(e) => setPhone(e.detail.value)}
maxlength={11}
/>
- {phone.length}/11
+
+ 0 ? 'count_number active' : 'count_number'}>
+ {phone.length}
+
+ /11
+
@@ -171,11 +193,20 @@ const VerificationPage: React.FC = () => {
type="number"
placeholder="输入短信验证码"
placeholderClass="input_placeholder"
+ placeholderStyle="color:#999999;"
+ focus={code_input_focus}
value={verification_code}
onInput={(e) => setVerificationCode(e.detail.value)}
+ onFocus={() => setCodeInputFocus(true)}
+ onBlur={() => setCodeInputFocus(false)}
maxlength={6}
/>
- {verification_code.length}/6
+
+ 0 ? 'count_number active' : 'count_number'}>
+ {verification_code.length}
+
+ /6
+
+ {/* 调试信息 */}
+ {/* {process.env.NODE_ENV === 'development' && (
+
+ 调试: can_send_code={can_send_code.toString()}, countdown={countdown}
+
+ )} */}
{/* 登录按钮 */}
+ {/* 调试信息 */}
+ {/* {process.env.NODE_ENV === 'development' && (
+
+ 调试: 手机号长度={phone.length}, 验证码长度={verification_code.length}, 可登录={can_login.toString()}
+
+ )} */}
-
+
{/* 底部指示器 */}
diff --git a/src/services/loginService.ts b/src/services/loginService.ts
index 603f85f..54036ff 100644
--- a/src/services/loginService.ts
+++ b/src/services/loginService.ts
@@ -1,5 +1,6 @@
import Taro from '@tarojs/taro';
import httpService from './httpService';
+import tokenManager from '../utils/tokenManager';
// 微信用户信息接口
export interface WechatUserInfo {
@@ -130,7 +131,8 @@ export const send_sms_code = async (phone: string): Promise => {
phone: phone
});
- if (response.success) {
+ // 修复响应检查逻辑:检查 code === 0 或 success === true
+ if (response.code === 0 || response.success === true) {
return {
success: true,
message: '验证码发送成功'
@@ -199,7 +201,14 @@ export const get_user_profile = (): Promise => {
// 保存用户登录状态
export const save_login_state = (token: string, user_info: WechatUserInfo) => {
try {
- Taro.setStorageSync('user_token', token);
+ // 使用 tokenManager 保存令牌信息,设置24小时过期
+ const expires_at = Date.now() + 24 * 60 * 60 * 1000; // 24小时后过期
+ tokenManager.setToken({
+ accessToken: token,
+ expiresAt: expires_at
+ });
+
+ // 保存用户信息
Taro.setStorageSync('user_info', user_info);
Taro.setStorageSync('is_logged_in', true);
Taro.setStorageSync('login_time', Date.now());
@@ -211,7 +220,10 @@ export const save_login_state = (token: string, user_info: WechatUserInfo) => {
// 清除登录状态
export const clear_login_state = () => {
try {
- Taro.removeStorageSync('user_token');
+ // 使用 tokenManager 清除令牌
+ tokenManager.clearTokens();
+
+ // 清除其他登录状态
Taro.removeStorageSync('user_info');
Taro.removeStorageSync('is_logged_in');
Taro.removeStorageSync('login_time');
@@ -223,22 +235,53 @@ export const clear_login_state = () => {
// 检查是否已登录
export const check_login_status = (): boolean => {
try {
- const is_logged_in = Taro.getStorageSync('is_logged_in');
- const token = Taro.getStorageSync('user_token');
- const login_time = Taro.getStorageSync('login_time');
-
- // 检查登录是否过期(7天)
- if (login_time && Date.now() - login_time > 7 * 24 * 60 * 60 * 1000) {
+ // 使用 tokenManager 检查令牌有效性
+ if (!tokenManager.hasValidToken()) {
clear_login_state();
return false;
}
- return !!(is_logged_in && token);
+ const is_logged_in = Taro.getStorageSync('is_logged_in');
+ return !!is_logged_in;
} catch (error) {
return false;
}
};
+// 检查令牌是否需要刷新(剩余时间少于1小时时)
+export const should_refresh_token = (): boolean => {
+ try {
+ const remaining_time = tokenManager.getTokenRemainingTime();
+ const one_hour = 60 * 60 * 1000; // 1小时
+ return remaining_time > 0 && remaining_time < one_hour;
+ } catch (error) {
+ return false;
+ }
+};
+
+// 获取令牌状态信息
+export const get_token_status = () => {
+ try {
+ const is_valid = tokenManager.hasValidToken();
+ const remaining_time = tokenManager.getTokenRemainingTime();
+ const is_expired = tokenManager.isTokenExpired();
+
+ return {
+ is_valid,
+ remaining_time,
+ is_expired,
+ expires_in_minutes: Math.floor(remaining_time / (60 * 1000))
+ };
+ } catch (error) {
+ return {
+ is_valid: false,
+ remaining_time: 0,
+ is_expired: true,
+ expires_in_minutes: 0
+ };
+ }
+};
+
// 获取用户信息
export const get_user_info = (): WechatUserInfo | null => {
try {
@@ -251,7 +294,8 @@ export const get_user_info = (): WechatUserInfo | null => {
// 获取用户token
export const get_user_token = (): string | null => {
try {
- return Taro.getStorageSync('user_token') || null;
+ // 使用 tokenManager 获取令牌
+ return tokenManager.getAccessToken();
} catch (error) {
return null;
}
diff --git a/src/utils/tokenManager.ts b/src/utils/tokenManager.ts
index b2c680a..435cede 100644
--- a/src/utils/tokenManager.ts
+++ b/src/utils/tokenManager.ts
@@ -85,6 +85,17 @@ class TokenManager {
return !!token && !this.isTokenExpired()
}
+ // 获取令牌剩余有效时间(毫秒)
+ getTokenRemainingTime(): number {
+ const expiresAt = this.getTokenExpires()
+ if (!expiresAt) {
+ return 0 // 如果没有过期时间,返回0
+ }
+
+ const remaining = expiresAt - Date.now()
+ return remaining > 0 ? remaining : 0
+ }
+
// 获取Authorization头
getAuthHeader(): Record {
const token = this.getAccessToken()
@@ -93,7 +104,7 @@ class TokenManager {
}
return {
- 'Authorization': `Bearer ${token}`
+ 'applet-token': `${token}`
}
}
}