N3 洞察页三 tab(飞轮/健康中心/全局治理):
- FlywheelPanel(版本队列/阻塞/停转归档/Git质量/梦核)整体迁出 BlueprintModal
——跨项目内容不再寄生单项目弹窗,BlueprintModal 减重 414 行
- CONVENTIONS 规则来源 + 应用梦核建议迁至全局治理 tab(影响所有项目的操作归全局层)
- BlueprintModal 侧板只留单项目内容(模块详情/余票/可派发/项目治理)
N4 Gitea 层级归位:实例管理(全局配置)拆为 GiteaInstancesSection 挂设置页;
项目绑定+webhook 留治理面板,无实例时提示去设置页添加;共用 queryKey 缓存
N5 仓库注册表并入 项目→管理→仓库 tab(RegistryTab 复用),Sidebar 底部入口
与弹窗死壳移除;总览页更名对齐"跨项目行动项"定位
至此 ui-restructure N1-N5 全部完成:三条公理(名实一致/层级对齐/频率分层)落地。
零后端变更,typecheck 全绿。
82 lines
3.2 KiB
TypeScript
82 lines
3.2 KiB
TypeScript
import { useState, useEffect } from "react";
|
||
import { OverviewPage } from "./components/overview/OverviewPage";
|
||
import { Dashboard } from "./components/dashboard/Dashboard";
|
||
import { ProjectModal } from "./components/dashboard/ProjectModal";
|
||
import { ResourcesPage } from "./components/resources/ResourcesPage";
|
||
import { ToolsPage } from "./components/tools/ToolsPage";
|
||
import { SettingsPage } from "./components/settings/SettingsPage";
|
||
import { InsightPage } from "./components/insight/InsightPage";
|
||
import { Sidebar, type Page } from "./components/layout/Sidebar";
|
||
import { Toast } from "./components/ui/Toast";
|
||
import { getStartupAlerts, type StartupAlert } from "./lib/commands";
|
||
import { useUIStore } from "./store/ui";
|
||
import { check as checkUpdate } from "@tauri-apps/plugin-updater";
|
||
|
||
export default function App() {
|
||
const [page, setPage] = useState<Page>("overview");
|
||
const [alerts, setAlerts] = useState<StartupAlert[]>([]);
|
||
const [alertsDismissed, setAlertsDismissed] = useState(false);
|
||
const showToast = useUIStore((s) => s.showToast);
|
||
|
||
// 启动时静默检查更新
|
||
useEffect(() => {
|
||
checkUpdate()
|
||
.then((update) => {
|
||
if (update?.available) {
|
||
showToast(`🆕 发现新版本 v${update.version},前往「设置」页更新`);
|
||
}
|
||
})
|
||
.catch(() => {}); // 静默失败,不打扰用户
|
||
}, []);
|
||
|
||
// 启动健康扫描结果(延迟 2s 等后端扫描完成)
|
||
useEffect(() => {
|
||
const timer = setTimeout(() => {
|
||
getStartupAlerts()
|
||
.then((list) => { if (list.length > 0) setAlerts(list); })
|
||
.catch(() => {});
|
||
}, 2000);
|
||
return () => clearTimeout(timer);
|
||
}, []);
|
||
|
||
return (
|
||
<div className="h-screen flex overflow-hidden">
|
||
<Sidebar
|
||
page={page}
|
||
onPageChange={setPage}
|
||
/>
|
||
|
||
<main className="flex-1 overflow-auto bg-gray-50 flex flex-col min-h-0">
|
||
{alerts.length > 0 && !alertsDismissed && (
|
||
<div className="shrink-0 bg-amber-50 border-b border-amber-200 px-6 py-2.5 flex items-start gap-3">
|
||
<span className="text-amber-500 shrink-0 mt-0.5">⚠️</span>
|
||
<div className="flex-1 min-w-0">
|
||
<span className="text-xs font-semibold text-amber-800">项目需要关注:</span>
|
||
<span className="text-xs text-amber-700 ml-1">
|
||
{alerts.slice(0, 3).map((a) => `${a.project_name}(${a.detail})`).join("、")}
|
||
{alerts.length > 3 && `,等 ${alerts.length - 3} 个项目`}
|
||
</span>
|
||
</div>
|
||
<button
|
||
onClick={() => setAlertsDismissed(true)}
|
||
className="shrink-0 text-amber-400 hover:text-amber-600 text-sm leading-none"
|
||
aria-label="关闭"
|
||
>×</button>
|
||
</div>
|
||
)}
|
||
<div className="flex-1 overflow-auto min-h-0">
|
||
{page === "overview" && <OverviewPage />}
|
||
{page === "dashboard" && <Dashboard />}
|
||
{page === "resources" && <ResourcesPage />}
|
||
{page === "insight" && <InsightPage />}
|
||
{page === "tools" && <ToolsPage />}
|
||
{page === "settings" && <SettingsPage />}
|
||
</div>
|
||
</main>
|
||
|
||
<ProjectModal />
|
||
<Toast />
|
||
</div>
|
||
);
|
||
}
|