feat(admin): 管理端 UI/UX 深度优化——错误/加载/空状态、表单快捷键、移动端适配与无障碍
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { Alert, Button, Card, Descriptions, Empty, Space, Spin, Table, Tag, Tooltip } from 'antd';
|
||||
import {Alert, Button, Card, Descriptions, Empty, Space, Table, Tag, Tooltip, Skeleton} from 'antd';
|
||||
import { QueryErrorState } from '../../components/QueryState';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { ArrowLeftOutlined, EyeOutlined } from '@ant-design/icons';
|
||||
import { useNavigate, useParams } from 'react-router';
|
||||
@@ -15,7 +16,6 @@ import { examDetailSchema } from '../../api/schemas';
|
||||
import { usePermission } from '../../hooks/usePermission';
|
||||
import type { ExamItem } from './types';
|
||||
import './style.css';
|
||||
import { getErrorMessage } from '../../utils/error';
|
||||
|
||||
interface ScoreRow {
|
||||
id: number;
|
||||
@@ -56,19 +56,10 @@ const ExamDetailPage: React.FC = () => {
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { data: detail, isLoading, isFetching } = useQuery<ExamDetail | null>({
|
||||
const { data: detail, isLoading, isFetching, isError, refetch } = useQuery<ExamDetail | null>({
|
||||
queryKey: ['exams', 'detail', id],
|
||||
queryFn: async () => {
|
||||
try {
|
||||
return validateResponse<ExamDetail>(
|
||||
examDetailSchema,
|
||||
await api.get<ExamDetail>(`/exams/${id}`),
|
||||
);
|
||||
} catch (error) {
|
||||
message.error(getErrorMessage(error, '加载考试失败'));
|
||||
return null;
|
||||
}
|
||||
},
|
||||
queryFn: async () =>
|
||||
validateResponse<ExamDetail>(examDetailSchema, await api.get<ExamDetail>(`/exams/${id}`)),
|
||||
});
|
||||
const loading = isLoading || isFetching;
|
||||
|
||||
@@ -145,9 +136,18 @@ const ExamDetailPage: React.FC = () => {
|
||||
if (loading && !detail)
|
||||
return (
|
||||
<div className="exam-detail-loading">
|
||||
<Spin size="large" />
|
||||
<Skeleton active paragraph={{ rows: 10 }} />
|
||||
</div>
|
||||
);
|
||||
if (isError) {
|
||||
return (
|
||||
<QueryErrorState
|
||||
title="考试详情加载失败"
|
||||
description="请检查网络后重试。"
|
||||
onRetry={() => void refetch()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (!detail) return <Empty description="考试不存在或无权访问" />;
|
||||
|
||||
const average = detail.scores.find((row) => row.classAvg !== null)?.classAvg ?? null;
|
||||
|
||||
Reference in New Issue
Block a user