feat(test): 添加测试用例导入功能

- 新增导入测试用例的 API 接口函数
- 在测试实例页面添加文件选择与上传逻辑
- 支持 .xlsx 和 .xls 文件类型的验证
- 实现隐藏文件输入框并绑定点击事件
- 更新按钮文案以区分导出模板和导入操作
- 导入成功后自动刷新测试用例列表
master
钟良源 2 months ago
parent 13b17c48db
commit 399d3676c0

@ -37,4 +37,15 @@ export function exportTemplate(componentBaseId) {
// 导出当前测试用例 // 导出当前测试用例
export function exportTestCases(componentBaseId) { export function exportTestCases(componentBaseId) {
return axios.get(`${urlPrefix}/componentTestCase/export/${componentBaseId}`, { responseType: 'blob' }); return axios.get(`${urlPrefix}/componentTestCase/export/${componentBaseId}`, { responseType: 'blob' });
}
// 导入测试用例
export function importTestCases(params: { componentBaseId: string, file: File }) {
const formData = new FormData();
formData.append('file', params.file);
return axios.post(`${urlPrefix}/componentTestCase/import/${params.componentBaseId}`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
} }

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import { Button, Space, Tree, Collapse, Divider, Message, Modal } from '@arco-design/web-react'; import { Button, Space, Tree, Collapse, Divider, Message, Modal } from '@arco-design/web-react';
import { IconLeft, IconPlus, IconEdit, IconDelete, IconLink, IconSend } from '@arco-design/web-react/icon'; import { IconLeft, IconPlus, IconEdit, IconDelete, IconLink, IconSend } from '@arco-design/web-react/icon';
import styles from './style/testInstance.module.less'; import styles from './style/testInstance.module.less';
@ -8,7 +8,8 @@ import {
submitTestCase, submitTestCase,
deleteTestCase, deleteTestCase,
exportTemplate, exportTemplate,
exportTestCases exportTestCases,
importTestCases
} from '@/api/componentTestCase'; } from '@/api/componentTestCase';
import TestCaseModal from './TestCaseModal'; import TestCaseModal from './TestCaseModal';
import useWebSocket from '@/hooks/useWebSocket'; import useWebSocket from '@/hooks/useWebSocket';
@ -25,6 +26,7 @@ const TestInstance = ({ instance, parentId, onBack }: { instance: any; parentId:
const [editingTestCase, setEditingTestCase] = useState(null); const [editingTestCase, setEditingTestCase] = useState(null);
const [logs, setLogs] = useState<string[]>([]); const [logs, setLogs] = useState<string[]>([]);
const [isSocketConnected, setIsSocketConnected] = useState(false); const [isSocketConnected, setIsSocketConnected] = useState(false);
const fileInputRef = useRef<HTMLInputElement>(null);
// WebSocket hook // WebSocket hook
const { connect, disconnect, isConnected, sendMessage } = useWebSocket({ const { connect, disconnect, isConnected, sendMessage } = useWebSocket({
@ -224,6 +226,52 @@ const TestInstance = ({ instance, parentId, onBack }: { instance: any; parentId:
} }
}; };
// 触发文件选择
const handleImportClick = () => {
fileInputRef.current?.click();
};
// 处理文件上传
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file) return;
// 验证文件类型
const allowedTypes = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
'application/vnd.ms-excel' // .xls
];
if (!allowedTypes.includes(file.type) && !file.name.match(/\.(xlsx|xls)$/i)) {
Message.error('请选择Excel文件.xlsx 或 .xls');
event.target.value = ''; // 清空input
return;
}
try {
Message.loading('正在导入测试用例...');
const res: any = await importTestCases({
componentBaseId: parentId,
file: file
});
if (res.code === 200) {
Message.success(`导入成功!`);
getTestCaseList(); // 刷新列表
}
else {
Message.error(res.msg || '导入失败');
}
} catch (error) {
console.error('导入测试用例失败:', error);
Message.error('导入测试用例失败');
} finally {
// 清空input允许重复选择同一文件
event.target.value = '';
}
};
const handleModalOk = async (values: any) => { const handleModalOk = async (values: any) => {
const params = { const params = {
...values, ...values,
@ -246,6 +294,15 @@ const TestInstance = ({ instance, parentId, onBack }: { instance: any; parentId:
return ( return (
<div className={styles['test-instance']}> <div className={styles['test-instance']}>
{/* 隐藏的文件input */}
<input
ref={fileInputRef}
type="file"
accept=".xlsx,.xls"
style={{ display: 'none' }}
onChange={handleFileChange}
/>
{/* 顶部标签栏 */} {/* 顶部标签栏 */}
<div className={styles['tabs']}> <div className={styles['tabs']}>
<div className={styles['tab-left']}> <div className={styles['tab-left']}>
@ -263,11 +320,11 @@ const TestInstance = ({ instance, parentId, onBack }: { instance: any; parentId:
type="outline" type="outline"
onClick={handleExportTemplate} onClick={handleExportTemplate}
> >
</Button> </Button>
<Button <Button
type="outline" type="outline"
onClick={() => setActiveTab('add')} onClick={handleImportClick}
> >
</Button> </Button>

Loading…
Cancel
Save