75 lines
2.8 KiB
TypeScript
75 lines
2.8 KiB
TypeScript
// 用例导出面板:格式切换 + 导出下载
|
|
|
|
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import type { ExportFormat } from '@/lib/types';
|
|
import { exportTestCases } from '@/lib/api';
|
|
|
|
interface ExportPanelProps {
|
|
tcSetId: string;
|
|
}
|
|
|
|
const EXPORT_FORMATS: { key: ExportFormat; label: string; description: string }[] = [
|
|
{ key: 'yaml', label: 'YAML', description: '自动化测试可解析的结构化用例' },
|
|
{ key: 'csv', label: 'CSV 表格', description: '适合 Excel 查看与评审归档' },
|
|
{ key: 'xmind', label: 'XMind', description: '思维导图,便于评审展示' },
|
|
];
|
|
|
|
export default function ExportPanel({ tcSetId }: ExportPanelProps) {
|
|
const [activeFormat, setActiveFormat] = useState<ExportFormat>('yaml');
|
|
const [exporting, setExporting] = useState(false);
|
|
|
|
const handleExport = async () => {
|
|
setExporting(true);
|
|
try {
|
|
const blob = await exportTestCases(tcSetId, activeFormat);
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = `testcases.${activeFormat === 'csv' ? 'csv' : activeFormat === 'yaml' ? 'yaml' : 'xmind'}`;
|
|
a.click();
|
|
URL.revokeObjectURL(url);
|
|
} catch (err) {
|
|
console.error('Export failed:', err);
|
|
} finally {
|
|
setExporting(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="rounded-lg border border-gray-200 bg-white p-6">
|
|
<h3 className="mb-4 text-lg font-semibold text-gray-900">导出测试用例</h3>
|
|
|
|
{/* 格式切换标签 */}
|
|
<div className="mb-6 flex gap-2">
|
|
{EXPORT_FORMATS.map((fmt) => (
|
|
<button
|
|
key={fmt.key}
|
|
onClick={() => setActiveFormat(fmt.key)}
|
|
className={`rounded-lg border px-4 py-3 text-sm transition
|
|
${activeFormat === fmt.key
|
|
? 'border-blue-500 bg-blue-50 text-blue-700'
|
|
: 'border-gray-200 text-gray-600 hover:border-gray-300 hover:bg-gray-50'}`}
|
|
>
|
|
<div className="font-medium">{fmt.label}</div>
|
|
<div className="mt-0.5 text-xs text-gray-400">{fmt.description}</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{/* 导出按钮 */}
|
|
<button
|
|
onClick={handleExport}
|
|
disabled={exporting}
|
|
className="flex items-center gap-2 rounded bg-green-600 px-6 py-2.5 text-sm font-medium text-white hover:bg-green-700 disabled:opacity-50"
|
|
>
|
|
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
</svg>
|
|
{exporting ? '导出中...' : `下载 ${activeFormat.toUpperCase()}`}
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|