parent
18492ec568
commit
16d60c3f39
|
@ -7,8 +7,11 @@ import io.metersphere.base.domain.ApiTestEnvironmentExample;
|
|||
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
|
||||
import io.metersphere.base.mapper.ApiTestEnvironmentMapper;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.controller.request.EnvironmentRequest;
|
||||
import io.metersphere.dto.BaseSystemConfigDTO;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.service.SystemParameterService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -90,6 +93,18 @@ public class ApiTestEnvironmentService {
|
|||
* @return
|
||||
*/
|
||||
public synchronized ApiTestEnvironmentWithBLOBs getMockEnvironmentByProjectId(String projectId, String protocal, String baseUrl) {
|
||||
//创建的时候检查当前站点
|
||||
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
|
||||
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
|
||||
if (baseSystemConfigDTO != null && StringUtils.isNotEmpty(baseSystemConfigDTO.getUrl())) {
|
||||
baseUrl = baseSystemConfigDTO.getUrl();
|
||||
if (baseUrl.startsWith("http:")) {
|
||||
protocal = "http";
|
||||
} else if (baseUrl.startsWith("https:")) {
|
||||
protocal = "https";
|
||||
}
|
||||
}
|
||||
|
||||
String apiName = MockConfigStaticData.MOCK_EVN_NAME;
|
||||
ApiTestEnvironmentWithBLOBs returnModel = null;
|
||||
ApiTestEnvironmentExample example = new ApiTestEnvironmentExample();
|
||||
|
@ -117,6 +132,21 @@ public class ApiTestEnvironmentService {
|
|||
JSONArray conditions = httpObj.getJSONArray("conditions");
|
||||
if (conditions.isEmpty()) {
|
||||
needUpdate = true;
|
||||
} else {
|
||||
for (int i = 0; i < conditions.size(); i++) {
|
||||
JSONObject obj = conditions.getJSONObject(i);
|
||||
String socket = url;
|
||||
if (socket.startsWith("http://")) {
|
||||
socket = socket.substring(7);
|
||||
} else if (socket.startsWith("https://")) {
|
||||
socket = socket.substring(8);
|
||||
}
|
||||
if (!obj.containsKey("socket") || !StringUtils.equals(socket, String.valueOf(obj.get("socket")))) {
|
||||
needUpdate = true;
|
||||
} else if (!obj.containsKey("protocol") || !StringUtils.equals(protocal, String.valueOf(obj.get("protocol")))) {
|
||||
needUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,4 +258,20 @@ public class ApiTestEnvironmentService {
|
|||
|
||||
return blobs;
|
||||
}
|
||||
|
||||
public void checkMockEvnInfoByBaseUrl(String baseUrl) {
|
||||
List<ApiTestEnvironmentWithBLOBs> allEvnList = this.selectByExampleWithBLOBs(null);
|
||||
for (ApiTestEnvironmentWithBLOBs model : allEvnList) {
|
||||
if (StringUtils.equals(model.getName(), MockConfigStaticData.MOCK_EVN_NAME)) {
|
||||
String protocal = "";
|
||||
if (baseUrl.startsWith("http:")) {
|
||||
protocal = "http";
|
||||
} else if (baseUrl.startsWith("https:")) {
|
||||
protocal = "https";
|
||||
}
|
||||
|
||||
model = this.checkMockEvnIsRightful(model, protocal, model.getProjectId(), model.getName(), baseUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package io.metersphere.excel.handler;
|
||||
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
|
||||
import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
import org.apache.poi.ss.usermodel.Drawing;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/5/7 2:17 下午
|
||||
* @Description
|
||||
*/
|
||||
public class FunctionCaseTemplateWriteHandler extends AbstractRowHeightStyleStrategy {
|
||||
|
||||
@Override
|
||||
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
|
||||
super.afterRowDispose(writeSheetHolder, writeTableHolder, row, relativeRowIndex, isHead);
|
||||
if (isHead) {
|
||||
Sheet sheet = writeSheetHolder.getSheet();
|
||||
Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
|
||||
|
||||
// 在第一行 第3列创建一个批注
|
||||
Comment comment1 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 2, 0, (short) 3, 1));
|
||||
// 输入批注信息
|
||||
comment1.setString(new XSSFRichTextString(Translator.get("do_not_modify_header_order") + "," + Translator.get("num_needed_modify_testcase") + "," + Translator.get("num_needless_create_testcase")));
|
||||
|
||||
// 在第一行 第4列创建一个批注
|
||||
Comment comment2 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 0, (short) 3, 1));
|
||||
// 输入批注信息
|
||||
comment2.setString(new XSSFRichTextString(Translator.get("module_created_automatically")));
|
||||
|
||||
// 在第一行 第5列创建一个批注
|
||||
Comment comment3 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 4, 0, (short) 3, 1));
|
||||
// 输入批注信息
|
||||
comment3.setString(new XSSFRichTextString(Translator.get("options") + "(functional、performance、api)"));
|
||||
|
||||
|
||||
// 在第一行 第6列创建一个批注
|
||||
Comment comment4 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 5, 0, (short) 3, 1));
|
||||
// 输入批注信息
|
||||
comment4.setString(new XSSFRichTextString(Translator.get("please_input_workspace_member")));
|
||||
|
||||
// 在第一行 第7列创建一个批注
|
||||
Comment comment5 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 6, 0, (short) 3, 1));
|
||||
// 输入批注信息
|
||||
comment5.setString(new XSSFRichTextString(Translator.get("options") + "(P0、P1、P2、P3)"));
|
||||
|
||||
// 在第一行 第8列创建一个批注
|
||||
Comment comment6 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 7, 0, (short) 3, 1));
|
||||
// 输入批注信息
|
||||
comment6.setString(new XSSFRichTextString(Translator.get("tag_tip_pattern")));
|
||||
|
||||
// 将批注添加到单元格对象中
|
||||
sheet.getRow(0).getCell(1).setCellComment(comment1);
|
||||
sheet.getRow(0).getCell(1).setCellComment(comment2);
|
||||
sheet.getRow(0).getCell(1).setCellComment(comment3);
|
||||
sheet.getRow(0).getCell(1).setCellComment(comment4);
|
||||
sheet.getRow(0).getCell(1).setCellComment(comment5);
|
||||
sheet.getRow(0).getCell(1).setCellComment(comment6);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setHeadColumnHeight(Row row, int relativeRowIndex) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setContentColumnHeight(Row row, int relativeRowIndex) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,338 @@
|
|||
package io.metersphere.excel.listener;
|
||||
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.base.domain.TestCaseWithBLOBs;
|
||||
import io.metersphere.commons.constants.TestCaseConstants;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.excel.domain.ExcelErrData;
|
||||
import io.metersphere.excel.domain.TestCaseExcelData;
|
||||
import io.metersphere.excel.utils.ExcelValidateHelper;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.track.service.TestCaseService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class TestCaseDataIgnoreErrorListener extends EasyExcelListener<TestCaseExcelData> {
|
||||
|
||||
private TestCaseService testCaseService;
|
||||
|
||||
private String projectId;
|
||||
|
||||
protected List<TestCaseExcelData> updateList = new ArrayList<>(); //存储待更新用例的集合
|
||||
|
||||
protected boolean isUpdated = false; //判断是否更新过用例,将会传给前端
|
||||
|
||||
Set<String> testCaseNames;
|
||||
|
||||
Set<String> userIds;
|
||||
|
||||
public boolean isUpdated() {
|
||||
return isUpdated;
|
||||
}
|
||||
|
||||
public TestCaseDataIgnoreErrorListener(Class clazz, String projectId, Set<String> testCaseNames, Set<String> userIds) {
|
||||
this.clazz = clazz;
|
||||
this.testCaseService = (TestCaseService) CommonBeanFactory.getBean("testCaseService");
|
||||
this.projectId = projectId;
|
||||
this.testCaseNames = testCaseNames;
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validate(TestCaseExcelData data, String errMsg) {
|
||||
String nodePath = data.getNodePath();
|
||||
StringBuilder stringBuilder = new StringBuilder(errMsg);
|
||||
//校验”所属模块"
|
||||
if (nodePath != null) {
|
||||
String[] nodes = nodePath.split("/");
|
||||
//校验模块深度
|
||||
if (nodes.length > TestCaseConstants.MAX_NODE_DEPTH + 1) {
|
||||
stringBuilder.append(Translator.get("test_case_node_level_tip") +
|
||||
TestCaseConstants.MAX_NODE_DEPTH + Translator.get("test_case_node_level") + "; ");
|
||||
}
|
||||
//模块名不能为空
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
if (i != 0 && StringUtils.equals(nodes[i].trim(), "")) {
|
||||
stringBuilder.append(Translator.get("module_not_null") + "; ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
//增加字数校验,每一层不能超过100字
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
String nodeStr = nodes[i];
|
||||
if (StringUtils.isNotEmpty(nodeStr)) {
|
||||
if (nodeStr.trim().length() > 100) {
|
||||
stringBuilder.append(Translator.get("module") + Translator.get("test_track.length_less_than") + "100:" + nodeStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//校验维护人
|
||||
if (!userIds.contains(data.getMaintainer())) {
|
||||
stringBuilder.append(Translator.get("user_not_exists") + ":" + data.getMaintainer() + "; ");
|
||||
}
|
||||
|
||||
/*
|
||||
校验Excel中是否有ID
|
||||
有的话校验ID是否已在当前项目中存在,存在则更新用例,
|
||||
不存在则继续校验看是否重复,不重复则新建用例。
|
||||
*/
|
||||
if (null != data.getNum()) { //当前读取的数据有ID
|
||||
if (null != testCaseService.checkIdExist(data.getNum(), projectId)) { //该ID在当前项目中存在
|
||||
//如果前面所经过的校验都没报错
|
||||
if (StringUtils.isEmpty(stringBuilder)) {
|
||||
updateList.add(data); //将当前数据存入更新列表
|
||||
stringBuilder.append("update_testcase"); //该信息用于在invoke方法中判断是否该更新用例
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
} else {
|
||||
/*
|
||||
该ID在当前数据库中不存在,应当继续校验用例是否重复,
|
||||
在下面的校验过程中,num的值会被用于判断是否重复,所以应当先设置为null
|
||||
*/
|
||||
data.setNum(null);
|
||||
}
|
||||
}
|
||||
/*
|
||||
校验用例
|
||||
*/
|
||||
if (testCaseNames.contains(data.getName())) {
|
||||
TestCaseWithBLOBs testCase = new TestCaseWithBLOBs();
|
||||
BeanUtils.copyBean(testCase, data);
|
||||
testCase.setProjectId(projectId);
|
||||
String steps = getSteps(data);
|
||||
testCase.setSteps(steps);
|
||||
boolean dbExist = testCaseService.exist(testCase);
|
||||
boolean excelExist = false;
|
||||
if (dbExist) {
|
||||
// db exist
|
||||
stringBuilder.append(Translator.get("test_case_already_exists") + ":" + data.getName() + "; ");
|
||||
} else {
|
||||
// @Data 重写了 equals 和 hashCode 方法
|
||||
excelExist = excelDataList.contains(data);
|
||||
}
|
||||
if (excelExist) {
|
||||
// excel exist
|
||||
stringBuilder.append(Translator.get("test_case_already_exists_excel") + ":" + data.getName() + "; ");
|
||||
} else {
|
||||
excelDataList.add(data);
|
||||
}
|
||||
} else {
|
||||
testCaseNames.add(data.getName());
|
||||
excelDataList.add(data);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
if (!(list.size() == 0)) {
|
||||
Collections.reverse(list); //因为saveImportData里面是先分配最大的ID,这个ID应该先发给list中最后的数据,所以要reverse
|
||||
List<TestCaseWithBLOBs> result = list.stream()
|
||||
.map(item -> this.convert2TestCase(item))
|
||||
.collect(Collectors.toList());
|
||||
testCaseService.saveImportData(result, projectId);
|
||||
this.isUpdated = true;
|
||||
}
|
||||
|
||||
if (!(updateList.size() == 0)) {
|
||||
List<TestCaseWithBLOBs> result2 = updateList.stream()
|
||||
.map(item -> this.convert2TestCaseForUpdate(item))
|
||||
.collect(Collectors.toList());
|
||||
testCaseService.updateImportDataCarryId(result2, projectId);
|
||||
this.isUpdated = true;
|
||||
updateList.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private TestCaseWithBLOBs convert2TestCase(TestCaseExcelData data) {
|
||||
TestCaseWithBLOBs testCase = new TestCaseWithBLOBs();
|
||||
BeanUtils.copyBean(testCase, data);
|
||||
testCase.setId(UUID.randomUUID().toString());
|
||||
testCase.setProjectId(this.projectId);
|
||||
testCase.setCreateTime(System.currentTimeMillis());
|
||||
testCase.setUpdateTime(System.currentTimeMillis());
|
||||
testCase.setCustomNum(data.getCustomNum());
|
||||
String nodePath = data.getNodePath();
|
||||
|
||||
if (!nodePath.startsWith("/")) {
|
||||
nodePath = "/" + nodePath;
|
||||
}
|
||||
if (nodePath.endsWith("/")) {
|
||||
nodePath = nodePath.substring(0, nodePath.length() - 1);
|
||||
}
|
||||
testCase.setNodePath(nodePath);
|
||||
|
||||
//将标签设置为前端可解析的格式
|
||||
String modifiedTags = modifyTagPattern(data);
|
||||
testCase.setTags(modifiedTags);
|
||||
|
||||
if (StringUtils.isNotBlank(data.getStepModel())
|
||||
&& StringUtils.equals(data.getStepModel(), TestCaseConstants.StepModel.TEXT.name())) {
|
||||
testCase.setStepDescription(data.getStepDesc());
|
||||
testCase.setExpectedResult(data.getStepResult());
|
||||
} else {
|
||||
String steps = getSteps(data);
|
||||
testCase.setSteps(steps);
|
||||
}
|
||||
return testCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Excel中的数据对象转换为用于更新操作的用例数据对象,
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
private TestCaseWithBLOBs convert2TestCaseForUpdate(TestCaseExcelData data) {
|
||||
TestCaseWithBLOBs testCase = new TestCaseWithBLOBs();
|
||||
BeanUtils.copyBean(testCase, data);
|
||||
testCase.setProjectId(this.projectId);
|
||||
testCase.setUpdateTime(System.currentTimeMillis());
|
||||
|
||||
//调整nodePath格式
|
||||
String nodePath = data.getNodePath();
|
||||
if (!nodePath.startsWith("/")) {
|
||||
nodePath = "/" + nodePath;
|
||||
}
|
||||
if (nodePath.endsWith("/")) {
|
||||
nodePath = nodePath.substring(0, nodePath.length() - 1);
|
||||
}
|
||||
testCase.setNodePath(nodePath);
|
||||
|
||||
String steps = getSteps(data);
|
||||
testCase.setSteps(steps);
|
||||
|
||||
//将标签设置为前端可解析的格式
|
||||
String modifiedTags = modifyTagPattern(data);
|
||||
testCase.setTags(modifiedTags);
|
||||
|
||||
return testCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整tags格式,便于前端进行解析。
|
||||
* 例如对于:标签1,标签2。将调整为:["标签1","标签2"]。
|
||||
*/
|
||||
public String modifyTagPattern(TestCaseExcelData data) {
|
||||
String tags = data.getTags();
|
||||
try {
|
||||
if (StringUtils.isNotBlank(tags)) {
|
||||
JSONArray.parse(tags);
|
||||
return tags;
|
||||
}
|
||||
return "[]";
|
||||
} catch (Exception e) {
|
||||
if (tags != null) {
|
||||
Stream<String> stringStream = Arrays.stream(tags.split("[,;,;]")); //当标签值以中英文的逗号和分号分隔时才能正确解析
|
||||
List<String> tagList = stringStream.map(tag -> tag = "\"" + tag + "\"")
|
||||
.collect(Collectors.toList());
|
||||
String modifiedTags = StringUtils.join(tagList, ",");
|
||||
modifiedTags = "[" + modifiedTags + "]";
|
||||
return modifiedTags;
|
||||
} else {
|
||||
return "[]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getSteps(TestCaseExcelData data) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
|
||||
String[] stepDesc = new String[1];
|
||||
String[] stepRes = new String[1];
|
||||
|
||||
if (data.getStepDesc() != null) {
|
||||
stepDesc = data.getStepDesc().split("\r\n|\n");
|
||||
} else {
|
||||
stepDesc[0] = "";
|
||||
}
|
||||
if (data.getStepResult() != null) {
|
||||
stepRes = data.getStepResult().split("\r\n|\n");
|
||||
} else {
|
||||
stepRes[0] = "";
|
||||
}
|
||||
|
||||
String pattern = "(^\\d+)(\\.)?";
|
||||
int index = stepDesc.length > stepRes.length ? stepDesc.length : stepRes.length;
|
||||
|
||||
for (int i = 0; i < index; i++) {
|
||||
|
||||
// 保持插入顺序,判断用例是否有相同的steps
|
||||
JSONObject step = new JSONObject(true);
|
||||
step.put("num", i + 1);
|
||||
|
||||
Pattern descPattern = Pattern.compile(pattern);
|
||||
Pattern resPattern = Pattern.compile(pattern);
|
||||
|
||||
if (i < stepDesc.length) {
|
||||
Matcher descMatcher = descPattern.matcher(stepDesc[i]);
|
||||
if (descMatcher.find()) {
|
||||
step.put("desc", descMatcher.replaceAll(""));
|
||||
} else {
|
||||
step.put("desc", stepDesc[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < stepRes.length) {
|
||||
Matcher resMatcher = resPattern.matcher(stepRes[i]);
|
||||
if (resMatcher.find()) {
|
||||
step.put("result", resMatcher.replaceAll(""));
|
||||
} else {
|
||||
step.put("result", stepRes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
jsonArray.add(step);
|
||||
}
|
||||
return jsonArray.toJSONString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(TestCaseExcelData testCaseExcelData, AnalysisContext analysisContext) {
|
||||
String errMsg;
|
||||
Integer rowIndex = analysisContext.readRowHolder().getRowIndex();
|
||||
String updateMsg = "update_testcase";
|
||||
try {
|
||||
//根据excel数据实体中的javax.validation + 正则表达式来校验excel数据
|
||||
errMsg = ExcelValidateHelper.validateEntity(testCaseExcelData);
|
||||
//自定义校验规则
|
||||
errMsg = validate(testCaseExcelData, errMsg);
|
||||
} catch (NoSuchFieldException e) {
|
||||
errMsg = Translator.get("parse_data_error");
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(errMsg)) {
|
||||
|
||||
//如果errMsg只有"update testcase",说明用例待更新
|
||||
if (!errMsg.equals(updateMsg)) {
|
||||
ExcelErrData excelErrData = new ExcelErrData(testCaseExcelData, rowIndex,
|
||||
Translator.get("number") + " " + rowIndex + " " + Translator.get("row") + Translator.get("error")
|
||||
+ ":" + errMsg);
|
||||
|
||||
errList.add(excelErrData);
|
||||
}
|
||||
} else {
|
||||
list.add(testCaseExcelData);
|
||||
}
|
||||
|
||||
if (list.size() > BATCH_COUNT) {
|
||||
saveData();
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.excel.utils;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.write.handler.WriteHandler;
|
||||
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
|
||||
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
|
@ -38,4 +39,19 @@ public class EasyExcelExporter {
|
|||
}
|
||||
}
|
||||
|
||||
public void exportByCustomWriteHandler(HttpServletResponse response, List data, String fileName, String sheetName, WriteHandler writeHandler) {
|
||||
response.setContentType("application/vnd.ms-excel");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
try {
|
||||
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
|
||||
EasyExcel.write(response.getOutputStream(), this.clazz).registerWriteHandler(writeHandler).sheet(sheetName).doWrite(data);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
throw new ExcelException("Utf-8 encoding is not supported");
|
||||
} catch (IOException e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
throw new ExcelException("IO exception");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.service;
|
||||
|
||||
import io.metersphere.api.service.ApiTestEnvironmentService;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.SystemHeaderMapper;
|
||||
import io.metersphere.base.mapper.SystemParameterMapper;
|
||||
|
@ -42,6 +43,8 @@ public class SystemParameterService {
|
|||
private ExtSystemParameterMapper extSystemParameterMapper;
|
||||
@Resource
|
||||
private SystemHeaderMapper systemHeaderMapper;
|
||||
@Resource
|
||||
private ApiTestEnvironmentService apiTestEnvironmentService;
|
||||
|
||||
public String searchEmail() {
|
||||
return extSystemParameterMapper.email();
|
||||
|
@ -237,6 +240,7 @@ public class SystemParameterService {
|
|||
|
||||
public void saveBaseInfo(List<SystemParameter> parameters) {
|
||||
SystemParameterExample example = new SystemParameterExample();
|
||||
|
||||
parameters.forEach(param -> {
|
||||
// 去掉路径最后的 /
|
||||
param.setParamValue(StringUtils.removeEnd(param.getParamValue(), "/"));
|
||||
|
@ -247,6 +251,10 @@ public class SystemParameterService {
|
|||
systemParameterMapper.insert(param);
|
||||
}
|
||||
example.clear();
|
||||
|
||||
if (StringUtils.equals(param.getParamKey(), "base.url")) {
|
||||
apiTestEnvironmentService.checkMockEvnInfoByBaseUrl(param.getParamValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -154,6 +154,13 @@ public class TestCaseController {
|
|||
return testCaseService.testCaseImport(file, projectId, userId);
|
||||
}
|
||||
|
||||
@PostMapping("/importIgnoreError/{projectId}/{userId}")
|
||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||
public ExcelResponse testCaseImportIgnoreError(MultipartFile file, @PathVariable String projectId, @PathVariable String userId) {
|
||||
checkPermissionService.checkProjectOwner(projectId);
|
||||
return testCaseService.testCaseImportIgnoreError(file, projectId, userId);
|
||||
}
|
||||
|
||||
@GetMapping("/export/template")
|
||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||
public void testCaseTemplateExport(HttpServletResponse response) {
|
||||
|
|
|
@ -19,6 +19,8 @@ import io.metersphere.excel.domain.ExcelErrData;
|
|||
import io.metersphere.excel.domain.ExcelResponse;
|
||||
import io.metersphere.excel.domain.TestCaseExcelData;
|
||||
import io.metersphere.excel.domain.TestCaseExcelDataFactory;
|
||||
import io.metersphere.excel.handler.FunctionCaseTemplateWriteHandler;
|
||||
import io.metersphere.excel.listener.TestCaseDataIgnoreErrorListener;
|
||||
import io.metersphere.excel.listener.TestCaseDataListener;
|
||||
import io.metersphere.excel.utils.EasyExcelExporter;
|
||||
import io.metersphere.i18n.Translator;
|
||||
|
@ -97,7 +99,8 @@ public class TestCaseService {
|
|||
TestCaseFileMapper testCaseFileMapper;
|
||||
@Resource
|
||||
TestCaseTestMapper testCaseTestMapper;
|
||||
private void setNode(TestCaseWithBLOBs testCase){
|
||||
|
||||
private void setNode(TestCaseWithBLOBs testCase) {
|
||||
if (StringUtils.isEmpty(testCase.getNodeId()) || "default-module".equals(testCase.getNodeId())) {
|
||||
TestCaseNodeExample example = new TestCaseNodeExample();
|
||||
example.createCriteria().andProjectIdEqualTo(testCase.getProjectId()).andNameEqualTo("默认模块");
|
||||
|
@ -224,7 +227,7 @@ public class TestCaseService {
|
|||
String remark = tc.getRemark();
|
||||
String prerequisite = tc.getPrerequisite();
|
||||
if (StringUtils.equals(steps, caseSteps) && StringUtils.equals(remark, caseRemark) && StringUtils.equals(prerequisite, casePrerequisite)) {
|
||||
//MSException.throwException(Translator.get("test_case_already_exists"));
|
||||
//MSException.throwException(Translator.get("test_case_already_exists"));
|
||||
return tc;
|
||||
}
|
||||
}
|
||||
|
@ -487,7 +490,7 @@ public class TestCaseService {
|
|||
testcase.setCustomNum(String.valueOf(number));
|
||||
}
|
||||
testcase.setReviewStatus(TestCaseReviewStatus.Prepare.name());
|
||||
mapper.insert(testcase);
|
||||
mapper.insert(testcase);
|
||||
});
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
|
@ -516,6 +519,7 @@ public class TestCaseService {
|
|||
/**
|
||||
* 把Excel中带ID的数据更新到数据库
|
||||
* feat(测试跟踪):通过Excel导入导出时有ID字段,可通过Excel导入来更新用例。 (#1727)
|
||||
*
|
||||
* @param testCases
|
||||
* @param projectId
|
||||
*/
|
||||
|
@ -555,8 +559,9 @@ public class TestCaseService {
|
|||
public void testCaseTemplateExport(HttpServletResponse response) {
|
||||
try {
|
||||
EasyExcelExporter easyExcelExporter = new EasyExcelExporter(new TestCaseExcelDataFactory().getExcelDataByLocal());
|
||||
easyExcelExporter.export(response, generateExportTemplate(),
|
||||
Translator.get("test_case_import_template_name"), Translator.get("test_case_import_template_sheet"));
|
||||
FunctionCaseTemplateWriteHandler handler = new FunctionCaseTemplateWriteHandler();
|
||||
easyExcelExporter.exportByCustomWriteHandler(response, generateExportTemplate(),
|
||||
Translator.get("test_case_import_template_name"), Translator.get("test_case_import_template_sheet"), handler);
|
||||
} catch (Exception e) {
|
||||
MSException.throwException(e);
|
||||
}
|
||||
|
@ -619,16 +624,15 @@ public class TestCaseService {
|
|||
}
|
||||
|
||||
list.add(new TestCaseExcelData());
|
||||
TestCaseExcelData explain = new TestCaseExcelData();
|
||||
explain.setName(Translator.get("do_not_modify_header_order") + "," + Translator.get("num_needed_modify_testcase") + "," + Translator.get("num_needless_create_testcase"));
|
||||
explain.setNodePath(Translator.get("module_created_automatically"));
|
||||
explain.setType(Translator.get("options") + "(functional、performance、api)");
|
||||
explain.setTags(Translator.get("tag_tip_pattern"));
|
||||
// explain.setMethod(Translator.get("options") + "(manual、auto)");
|
||||
explain.setPriority(Translator.get("options") + "(P0、P1、P2、P3)");
|
||||
explain.setMaintainer(Translator.get("please_input_workspace_member"));
|
||||
|
||||
list.add(explain);
|
||||
// TestCaseExcelData explain = new TestCaseExcelData();
|
||||
// explain.setName(Translator.get("do_not_modify_header_order") + "," + Translator.get("num_needed_modify_testcase") + "," + Translator.get("num_needless_create_testcase"));
|
||||
// explain.setNodePath(Translator.get("module_created_automatically"));
|
||||
// explain.setType(Translator.get("options") + "(functional、performance、api)");
|
||||
// explain.setTags(Translator.get("tag_tip_pattern"));
|
||||
//// explain.setMethod(Translator.get("options") + "(manual、auto)");
|
||||
// explain.setPriority(Translator.get("options") + "(P0、P1、P2、P3)");
|
||||
// explain.setMaintainer(Translator.get("please_input_workspace_member"));
|
||||
// list.add(explain);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -1020,9 +1024,95 @@ public class TestCaseService {
|
|||
|
||||
/**
|
||||
* 更新项目下用例的CustomNum值
|
||||
*
|
||||
* @param projectId 项目ID
|
||||
*/
|
||||
public void updateTestCaseCustomNumByProjectId(String projectId) {
|
||||
extTestCaseMapper.updateTestCaseCustomNumByProjectId(projectId);
|
||||
}
|
||||
|
||||
public ExcelResponse testCaseImportIgnoreError(MultipartFile multipartFile, String projectId, String userId) {
|
||||
|
||||
ExcelResponse excelResponse = new ExcelResponse();
|
||||
boolean isUpdated = false; //判断是否更新了用例
|
||||
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||
QueryTestCaseRequest queryTestCaseRequest = new QueryTestCaseRequest();
|
||||
queryTestCaseRequest.setProjectId(projectId);
|
||||
List<TestCase> testCases = extTestCaseMapper.getTestCaseNames(queryTestCaseRequest);
|
||||
Set<String> testCaseNames = testCases.stream()
|
||||
.map(TestCase::getName)
|
||||
.collect(Collectors.toSet());
|
||||
List<ExcelErrData<TestCaseExcelData>> errList = null;
|
||||
if (multipartFile == null) {
|
||||
MSException.throwException(Translator.get("upload_fail"));
|
||||
}
|
||||
if (multipartFile.getOriginalFilename().endsWith(".xmind")) {
|
||||
try {
|
||||
XmindCaseParser xmindParser = new XmindCaseParser(this, userId, projectId, testCaseNames);
|
||||
errList = xmindParser.parse(multipartFile);
|
||||
if (CollectionUtils.isEmpty(xmindParser.getNodePaths())
|
||||
&& CollectionUtils.isEmpty(xmindParser.getTestCase())
|
||||
&& CollectionUtils.isEmpty(xmindParser.getUpdateTestCase())) {
|
||||
if (errList == null) {
|
||||
errList = new ArrayList<>();
|
||||
}
|
||||
ExcelErrData excelErrData = new ExcelErrData(null, 1, Translator.get("upload_fail") + ":" + Translator.get("upload_content_is_null"));
|
||||
errList.add(excelErrData);
|
||||
excelResponse.setErrList(errList);
|
||||
}
|
||||
List<TestCaseWithBLOBs> continueCaseList = xmindParser.getContinueValidatedCase();
|
||||
if (CollectionUtils.isNotEmpty(continueCaseList) || CollectionUtils.isNotEmpty(xmindParser.getUpdateTestCase())) {
|
||||
if (CollectionUtils.isNotEmpty(xmindParser.getUpdateTestCase())) {
|
||||
continueCaseList.removeAll(xmindParser.getUpdateTestCase());
|
||||
this.updateImportData(xmindParser.getUpdateTestCase(), projectId);
|
||||
}
|
||||
List<String> nodePathList = xmindParser.getValidatedNodePath();
|
||||
if (CollectionUtils.isNotEmpty(nodePathList)) {
|
||||
testCaseNodeService.createNodes(nodePathList, projectId);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(continueCaseList)) {
|
||||
Collections.reverse(continueCaseList);
|
||||
this.saveImportData(continueCaseList, projectId);
|
||||
}
|
||||
}
|
||||
xmindParser.clear();
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
UserRoleExample userRoleExample = new UserRoleExample();
|
||||
userRoleExample.createCriteria()
|
||||
.andRoleIdIn(Arrays.asList(RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER))
|
||||
.andSourceIdEqualTo(currentWorkspaceId);
|
||||
|
||||
Set<String> userIds = userRoleMapper.selectByExample(userRoleExample).stream().map(UserRole::getUserId).collect(Collectors.toSet());
|
||||
|
||||
try {
|
||||
//根据本地语言环境选择用哪种数据对象进行存放读取的数据
|
||||
Class clazz = new TestCaseExcelDataFactory().getExcelDataByLocal();
|
||||
|
||||
TestCaseDataIgnoreErrorListener easyExcelListener = new TestCaseDataIgnoreErrorListener(clazz, projectId, testCaseNames, userIds);
|
||||
|
||||
//读取excel数据
|
||||
EasyExcelFactory.read(multipartFile.getInputStream(), clazz, easyExcelListener).sheet().doRead();
|
||||
|
||||
errList = easyExcelListener.getErrList();
|
||||
isUpdated = easyExcelListener.isUpdated();
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException(e.getMessage());
|
||||
}
|
||||
}
|
||||
//如果包含错误信息就导出错误信息
|
||||
if (!errList.isEmpty()) {
|
||||
excelResponse.setSuccess(false);
|
||||
excelResponse.setErrList(errList);
|
||||
excelResponse.setIsUpdated(isUpdated);
|
||||
} else {
|
||||
excelResponse.setSuccess(true);
|
||||
}
|
||||
|
||||
return excelResponse;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,10 @@ public class XmindCaseParser {
|
|||
*/
|
||||
private List<String> nodePaths;
|
||||
|
||||
private List<TestCaseWithBLOBs> continueValidatedCase;
|
||||
|
||||
private List<String> errorPath;
|
||||
|
||||
public XmindCaseParser(TestCaseService testCaseService, String userId, String projectId, Set<String> testCaseNames) {
|
||||
this.testCaseService = testCaseService;
|
||||
this.maintainer = userId;
|
||||
|
@ -69,11 +73,14 @@ public class XmindCaseParser {
|
|||
compartDatas = new ArrayList<>();
|
||||
process = new DetailUtil();
|
||||
nodePaths = new ArrayList<>();
|
||||
continueValidatedCase = new ArrayList<>();
|
||||
errorPath = new ArrayList<>();
|
||||
}
|
||||
|
||||
private static final String TC_REGEX = "(?:tc:|tc:|tc)";
|
||||
private static final String PC_REGEX = "(?:pc:|pc:|pc)";
|
||||
private static final String RC_REGEX = "(?:rc:|rc:|rc)";
|
||||
private static final String ID_REGEX = "(?:id:|id:|id)";
|
||||
private static final String TAG_REGEX = "(?:tag:|tag:|tag)";
|
||||
|
||||
public void clear() {
|
||||
|
@ -126,6 +133,7 @@ public class XmindCaseParser {
|
|||
* 验证用例的合规性
|
||||
*/
|
||||
private boolean validate(TestCaseWithBLOBs data) {
|
||||
boolean validatePass = true;
|
||||
String nodePath = data.getNodePath();
|
||||
if (!nodePath.startsWith("/")) {
|
||||
nodePath = "/" + nodePath;
|
||||
|
@ -137,27 +145,41 @@ public class XmindCaseParser {
|
|||
|
||||
|
||||
if (data.getName().length() > 200) {
|
||||
validatePass = false;
|
||||
process.add(Translator.get("test_case") + Translator.get("test_track.length_less_than") + "200", nodePath + data.getName());
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(nodePath)) {
|
||||
String[] nodes = nodePath.split("/");
|
||||
if (nodes.length > TestCaseConstants.MAX_NODE_DEPTH + 1) {
|
||||
validatePass = false;
|
||||
process.add(Translator.get("test_case_node_level_tip") +
|
||||
TestCaseConstants.MAX_NODE_DEPTH + Translator.get("test_case_node_level"), nodePath);
|
||||
if (!errorPath.contains(nodePath)) {
|
||||
errorPath.add(nodePath);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
if (i != 0 && StringUtils.equals(nodes[i].trim(), "")) {
|
||||
validatePass = false;
|
||||
process.add(Translator.get("test_case") + Translator.get("module_not_null"), nodePath + data.getName());
|
||||
if (!errorPath.contains(nodePath)) {
|
||||
errorPath.add(nodePath);
|
||||
}
|
||||
break;
|
||||
} else if (nodes[i].trim().length() > 100) {
|
||||
validatePass = false;
|
||||
process.add(Translator.get("module") + Translator.get("test_track.length_less_than") + "100 ", nodes[i].trim());
|
||||
if (!errorPath.contains(nodePath)) {
|
||||
errorPath.add(nodePath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.equals(data.getType(), TestCaseConstants.Type.Functional.getValue()) && StringUtils.equals(data.getMethod(), TestCaseConstants.Method.Auto.getValue())) {
|
||||
validatePass = false;
|
||||
process.add(Translator.get("functional_method_tip"), nodePath + data.getName());
|
||||
}
|
||||
|
||||
|
@ -176,9 +198,11 @@ public class XmindCaseParser {
|
|||
|
||||
// 用例等级和用例性质处理
|
||||
if (!priorityList.contains(data.getPriority())) {
|
||||
validatePass = false;
|
||||
process.add(Translator.get("test_case_priority") + Translator.get("incorrect_format"), nodePath + data.getName());
|
||||
}
|
||||
if (data.getType() == null) {
|
||||
validatePass = false;
|
||||
process.add(Translator.get("test_case_type") + Translator.get("incorrect_format"), nodePath + data.getName());
|
||||
}
|
||||
|
||||
|
@ -186,9 +210,13 @@ public class XmindCaseParser {
|
|||
TestCaseExcelData compartData = new TestCaseExcelData();
|
||||
BeanUtils.copyBean(compartData, data);
|
||||
if (compartDatas.contains(compartData)) {
|
||||
validatePass = false;
|
||||
process.add(Translator.get("test_case_already_exists_excel"), nodePath + "/" + compartData.getName());
|
||||
}
|
||||
compartDatas.add(compartData);
|
||||
if (validatePass) {
|
||||
this.continueValidatedCase.add(data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -305,6 +333,7 @@ public class XmindCaseParser {
|
|||
List<Attached> steps = new LinkedList<>();
|
||||
StringBuilder rc = new StringBuilder();
|
||||
List<String> tags = new LinkedList<>();
|
||||
StringBuilder customId = new StringBuilder();
|
||||
if (attacheds != null && !attacheds.isEmpty()) {
|
||||
attacheds.forEach(item -> {
|
||||
if (isAvailable(item.getTitle(), PC_REGEX)) {
|
||||
|
@ -314,12 +343,15 @@ public class XmindCaseParser {
|
|||
rc.append("\n");
|
||||
} else if (isAvailable(item.getTitle(), TAG_REGEX)) {
|
||||
tags.add(replace(item.getTitle(), TAG_REGEX));
|
||||
} else if (isAvailable(item.getTitle(), ID_REGEX)) {
|
||||
customId.append(replace(item.getTitle(), ID_REGEX));
|
||||
} else {
|
||||
steps.add(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
testCase.setRemark(rc.toString());
|
||||
testCase.setCustomNum(customId.toString());
|
||||
testCase.setTags(JSON.toJSONString(tags));
|
||||
testCase.setSteps(this.getSteps(steps));
|
||||
// 校验合规性
|
||||
|
@ -364,8 +396,23 @@ public class XmindCaseParser {
|
|||
//检查目录合规性
|
||||
this.validate();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return process.parse(ex.getMessage());
|
||||
}
|
||||
return process.parse();
|
||||
}
|
||||
|
||||
public List<TestCaseWithBLOBs> getContinueValidatedCase() {
|
||||
return this.continueValidatedCase;
|
||||
}
|
||||
|
||||
public List<String> getValidatedNodePath() {
|
||||
List<String> returnPathList = new ArrayList<>(nodePaths);
|
||||
if (CollectionUtils.isNotEmpty(returnPathList)) {
|
||||
if (CollectionUtils.isNotEmpty(errorPath)) {
|
||||
returnPathList.removeAll(errorPath);
|
||||
}
|
||||
}
|
||||
return returnPathList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
<el-dialog class="testcase-import" :title="$t('test_track.case.import.case_import')" :visible.sync="dialogVisible"
|
||||
@close="close">
|
||||
|
||||
<el-tabs v-model="activeName" simple>
|
||||
<el-tabs v-model="activeName" @tab-click="clickTabs" simple>
|
||||
<el-tab-pane :label="$t('test_track.case.import.excel_title')" name="excelImport">
|
||||
|
||||
<el-row>
|
||||
<el-link type="primary" class="download-template"
|
||||
@click="downloadTemplate"
|
||||
>{{$t('test_track.case.import.download_template')}}
|
||||
>{{ $t('test_track.case.import.download_template') }}
|
||||
</el-link>
|
||||
</el-row>
|
||||
<el-row>
|
||||
|
@ -39,10 +39,20 @@
|
|||
<el-row>
|
||||
<ul>
|
||||
<li v-for="errFile in errList" :key="errFile.rowNum">
|
||||
{{errFile.errMsg}}
|
||||
{{ errFile.errMsg }}
|
||||
</li>
|
||||
</ul>
|
||||
</el-row>
|
||||
|
||||
<el-row style="text-align: right" v-if="showExcelImportContinueBtn">
|
||||
<div style="margin-right: 20px;margin-bottom: 10px;">
|
||||
<el-checkbox v-model="uploadIgnoreError">{{ $t('test_track.case.import.ignore_error') }}</el-checkbox>
|
||||
</div>
|
||||
<el-button type="primary" @click="uploadContinue(false)">{{ $t('test_track.case.import.continue_upload') }}
|
||||
</el-button>
|
||||
<el-button @click="close">{{ $t('commons.cancel') }}</el-button>
|
||||
</el-row>
|
||||
|
||||
</el-tab-pane>
|
||||
<!-- Xmind 导入 -->
|
||||
<el-tab-pane :label="$t('test_track.case.import.xmind_title')" name="xmindImport" style="border: 0px">
|
||||
|
@ -98,10 +108,18 @@
|
|||
<el-row>
|
||||
<ul>
|
||||
<li v-for="errFile in xmindErrList" :key="errFile.rowNum">
|
||||
{{errFile.errMsg}}
|
||||
{{ errFile.errMsg }}
|
||||
</li>
|
||||
</ul>
|
||||
</el-row>
|
||||
<el-row style="text-align: right" v-if="showXmindImportContinueBtn">
|
||||
<div style="margin-right: 20px;margin-bottom: 10px;">
|
||||
<el-checkbox v-model="uploadXmindIgnoreError">{{ $t('test_track.case.import.ignore_error') }}</el-checkbox>
|
||||
</div>
|
||||
<el-button type="primary" @click="uploadContinue(true)">{{ $t('test_track.case.import.continue_upload') }}
|
||||
</el-button>
|
||||
<el-button @click="close">{{ $t('commons.cancel') }}</el-button>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
|
@ -124,16 +142,34 @@
|
|||
activeName: 'excelImport',
|
||||
dialogVisible: false,
|
||||
fileList: [],
|
||||
lastXmindFile: null,
|
||||
lastExcelFile: null,
|
||||
errList: [],
|
||||
xmindErrList: [],
|
||||
isLoading: false,
|
||||
isUpdated: false
|
||||
isUpdated: false,
|
||||
clickTabsName: "",
|
||||
showExcelImportContinueBtn: false,
|
||||
showXmindImportContinueBtn: false,
|
||||
uploadIgnoreError: false,
|
||||
uploadXmindIgnoreError: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.showExcelImportContinueBtn = false;
|
||||
this.showXmindImportContinueBtn = false;
|
||||
},
|
||||
activated() {
|
||||
this.showExcelImportContinueBtn = false;
|
||||
this.showXmindImportContinueBtn = false;
|
||||
},
|
||||
methods: {
|
||||
handleExceed(files, fileList) {
|
||||
this.$warning(this.$t('test_track.case.import.upload_limit_count'));
|
||||
},
|
||||
clickTabs(tab, event) {
|
||||
this.clickTabsName = tab.name;
|
||||
},
|
||||
uploadValidate(file) {
|
||||
let suffix = file.name.substring(file.name.lastIndexOf('.') + 1);
|
||||
if (suffix != 'xls' && suffix != 'xlsx') {
|
||||
|
@ -179,11 +215,13 @@
|
|||
removeGoBackListener(this.close);
|
||||
this.dialogVisible = false;
|
||||
this.fileList = [];
|
||||
this.showExcelImportContinueBtn = false;
|
||||
this.showXmindImportContinueBtn = false;
|
||||
this.errList = [];
|
||||
this.xmindErrList = [];
|
||||
|
||||
//通过excel导入更新过数据的话就刷新页面
|
||||
if (this.isUpdated === true){
|
||||
if (this.isUpdated === true) {
|
||||
this.$emit("refreshAll");
|
||||
this.isUpdated = false;
|
||||
}
|
||||
|
@ -202,8 +240,10 @@
|
|||
});
|
||||
},
|
||||
upload(file) {
|
||||
this.isLoading = false;
|
||||
this.lastExcelFile = file.file;
|
||||
this.fileList.push(file.file);
|
||||
this.isLoading = false;
|
||||
|
||||
let user = JSON.parse(localStorage.getItem(TokenKey));
|
||||
|
||||
this.result = this.$fileUpload('/test/case/import/' + this.projectId + '/' + user.id, file.file, null, {}, response => {
|
||||
|
@ -212,18 +252,57 @@
|
|||
this.$success(this.$t('test_track.case.import.success'));
|
||||
this.dialogVisible = false;
|
||||
this.$emit("refreshAll");
|
||||
this.lastXmindFile = null;
|
||||
this.lastExcelFile = null;
|
||||
this.showExcelImportContinueBtn = false;
|
||||
this.showXmindImportContinueBtn = false;
|
||||
} else {
|
||||
this.errList = res.errList;
|
||||
this.isUpdated = res.isUpdated;
|
||||
this.showExcelImportContinueBtn = true;
|
||||
}
|
||||
this.fileList = [];
|
||||
}, erro => {
|
||||
this.fileList = [];
|
||||
this.lastXmindFile = null;
|
||||
this.lastExcelFile = null;
|
||||
});
|
||||
},
|
||||
uploadContinue(isImportXmind) {
|
||||
this.isLoading = false;
|
||||
let user = JSON.parse(localStorage.getItem(TokenKey));
|
||||
let file = null;
|
||||
if (isImportXmind) {
|
||||
this.uploadXmindIgnoreError = true;
|
||||
file = this.lastXmindFile;
|
||||
} else {
|
||||
this.uploadIgnoreError = true;
|
||||
file = this.lastExcelFile;
|
||||
}
|
||||
this.result = this.$fileUpload('/test/case/importIgnoreError/' + this.projectId + '/' + user.id, file, null, {}, response => {
|
||||
let res = response.data;
|
||||
this.$success(this.$t('test_track.case.import.success'));
|
||||
this.dialogVisible = false;
|
||||
this.$emit("refreshAll");
|
||||
this.fileList = [];
|
||||
this.lastXmindFile = null;
|
||||
this.lastExcelFile = null;
|
||||
this.showExcelImportContinueBtn = false;
|
||||
this.showXmindImportContinueBtn = false;
|
||||
this.uploadIgnoreError = false;
|
||||
this.uploadXmindIgnoreError = false;
|
||||
}, erro => {
|
||||
this.fileList = [];
|
||||
this.lastXmindFile = null;
|
||||
this.lastExcelFile = null;
|
||||
this.uploadIgnoreError = false;
|
||||
this.uploadXmindIgnoreError = false;
|
||||
});
|
||||
},
|
||||
uploadXmind(file) {
|
||||
this.isLoading = false;
|
||||
this.fileList.push(file.file);
|
||||
this.lastXmindFile = file.file;
|
||||
let user = JSON.parse(localStorage.getItem(TokenKey));
|
||||
|
||||
this.result = this.$fileUpload('/test/case/import/' + this.projectId + '/' + user.id, file.file, null, {}, response => {
|
||||
|
@ -232,8 +311,13 @@
|
|||
this.$success(this.$t('test_track.case.import.success'));
|
||||
this.dialogVisible = false;
|
||||
this.$emit("refreshAll");
|
||||
this.lastXmindFile = null;
|
||||
this.lastExcelFile = null;
|
||||
this.showExcelImportContinueBtn = false;
|
||||
this.showXmindImportContinueBtn = false;
|
||||
} else {
|
||||
this.xmindErrList = res.errList;
|
||||
this.showXmindImportContinueBtn = true;
|
||||
}
|
||||
this.fileList = [];
|
||||
}, erro => {
|
||||
|
|
|
@ -1342,6 +1342,8 @@ export default {
|
|||
xmind_title: "Xmind",
|
||||
import_desc: "Import instructions",
|
||||
import_file: "upload files",
|
||||
ignore_error: "Ignore errors ",
|
||||
continue_upload: "Upload continue",
|
||||
},
|
||||
export: {
|
||||
export: "Export cases"
|
||||
|
|
|
@ -1347,6 +1347,8 @@ export default {
|
|||
xmind_title: "思维导图",
|
||||
import_desc: "导入说明",
|
||||
import_file: "上传文件",
|
||||
ignore_error: "忽略错误",
|
||||
continue_upload: "继续上传",
|
||||
},
|
||||
export: {
|
||||
export: "导出用例"
|
||||
|
|
|
@ -1347,6 +1347,8 @@ export default {
|
|||
xmind_title: "思維導圖",
|
||||
import_desc: "導入說明",
|
||||
import_file: "上傳文件",
|
||||
ignore_error: "忽略錯誤",
|
||||
continue_upload: "繼續上傳",
|
||||
},
|
||||
export: {
|
||||
export: "導出用例"
|
||||
|
|
Loading…
Reference in New Issue