feat(测试用例): 测试用例支持导出Xmind #1001755
--story=1001755 --user=宋天阳 9.测试用例导出支持导出成.xmind https://www.tapd.cn/55049933/s/1032481
This commit is contained in:
parent
51fb710daa
commit
724d0d32f9
|
@ -434,7 +434,12 @@
|
|||
<artifactId>Java-WebSocket</artifactId>
|
||||
<version>1.3.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- xmind export-->
|
||||
<dependency>
|
||||
<groupId>com.github.eljah</groupId>
|
||||
<artifactId>xmindjbehaveplugin</artifactId>
|
||||
<version>0.8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -342,6 +342,10 @@
|
|||
<property name="objectKey" value="request.combine.tags"/>
|
||||
</include>
|
||||
</if>
|
||||
|
||||
<if test="request.statusIsNot != null">
|
||||
and (test_case.status is null or test_case.status != #{request.statusIsNot})
|
||||
</if>
|
||||
<if test="request.name != null">
|
||||
and (test_case.name like CONCAT('%', #{request.name},'%')
|
||||
or test_case.num like CONCAT('%', #{request.name},'%')
|
||||
|
|
|
@ -196,6 +196,13 @@ public class TestCaseController {
|
|||
testCaseService.testCaseExport(response, request);
|
||||
}
|
||||
|
||||
@PostMapping("/export/testcase/xmind")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_CASE_READ_EXPORT)
|
||||
@MsAuditLog(module = "track_test_case", type = OperLogConstants.EXPORT, sourceId = "#request.id", title = "#request.name", project = "#request.projectId")
|
||||
public void testCaseXmindExport(HttpServletResponse response, @RequestBody TestCaseBatchRequest request) {
|
||||
testCaseService.testCaseXmindExport(response, request);
|
||||
}
|
||||
|
||||
@PostMapping("/batch/edit")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_CASE_READ_EDIT)
|
||||
@MsAuditLog(module = "track_test_case", type = OperLogConstants.BATCH_UPDATE, beforeEvent = "#msClass.getLogDetails(#request.ids)", content = "#msClass.getLogDetails(#request.ids)", msClass = TestCaseService.class)
|
||||
|
|
|
@ -29,6 +29,8 @@ public class QueryTestCaseRequest extends BaseQueryRequest {
|
|||
|
||||
private String nodeId;
|
||||
|
||||
private String statusIsNot;
|
||||
|
||||
private long createTime = 0;
|
||||
private long relevanceCreateTime = 0;
|
||||
private List<String> testCaseContainIds;
|
||||
|
|
|
@ -749,4 +749,19 @@ public class TestCaseNodeService extends NodeTreeService<TestCaseNodeDTO> {
|
|||
example.createCriteria().andIdEqualTo(nodeId);
|
||||
return testCaseNodeMapper.countByExample(example);
|
||||
}
|
||||
|
||||
public LinkedList<TestCaseNode> getPathNodeById(String moduleId) {
|
||||
TestCaseNode testCaseNode = testCaseNodeMapper.selectByPrimaryKey(moduleId);
|
||||
LinkedList<TestCaseNode> returnList = new LinkedList<>();
|
||||
|
||||
while (testCaseNode != null){
|
||||
returnList.addFirst(testCaseNode);
|
||||
if(testCaseNode.getParentId() == null){
|
||||
testCaseNode = null;
|
||||
}else {
|
||||
testCaseNode = testCaseNodeMapper.selectByPrimaryKey(testCaseNode.getParentId());
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
|||
import io.metersphere.track.request.testcase.TestCaseBatchRequest;
|
||||
import io.metersphere.track.request.testcase.TestCaseMinderEditRequest;
|
||||
import io.metersphere.xmind.XmindCaseParser;
|
||||
import io.metersphere.xmind.pojo.TestCaseXmindData;
|
||||
import io.metersphere.xmind.utils.XmindExportUtil;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -47,7 +49,6 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -691,7 +692,7 @@ public class TestCaseService {
|
|||
.andProjectIdEqualTo(projectId);
|
||||
List<TestCase> testCasesList = testCaseMapper.selectByExample(example);
|
||||
Map<String, String> customIdMap = testCasesList.stream()
|
||||
.collect(Collectors.toMap(TestCase::getCustomNum, TestCase::getId));
|
||||
.collect(Collectors.toMap(TestCase::getCustomNum, TestCase::getId, (k1,k2) -> k1));
|
||||
|
||||
|
||||
if (!testCases.isEmpty()) {
|
||||
|
@ -863,6 +864,56 @@ public class TestCaseService {
|
|||
MSException.throwException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testCaseXmindExport(HttpServletResponse response, TestCaseBatchRequest request) {
|
||||
try {
|
||||
request.getCondition().setStatusIsNot("Trash");
|
||||
List<TestCaseDTO> testCaseDTOList= this.findByBatchRequest(request);
|
||||
|
||||
TestCaseXmindData rootXmindData = this.generateTestCaseXmind(testCaseDTOList);
|
||||
boolean isUseCustomId = projectService.useCustomNum(request.getProjectId());
|
||||
XmindExportUtil xmindExportUtil = new XmindExportUtil(isUseCustomId);
|
||||
xmindExportUtil.exportXmind(response,rootXmindData);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private TestCaseXmindData generateTestCaseXmind(List<TestCaseDTO> testCaseDTOList) {
|
||||
Map<String,List<TestCaseDTO>> moduleTestCaseMap = new HashMap<>();
|
||||
for (TestCaseDTO dto : testCaseDTOList) {
|
||||
String moduleId = dto.getNodeId();
|
||||
if(StringUtils.isEmpty(moduleId)){
|
||||
moduleId = "default";
|
||||
}
|
||||
if(moduleTestCaseMap.containsKey(moduleId)){
|
||||
moduleTestCaseMap.get(moduleId).add(dto);
|
||||
}else {
|
||||
List<TestCaseDTO> list = new ArrayList<>();
|
||||
list.add(dto);
|
||||
moduleTestCaseMap.put(moduleId,list);
|
||||
}
|
||||
}
|
||||
|
||||
TestCaseXmindData rootMind = new TestCaseXmindData("ROOT","ROOT");
|
||||
|
||||
for (Map.Entry<String,List<TestCaseDTO>> entry:moduleTestCaseMap.entrySet()) {
|
||||
String moduleId = entry.getKey();
|
||||
List<TestCaseDTO> dataList = entry.getValue();
|
||||
|
||||
if(StringUtils.equals(moduleId,"ROOT")){
|
||||
rootMind.setTestCaseList(dataList);
|
||||
}else {
|
||||
LinkedList<TestCaseNode> modulePathDataList = testCaseNodeService.getPathNodeById(moduleId);
|
||||
rootMind.setItem(modulePathDataList,dataList);
|
||||
}
|
||||
}
|
||||
|
||||
return rootMind;
|
||||
}
|
||||
|
||||
private List<List<Object>> generateTestCaseExcel(List<List<String>> headListParams,List<TestCaseExcelData> datas) {
|
||||
List<List<Object>> returnDatas = new ArrayList<>();
|
||||
//转化excel头
|
||||
|
@ -921,10 +972,10 @@ public class TestCaseService {
|
|||
}
|
||||
return returnDatas;
|
||||
}
|
||||
private List<TestCaseExcelData> generateTestCaseExcel(TestCaseBatchRequest request) {
|
||||
|
||||
public List<TestCaseDTO> findByBatchRequest(TestCaseBatchRequest request){
|
||||
ServiceUtils.getSelectAllIds(request, request.getCondition(),
|
||||
(query) -> extTestCaseMapper.selectIds(query));
|
||||
boolean isUseCustomId = projectService.useCustomNum(request.getProjectId());
|
||||
QueryTestCaseRequest condition = request.getCondition();
|
||||
List<OrderRequest> orderList = new ArrayList<>();
|
||||
if (condition != null) {
|
||||
|
@ -935,11 +986,18 @@ public class TestCaseService {
|
|||
order.setType("desc");
|
||||
orderList.add(order);
|
||||
request.setOrders(orderList);
|
||||
List<TestCaseDTO> TestCaseList = extTestCaseMapper.listByTestCaseIds(request);
|
||||
List<TestCaseDTO> testCaseList = extTestCaseMapper.listByTestCaseIds(request);
|
||||
return testCaseList;
|
||||
}
|
||||
|
||||
private List<TestCaseExcelData> generateTestCaseExcel(TestCaseBatchRequest request) {
|
||||
request.getCondition().setStatusIsNot("Trash");
|
||||
List<TestCaseDTO> testCaseList = this.findByBatchRequest(request);
|
||||
boolean isUseCustomId = projectService.useCustomNum(request.getProjectId());
|
||||
List<TestCaseExcelData> list = new ArrayList<>();
|
||||
StringBuilder step = new StringBuilder("");
|
||||
StringBuilder result = new StringBuilder("");
|
||||
TestCaseList.forEach(t -> {
|
||||
testCaseList.forEach(t -> {
|
||||
TestCaseExcelData data = new TestCaseExcelData();
|
||||
data.setNum(t.getNum());
|
||||
data.setName(t.getName());
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package io.metersphere.xmind.pojo;
|
||||
|
||||
import io.metersphere.base.domain.TestCaseNode;
|
||||
import io.metersphere.track.dto.TestCaseDTO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/8/3 4:37 下午
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class TestCaseXmindData {
|
||||
private List<TestCaseDTO> testCaseList;
|
||||
private String moduleName;
|
||||
private String moduleId;
|
||||
|
||||
private List<TestCaseXmindData> children = new ArrayList<>();
|
||||
|
||||
public TestCaseXmindData(String moduleId, String moduleName) {
|
||||
this.moduleId = moduleId;
|
||||
this.moduleName = moduleName;
|
||||
}
|
||||
|
||||
public void setItem(LinkedList<TestCaseNode> modulePathDataList, List<TestCaseDTO> dataList) {
|
||||
if (CollectionUtils.isNotEmpty(modulePathDataList) && CollectionUtils.isNotEmpty(dataList)) {
|
||||
if (modulePathDataList.size() == 1) {
|
||||
this.setData(modulePathDataList.getFirst(), dataList);
|
||||
} else {
|
||||
TestCaseNode caseNode = modulePathDataList.getFirst();
|
||||
if (caseNode != null) {
|
||||
TestCaseXmindData matchedData = null;
|
||||
for (TestCaseXmindData item : children) {
|
||||
if (StringUtils.equals(item.getModuleId(), caseNode.getId())) {
|
||||
matchedData = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(matchedData == null){
|
||||
matchedData = new TestCaseXmindData(caseNode.getId(), caseNode.getName());
|
||||
this.children.add(matchedData);
|
||||
}
|
||||
modulePathDataList.removeFirst();
|
||||
matchedData.setItem(modulePathDataList,dataList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setData(TestCaseNode caseNode, List<TestCaseDTO> dataList) {
|
||||
if (caseNode != null && CollectionUtils.isNotEmpty(dataList)) {
|
||||
boolean matching = false;
|
||||
for (TestCaseXmindData item : children) {
|
||||
if (StringUtils.equals(item.getModuleId(), caseNode.getId())) {
|
||||
matching = true;
|
||||
item.getTestCaseList().addAll(dataList);
|
||||
}
|
||||
}
|
||||
if (!matching) {
|
||||
TestCaseXmindData child = new TestCaseXmindData(caseNode.getId(), caseNode.getName());
|
||||
child.setTestCaseList(dataList);
|
||||
this.children.add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,295 @@
|
|||
package io.metersphere.xmind.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.exception.ExcelException;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.track.dto.TestCaseDTO;
|
||||
import io.metersphere.xmind.pojo.TestCaseXmindData;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.xmind.core.*;
|
||||
import org.xmind.core.style.IStyle;
|
||||
import org.xmind.core.style.IStyleSheet;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/7/30 11:05 上午
|
||||
*/
|
||||
public class XmindExportUtil {
|
||||
|
||||
boolean isUseCustomId = false;
|
||||
|
||||
public XmindExportUtil(boolean isUseCustomId) {
|
||||
this.isUseCustomId = isUseCustomId;
|
||||
}
|
||||
|
||||
public void exportXmind(HttpServletResponse response, TestCaseXmindData rootXmind) {
|
||||
IWorkbook workBook = this.createXmindByTestCase(rootXmind);
|
||||
|
||||
response.setContentType("application/octet-stream");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
try {
|
||||
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("TestCaseExport", "UTF-8") + ".xmind");
|
||||
workBook.save(response.getOutputStream());
|
||||
// EasyExcel.write(response.getOutputStream(), this.clazz).registerWriteHandler(horizontalCellStyleStrategy).sheet(sheetName).doWrite(data);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
throw new ExcelException("Utf-8 encoding is not supported");
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
throw new ExcelException("IO exception");
|
||||
}
|
||||
}
|
||||
|
||||
public void saveXmind(TestCaseXmindData rootXmind) throws IOException, CoreException {
|
||||
this.createXmindByTestCase(rootXmind).save(File.separator + "User" + File.separator + "admin" + "/test.xmind");
|
||||
}
|
||||
|
||||
public IWorkbook createXmindByTestCase(TestCaseXmindData rootXmind) {
|
||||
// 创建思维导图的工作空间
|
||||
IWorkbookBuilder workbookBuilder = Core.getWorkbookBuilder();
|
||||
IWorkbook workbook = workbookBuilder.createWorkbook();
|
||||
|
||||
Map<String, IStyle> styleMap = this.initTheme(workbook);
|
||||
|
||||
// 获得默认sheet
|
||||
ISheet primarySheet = workbook.getPrimarySheet();
|
||||
if (styleMap.containsKey("mapStyle")) {
|
||||
primarySheet.setStyleId(styleMap.get("mapStyle").getId());
|
||||
}
|
||||
// 获得根主题
|
||||
ITopic rootTopic = primarySheet.getRootTopic();
|
||||
if (styleMap.containsKey("centralTopicStyle")) {
|
||||
rootTopic.setStyleId(styleMap.get("centralTopicStyle").getId());
|
||||
}
|
||||
// 设置根主题的标题
|
||||
rootTopic.setTitleText(Translator.get("test_case"));
|
||||
|
||||
if (CollectionUtils.isNotEmpty(rootXmind.getChildren())) {
|
||||
for (TestCaseXmindData data : rootXmind.getChildren()) {
|
||||
addItemTopic(rootTopic, workbook, styleMap, data, true);
|
||||
}
|
||||
}
|
||||
return workbook;
|
||||
}
|
||||
|
||||
private Map<String, IStyle> initTheme(IWorkbook workbook) {
|
||||
Map<String, IStyle> styleMap = new HashMap<>();
|
||||
|
||||
IStyleSheet styleSheet = workbook.getStyleSheet();
|
||||
IStyle mapStyle = styleSheet.createStyle(IStyle.MAP);
|
||||
mapStyle.setProperty("line-tapered","none");
|
||||
mapStyle.setProperty("multi-line-colors","none");
|
||||
mapStyle.setProperty("svg:fill","#FFFFFF");
|
||||
mapStyle.setProperty("color-gradient","none");
|
||||
styleSheet.addStyle(mapStyle, IStyleSheet.NORMAL_STYLES);
|
||||
styleMap.put("mapStyle",mapStyle);
|
||||
|
||||
IStyle centralTopicStyle = styleSheet.createStyle(IStyle.TOPIC);
|
||||
centralTopicStyle.setProperty("line-width", "1pt");
|
||||
centralTopicStyle.setProperty("svg:fill", "#DCE6F2");
|
||||
centralTopicStyle.setProperty("fo:font-family", "Microsoft YaHei");
|
||||
centralTopicStyle.setProperty("border-line-width", "5pt");
|
||||
centralTopicStyle.setProperty("shape-class", "org.xmind.topicShape.roundedRect");
|
||||
centralTopicStyle.setProperty("fo:color", "#376092");
|
||||
centralTopicStyle.setProperty("line-class", "org.xmind.branchConnection.curve");
|
||||
centralTopicStyle.setProperty("border-line-color", "#558ED5");
|
||||
centralTopicStyle.setProperty("line-color", "#558ED5");
|
||||
styleSheet.addStyle(centralTopicStyle, IStyleSheet.NORMAL_STYLES);
|
||||
styleMap.put("centralTopicStyle", centralTopicStyle);
|
||||
|
||||
IStyle mainTopicStyle = styleSheet.createStyle(IStyle.TOPIC);
|
||||
mainTopicStyle.setProperty("line-width", "1pt");
|
||||
mainTopicStyle.setProperty("svg:fill", "#DCE6F2");
|
||||
mainTopicStyle.setProperty("fo:font-family", "Microsoft YaHei");
|
||||
mainTopicStyle.setProperty("border-line-width", "2pt");
|
||||
mainTopicStyle.setProperty("shape-class", "org.xmind.topicShape.roundedRect");
|
||||
mainTopicStyle.setProperty("fo:color", "#17375E");
|
||||
mainTopicStyle.setProperty("line-class", "org.xmind.branchConnection.curve");
|
||||
mainTopicStyle.setProperty("border-line-color", "#558ED5");
|
||||
mainTopicStyle.setProperty("line-color", "#558ED5");
|
||||
styleSheet.addStyle(mainTopicStyle, IStyleSheet.NORMAL_STYLES);
|
||||
styleMap.put("mainTopicStyle", mainTopicStyle);
|
||||
|
||||
IStyle subTopicStyle = styleSheet.createStyle(IStyle.TOPIC);
|
||||
subTopicStyle.setProperty("line-width", "1pt");
|
||||
subTopicStyle.setProperty("fo:font-family", "Microsoft YaHei");
|
||||
subTopicStyle.setProperty("border-line-width", "3pt");
|
||||
subTopicStyle.setProperty("line-class", "org.xmind.branchConnection.curve");
|
||||
subTopicStyle.setProperty("border-line-color", "#558ED5");
|
||||
subTopicStyle.setProperty("line-color", "#558ED5");
|
||||
styleSheet.addStyle(subTopicStyle, IStyleSheet.NORMAL_STYLES);
|
||||
styleMap.put("subTopicStyle", subTopicStyle);
|
||||
|
||||
IStyle floatingTopicStyle = styleSheet.createStyle(IStyle.TOPIC);
|
||||
floatingTopicStyle.setProperty("svg:fill","#558ED5");
|
||||
floatingTopicStyle.setProperty("fo:font-family","Microsoft YaHei");
|
||||
floatingTopicStyle.setProperty("border-line-width","0pt");
|
||||
floatingTopicStyle.setProperty("fo:color","#FFFFFF");
|
||||
floatingTopicStyle.setProperty("fo:font-weight","bold");
|
||||
floatingTopicStyle.setProperty("line-color","#558ED5");
|
||||
styleSheet.addStyle(floatingTopicStyle, IStyleSheet.NORMAL_STYLES);
|
||||
styleMap.put("floatingTopicStyle", floatingTopicStyle);
|
||||
|
||||
IStyle summaryTopic = styleSheet.createStyle(IStyle.TOPIC);
|
||||
summaryTopic.setProperty("fo:font-style","italic");
|
||||
summaryTopic.setProperty("svg:fill","#77933C");
|
||||
summaryTopic.setProperty("fo:font-family","Microsoft YaHei");
|
||||
summaryTopic.setProperty("border-line-width","0pt");
|
||||
summaryTopic.setProperty("fo:font-size","10pt");
|
||||
summaryTopic.setProperty("shape-class","org.xmind.topicShape.roundedRect");
|
||||
summaryTopic.setProperty("fo:color","#FFFFFF");
|
||||
summaryTopic.setProperty("line-class","org.xmind.branchConnection.curve");
|
||||
styleSheet.addStyle(summaryTopic, IStyleSheet.NORMAL_STYLES);
|
||||
styleMap.put("summaryTopic", floatingTopicStyle);
|
||||
|
||||
IStyle itemTopic = styleSheet.createStyle(IStyle.TOPIC);
|
||||
itemTopic.setProperty("fo:text-align","center");
|
||||
itemTopic.setProperty("line-width","1pt");
|
||||
itemTopic.setProperty("svg:fill","none");
|
||||
itemTopic.setProperty("fo:font-family","Microsoft YaHei");
|
||||
itemTopic.setProperty("border-line-width","2pt");
|
||||
itemTopic.setProperty("shape-class","org.xmind.topicShape.underline");
|
||||
itemTopic.setProperty("fo:font-size","14pt");
|
||||
itemTopic.setProperty("fo:color","#17375E");
|
||||
itemTopic.setProperty("line-class","org.xmind.branchConnection.curve");
|
||||
itemTopic.setProperty("border-line-color","#558ED5");
|
||||
itemTopic.setProperty("line-color","#558ED5");
|
||||
styleSheet.addStyle(itemTopic, IStyleSheet.NORMAL_STYLES);
|
||||
styleMap.put("itemTopic",itemTopic);
|
||||
|
||||
return styleMap;
|
||||
}
|
||||
|
||||
private void addItemTopic(ITopic parentTpoic, IWorkbook workbook, Map<String, IStyle> styleMap, TestCaseXmindData xmindData, boolean isFirstLevel) {
|
||||
ITopic topic = workbook.createTopic();
|
||||
topic.setTitleText(xmindData.getModuleName());
|
||||
if (isFirstLevel) {
|
||||
if (styleMap.containsKey("mainTopicStyle")) {
|
||||
topic.setStyleId(styleMap.get("mainTopicStyle").getId());
|
||||
}
|
||||
} else {
|
||||
if (styleMap.containsKey("subTopicStyle")) {
|
||||
topic.setStyleId(styleMap.get("subTopicStyle").getId());
|
||||
}
|
||||
}
|
||||
parentTpoic.add(topic);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(xmindData.getTestCaseList())) {
|
||||
IStyle style = null;
|
||||
if (styleMap.containsKey("subTopicStyle")) {
|
||||
style = styleMap.get("subTopicStyle");
|
||||
}
|
||||
for (TestCaseDTO dto : xmindData.getTestCaseList()) {
|
||||
// 创建小节节点
|
||||
ITopic itemTopic = workbook.createTopic();
|
||||
if (style != null) {
|
||||
itemTopic.setStyleId(style.getId());
|
||||
}
|
||||
itemTopic.setTitleText("tc:" + dto.getName());
|
||||
|
||||
String id = dto.getNum().toString();
|
||||
if (this.isUseCustomId) {
|
||||
id = dto.getCustomNum();
|
||||
}
|
||||
ITopic idTopic = workbook.createTopic();
|
||||
idTopic.setTitleText("id:" + id);
|
||||
if (style != null) {
|
||||
idTopic.setStyleId(style.getId());
|
||||
}
|
||||
itemTopic.add(idTopic, ITopic.ATTACHED);
|
||||
|
||||
if (dto.getPrerequisite() != null) {
|
||||
ITopic pcTopic = workbook.createTopic();
|
||||
pcTopic.setTitleText("pc:" + dto.getPrerequisite());
|
||||
if (style != null) {
|
||||
pcTopic.setStyleId(style.getId());
|
||||
}
|
||||
itemTopic.add(pcTopic, ITopic.ATTACHED);
|
||||
}
|
||||
|
||||
if (dto.getRemark() != null) {
|
||||
ITopic rcTopic = workbook.createTopic();
|
||||
rcTopic.setTitleText("rc:" + dto.getRemark());
|
||||
if (style != null) {
|
||||
rcTopic.setStyleId(style.getId());
|
||||
}
|
||||
itemTopic.add(rcTopic, ITopic.ATTACHED);
|
||||
}
|
||||
|
||||
if (dto.getTags() != null) {
|
||||
try {
|
||||
JSONArray arr = JSONArray.parseArray(dto.getTags());
|
||||
String tagStr = "";
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
tagStr = tagStr + arr.getString(i) + ",";
|
||||
}
|
||||
if (tagStr.endsWith(",")) {
|
||||
tagStr = tagStr.substring(0, tagStr.length() - 1);
|
||||
}
|
||||
ITopic tagTopic = workbook.createTopic();
|
||||
tagTopic.setTitleText("tag:" + tagStr);
|
||||
if (style != null) {
|
||||
tagTopic.setStyleId(style.getId());
|
||||
}
|
||||
itemTopic.add(tagTopic, ITopic.ATTACHED);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (dto.getSteps() != null) {
|
||||
try {
|
||||
JSONArray arr = JSONArray.parseArray(dto.getSteps());
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
JSONObject obj = arr.getJSONObject(i);
|
||||
if (obj.containsKey("desc")) {
|
||||
ITopic stepTopic = workbook.createTopic();
|
||||
String desc = obj.getString("desc");
|
||||
stepTopic.setTitleText(desc);
|
||||
if (style != null) {
|
||||
stepTopic.setStyleId(style.getId());
|
||||
}
|
||||
|
||||
boolean hasResult = false;
|
||||
if (obj.containsKey("result")) {
|
||||
String result = obj.getString("result");
|
||||
if (StringUtils.isNotEmpty(result)) {
|
||||
hasResult = true;
|
||||
ITopic resultTopic = workbook.createTopic();
|
||||
resultTopic.setTitleText(result);
|
||||
if (style != null) {
|
||||
resultTopic.setStyleId(style.getId());
|
||||
}
|
||||
stepTopic.add(resultTopic, ITopic.ATTACHED);
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(desc) || hasResult) {
|
||||
itemTopic.add(stepTopic, ITopic.ATTACHED);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
topic.add(itemTopic);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(xmindData.getChildren())) {
|
||||
for (TestCaseXmindData data : xmindData.getChildren()) {
|
||||
addItemTopic(topic, workbook, styleMap, data, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -292,12 +292,12 @@ export default {
|
|||
this.activeName = "default";
|
||||
}
|
||||
},
|
||||
exportTestCase() {
|
||||
exportTestCase(type) {
|
||||
if (this.activeDom !== 'left') {
|
||||
this.$warning(this.$t('test_track.case.export.export_tip'));
|
||||
return;
|
||||
}
|
||||
this.$refs.testCaseList.exportTestCase();
|
||||
this.$refs.testCaseList.exportTestCase(type);
|
||||
},
|
||||
addListener() {
|
||||
let index = this.tabs.findIndex(item => item.name === this.activeName); // 找到当前选中tab的index
|
||||
|
|
|
@ -1,27 +1,85 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-link type="primary" class="download-case"
|
||||
@click="downloadCase"
|
||||
>{{$t('test_track.case.import.download_case')}}
|
||||
</el-link>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-dialog class="testcase-import" :title="$t('test_track.case.import.case_import')" :visible.sync="dialogVisible"
|
||||
@close="close">
|
||||
|
||||
<el-row class="import-row" style="margin-left: 34px">
|
||||
<el-radio v-model="exportType" label="excel">{{$t('commons.excelFile')}}</el-radio>
|
||||
<el-radio v-model="exportType" label="xmind">{{$t('commons.xmindFile')}}</el-radio>
|
||||
</el-row>
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">{{$t('commons.cancel')}}</el-button>
|
||||
<el-button type="primary" @click="exportTestCase">{{$t('commons.export')}}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "TestCaseExport",
|
||||
import ElUploadList from "element-ui/packages/upload/src/upload-list";
|
||||
import MsTableButton from '../../../../components/common/components/MsTableButton';
|
||||
import {getCurrentProjectID, listenGoBack, removeGoBackListener} from "../../../../../common/js/utils";
|
||||
import {TokenKey} from '../../../../../common/js/constants';
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
name: "TestCaseImport",
|
||||
components: {ElUploadList, MsTableButton},
|
||||
data() {
|
||||
return {
|
||||
exportType:"excel",
|
||||
dialogVisible: false,
|
||||
projectId:"",
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
activated() {
|
||||
},
|
||||
methods: {
|
||||
downloadCase() {
|
||||
|
||||
handleError(err, file, fileList) {
|
||||
this.isLoading = false;
|
||||
this.$error(err.message);
|
||||
},
|
||||
open() {
|
||||
listenGoBack(this.close);
|
||||
this.projectId = getCurrentProjectID();
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
close() {
|
||||
removeGoBackListener(this.close);
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
exportTestCase(){
|
||||
this.$emit('exportTestCase',this.exportType);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.download-template {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.import-row {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.testcase-import >>> .el-dialog {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.testcase-import-img {
|
||||
width: 614px;
|
||||
height: 312px;
|
||||
size: 200px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
|
|
@ -693,18 +693,31 @@ export default {
|
|||
}
|
||||
this.$refs.testCaseImport.open();
|
||||
},
|
||||
exportTestCase() {
|
||||
exportTestCase(exportType) {
|
||||
if (!this.projectId) {
|
||||
this.$warning(this.$t('commons.check_project_tip'));
|
||||
return;
|
||||
}
|
||||
|
||||
let config = {
|
||||
let config = {};
|
||||
let fileNameSuffix = "";
|
||||
if(exportType === 'xmind'){
|
||||
config = {
|
||||
url: '/test/case/export/testcase/xmind',
|
||||
method: 'post',
|
||||
responseType: 'blob',
|
||||
data: buildBatchParam(this, this.$refs.table.selectIds)
|
||||
};
|
||||
fileNameSuffix = ".xmind";
|
||||
}else {
|
||||
config = {
|
||||
url: '/test/case/export/testcase',
|
||||
method: 'post',
|
||||
responseType: 'blob',
|
||||
data: buildBatchParam(this, this.$refs.table.selectIds)
|
||||
};
|
||||
fileNameSuffix = ".xlsx";
|
||||
}
|
||||
|
||||
if (config.data.ids === undefined || config.data.ids.length < 1) {
|
||||
this.$warning(this.$t("test_track.case.check_select"));
|
||||
|
@ -712,7 +725,7 @@ export default {
|
|||
}
|
||||
|
||||
this.page.result = this.$request(config).then(response => {
|
||||
const filename = "Metersphere_case_" + this.projectName+ ".xlsx";
|
||||
const filename = "Metersphere_case_" + this.projectName+ fileNameSuffix;
|
||||
const blob = new Blob([response.data]);
|
||||
if ("download" in document.createElement("a")) {
|
||||
let aTag = document.createElement('a');
|
||||
|
@ -728,7 +741,7 @@ export default {
|
|||
handleBatch(type) {
|
||||
if (this.$refs.selectRows.size < 1) {
|
||||
if (type === 'export') {
|
||||
this.exportTestCase();
|
||||
this.handleExportTestCase();
|
||||
return;
|
||||
} else {
|
||||
this.$warning(this.$t('test_track.plan_view.select_manipulate'));
|
||||
|
@ -741,7 +754,7 @@ export default {
|
|||
} else if (type === 'delete') {
|
||||
this.handleDeleteBatch();
|
||||
} else {
|
||||
this.exportTestCase();
|
||||
this.handleExportTestCase();
|
||||
}
|
||||
},
|
||||
batchEdit(form) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
</template>
|
||||
</ms-node-tree>
|
||||
<test-case-import @refreshAll="refreshAll" ref="testCaseImport"></test-case-import>
|
||||
<test-case-export @refreshAll="refreshAll" @exportTestCase="exportTestCase" ref="testCaseExport"></test-case-export>
|
||||
<test-case-create
|
||||
:tree-nodes="treeNodes"
|
||||
@saveAsEdit="saveAsEdit"
|
||||
|
@ -41,6 +42,7 @@ import NodeEdit from "./NodeEdit";
|
|||
import MsNodeTree from "./NodeTree";
|
||||
import TestCaseCreate from "@/business/components/track/case/components/TestCaseCreate";
|
||||
import TestCaseImport from "@/business/components/track/case/components/TestCaseImport";
|
||||
import TestCaseExport from "@/business/components/track/case/components/TestCaseExport";
|
||||
import MsSearchBar from "@/business/components/common/components/search/MsSearchBar";
|
||||
import {buildTree} from "../../api/definition/model/NodeTree";
|
||||
import {buildNodePath} from "@/business/components/api/definition/model/NodeTree";
|
||||
|
@ -49,7 +51,7 @@ import ModuleTrashButton from "@/business/components/api/definition/components/m
|
|||
|
||||
export default {
|
||||
name: "TestCaseNodeTree",
|
||||
components: {MsSearchBar, TestCaseImport, TestCaseCreate, MsNodeTree, NodeEdit,ModuleTrashButton},
|
||||
components: {MsSearchBar, TestCaseImport,TestCaseExport, TestCaseCreate, MsNodeTree, NodeEdit,ModuleTrashButton},
|
||||
data() {
|
||||
return {
|
||||
defaultProps: {
|
||||
|
@ -75,9 +77,7 @@ export default {
|
|||
},
|
||||
{
|
||||
label: this.$t('api_test.export_config'),
|
||||
callback: () => {
|
||||
this.$emit('exportTestCase');
|
||||
},
|
||||
callback: this.handleExport,
|
||||
permissions: ['PROJECT_TRACK_CASE:READ+EXPORT']
|
||||
}
|
||||
]
|
||||
|
@ -176,6 +176,16 @@ export default {
|
|||
}
|
||||
this.$refs.testCaseImport.open();
|
||||
},
|
||||
handleExport() {
|
||||
if (!this.projectId) {
|
||||
this.$warning(this.$t('commons.check_project_tip'));
|
||||
return;
|
||||
}
|
||||
this.$refs.testCaseExport.open();
|
||||
},
|
||||
exportTestCase(type){
|
||||
this.$emit('exportTestCase',type);
|
||||
},
|
||||
remove(nodeIds) {
|
||||
this.$post("/case/node/delete", nodeIds, () => {
|
||||
this.list();
|
||||
|
|
|
@ -6,6 +6,8 @@ export default {
|
|||
trash: "Trash",
|
||||
yes: "yes",
|
||||
no: "no",
|
||||
excelFile: "Excel",
|
||||
xmindFile: "Xmind",
|
||||
default: "default",
|
||||
please_select_import_mode: 'Please select import mode',
|
||||
please_select_import_module: 'Please select import module',
|
||||
|
|
|
@ -6,6 +6,8 @@ export default {
|
|||
trash: "回收站",
|
||||
yes: "是",
|
||||
no: "否",
|
||||
excelFile: "表格文件.xls",
|
||||
xmindFile: "思维导图.xmind",
|
||||
default: "默认值",
|
||||
please_select_import_mode: '请选择导入模式',
|
||||
please_select_import_module: '请选择导入模块',
|
||||
|
|
|
@ -6,6 +6,8 @@ export default {
|
|||
trash: "回收站",
|
||||
yes: "是",
|
||||
no: "否",
|
||||
excelFile: "表格文件.xls",
|
||||
xmindFile: "思維導圖.xmind",
|
||||
default: "默認值",
|
||||
please_select_import_mode: '請選擇導入模式',
|
||||
please_select_import_module: '請選擇導入模塊',
|
||||
|
|
Loading…
Reference in New Issue