Files
MyGoNavi/frontend/src/components/ExportProgressBar.tsx
Syngnat 2a8ae05363 🐛 fix(export-workbench): 修正未知总数进度展示并优化 XLSX 收尾阶段
- 修正总行数为 0 时仍被当作已知总数的问题,避免导出进度百分比失真
- 调整导出进度条判定逻辑,未知总数时改为展示实时写入进度
- 统一 Sidebar、TableOverview 和导出工作台的预计行数口径,仅在总数大于 0 时视为已知
- 优化 XLSX 收尾阶段的 ZIP 压缩策略和拷贝缓冲,降低 Windows 大文件导出封装耗时
- 细化 finalizing 阶段文案,明确显示 XLSX 正在封装压缩
- 补充导出进度状态与零总数场景的回归测试
2026-06-18 10:15:00 +08:00

87 lines
2.2 KiB
TypeScript

import React from 'react';
import { Progress } from 'antd';
import {
resolveExportProgressPercent,
shouldUseIndeterminateExportProgress,
type ExportProgressStatus,
} from '../utils/exportProgress';
const INDETERMINATE_ANIMATION_NAME = 'gonavi-export-indeterminate-progress';
const normalizeCount = (value: unknown): number => {
const next = Number(value);
if (!Number.isFinite(next) || next < 0) {
return 0;
}
return Math.trunc(next);
};
type ExportProgressBarProps = {
status: ExportProgressStatus;
current: number;
total: number;
totalRowsKnown: boolean;
};
export const ExportProgressBar: React.FC<ExportProgressBarProps> = ({
status,
current,
total,
totalRowsKnown,
}) => {
const isIndeterminate = shouldUseIndeterminateExportProgress(status, total, totalRowsKnown);
const progressStatus = status === 'error'
? 'exception'
: (status === 'done' ? 'success' : 'active');
if (isIndeterminate) {
return (
<div data-export-progress-mode="indeterminate">
<style>{`
@keyframes ${INDETERMINATE_ANIMATION_NAME} {
0% { transform: translateX(-130%); }
100% { transform: translateX(430%); }
}
`}</style>
<div
style={{
position: 'relative',
width: '100%',
height: 8,
overflow: 'hidden',
borderRadius: 999,
background: 'rgba(15, 23, 42, 0.08)',
}}
>
<div
style={{
position: 'absolute',
inset: 0,
width: '24%',
borderRadius: 999,
background: '#1677ff',
animation: `${INDETERMINATE_ANIMATION_NAME} 1.25s ease-in-out infinite`,
}}
/>
</div>
</div>
);
}
const percent = resolveExportProgressPercent(status, current, total, totalRowsKnown);
return (
<div data-export-progress-mode="determinate">
<Progress
percent={Math.round(percent)}
status={progressStatus}
format={() => totalRowsKnown
? `${normalizeCount(current)}/${normalizeCount(total)}`
: `${Math.round(percent)}%`}
/>
</div>
);
};
export default ExportProgressBar;