Add backend and frontend support for NapCat auto-update

Introduces backend API and router for updating NapCat, including update logic and pending update application on startup. Adds frontend integration with update button and request handling. Refactors system info component to remove legacy new version tip. Updates types and runtime to track working environment for update selection. Implements lazy loading for pty in unixTerminal to avoid early initialization.
This commit is contained in:
手瓜一十雪
2025-11-19 21:05:08 +08:00
parent 907861102b
commit acdd56eb5e
11 changed files with 641 additions and 164 deletions

View File

@@ -1,4 +1,5 @@
import { Card, CardBody } from '@heroui/card';
import { Button } from '@heroui/button';
import { Image } from '@heroui/image';
import { Link } from '@heroui/link';
import { Skeleton } from '@heroui/skeleton';
@@ -7,6 +8,7 @@ import { useRequest } from 'ahooks';
import { useMemo } from 'react';
import { BsTelegram, BsTencentQq } from 'react-icons/bs';
import { IoDocument } from 'react-icons/io5';
import toast from 'react-hot-toast';
import HoverTiltedCard from '@/components/hover_titled_card';
import NapCatRepoInfo from '@/components/napcat_repo_info';
@@ -20,9 +22,44 @@ import WebUIManager from '@/controllers/webui_manager';
function VersionInfo () {
const { data, loading, error } = useRequest(WebUIManager.GetNapCatVersion);
// 更新NapCat
const { run: updateNapCat, loading: updating } = useRequest(
WebUIManager.UpdateNapCat,
{
manual: true,
onSuccess: (response) => {
console.log('UpdateNapCat onSuccess response:', response);
console.log('response.code:', response.code);
console.log('response.data:', response.data);
console.log('response.message:', response.message);
if (response.code === 0) {
const message = response.data?.message || '更新完成';
console.log('显示消息:', message);
toast.success(message, {
duration: 5000,
});
} else {
console.log('显示错误消息:', response.message || '更新失败');
toast.error(response.message || '更新失败');
}
},
onError: (error) => {
toast.error('更新失败: ' + error.message);
},
}
);
const handleUpdate = () => {
if (!updating) {
updateNapCat();
}
};
return (
<div className='flex items-center gap-2 text-2xl font-bold'>
<div className='flex items-center gap-2'>
<div className='flex items-center gap-4'>
<div className='flex items-center gap-2 text-2xl font-bold'>
<div className='text-primary-500 drop-shadow-md'>NapCat</div>
{error
? (
@@ -47,6 +84,16 @@ function VersionInfo () {
/>
)}
</div>
<Button
color="primary"
variant="solid"
size="sm"
isLoading={updating}
onPress={handleUpdate}
isDisabled={updating}
>
{updating ? '更新中...' : '更新'}
</Button>
</div>
);
}