fix: refresh grading status after review and ignore stale student responses

This commit is contained in:
2026-10-18 12:18:49 +08:00
parent 4fec28ce8d
commit aa825231ba
2 changed files with 71 additions and 3 deletions
+5 -3
View File
@@ -207,6 +207,7 @@ function Projects({ openScores }: { openScores: (id: number) => void }) {
function Scores({ batchId, projectId }: { batchId?: number; projectId?: number }) {
const [batches, setBatches] = useState<any[]>([]), [projects, setProjects] = useState<any[]>([]), [batch, setBatch] = useState<number | undefined>(batchId), [project, setProject] = useState<number | undefined>(projectId), [result, setResult] = useState<any>(), [review, setReview] = useState<any>(), [revisions, setRevisions] = useState<any[]>([]);
const [scoreFilter, setScoreFilter] = useState('all');
const [refreshVersion, setRefreshVersion] = useState(0);
const [form] = Form.useForm();
const [sourcesReady, setSourcesReady] = useState(false);
useEffect(() => {
@@ -216,12 +217,12 @@ function Scores({ batchId, projectId }: { batchId?: number; projectId?: number }
setBatches(batchRows); setProjects(projectRows); setSourcesReady(true);
}).catch(error => { if (!cancelled) fail(error); });
return () => { cancelled = true; };
}, []);
}, [refreshVersion]);
const selectedBatch = batches.find(item => item.id === batch);
const scopedProjects = projectsInBatch(selectedBatch, projects);
useEffect(() => { setScoreFilter('all'); }, [batch, project]);
useEffect(() => {
setResult(undefined); setReview(undefined); setRevisions([]);
setScoreFilter('all');
if (!sourcesReady || !selectedBatch) return;
if (!scopedProjects.some(item => item.id === project)) {
setProject(scopedProjects.length === 1 ? scopedProjects[0].id : undefined);
@@ -232,7 +233,7 @@ function Scores({ batchId, projectId }: { batchId?: number; projectId?: number }
.catch(error => { if (!cancelled) fail(error); });
return () => { cancelled = true; };
}, [batch, project, batches, projects, sourcesReady]);
const refresh = () => batch && project && load(`/projects/${project}/scores?batch_id=${batch}`, setResult);
const refresh = () => setRefreshVersion(value => value + 1);
const scoreRows: any[] = result?.rows || [];
const count = (status: string) => scoreRows.filter(row => row.status === status).length;
const unfinished = (row: any) => !['scored', 'reviewed'].includes(row.status);
@@ -245,6 +246,7 @@ function Scores({ batchId, projectId }: { batchId?: number; projectId?: number }
options={options(batches, b => `批次 #${b.id} · ${batchStatusLabel(b.status)}`)} onChange={setBatch} />
<Select aria-label="学生项目" style={{ width: 460 }} placeholder="选择该批次中的学生项目" value={project}
disabled={!sourcesReady || !selectedBatch} options={options(scopedProjects, projectLabel)} onChange={setProject} />
<Button disabled={!sourcesReady || !selectedBatch || !project} onClick={refresh}>刷新评分</Button>
</Space>
{selectedBatch && <Alert className="top-gap" type="info" showIcon
message={`批次 #${batch} 包含 ${scopedProjects.length} 个项目。下方分数仅对应当前选中的学生项目。`} />}