修改用户登陆认证流程
This commit is contained in:
@@ -6,6 +6,7 @@ import "./scss/qweather-icons/qweather-icons.css";
|
||||
import { useGlobalStore } from "./store/global";
|
||||
import { removeStorage } from "./store/storage";
|
||||
import { sceneRedirectLogic } from './utils/helper'
|
||||
import { silentLogin } from "./services/loginService";
|
||||
|
||||
interface AppProps {
|
||||
children: ReactNode;
|
||||
@@ -24,6 +25,9 @@ class App extends Component<AppProps> {
|
||||
// 这里可以自定义弹窗(或直接默认同意)
|
||||
resolve({ event: 'agree' }); // 同意隐私协议
|
||||
});
|
||||
|
||||
// 移除这里的静默登录调用,避免重复调用
|
||||
// 静默登录在 home_pages/index.tsx 中统一执行
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
@@ -1,85 +1,14 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { View } from "@tarojs/components";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { getCurrentFullPath } from '@/utils';
|
||||
import { check_login_status, clear_login_state } from "@/services/loginService";
|
||||
import React from "react";
|
||||
import { check_login_status } from "@/services/loginService";
|
||||
|
||||
// withAuth 现在改为可选登录检查,不强制跳转
|
||||
// 如果需要强制登录,请在组件内部使用 requireLogin() 工具函数
|
||||
export default function withAuth<P extends object>(
|
||||
WrappedComponent: React.ComponentType<P>,
|
||||
) {
|
||||
const ComponentWithAuth: React.FC<P> = (props: P) => {
|
||||
const [authed, setAuthed] = useState<boolean | null>(null); // null表示未检查
|
||||
const [isChecking, setIsChecking] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const checkAuth = async () => {
|
||||
setIsChecking(true);
|
||||
try {
|
||||
const is_login = check_login_status();
|
||||
|
||||
if (!is_login) {
|
||||
// 未登录,清除可能过期的状态
|
||||
clear_login_state();
|
||||
const currentPage = getCurrentFullPath();
|
||||
// 跳转到登录页,并保存当前页面路径用于登录后跳转
|
||||
(Taro as any).redirectTo({
|
||||
url: `/login_pages/index/index${
|
||||
currentPage ? `?redirect=${encodeURIComponent(currentPage)}` : ""
|
||||
}`,
|
||||
});
|
||||
setAuthed(false);
|
||||
return;
|
||||
}
|
||||
|
||||
setAuthed(true);
|
||||
} catch (error) {
|
||||
console.error('检查登录状态失败:', error);
|
||||
clear_login_state();
|
||||
(Taro as any).redirectTo({ url: '/login_pages/index/index' });
|
||||
setAuthed(false);
|
||||
} finally {
|
||||
setIsChecking(false);
|
||||
}
|
||||
};
|
||||
|
||||
checkAuth();
|
||||
}, []);
|
||||
|
||||
// 正在检查登录状态,显示空白页面避免闪烁
|
||||
if (isChecking || authed === null) {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
backgroundColor: "#FAFAFA",
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 999,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 未登录,显示空白页面(已跳转,这里只是防止渲染)
|
||||
if (!authed) {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
backgroundColor: "#FAFAFA",
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 999,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 已登录,正常渲染组件
|
||||
// 不再强制检查登录状态,直接渲染组件
|
||||
// 组件内部可以在需要时调用 requireLogin() 进行检查
|
||||
return <WrappedComponent {...props} />;
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import * as LoginService from "@/services/loginService";
|
||||
import { getCurrentLocation } from "@/utils/locationUtils";
|
||||
import { useUserInfo, useUserActions } from "@/store/userStore";
|
||||
import { useGlobalState } from "@/store/global";
|
||||
import { requireLoginWithPhone } from "@/utils/helper";
|
||||
import GameTags from "./components/GameTags";
|
||||
import Carousel from "./components/Carousel";
|
||||
import StickyBottom from "./components/StickyBottom";
|
||||
@@ -112,6 +113,11 @@ function Index() {
|
||||
}
|
||||
|
||||
const handleJoinGame = async () => {
|
||||
// 检查登录状态和手机号
|
||||
if (!requireLoginWithPhone()) {
|
||||
return; // 未登录或未绑定手机号,已跳转到登录页
|
||||
}
|
||||
|
||||
if (isMyOwn) {
|
||||
const res = await DetailService.organizerJoin(Number(id));
|
||||
if (res.code === 0) {
|
||||
@@ -274,6 +280,4 @@ function Index() {
|
||||
);
|
||||
}
|
||||
|
||||
// export default withAuth(Index);
|
||||
const ExportPage = withAuth(Index);
|
||||
export default ExportPage;
|
||||
export default Index;
|
||||
|
||||
@@ -606,4 +606,4 @@ const ListPage = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withAuth(ListPage);
|
||||
export default ListPage;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { View, } from '@tarojs/components';
|
||||
import { check_login_status } from '@/services/loginService';
|
||||
import { silentLogin } from '@/services/loginService';
|
||||
import { useUserActions } from '@/store/userStore';
|
||||
import Taro from '@tarojs/taro';
|
||||
import "./index.scss";
|
||||
@@ -9,18 +9,25 @@ const HomePage: React.FC = () => {
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const handleLoginRedirect = () => {
|
||||
const login_status = check_login_status();
|
||||
if (login_status) {
|
||||
// 先跳转,不阻塞启动
|
||||
Taro.redirectTo({ url: '/main_pages/index' });
|
||||
// 异步获取用户信息,不阻塞跳转
|
||||
fetchUserInfo().catch((error) => {
|
||||
console.error('获取用户信息失败:', error);
|
||||
});
|
||||
} else {
|
||||
Taro.redirectTo({ url: '/login_pages/index/index' });
|
||||
const handleLoginRedirect = async () => {
|
||||
// 先执行静默登录,然后再跳转
|
||||
try {
|
||||
console.log('开始静默登录...');
|
||||
const loginResult = await silentLogin();
|
||||
console.log('静默登录结果:', loginResult);
|
||||
if (loginResult.success) {
|
||||
// 静默登录成功,获取用户信息
|
||||
fetchUserInfo().catch((error) => {
|
||||
console.error('获取用户信息失败:', error);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('静默登录失败:', error);
|
||||
// 静默登录失败不影响使用
|
||||
}
|
||||
|
||||
// 无论静默登录是否成功,都跳转到主页面
|
||||
Taro.redirectTo({ url: '/main_pages/index' });
|
||||
};
|
||||
|
||||
handleLoginRedirect();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { View } from "@tarojs/components";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { check_login_status } from "@/services/loginService";
|
||||
import { check_login_status, silentLogin } from "@/services/loginService";
|
||||
import { useUserActions } from "@/store/userStore";
|
||||
import GuideBar from "@/components/GuideBar";
|
||||
import { withAuth, GeneralNavbar } from "@/components";
|
||||
import { GeneralNavbar } from "@/components";
|
||||
import HomeNavbar from "@/components/HomeNavbar";
|
||||
import ListPageContent from "./components/ListPageContent";
|
||||
import MessagePageContent from "./components/MessagePageContent";
|
||||
@@ -27,16 +27,32 @@ const MainPage: React.FC = () => {
|
||||
|
||||
const { fetchUserInfo } = useUserActions();
|
||||
|
||||
// 初始化:检查登录状态并获取用户信息
|
||||
// 初始化:尝试静默登录并获取用户信息
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
// 先检查是否已登录
|
||||
const login_status = check_login_status();
|
||||
if (login_status) {
|
||||
// 已登录,获取用户信息
|
||||
try {
|
||||
await fetchUserInfo();
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
}
|
||||
} else {
|
||||
// 未登录,尝试静默登录
|
||||
try {
|
||||
const loginResult = await silentLogin();
|
||||
if (loginResult.success) {
|
||||
// 静默登录成功,获取用户信息
|
||||
fetchUserInfo().catch((error) => {
|
||||
console.error('获取用户信息失败:', error);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('静默登录失败:', error);
|
||||
// 静默登录失败不影响使用
|
||||
}
|
||||
}
|
||||
};
|
||||
init();
|
||||
@@ -213,5 +229,5 @@ const MainPage: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withAuth(MainPage);
|
||||
export default MainPage;
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import { withAuth, RefundPopup, GeneralNavbar } from "@/components";
|
||||
import img from "@/config/images";
|
||||
import CustomerIcon from "@/static/order/customer.svg";
|
||||
import { handleCustomerService } from "@/services/userService";
|
||||
import { requireLoginWithPhone } from "@/utils/helper";
|
||||
import { DECLAIMER } from "./config";
|
||||
import styles from "./index.module.scss";
|
||||
|
||||
@@ -583,6 +584,11 @@ const OrderCheck = () => {
|
||||
}
|
||||
|
||||
async function getPaymentParams() {
|
||||
// 检查登录状态和手机号(创建订单前检查)
|
||||
if (!requireLoginWithPhone()) {
|
||||
throw new Error("请先绑定手机号");
|
||||
}
|
||||
|
||||
const unPaidRes = await orderService.getUnpaidOrder(detail.id);
|
||||
if (unPaidRes.code === 0 && unPaidRes.data.has_unpaid_order) {
|
||||
return unPaidRes.data.payment_params;
|
||||
@@ -596,6 +602,10 @@ const OrderCheck = () => {
|
||||
|
||||
//TODO: get order msg from id
|
||||
const handlePay = async () => {
|
||||
// 检查登录状态和手机号
|
||||
if (!requireLoginWithPhone()) {
|
||||
return; // 未登录或未绑定手机号,已跳转到登录页
|
||||
}
|
||||
setPaying(true);
|
||||
Taro.showLoading({
|
||||
title: "支付中...",
|
||||
|
||||
@@ -17,7 +17,7 @@ import { withAuth, RefundPopup, GeneralNavbar } from "@/components";
|
||||
import { payOrder, generateOrderActions } from "@/utils";
|
||||
import emptyContent from "@/static/emptyStatus/publish-empty.png";
|
||||
import CustomerIcon from "@/static/order/customer.svg";
|
||||
import { insertDotInTags, genNTRPRequirementText } from "@/utils/helper";
|
||||
import { insertDotInTags, genNTRPRequirementText, requireLoginWithPhone } from "@/utils/helper";
|
||||
import styles from "./index.module.scss";
|
||||
|
||||
dayjs.locale("zh-cn");
|
||||
@@ -111,6 +111,11 @@ const OrderList = () => {
|
||||
}
|
||||
|
||||
async function handlePayNow(item) {
|
||||
// 检查登录状态和手机号
|
||||
if (!requireLoginWithPhone()) {
|
||||
return; // 未登录或未绑定手机号,已跳转到登录页
|
||||
}
|
||||
|
||||
try {
|
||||
const unPaidRes = await orderService.getUnpaidOrder(item.game_info?.id);
|
||||
if (unPaidRes.code === 0 && unPaidRes.data.has_unpaid_order) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from "../../config/formSchema/publishBallFormSchema";
|
||||
import { PublishBallFormData } from "../../../types/publishBall";
|
||||
import PublishService from "@/services/publishService";
|
||||
import { getNextHourTime, getEndTime, delay } from "@/utils";
|
||||
import { getNextHourTime, getEndTime, delay, requireLoginWithPhone } from "@/utils";
|
||||
import { useGlobalState } from "@/store/global";
|
||||
import GeneralNavbar from "@/components/GeneralNavbar";
|
||||
import images from "@/config/images";
|
||||
@@ -344,6 +344,10 @@ const PublishBall: React.FC = () => {
|
||||
};
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
// 检查登录状态和手机号
|
||||
if (!requireLoginWithPhone()) {
|
||||
return; // 未登录或未绑定手机号,已跳转到登录页
|
||||
}
|
||||
// 基础验证
|
||||
console.log(formData, "formData");
|
||||
const params = getParams();
|
||||
|
||||
@@ -420,3 +420,93 @@ export const unFollowUser = async (following_id) => {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 静默登录锁,防止并发调用
|
||||
let silentLoginPromise: Promise<LoginResponse> | null = null;
|
||||
|
||||
// 静默登录:只获取用户ID和token,不需要手机号
|
||||
export const silentLogin = async (): Promise<LoginResponse> => {
|
||||
// 如果已经有正在进行的静默登录,直接返回该 Promise
|
||||
if (silentLoginPromise) {
|
||||
console.log('静默登录正在进行中,等待结果...');
|
||||
return silentLoginPromise;
|
||||
}
|
||||
|
||||
// 先检查是否已经登录
|
||||
if (check_login_status()) {
|
||||
console.log('已登录,跳过静默登录');
|
||||
return {
|
||||
success: true,
|
||||
message: "已登录",
|
||||
token: get_user_token() || undefined,
|
||||
user_info: get_user_info() || undefined,
|
||||
};
|
||||
}
|
||||
|
||||
// 创建静默登录 Promise
|
||||
silentLoginPromise = (async (): Promise<LoginResponse> => {
|
||||
try {
|
||||
console.log('开始执行静默登录...');
|
||||
// 调用微信登录获取code
|
||||
const login_result = await Taro.login();
|
||||
console.log('微信登录结果:', login_result);
|
||||
|
||||
if (!login_result.code) {
|
||||
console.error('微信登录失败:未获取到code');
|
||||
return {
|
||||
success: false,
|
||||
message: "微信登录失败",
|
||||
};
|
||||
}
|
||||
|
||||
// 调用微信授权接口,不传 phone_code(静默登录)
|
||||
console.log('调用后端接口进行静默登录...');
|
||||
const auth_response = await httpService.post("user/wx_auth", {
|
||||
code: login_result.code,
|
||||
// 不传 phone_code,实现静默登录
|
||||
}, {
|
||||
showLoading: false, // 静默登录不显示loading
|
||||
});
|
||||
|
||||
console.log('后端接口响应:', auth_response);
|
||||
|
||||
if (auth_response.code === 0) {
|
||||
const token = auth_response.data?.token || "";
|
||||
const user_info = auth_response.data?.userInfo;
|
||||
|
||||
// 保存登录状态
|
||||
if (token && user_info) {
|
||||
console.log('保存登录状态...');
|
||||
save_login_state(token, user_info);
|
||||
console.log('静默登录成功,已保存登录状态');
|
||||
} else {
|
||||
console.warn('静默登录成功,但token或user_info为空');
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "静默登录成功",
|
||||
token,
|
||||
user_info,
|
||||
};
|
||||
} else {
|
||||
console.error('静默登录失败:', auth_response.message);
|
||||
return {
|
||||
success: false,
|
||||
message: auth_response.message || "静默登录失败",
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("静默登录异常:", error);
|
||||
return {
|
||||
success: false,
|
||||
message: "静默登录失败,请重试",
|
||||
};
|
||||
} finally {
|
||||
// 清除锁,允许下次调用
|
||||
silentLoginPromise = null;
|
||||
}
|
||||
})();
|
||||
|
||||
return silentLoginPromise;
|
||||
};
|
||||
@@ -1,4 +1,6 @@
|
||||
import Taro from "@tarojs/taro";
|
||||
import { check_login_status, get_user_info } from "@/services/loginService";
|
||||
import { useUser } from "@/store/userStore";
|
||||
|
||||
// 普通函数,不调用 useLoad
|
||||
export const sceneRedirectLogic = (options, defaultPage: string) => {
|
||||
@@ -25,6 +27,64 @@ export const sceneRedirectLogic = (options, defaultPage: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 获取当前页面路径
|
||||
const getCurrentPagePath = (): string => {
|
||||
const pages = Taro.getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
return currentPage ? `/${currentPage.route}${currentPage.options ? '?' + Object.entries(currentPage.options).map(([k, v]) => `${k}=${encodeURIComponent(v as string)}`).join('&') : ''}` : '';
|
||||
};
|
||||
|
||||
// 跳转到登录页
|
||||
const navigateToLogin = (currentPath?: string) => {
|
||||
const path = currentPath || getCurrentPagePath();
|
||||
(Taro as any).navigateTo({
|
||||
url: `/login_pages/index/index${path ? `?redirect=${encodeURIComponent(path)}` : ''}`,
|
||||
});
|
||||
};
|
||||
|
||||
// 检查登录状态,如果未登录则跳转到登录页
|
||||
export const requireLogin = (): boolean => {
|
||||
const isLoggedIn = check_login_status();
|
||||
|
||||
if (!isLoggedIn) {
|
||||
navigateToLogin();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// 检查登录状态和手机号,如果未登录或没有手机号则跳转到登录页绑定手机号
|
||||
export const requireLoginWithPhone = (): boolean => {
|
||||
// 先检查登录状态
|
||||
const isLoggedIn = check_login_status();
|
||||
|
||||
if (!isLoggedIn) {
|
||||
navigateToLogin();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否有手机号
|
||||
// 优先从 store 中获取用户信息
|
||||
const userInfo = useUser.getState().user;
|
||||
let phone = (userInfo as any)?.phone;
|
||||
|
||||
// 如果 store 中没有,尝试从本地存储获取
|
||||
if (!phone || phone.trim() === '') {
|
||||
const localUserInfo = get_user_info();
|
||||
phone = localUserInfo?.phone;
|
||||
}
|
||||
|
||||
// 如果用户信息中没有手机号,或者手机号为空
|
||||
if (!phone || phone.trim() === '') {
|
||||
console.log('用户未绑定手机号,跳转到登录页绑定');
|
||||
navigateToLogin();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
export function navto(url) {
|
||||
Taro.navigateTo({
|
||||
url: url,
|
||||
|
||||
@@ -11,3 +11,4 @@ export * from './share'
|
||||
export * from './genPoster'
|
||||
export * from './wx_helper'
|
||||
export * from './navigation';
|
||||
export * from './helper';
|
||||
|
||||
Reference in New Issue
Block a user