Commit 99687a26 authored by 375242562@qq.com's avatar 375242562@qq.com

fix: 批量日志补全操作列 — 新增停止按钮

- 表头补全"操作"列(此前数据行有对应单元格但表头缺失导致列不显示)
- 运行中/待启动的任务显示停止按钮(StopCircleIcon),点击后调用
  cancelJob 并刷新日志列表,停止中显示 CircularProgress
- 同步更新当前追踪的 batchJob 状态
- colSpan 更新为 9(含新操作列)
Co-Authored-By: default avatarClaude Sonnet 4.6 <noreply@anthropic.com>
parent e4f59292
......@@ -2,7 +2,7 @@ import { useState, useEffect, useCallback } from 'react'
import {
Box, Typography, Card, CardContent, CardHeader, Grid,
FormControl, InputLabel, Select, MenuItem, Stack,
Tabs, Tab, Alert, Divider, LinearProgress, Chip, Button,
Tabs, Tab, Alert, Divider, LinearProgress, Chip, Button, CircularProgress,
Table, TableBody, TableCell, TableHead, TableRow,
Collapse, IconButton, Tooltip, TablePagination,
} from '@mui/material'
......@@ -14,6 +14,7 @@ import { PermissionButton } from '../components/auth/PermissionButton'
import PsychologyIcon from '@mui/icons-material/Psychology'
import BatchPredictionIcon from '@mui/icons-material/BatchPrediction'
import StopIcon from '@mui/icons-material/Stop'
import StopCircleIcon from '@mui/icons-material/StopCircle'
import { MatchingStepper } from '../components/matching/MatchingStepper'
import { MatchingResultCard } from '../components/matching/MatchingResultCard'
import { ReasoningTimeline } from '../components/matching/ReasoningTimeline'
......@@ -74,6 +75,7 @@ export function MatchingPage() {
const [logTotal, setLogTotal] = useState(0)
const [logPage, setLogPage] = useState(0)
const [expandedErrorId, setExpandedErrorId] = useState<string | null>(null)
const [cancellingJobId, setCancellingJobId] = useState<string | null>(null)
const loadJobHistory = useCallback(async (page = 0) => {
// fetch PAGE_SIZE+1 to detect if a next page exists
......@@ -163,6 +165,21 @@ export function MatchingPage() {
}
}
const handleCancelFromLog = async (job: BatchJob) => {
setCancellingJobId(job.id)
try {
const updated = await batchMatchingService.cancelJob(job.id)
// 如果是当前追踪的 job,同步状态
if (batchJob?.id === job.id) setBatchJob(updated)
loadJobHistory(logPage)
} catch (e: unknown) {
const msg = e instanceof Error ? e.message : '停止失败'
setBatchError(msg)
} finally {
setCancellingJobId(null)
}
}
const handleLogPageChange = (_: unknown, newPage: number) => {
setLogPage(newPage)
loadJobHistory(newPage)
......@@ -322,6 +339,7 @@ export function MatchingPage() {
<TableCell>触发时间</TableCell>
<TableCell>完成时间</TableCell>
<TableCell>耗时</TableCell>
<TableCell align="center">操作</TableCell>
</TableRow>
</TableHead>
<TableBody>
......@@ -387,10 +405,28 @@ export function MatchingPage() {
{formatDuration(job.created_at, job.completed_at)}
</Typography>
</TableCell>
<TableCell align="center">
{(job.status === 'running' || job.status === 'pending') && (
<Tooltip title={job.cancel_requested ? '停止中...' : '停止该任务'}>
<span>
<IconButton
size="small"
color="error"
disabled={!!job.cancel_requested || cancellingJobId === job.id}
onClick={() => handleCancelFromLog(job)}
>
{cancellingJobId === job.id
? <CircularProgress size={14} color="error" />
: <StopCircleIcon fontSize="small" />}
</IconButton>
</span>
</Tooltip>
)}
</TableCell>
</TableRow>
{hasError && (
<TableRow key={`${job.id}-err`}>
<TableCell colSpan={8} sx={{ py: 0 }}>
<TableCell colSpan={9} sx={{ py: 0 }}>
<Collapse in={isExpanded}>
<Box sx={{ p: 1.5, bgcolor: 'grey.50', borderRadius: 1, my: 0.5 }}>
<Typography
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment