diff --git a/.gitignore b/.gitignore index 15342e7..4e79c7e 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ library/MinerU/ libs/ .claude .checkpoints +.mimocode/ +.zcode/ diff --git a/dashboard/src/App.tsx b/dashboard/src/App.tsx index 38f2ef9..a610865 100644 --- a/dashboard/src/App.tsx +++ b/dashboard/src/App.tsx @@ -16,6 +16,9 @@ import { UncachedPaperModal } from './components/dialogs/UncachedPaperModal'; import { PaperDetailModal } from './components/dialogs/PaperDetailModal'; import { Logo } from './components/Logo'; import { ErrorBoundary } from './components/ErrorBoundary'; +import { motion, AnimatePresence } from 'framer-motion'; +import { ToastContainer } from './components/layout/ToastContainer'; +import type { ToastItem } from './components/layout/ToastContainer'; // 引入拆分出的业务逻辑 Hooks import { useAuth } from './hooks/useAuth'; @@ -29,7 +32,7 @@ export default function App() { // 移动端菜单显示状态 const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false); - // 1. 全局自定义 Dialog 弹窗管理 (Alert / Confirm) + // 1. 全局自定义 Dialog 弹窗与 Toast 通知管理 const [dialog, setDialog] = useState<{ type: 'alert' | 'confirm'; title: string; @@ -38,14 +41,53 @@ export default function App() { onCancel?: () => void; } | null>(null); - const showAlert = useCallback((message: string, title = '系统提示') => { - setDialog({ - type: 'alert', - title, - message, - onConfirm: () => {}, - }); - }, []); + const [toasts, setToasts] = useState([]); + + const showToast = useCallback( + (message: string, type: 'success' | 'error' | 'info' = 'success') => { + const id = Date.now() + Math.random(); + setToasts((prev) => [...prev, { id, message, type }]); + setTimeout(() => { + setToasts((prev) => prev.filter((t) => t.id !== id)); + }, 3000); + }, + [] + ); + + const showAlert = useCallback( + (message: string, title = '系统提示') => { + const toastTriggers = [ + '成功', + '完成', + '复制', + '导入', + '保存', + '通知', + '已存', + '提示', + ]; + const isToast = toastTriggers.some( + (t) => + title.includes(t) || + message.includes('成功') || + message.includes('复制') || + message.includes('完成') || + message.includes('已存') + ); + + if (isToast) { + showToast(message, 'success'); + } else { + setDialog({ + type: 'alert', + title, + message, + onConfirm: () => {}, + }); + } + }, + [showToast] + ); const showConfirm = useCallback( (message: string, onConfirm: () => void, title = '确认操作') => { @@ -344,10 +386,10 @@ export default function App() { // 4. 渲染顶层登录页面 if (auth.isAuthenticated === null) { return ( -
+
- - + + 正在校验系统安全凭证...
@@ -357,26 +399,32 @@ export default function App() { if (auth.isAuthenticated === false) { return ( -
-
-
+
+
+
-
+
-
+
-

+

AstroResearch

-

+

天文学科研辅助系统 · 安全登录

-