forked from 77media/video-flow
选择左侧列表右侧时间线高亮显示
This commit is contained in:
parent
f8a2ac1e34
commit
151f05caad
@ -852,6 +852,10 @@ export function NetworkTimeline({
|
||||
|
||||
// 智能时间格式化 - 提升用户体验
|
||||
function formatTime(ms: number): string {
|
||||
// 统一兜底:避免负值/NaN 导致显示 "-Xs"
|
||||
if (!Number.isFinite(ms) || ms <= 0) {
|
||||
return '0s';
|
||||
}
|
||||
if (ms < 1000) {
|
||||
return `${Math.round(ms)}ms`;
|
||||
}
|
||||
@ -983,8 +987,51 @@ export function NetworkTimeline({
|
||||
});
|
||||
}, []);
|
||||
|
||||
// 计算时间线位置
|
||||
// 计算时间线位置(用于绘制可视化相对宽度)
|
||||
const maxTime = Math.max(...(filteredTaskExecutions.length > 0 ? filteredTaskExecutions.map((task: TaskExecution) => task.endTime) : [0]));
|
||||
|
||||
// 计算“项目总耗时”应独立于过滤条件,直接基于原始 tasks
|
||||
// 规则:
|
||||
// 1) 全局开始时间 = 所有任务 start_time/created_at 的最小值
|
||||
// 2) 全局结束时间 =
|
||||
// - 若存在已结束任务:取已结束任务 end_time 的最大值
|
||||
// - 否则:取所有任务 updated_at 的最大值(表示仍在进行中的最近更新时间)
|
||||
const projectDurationMs = React.useMemo(() => {
|
||||
if (!tasks || tasks.length === 0) return 0;
|
||||
|
||||
const toMs = (v: any) => {
|
||||
const n = new Date(v as string).getTime();
|
||||
return Number.isNaN(n) ? NaN : n;
|
||||
};
|
||||
|
||||
// 1) 全局开始
|
||||
const allStarts = tasks
|
||||
.map((t: any) => toMs(t.start_time || t.created_at))
|
||||
.filter((n: number) => !Number.isNaN(n));
|
||||
const globalStart = allStarts.length > 0 ? Math.min(...allStarts) : Date.now();
|
||||
|
||||
// 2) 终止态集合
|
||||
const terminal = new Set(['COMPLETED','SUCCESS','FINISHED','FAILED','FAILURE','ERROR','CANCELLED','TIMEOUT']);
|
||||
|
||||
// 3) 已结束任务的结束时间
|
||||
const endedEnds = tasks
|
||||
.map((t: any) => terminal.has(t.task_status) ? toMs(t.end_time) : NaN)
|
||||
.filter((n: number) => !Number.isNaN(n));
|
||||
|
||||
let globalEnd: number | null = null;
|
||||
if (endedEnds.length > 0) {
|
||||
globalEnd = Math.max(...endedEnds);
|
||||
} else {
|
||||
// 4) 无已结束任务,则取最近一次 updated_at 代表“当前进度”
|
||||
const latestUpdated = tasks
|
||||
.map((t: any) => toMs(t.updated_at || t.created_at))
|
||||
.filter((n: number) => !Number.isNaN(n));
|
||||
if (latestUpdated.length > 0) globalEnd = Math.max(...latestUpdated);
|
||||
}
|
||||
|
||||
if (!globalEnd || Number.isNaN(globalEnd)) return 0;
|
||||
return Math.max(0, globalEnd - globalStart);
|
||||
}, [tasks]);
|
||||
|
||||
return (
|
||||
<div className={cn("h-full flex flex-col bg-gray-950 overflow-hidden", className)}>
|
||||
@ -1382,7 +1429,7 @@ export function NetworkTimeline({
|
||||
<div className="w-1/2 flex flex-col min-h-0">
|
||||
<div className="px-4 py-2.5 bg-gray-900/50 border-b border-gray-800 flex-shrink-0">
|
||||
<div className="text-sm font-medium text-gray-300 text-center">
|
||||
时间线视图 (总耗时: {formatTime(maxTime)})
|
||||
时间线视图 (总耗时: {formatTime(projectDurationMs)})
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 p-3.5 overflow-y-auto min-h-0">
|
||||
@ -1430,12 +1477,15 @@ export function NetworkTimeline({
|
||||
{/* 任务条 */}
|
||||
<div
|
||||
className={cn(
|
||||
"absolute rounded-sm cursor-pointer transition-opacity",
|
||||
"absolute rounded-sm cursor-pointer transition-all duration-200",
|
||||
task.level === 0 ? "top-0.5 h-3.5" : "top-0.5 h-2.5",
|
||||
task.statusCode === 200 ? "bg-emerald-500" :
|
||||
task.statusCode === 202 ? "bg-cyan-500" :
|
||||
task.statusCode >= 400 ? "bg-rose-500" : "bg-amber-500",
|
||||
selectedTask === task.id ? "opacity-100" : "opacity-80 hover:opacity-95",
|
||||
// 选中时明显高亮:提高不透明度、描边、阴影与z-index
|
||||
selectedTask === task.id
|
||||
? "opacity-100 ring-2 ring-cyan-300/90 shadow-[0_0_10px_rgba(34,211,238,0.6)] z-10"
|
||||
: "opacity-80 hover:opacity-95",
|
||||
task.level === 1 && "opacity-70"
|
||||
)}
|
||||
style={{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user