mirror of
https://github.com/JefferyHcool/BiliNote.git
synced 2026-05-13 17:30:44 +08:00
P1 已经把 backend-warning / backend-terminated 横幅做出来了;P2 把
lib.rs 那条 stdout/stderr/terminated 信息流真正落到一个常驻 UI 上:
- 右下角浮动状态点(绿/黄/红),轮询 /api/sys_health 决定颜色
- 点开抽屉看最近 200 行日志(ring buffer),含「重启后端」「复制日志」按钮
Rust:
- src-tauri/src/lib.rs:把 sidecar 启动抽出 spawn_backend_sidecar(),
CommandChild 存进 SidecarHandle(Mutex<Option<CommandChild>>) 这个 state
- 新增 #[tauri::command] restart_backend_sidecar:kill 旧 child + 重新 spawn +
emit 'backend-restarted' 给前端
- 监听任务 stdout/stderr emit 时不再用 format!("'{}'", ...) 包引号,原文直传;
前端 hook 同时兼容旧形式(兜底剥引号)
前端:
- components/BackendHealth/useBackendEvents.ts:listen 四个事件 +
ring buffer (MAX 200 行) + invoke restart + clipboard 复制日志
- BackendHealthIndicator.tsx:右下角浮动状态点,5s 轮询 /api/sys_health;
连续 3 次失败或 backend-terminated 触发 → 红
- BackendLogPanel.tsx:右侧抽屉,深色 monospace 日志区 + 操作按钮
- 纯 web 环境(无 __TAURI_INTERNALS__)下静默不挂载
P3 / P4 还在路上。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
79 lines
3.1 KiB
TypeScript
79 lines
3.1 KiB
TypeScript
import './App.css'
|
|
import { lazy, Suspense, useEffect } from 'react'
|
|
import { BrowserRouter, Navigate, Routes, Route } from 'react-router-dom'
|
|
import { useTaskPolling } from '@/hooks/useTaskPolling.ts'
|
|
import { useCheckBackend } from '@/hooks/useCheckBackend.ts'
|
|
import { systemCheck } from '@/services/system.ts'
|
|
import BackendInitDialog from '@/components/BackendInitDialog'
|
|
import StartupBanner from '@/components/SystemDiagnostic/StartupBanner'
|
|
import BackendHealthIndicator from '@/components/BackendHealth/BackendHealthIndicator'
|
|
import Index from '@/pages/Index.tsx'
|
|
import { HomePage } from './pages/HomePage/Home.tsx'
|
|
|
|
// 非首屏页面使用 React.lazy 按需加载
|
|
const SettingPage = lazy(() => import('./pages/SettingPage/index.tsx'))
|
|
const Model = lazy(() => import('@/pages/SettingPage/Model.tsx'))
|
|
const ProviderForm = lazy(() => import('@/components/Form/modelForm/Form.tsx'))
|
|
const AboutPage = lazy(() => import('@/pages/SettingPage/about.tsx'))
|
|
const Monitor = lazy(() => import('@/pages/SettingPage/Monitor.tsx'))
|
|
const Downloader = lazy(() => import('@/pages/SettingPage/Downloader.tsx'))
|
|
const DownloaderForm = lazy(() => import('@/components/Form/DownloaderForm/Form.tsx'))
|
|
const TranscriberPage = lazy(() => import('@/pages/SettingPage/transcriber.tsx'))
|
|
const NotFoundPage = lazy(() => import('@/pages/NotFoundPage'))
|
|
|
|
function App() {
|
|
useTaskPolling(3000) // 每 3 秒轮询一次
|
|
const { loading, initialized } = useCheckBackend()
|
|
|
|
// 在后端初始化完成后执行系统检查
|
|
useEffect(() => {
|
|
if (initialized) {
|
|
systemCheck()
|
|
}
|
|
}, [initialized])
|
|
|
|
// 如果后端还未初始化,显示初始化对话框
|
|
if (!initialized) {
|
|
return (
|
|
<>
|
|
<StartupBanner />
|
|
<BackendInitDialog open={loading} />
|
|
</>
|
|
)
|
|
}
|
|
|
|
// 后端已初始化,渲染主应用
|
|
return (
|
|
<>
|
|
<StartupBanner />
|
|
<BackendHealthIndicator />
|
|
<BrowserRouter>
|
|
<Suspense fallback={<div className="flex h-screen items-center justify-center">加载中…</div>}>
|
|
<Routes>
|
|
<Route path="/" element={<Index />}>
|
|
<Route index element={<HomePage />} />
|
|
<Route path="settings" element={<SettingPage />}>
|
|
<Route index element={<Navigate to="model" replace />} />
|
|
<Route path="model" element={<Model />}>
|
|
<Route path="new" element={<ProviderForm isCreate />} />
|
|
<Route path=":id" element={<ProviderForm />} />
|
|
</Route>
|
|
<Route path="download" element={<Downloader />}>
|
|
<Route path=":id" element={<DownloaderForm />} />
|
|
</Route>
|
|
<Route path="transcriber" element={<TranscriberPage />} />
|
|
<Route path="monitor" element={<Monitor />}></Route>
|
|
<Route path="about" element={<AboutPage />}></Route>
|
|
<Route path="*" element={<NotFoundPage />} />
|
|
</Route>
|
|
<Route path="*" element={<NotFoundPage />} />
|
|
</Route>
|
|
</Routes>
|
|
</Suspense>
|
|
</BrowserRouter>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default App
|