mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-01-18 22:40:28 +00:00
* feat: 优化离线重连机制,增加前端登录错误提示与二维码刷新功能 - 增加全局掉线检测弹窗 - 增强登录错误解析,支持显示 serverErrorCode 和 message - 优化二维码登录 UI,错误时显示详细原因并提供大按钮重新获取 - 核心层解耦,通过事件抛出 KickedOffLine 通知 - 支持前端点击刷新二维码接口 * feat: 新增看门狗汪汪汪 * cp napcat-shell-loader/launcher-win.bat * refactor: 重构重启流程,移除旧的重启逻辑,新增基于 WebUI 的重启请求处理 * fix: 刷新二维码清楚错误信息
139 lines
3.8 KiB
TypeScript
139 lines
3.8 KiB
TypeScript
import { Input } from '@heroui/input';
|
||
import { Button } from '@heroui/button';
|
||
import { useRequest } from 'ahooks';
|
||
import { useEffect, useState } from 'react';
|
||
import { Controller, useForm } from 'react-hook-form';
|
||
import toast from 'react-hot-toast';
|
||
|
||
import SaveButtons from '@/components/button/save_buttons';
|
||
import PageLoading from '@/components/page_loading';
|
||
|
||
import QQManager from '@/controllers/qq_manager';
|
||
import ProcessManager from '@/controllers/process_manager';
|
||
import { waitForBackendReady } from '@/utils/process_utils';
|
||
|
||
const LoginConfigCard = () => {
|
||
const [isRestarting, setIsRestarting] = useState(false);
|
||
const {
|
||
data: quickLoginData,
|
||
loading: quickLoginLoading,
|
||
error: quickLoginError,
|
||
refreshAsync: refreshQuickLogin,
|
||
} = useRequest(QQManager.getQuickLoginQQ);
|
||
const {
|
||
control,
|
||
handleSubmit: handleOnebotSubmit,
|
||
formState: { isSubmitting },
|
||
setValue: setOnebotValue,
|
||
} = useForm<{
|
||
quickLoginQQ: string;
|
||
}>({
|
||
defaultValues: {
|
||
quickLoginQQ: '',
|
||
},
|
||
});
|
||
|
||
const reset = () => {
|
||
setOnebotValue('quickLoginQQ', quickLoginData ?? '');
|
||
};
|
||
|
||
const onSubmit = handleOnebotSubmit(async (data) => {
|
||
try {
|
||
await QQManager.setQuickLoginQQ(data.quickLoginQQ);
|
||
toast.success('保存成功');
|
||
} catch (error) {
|
||
const msg = (error as Error).message;
|
||
toast.error(`保存失败: ${msg}`);
|
||
}
|
||
});
|
||
|
||
const onRefresh = async () => {
|
||
try {
|
||
await refreshQuickLogin();
|
||
toast.success('刷新成功');
|
||
} catch (error) {
|
||
const msg = (error as Error).message;
|
||
toast.error(`刷新失败: ${msg}`);
|
||
}
|
||
};
|
||
|
||
const onRestartProcess = async () => {
|
||
setIsRestarting(true);
|
||
try {
|
||
const result = await ProcessManager.restartProcess();
|
||
toast.success(result.message || '进程重启请求已发送');
|
||
|
||
// 轮询探测后端是否恢复
|
||
const isReady = await waitForBackendReady(
|
||
30000, // 30秒超时
|
||
() => {
|
||
setIsRestarting(false);
|
||
toast.success('进程重启完成');
|
||
},
|
||
() => {
|
||
setIsRestarting(false);
|
||
toast.error('后端在 30 秒内未响应,请检查 NapCat 运行日志');
|
||
}
|
||
);
|
||
|
||
if (!isReady) {
|
||
setIsRestarting(false);
|
||
}
|
||
} catch (error) {
|
||
const msg = (error as Error).message;
|
||
toast.error(`进程重启失败: ${msg}`);
|
||
setIsRestarting(false);
|
||
}
|
||
};
|
||
|
||
useEffect(() => {
|
||
reset();
|
||
}, [quickLoginData]);
|
||
|
||
if (quickLoginLoading) return <PageLoading loading />;
|
||
|
||
return (
|
||
<>
|
||
<title>OneBot配置 - NapCat WebUI</title>
|
||
<div className='flex-shrink-0 w-full'>快速登录QQ</div>
|
||
<Controller
|
||
control={control}
|
||
name='quickLoginQQ'
|
||
render={({ field }) => (
|
||
<Input
|
||
{...field}
|
||
label='快速登录QQ'
|
||
placeholder='请输入QQ号'
|
||
isDisabled={!!quickLoginError}
|
||
errorMessage={quickLoginError ? '获取快速登录QQ失败' : undefined}
|
||
/>
|
||
)}
|
||
/>
|
||
<SaveButtons
|
||
onSubmit={onSubmit}
|
||
reset={reset}
|
||
isSubmitting={isSubmitting || quickLoginLoading}
|
||
refresh={onRefresh}
|
||
/>
|
||
<div className='flex-shrink-0 w-full mt-6 pt-6 border-t border-divider'>
|
||
<div className='mb-3 text-sm text-default-600'>进程管理</div>
|
||
<Button
|
||
color='warning'
|
||
variant='flat'
|
||
onPress={onRestartProcess}
|
||
isLoading={isRestarting}
|
||
isDisabled={isRestarting}
|
||
fullWidth
|
||
>
|
||
{isRestarting ? '正在重启进程...' : '重启进程'}
|
||
</Button>
|
||
<div className='mt-2 text-xs text-default-500'>
|
||
重启进程将关闭当前 Worker 进程,等待 3 秒后启动新进程
|
||
</div>
|
||
</div>
|
||
</>
|
||
);
|
||
};
|
||
|
||
export default LoginConfigCard;
|