import config from '@/utils/config'; import { request } from '@/utils/http'; import Ansi from 'ansi-to-react'; import { Button, Modal, Progress, Space, Typography, message } from 'antd'; import { useState } from 'react'; import useUpgrade, { activeStatuses, phaseLabels, reloadKey, upgradeStore, } from '@/hooks/useUpgrade'; import intl from 'react-intl-universal'; const sizeLabel = (bytes: number) => `${(bytes / 1024 / 1024).toFixed(1)} MB`; const CheckUpdate = ({ systemInfo }: any) => { const { job, busy, connected } = useUpgrade(); const [details, setDetails] = useState(false); const active = activeStatuses.includes(job.status); const ready = job.status === 'ready'; const completed = job.status === 'completed'; const startUpdate = async () => { if (busy || active) return; if (!upgradeStore.beginMutation()) return; try { const result = await request.put(`${config.apiPrefix}system/update`); if (result.code !== 200) throw new Error(result.message); upgradeStore.setJob(result.data); } catch { message.error(intl.get('更新失败,请检查网络及日志或稍后再试')); } finally { upgradeStore.finishMutation(); } }; const checkUpgrade = async () => { if (!upgradeStore.beginMutation()) return; try { const { code, data } = await request.put( `${config.apiPrefix}system/update-check`, ); if (code !== 200) throw new Error('Update check failed'); Modal.confirm({ width: 500, title: intl.get(data.hasNewVersion ? '更新可用' : '已经是最新版了!'), content: data.hasNewVersion ? ( <>

{intl.get('新版本可用,当前版本', { version: data.lastVersion, current: systemInfo.version, })}

              {data.lastLog}
            
) : ( `${intl.get('青龙')} ${data.lastVersion}` ), okText: intl.get(data.hasNewVersion ? '下载更新' : '重新下载'), cancelText: intl.get('以后再说'), onOk: startUpdate, }); } catch { message.error(intl.get('检查更新失败,请检查网络后重试')); } finally { upgradeStore.finishMutation(); } }; const reloadSystem = async (apply: boolean) => { if (!upgradeStore.beginMutation()) return; try { const result = await request.put( `${config.apiPrefix}update/${apply ? 'system' : 'reload'}`, ); if (result.code !== 200) throw new Error(result.message); if (apply) { upgradeStore.setJob(result.data); sessionStorage.setItem(reloadKey, result.data.id); } else { message.success(intl.get('系统将在30秒后自动刷新')); setTimeout(() => window.location.reload(), 30000); } } catch { message.error(intl.get('升级任务启动失败,请检查日志后重试')); } finally { upgradeStore.finishMutation(); } }; const showReloadModal = () => Modal.confirm({ title: intl.get('确认重启'), content: intl.get('更新已就绪,重启后应用新版本'), okText: intl.get('重启并更新'), cancelText: intl.get('以后再说'), onOk: () => reloadSystem(true), }); const label = job.status === 'failed' ? intl.get('更新失败') : ready ? intl.get('下载完成,等待重启') : completed ? intl.get('升级成功') : intl.get(phaseLabels[job.phase || ''] || '正在准备更新'); const hasJob = job.status !== 'idle' && job.status !== 'loading'; const actions = !active && ( {!ready && !completed && ( )} ); return (
{!connected && ( {intl.get('连接已断开,正在重新连接')} )} {!hasJob && actions} {hasJob && (
{label} {job.version ? ` · v${job.version}` : ''} {job.status === 'failed' ? intl.get(job.error || '更新失败,请检查网络及日志或稍后再试') || job.error : intl.get( completed ? '已重新启动并运行新版本,无需再次重启。' : ready ? '更新已就绪,重启后应用新版本' : '更新在后台进行,可以继续使用面板', )} {job.phase === 'downloading' && active && (
{intl.get( job.artifact === 'qinglong-bundle' ? '下载更新包' : job.artifact === 'qinglong-static' ? '下载构建产物' : '下载源码', )} {sizeLabel(job.downloadedBytes || 0)} {job.totalBytes ? ` / ${sizeLabel(job.totalBytes)}` : ''}
)}
{actions}
)} setDetails(false)} width={700} >
          {job.log || intl.get('暂无日志')}
        
); }; export default CheckUpdate;