Files
YG-Datasets/easy-dataset-main/app/projects/[projectId]/blind-test-tasks/[taskId]/page.js

160 lines
4.5 KiB
JavaScript
Raw Normal View History

2026-03-17 14:36:31 +08:00
'use client';
import { useState } from 'react';
import { useParams, useRouter } from 'next/navigation';
import {
Box,
Container,
Button,
CircularProgress,
Alert,
Dialog,
DialogTitle,
DialogContent,
DialogContentText,
DialogActions
} from '@mui/material';
import StopIcon from '@mui/icons-material/Stop';
import { useTranslation } from 'react-i18next';
import useBlindTestDetail from '../hooks/useBlindTestDetail';
import BlindTestHeader from '../components/BlindTestHeader';
import ResultSummary from '../components/ResultSummary';
import ResultDetailList from '../components/ResultDetailList';
import BlindTestInProgress from '../components/BlindTestInProgress';
export default function BlindTestDetailPage() {
const { projectId, taskId } = useParams();
const router = useRouter();
const { t } = useTranslation();
const {
task,
loading,
error,
setError,
currentQuestion,
leftAnswer,
rightAnswer,
answersLoading,
streamingA,
streamingB,
voting,
completed,
fetchCurrentQuestion,
submitVote,
interruptTask,
getResultStats
} = useBlindTestDetail(projectId, taskId);
const [interruptDialog, setInterruptDialog] = useState(false);
const handleBack = () => router.push(`/projects/${projectId}/blind-test-tasks`);
const handleVote = async vote => {
await submitVote(vote);
};
const handleInterrupt = async () => {
await interruptTask();
setInterruptDialog(false);
};
// 加载中
if (loading) {
return (
<Container
maxWidth="xl"
sx={{ py: 3, height: 'calc(100vh - 64px)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
>
<CircularProgress />
</Container>
);
}
// 任务不存在
if (!task) {
return (
<Container maxWidth="xl" sx={{ py: 3 }}>
<BlindTestHeader title={t('blindTest.taskNotFound', '任务不存在')} onBack={handleBack} />
<Alert severity="error">{t('blindTest.taskNotFound', '任务不存在')}</Alert>
</Container>
);
}
const isResultView = completed || task.status !== 0;
const stats = getResultStats();
// 结果展示页面(已完成或已中断)
if (isResultView) {
return (
<Container maxWidth="xl" sx={{ py: 3, height: 'calc(100vh - 64px)', overflow: 'auto' }}>
<BlindTestHeader title={t('blindTest.resultTitle', '盲测结果')} status={task.status} onBack={handleBack} />
<Box sx={{ maxWidth: 1200, mx: 'auto' }}>
<ResultSummary stats={stats} modelInfo={task.modelInfo || '{}'} />
<ResultDetailList task={task} />
</Box>
</Container>
);
}
// 盲测进行中页面
return (
<Container maxWidth="xl" sx={{ py: 3, height: 'calc(100vh - 64px)', display: 'flex', flexDirection: 'column' }}>
<BlindTestHeader
title={t('blindTest.inProgress', '盲测进行中')}
onBack={handleBack}
actions={
<Button
variant="outlined"
color="warning"
startIcon={<StopIcon />}
onClick={() => setInterruptDialog(true)}
size="small"
>
{t('blindTest.interrupt', '中断任务')}
</Button>
}
/>
{error && (
<Alert severity="error" sx={{ mb: 2 }} onClose={() => setError('')}>
{error}
</Alert>
)}
<Box sx={{ flex: 1, minHeight: 0 }}>
<BlindTestInProgress
task={task}
currentQuestion={currentQuestion}
leftAnswer={leftAnswer}
rightAnswer={rightAnswer}
streamingA={streamingA}
streamingB={streamingB}
answersLoading={answersLoading}
voting={voting}
onVote={handleVote}
onReload={fetchCurrentQuestion}
/>
</Box>
{/* 中断确认对话框 */}
<Dialog open={interruptDialog} onClose={() => setInterruptDialog(false)}>
<DialogTitle>{t('blindTest.interruptConfirmTitle', '确认中断')}</DialogTitle>
<DialogContent>
<DialogContentText>
{t('blindTest.interruptConfirmMessage', '确定要中断这个盲测任务吗?已完成的评判结果将保留。')}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => setInterruptDialog(false)}>{t('common.cancel', '取消')}</Button>
<Button color="warning" variant="contained" onClick={handleInterrupt}>
{t('blindTest.interrupt', '中断')}
</Button>
</DialogActions>
</Dialog>
</Container>
);
}