ChatGPT-Next-Web/app/components/WechatLogin.tsx
2025-04-30 14:06:10 +08:00

175 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { Path } from "../constant";
import styles from "./WechatLogin.module.scss";
import LoadingIcon from "../icons/loading.svg";
// import QRCodeImage from "../icons/wechat-qrcode-mock.svg"; // 假设有一个模拟的二维码SVG
import SuccessIcon from "../icons/confirm.svg";
import ErrorIcon from "../icons/close.svg";
import Locale from "../locales";
import { useAccessStore } from "../store";
import { safeLocalStorage } from "../utils";
// 登录状态枚举
enum LoginStatus {
LOADING = "loading",
READY = "ready",
SCANNED = "scanned",
CONFIRMED = "confirmed",
SUCCESS = "success",
ERROR = "error",
}
export function WechatLogin() {
const navigate = useNavigate();
const [status, setStatus] = useState<LoginStatus>(LoginStatus.LOADING);
const [errorMessage, setErrorMessage] = useState<string>("");
const accessStore = useAccessStore();
const storage = safeLocalStorage();
// 模拟登录流程
useEffect(() => {
// 初始加载
const timer1 = setTimeout(() => {
setStatus(LoginStatus.READY);
}, 1000);
return () => {
clearTimeout(timer1);
};
}, []);
// 模拟二维码扫描和确认过程
const simulateLogin = () => {
// 模拟扫码
setStatus(LoginStatus.SCANNED);
// 模拟确认
setTimeout(() => {
setStatus(LoginStatus.CONFIRMED);
// 模拟登录成功
setTimeout(() => {
setStatus(LoginStatus.SUCCESS);
// 存储登录信息
const mockUserInfo = {
id: "wx_" + Math.floor(Math.random() * 1000000),
nickname: "微信用户",
avatar: "https://placekitten.com/100/100", // 模拟头像
accessToken: "mock_token_" + Date.now(),
};
storage.setItem("wechat_user_info", JSON.stringify(mockUserInfo));
// 更新访问状态
accessStore.update((access) => {
access.accessToken = mockUserInfo.accessToken;
access.wechatLoggedIn = true;
});
// 登录成功后跳转
setTimeout(() => {
navigate(Path.Chat);
}, 2000);
}, 1000);
}, 2000);
};
// 刷新二维码
const refreshQRCode = () => {
setStatus(LoginStatus.LOADING);
setTimeout(() => {
setStatus(LoginStatus.READY);
}, 1000);
};
// 处理登录错误
const handleLoginError = () => {
setStatus(LoginStatus.ERROR);
setErrorMessage("登录失败,请稍后重试");
};
return (
<div className={styles.container}>
<div className={styles.loginCard}>
<div className={styles.header}>
<h2>{Locale.Auth.Title}</h2>
<p className={styles.subtitle}>使</p>
</div>
<div className={styles.qrcodeContainer}>
{status === LoginStatus.LOADING && (
<div className={styles.loadingWrapper}>
<LoadingIcon className={styles.loadingIcon} />
<p>...</p>
</div>
)}
{status === LoginStatus.READY && (
<div className={styles.qrcodeWrapper} onClick={simulateLogin}>
{/* <QRCodeImage className={styles.qrcode} /> */}
<div className={styles.qrcodeOverlay}>
<p></p>
</div>
<p className={styles.qrcodeHint}>使</p>
</div>
)}
{status === LoginStatus.SCANNED && (
<div className={styles.statusWrapper}>
<div className={styles.statusIcon}>
<LoadingIcon className={styles.loadingIcon} />
</div>
<p className={styles.statusText}></p>
</div>
)}
{status === LoginStatus.CONFIRMED && (
<div className={styles.statusWrapper}>
<div className={styles.statusIcon}>
<LoadingIcon className={styles.loadingIcon} />
</div>
<p className={styles.statusText}>...</p>
</div>
)}
{status === LoginStatus.SUCCESS && (
<div className={styles.statusWrapper}>
<div className={styles.statusIcon}>
<SuccessIcon className={styles.successIcon} />
</div>
<p className={styles.statusText}>...</p>
</div>
)}
{status === LoginStatus.ERROR && (
<div className={styles.statusWrapper}>
<div className={styles.statusIcon}>
<ErrorIcon className={styles.errorIcon} />
</div>
<p className={styles.statusText}>{errorMessage}</p>
<button className={styles.refreshButton} onClick={refreshQRCode}>
</button>
</div>
)}
</div>
{(status === LoginStatus.READY || status === LoginStatus.LOADING) && (
<div className={styles.footer}>
<p className={styles.expireHint}>2</p>
<button
className={styles.refreshButton}
onClick={refreshQRCode}
disabled={status === LoginStatus.LOADING}
>
</button>
</div>
)}
</div>
</div>
);
}