Prechádzať zdrojové kódy

✨ feat(mobile): 集成react-toastify通知系统

- 替换antd的message组件为react-toastify的toast组件
- 在根组件中添加ToastContainer容器
- 更新所有错误提示为toast.error格式

🔧 chore(routes): 调整考试相关路由路径

- 交换ExamIndex和ExamCard组件的路由路径
- 将'/mobile/exam'路由指向ExamIndex组件
- 将'/mobile/exam/card'路由指向ExamCard组件
yourname 5 mesiacov pred
rodič
commit
02389f451c

+ 6 - 8
src/client/mobile/components/Exam/ExamCard.tsx

@@ -2,16 +2,13 @@ import React,{ useState, useCallback, useEffect } from 'react';
 import { useQuery } from '@tanstack/react-query';
 import { useSearchParams, useNavigate } from "react-router";
 import dayjs from 'dayjs';
-import { message } from 'antd';
 import { useSocketClient } from './hooks/useSocketClient';
 import { classroomDataClient } from '@/client/api';
 import type { QuizState } from './types';
 import type { AnswerRecord, Answer } from './types';
 import { useAuth } from '@/client/mobile/hooks/AuthProvider';
 import { ClassroomStatus } from '@/server/modules/classroom/classroom-data.entity';
-
-
-
+import { toast } from 'react-toastify';
 
 // 答题卡页面
 export default function ExamCard() {
@@ -39,7 +36,7 @@ export default function ExamCard() {
         query: { filters: JSON.stringify({ classroomNo: classroom }) }
       });
       if (response.status !== 200) {
-        message.error('获取教室数据失败');
+        toast.error('获取教室数据失败');
         return null;
       }
       const data = await response.json();
@@ -51,13 +48,14 @@ export default function ExamCard() {
   // 初始化答题卡数据
   const initExamCard = useCallback(async () => {
     if (!classroom || !user?.username) {
+      toast.error('参数缺少');
       // globalThis.location.href = '/exam';
       navigate('/mobile')
       return;
     }
     
     if (classroomData && classroomData.status !== ClassroomStatus.OPEN) {
-      message.error('该教室已关闭');
+      toast.error('该教室已关闭');
       // globalThis.location.href = '/exam';
       navigate('/mobile')
       return;
@@ -160,7 +158,7 @@ export default function ExamCard() {
           }
         );
       } catch (error) {
-        message.error('提交答案失败');
+        toast.error('提交答案失败');
       }
     }
   }, [classroom, user, currentDate, currentPrice, answerManagement]);
@@ -198,7 +196,7 @@ export default function ExamCard() {
           }
         );
       } catch (error) {
-        message.error('提交答案失败');
+        toast.error('提交答案失败');
       }
     }
   }, [classroom, user, currentDate, currentPrice, answerManagement]);

+ 6 - 6
src/client/mobile/components/Exam/ExamIndex.tsx

@@ -1,10 +1,10 @@
 import React, { useState, useCallback } from 'react';
 import { useNavigate } from "react-router";
 import dayjs from 'dayjs';
-import { message } from 'antd';
 import { classroomDataClient } from '@/client/api';
 import { ClassroomStatus } from '@/server/modules/classroom/classroom-data.entity';
 import type { InferResponseType } from 'hono/client';
+import { toast } from 'react-toastify';
 
 type ClassroomDataResponse = InferResponseType<typeof classroomDataClient.$get, 200>;
 type ClassroomData = ClassroomDataResponse['data'][0];
@@ -18,7 +18,7 @@ function ExamIndex() {
 
   const handleJoinTraining = useCallback(async () => {
     if (!classroom) {
-      message.error('教室号不能为空');
+      toast.error('教室号不能为空');
       return;
     }
 
@@ -29,14 +29,14 @@ function ExamIndex() {
       });
       
       if (response.status !== 200) {
-        message.error('获取教室数据失败');
+        toast.error('获取教室数据失败');
         setClassroomData(null);
         return;
       }
       
       const result = await response.json();
       if (!result.data?.length) {
-        message.error('教室不存在');
+        toast.error('教室不存在');
         setClassroomData(null);
         return;
       }
@@ -45,14 +45,14 @@ function ExamIndex() {
       setClassroomData(data);
 
       if (data.status !== ClassroomStatus.OPEN) {
-        message.error('该教室已关闭');
+        toast.error('该教室已关闭');
         return;
       }
 
       // 将教室号作为参数传递到答题页
       navigate(`/mobile/exam/card?classroom=${classroom}`);
     } catch (error) {
-      message.error('获取教室数据失败');
+      toast.error('获取教室数据失败');
       setClassroomData(null);
     } finally {
       setIsLoading(false);

+ 2 - 0
src/client/mobile/index.tsx

@@ -8,6 +8,7 @@ import 'dayjs/locale/zh-cn';
 
 import { AuthProvider } from './hooks/AuthProvider';
 import { router } from './routes';
+import { ToastContainer } from 'react-toastify';
 
 // 配置 dayjs 插件
 dayjs.extend(weekday);
@@ -26,6 +27,7 @@ const App = () => {
       <AuthProvider>
         <RouterProvider router={router} />
       </AuthProvider>
+      <ToastContainer />
     </QueryClientProvider>
   )
 };

+ 4 - 4
src/client/mobile/routes.tsx

@@ -68,8 +68,8 @@ export const router = createBrowserRouter([
     errorElement: <ErrorPage />
   },
   {
-    path: '/mobile/exam',
-    element: <ProtectedRoute><ExamIndex /></ProtectedRoute>,
+    path: '/mobile/exam/card',
+    element: <ProtectedRoute><ExamCard /></ProtectedRoute>,
     errorElement: <ErrorPage />
   },
   {
@@ -78,8 +78,8 @@ export const router = createBrowserRouter([
     errorElement: <ErrorPage />
   },
   {
-    path: '/mobile/exam/card',
-    element: <ProtectedRoute><ExamCard /></ProtectedRoute>,
+    path: '/mobile/exam',
+    element: <ProtectedRoute><ExamIndex /></ProtectedRoute>,
     errorElement: <ErrorPage />
   },
   {