mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-03-01 00:00:26 +00:00
Deleted the audio player component, songs context, and use-music hook, along with all related code and configuration. Updated affected components and pages to remove music player dependencies and UI. Also improved sidebar, background, and about page UI, and refactored site config icons to use react-icons.
184 lines
5.4 KiB
TypeScript
184 lines
5.4 KiB
TypeScript
import { Button } from '@heroui/button';
|
|
import { CardBody, CardHeader } from '@heroui/card';
|
|
import { Image } from '@heroui/image';
|
|
import { Tab, Tabs } from '@heroui/tabs';
|
|
import { useEffect, useRef, useState } from 'react';
|
|
import { toast } from 'react-hot-toast';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
import logo from '@/assets/images/logo.png';
|
|
|
|
import HoverEffectCard from '@/components/effect_card';
|
|
import { title } from '@/components/primitives';
|
|
import QrCodeLogin from '@/components/qr_code_login';
|
|
import QuickLogin from '@/components/quick_login';
|
|
import type { QQItem } from '@/components/quick_login';
|
|
import { ThemeSwitch } from '@/components/theme-switch';
|
|
|
|
import QQManager from '@/controllers/qq_manager';
|
|
import PureLayout from '@/layouts/pure';
|
|
import { motion } from 'motion/react';
|
|
|
|
export default function QQLoginPage () {
|
|
const navigate = useNavigate();
|
|
const [uinValue, setUinValue] = useState<string>('');
|
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
const [qrcode, setQrcode] = useState<string>('');
|
|
const [qqList, setQQList] = useState<(QQItem | LoginListItem)[]>([]);
|
|
const [refresh, setRefresh] = useState<boolean>(false);
|
|
const firstLoad = useRef<boolean>(true);
|
|
const onSubmit = async () => {
|
|
if (!uinValue) {
|
|
toast.error('请选择快捷登录的QQ');
|
|
|
|
return;
|
|
}
|
|
setIsLoading(true);
|
|
try {
|
|
await QQManager.setQuickLogin(uinValue);
|
|
} catch (error) {
|
|
const msg = (error as Error).message;
|
|
|
|
toast.error(`快速登录QQ失败: ${msg}`);
|
|
} finally {
|
|
setTimeout(() => {
|
|
setIsLoading(false);
|
|
}, 1000);
|
|
}
|
|
};
|
|
|
|
const onUpdateQrCode = async () => {
|
|
if (firstLoad.current) setIsLoading(true);
|
|
try {
|
|
const data = await QQManager.checkQQLoginStatusWithQrcode();
|
|
|
|
if (firstLoad.current) {
|
|
setIsLoading(false);
|
|
firstLoad.current = false;
|
|
}
|
|
if (data.isLogin) {
|
|
toast.success('QQ登录成功');
|
|
navigate('/', { replace: true });
|
|
} else {
|
|
setQrcode(data.qrcodeurl);
|
|
}
|
|
} catch (error) {
|
|
const msg = (error as Error).message;
|
|
|
|
toast.error(`获取二维码失败: ${msg}`);
|
|
}
|
|
};
|
|
|
|
const onUpdateQQList = async () => {
|
|
setRefresh(true);
|
|
try {
|
|
const data = await QQManager.getQQQuickLoginListNew();
|
|
setQQList(data);
|
|
} catch (_error) {
|
|
try {
|
|
const data = await QQManager.getQQQuickLoginList();
|
|
|
|
const qqList = data.map((item) => ({
|
|
uin: item,
|
|
}));
|
|
|
|
setQQList(qqList);
|
|
} catch (_error) {
|
|
const msg = (_error as Error).message;
|
|
|
|
toast.error(`获取QQ列表失败: ${msg}`);
|
|
}
|
|
} finally {
|
|
setRefresh(false);
|
|
}
|
|
};
|
|
|
|
const handleSelectionChange: React.ChangeEventHandler<HTMLSelectElement> = (
|
|
e
|
|
) => {
|
|
setUinValue(e.target.value);
|
|
};
|
|
|
|
useEffect(() => {
|
|
const timer = setInterval(() => {
|
|
onUpdateQrCode();
|
|
}, 3000);
|
|
|
|
onUpdateQrCode();
|
|
onUpdateQQList();
|
|
|
|
return () => clearInterval(timer);
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
<title>QQ登录 - NapCat WebUI</title>
|
|
<PureLayout>
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20, scale: 0.95 }}
|
|
animate={{ opacity: 1, y: 0, scale: 1 }}
|
|
transition={{ duration: 0.5, type: 'spring', stiffness: 120, damping: 20 }}
|
|
className='w-[608px] max-w-full py-8 px-2 md:px-8 overflow-hidden'
|
|
>
|
|
<HoverEffectCard
|
|
className='items-center gap-4 pt-0 pb-6 bg-default-50'
|
|
maxXRotation={3}
|
|
maxYRotation={3}
|
|
>
|
|
<CardHeader className='inline-block max-w-lg text-center justify-center'>
|
|
<div className='flex items-center justify-center w-full gap-2 pt-10'>
|
|
<Image alt='logo' height='7em' src={logo} />
|
|
<div>
|
|
<span className={title()}>Web </span>
|
|
<span className={title({ color: 'violet' })}>
|
|
Login
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<ThemeSwitch className='absolute right-4 top-4' />
|
|
</CardHeader>
|
|
|
|
<CardBody className='flex gap-5 p-10 pt-0'>
|
|
<Tabs
|
|
fullWidth
|
|
classNames={{
|
|
tabList: 'shadow-sm dark:shadow-none',
|
|
}}
|
|
isDisabled={isLoading}
|
|
size='lg'
|
|
>
|
|
<Tab key='shortcut' title='快速登录'>
|
|
<QuickLogin
|
|
handleSelectionChange={handleSelectionChange}
|
|
isLoading={isLoading}
|
|
qqList={qqList}
|
|
refresh={refresh}
|
|
selectedQQ={uinValue}
|
|
onSubmit={onSubmit}
|
|
onUpdateQQList={onUpdateQQList}
|
|
/>
|
|
</Tab>
|
|
<Tab key='qrcode' title='扫码登录'>
|
|
<QrCodeLogin qrcode={qrcode} />
|
|
</Tab>
|
|
</Tabs>
|
|
<Button
|
|
className='w-fit mx-auto'
|
|
variant='light'
|
|
color='primary'
|
|
onPress={() => {
|
|
navigate('/web_login', {
|
|
replace: true,
|
|
});
|
|
}}
|
|
>
|
|
返回 Web Login
|
|
</Button>
|
|
</CardBody>
|
|
</HoverEffectCard>
|
|
</motion.div>
|
|
</PureLayout>
|
|
</>
|
|
);
|
|
}
|