fix(测试计划): 导出自定义字段转换问题

This commit is contained in:
WangXu10 2024-08-12 16:50:28 +08:00 committed by Craftsman
parent 728cc21d38
commit 44c56232d6
9 changed files with 119 additions and 44 deletions

View File

@ -274,6 +274,7 @@ xmind_stepDescription=Step description
case.export.system.columns.name=Name
case.export.system.columns.id=ID
case.export.system.columns.prerequisite=Prerequisite
case.export.system.columns.module=Module
case.export.system.columns.text_description=Text description
case.export.system.columns.expected_result=Expected result
case.export.system.other.columns.last_execute_result=Last execution result

View File

@ -271,6 +271,7 @@ xmind_stepDescription=步骤描述
case.export.system.columns.name=用例名称
case.export.system.columns.id=ID
case.export.system.columns.prerequisite=前置条件
case.export.system.columns.module=模块
case.export.system.columns.text_description=步骤描述
case.export.system.columns.expected_result=预期结果
case.export.system.other.columns.last_execute_result=执行结果

View File

@ -275,6 +275,7 @@ case.find_file_error=找不到該文件
case.export.system.columns.name=用例名稱
case.export.system.columns.id=ID
case.export.system.columns.prerequisite=前置條件
case.export.system.columns.module=模塊
case.export.system.columns.text_description=步驟描述
case.export.system.columns.expected_result=預期結果
case.export.system.other.columns.last_execute_result=執行結果

View File

@ -2,15 +2,15 @@ package io.metersphere.functional.excel.constants;
public enum FunctionalCaseExportOtherField {
CREATE_USER("createUser"),
CREATE_TIME("createTime"),
UPDATE_USER("updateUser"),
UPDATE_TIME("updateTime"),
REVIEW_STATUS("reviewStatus"),
LAST_EXECUTE_RESULT("lastExecuteResult"),
CASE_COMMENT("caseComment"),
EXECUTE_COMMENT("executeComment"),
REVIEW_COMMENT("reviewComment");
CREATE_USER("create_user"),
CREATE_TIME("create_time"),
UPDATE_USER("update_user"),
UPDATE_TIME("update_time"),
REVIEW_STATUS("review_status"),
LAST_EXECUTE_RESULT("last_execute_result"),
CASE_COMMENT("case_comment"),
EXECUTE_COMMENT("execute_comment"),
REVIEW_COMMENT("review_comment");
private String value;

View File

@ -54,7 +54,7 @@ public class CustomFieldMultipleTextValidator extends AbstractCustomFieldValidat
@Override
public Object parse2Value(String keyOrValuesStr, TemplateCustomFieldDTO customField) {
if (StringUtils.isBlank(keyOrValuesStr)) {
if (StringUtils.isBlank(keyOrValuesStr) || StringUtils.equals(keyOrValuesStr, "[]")) {
return JSON.toJSONString(new ArrayList<>());
}
List<String> keyOrValues = parse2Array(keyOrValuesStr);

View File

@ -165,7 +165,7 @@ public class FunctionalCaseFileService {
for (String head : headList) {
boolean isSystemField = false;
for (FunctionalCaseImportFiled importFiled : importFields) {
if (StringUtils.equals("name", importFiled.getValue()) && model.getHyperLinkName() != null) {
if (importFiled.getFiledLangMap().containsValue(head) && StringUtils.equals("name", importFiled.getValue()) && model.getHyperLinkName() != null) {
fields.add(model.getHyperLinkName());
isSystemField = true;
break;
@ -759,8 +759,12 @@ public class FunctionalCaseFileService {
if (caseFieldvalueMap.containsKey(k)) {
AbstractCustomFieldValidator customFieldValidator = customFieldValidatorMap.get(v.getType());
if (customFieldValidator.isKVOption) {
if (!v.getInternal()) {
// 这里如果填的是选项值替换成选项ID保存
map.put(v.getFieldName(), customFieldValidator.parse2Value(caseFieldvalueMap.get(k), v));
} else {
map.put(v.getFieldName(), caseFieldvalueMap.get(k));
}
}
}
});

View File

@ -10,7 +10,6 @@ import io.metersphere.functional.xmind.domain.FunctionalCaseXmindDTO;
import io.metersphere.functional.xmind.domain.FunctionalCaseXmindData;
import io.metersphere.functional.xmind.utils.XmindExportUtil;
import io.metersphere.sdk.constants.LocalRepositoryDir;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.MsgType;
import io.metersphere.sdk.dto.ExportMsgDTO;
import io.metersphere.sdk.exception.MSException;
@ -126,8 +125,7 @@ public class FunctionalCaseXmindService {
tmpFile = new File(LocalRepositoryDir.getSystemTempDir() +
File.separatorChar + EXPORT_CASE_TMP_DIR + "_" + IDGenerator.nextStr() + ".xmind");
List<TemplateCustomFieldDTO> templateCustomFields = functionalCaseFileService.getCustomFields(request.getProjectId());
TemplateCustomFieldDTO templateCustomFieldDTO = templateCustomFields.stream().filter(item -> StringUtils.equalsIgnoreCase(item.getFieldName(), Translator.get("custom_field.functional_priority"))).findFirst().get();
XmindExportUtil.export(xmindData, request, tmpFile, templateCustomFieldDTO);
XmindExportUtil.export(xmindData, request, tmpFile, templateCustomFields);
functionalCaseFileService.uploadFileToMinio(XMIND, tmpFile, request.getFileId());
functionalCaseLogService.exportExcelLog(request);
@ -180,14 +178,9 @@ public class FunctionalCaseXmindService {
String moduleId = entry.getKey();
List<FunctionalCase> dataList = entry.getValue();
List<FunctionalCaseXmindDTO> dtos = buildXmindDTO(dataList, functionalCaseBlobMap, customFieldMap);
if (StringUtils.equals(moduleId, ModuleConstants.DEFAULT_NODE_ID)) {
xmindData.setFunctionalCaseList(dtos);
} else {
LinkedList<BaseTreeNode> returnList = new LinkedList<>();
LinkedList<BaseTreeNode> modulePathDataList = getModuleById(moduleId, tree, returnList);
xmindData.setItem(modulePathDataList, dtos);
System.out.println("modulePathDataList: " + modulePathDataList);
}
}
return xmindData;

View File

@ -4,6 +4,8 @@ import io.metersphere.functional.constants.FunctionalCaseTypeConstants;
import io.metersphere.functional.domain.FunctionalCaseCustomField;
import io.metersphere.functional.excel.domain.FunctionalCaseExportColumns;
import io.metersphere.functional.excel.domain.FunctionalCaseHeader;
import io.metersphere.functional.excel.validate.AbstractCustomFieldValidator;
import io.metersphere.functional.excel.validate.CustomFieldValidatorFactory;
import io.metersphere.functional.request.FunctionalCaseExportRequest;
import io.metersphere.functional.xmind.domain.FunctionalCaseXmindDTO;
import io.metersphere.functional.xmind.domain.FunctionalCaseXmindData;
@ -59,7 +61,7 @@ public class XmindExportUtil {
}
}
private static IWorkbook createXmindByCaseData(FunctionalCaseXmindData caseData, boolean template, Map<String, List<String>> customFieldOptionsMap, FunctionalCaseExportRequest request, TemplateCustomFieldDTO priority) {
private static IWorkbook createXmindByCaseData(FunctionalCaseXmindData caseData, boolean template, Map<String, List<String>> customFieldOptionsMap, FunctionalCaseExportRequest request, List<TemplateCustomFieldDTO> templateCustomFields) {
// 创建思维导图的工作空间
IWorkbookBuilder workbookBuilder = Core.getWorkbookBuilder();
IWorkbook workbook = workbookBuilder.createWorkbook();
@ -84,7 +86,7 @@ public class XmindExportUtil {
if (template) {
addTemplateTopic(rootTopic, workbook, styleMap, data, true, customFieldOptionsMap);
} else {
addTopic(rootTopic, workbook, styleMap, data, true, request, priority);
addTopic(rootTopic, workbook, styleMap, data, true, request, templateCustomFields);
}
}
}
@ -365,8 +367,8 @@ public class XmindExportUtil {
}
public static void export(FunctionalCaseXmindData xmindData, FunctionalCaseExportRequest request, File tmpFile, TemplateCustomFieldDTO priority) {
IWorkbook workBook = createXmindByCaseData(xmindData, false, null, request, priority);
public static void export(FunctionalCaseXmindData xmindData, FunctionalCaseExportRequest request, File tmpFile, List<TemplateCustomFieldDTO> templateCustomFields) {
IWorkbook workBook = createXmindByCaseData(xmindData, false, null, request, templateCustomFields);
try {
workBook.save(tmpFile.getPath());
} catch (UnsupportedEncodingException e) {
@ -379,7 +381,7 @@ public class XmindExportUtil {
}
private static void addTopic(ITopic parentTopic, IWorkbook workbook, Map<String, IStyle> styleMap, FunctionalCaseXmindData xmindData, boolean isFirstLevel, FunctionalCaseExportRequest request, TemplateCustomFieldDTO priority) {
private static void addTopic(ITopic parentTopic, IWorkbook workbook, Map<String, IStyle> styleMap, FunctionalCaseXmindData xmindData, boolean isFirstLevel, FunctionalCaseExportRequest request, List<TemplateCustomFieldDTO> templateCustomFields) {
ITopic topic = workbook.createTopic();
topic.setTitleText(xmindData.getModuleName());
if (isFirstLevel) {
@ -403,28 +405,30 @@ public class XmindExportUtil {
if (style != null) {
itemTopic.setStyleId(style.getId());
}
buildTopic(topic, style, dto, itemTopic, workbook, request, xmindData.getModuleName(), priority);
buildTopic(topic, style, dto, itemTopic, workbook, request, xmindData.getModuleName(), templateCustomFields);
}
}
if (CollectionUtils.isNotEmpty(xmindData.getChildren())) {
for (FunctionalCaseXmindData data : xmindData.getChildren()) {
addTopic(topic, workbook, styleMap, data, false, request, priority);
addTopic(topic, workbook, styleMap, data, false, request, templateCustomFields);
}
}
}
private static void buildTopic(ITopic topic, IStyle style, FunctionalCaseXmindDTO dto, ITopic itemTopic, IWorkbook workbook, FunctionalCaseExportRequest request, String moduleName, TemplateCustomFieldDTO priority) {
private static void buildTopic(ITopic topic, IStyle style, FunctionalCaseXmindDTO dto, ITopic itemTopic, IWorkbook workbook, FunctionalCaseExportRequest request, String moduleName, List<TemplateCustomFieldDTO> templateCustomFields) {
List<String> systemColumns = request.getSystemFields().stream().map(FunctionalCaseHeader::getId).toList();
FunctionalCaseExportColumns columns = new FunctionalCaseExportColumns();
Map<String, String> customFieldMap = dto.getCustomFieldDTOList().stream().collect(Collectors.toMap(FunctionalCaseCustomField::getFieldId, FunctionalCaseCustomField::getValue));
//用例名称
TemplateCustomFieldDTO priority = templateCustomFields.stream().filter(item -> StringUtils.equalsIgnoreCase(item.getFieldName(), Translator.get("custom_field.functional_priority"))).findFirst().get();
String casePriority = customFieldMap.get(priority.getFieldId());
itemTopic.setTitleText("case-".concat(StringUtils.defaultIfBlank(casePriority, StringUtils.EMPTY)).concat(": ").concat(dto.getName()));
//系统字段
systemColumns.forEach(item -> {
if (columns.getSystemColumns().containsKey(item) && !StringUtils.equalsIgnoreCase(item, "name")) {
if (columns.getSystemColumns().containsKey(item) && !StringUtils.equalsIgnoreCase(item, "name")
&& !StringUtils.equalsIgnoreCase(item, "text_description") && !StringUtils.equalsIgnoreCase(item, "expected_result")) {
ITopic preTopic = workbook.createTopic();
switch (item) {
case "num":
@ -436,12 +440,6 @@ public class XmindExportUtil {
case "module":
preTopic.setTitleText(columns.getSystemColumns().get(item).concat(": ").concat(moduleName));
break;
case "text_description":
preTopic.setTitleText(columns.getSystemColumns().get(item).concat(": ").concat(dto.getTextDescription()));
break;
case "expected_result":
preTopic.setTitleText(columns.getSystemColumns().get(item).concat(": ").concat(dto.getExpectedResult()));
break;
default:
break;
}
@ -452,14 +450,91 @@ public class XmindExportUtil {
}
});
if (StringUtils.equalsIgnoreCase(dto.getCaseEditType(), FunctionalCaseTypeConstants.CaseEditType.TEXT.name())) {
//文本描述
ITopic textDesTopic = workbook.createTopic();
String desc = dto.getTextDescription();
textDesTopic.setTitleText(Translator.get("xmind_textDescription").concat(": ").concat(dto.getTextDescription()));
if (style != null) {
textDesTopic.setStyleId(style.getId());
}
String result = dto.getExpectedResult();
ITopic resultTopic = workbook.createTopic();
resultTopic.setTitleText(Translator.get("xmind_expectedResult").concat(": ").concat(dto.getExpectedResult()));
if (style != null) {
resultTopic.setStyleId(style.getId());
}
textDesTopic.add(resultTopic, ITopic.ATTACHED);
if (StringUtils.isNotEmpty(desc) || StringUtils.isNotEmpty(result)) {
itemTopic.add(textDesTopic, ITopic.ATTACHED);
}
} else {
//步骤描述
try {
ITopic stepDesTopic = workbook.createTopic();
stepDesTopic.setTitleText(Translator.get("xmind_stepDescription"));
if (style != null) {
stepDesTopic.setStyleId(style.getId());
}
List<Map> arr = JSON.parseArray(dto.getSteps());
for (int i = 0; i < arr.size(); i++) {
Map<String, String> obj = arr.get(i);
if (obj.containsKey("desc")) {
ITopic stepTopic = workbook.createTopic();
String desc = obj.get("desc");
stepTopic.setTitleText(Translator.get("xmind_step").concat(": ").concat(desc));
if (style != null) {
stepTopic.setStyleId(style.getId());
}
boolean hasResult = false;
if (obj.containsKey("result")) {
String result = obj.get("result");
if (StringUtils.isNotEmpty(result)) {
hasResult = true;
ITopic resultTopic = workbook.createTopic();
resultTopic.setTitleText(Translator.get("xmind_expectedResult").concat(": ").concat(result));
if (style != null) {
resultTopic.setStyleId(style.getId());
}
stepTopic.add(resultTopic, ITopic.ATTACHED);
}
}
if (StringUtils.isNotEmpty(desc) || hasResult) {
stepDesTopic.add(stepTopic, ITopic.ATTACHED);
}
}
}
itemTopic.add(stepDesTopic, ITopic.ATTACHED);
} catch (Exception e) {
}
}
//自定义字段
Map<String, String> customColumnsMap = request.getCustomFields().stream().collect(Collectors.toMap(FunctionalCaseHeader::getId, FunctionalCaseHeader::getName));
Map<String, TemplateCustomFieldDTO> temCustomFieldsMap = templateCustomFields.stream().collect(Collectors.toMap(TemplateCustomFieldDTO::getFieldId, i -> i));
HashMap<String, AbstractCustomFieldValidator> customFieldValidatorMap = CustomFieldValidatorFactory.getValidatorMap();
customColumnsMap.forEach((k, v) -> {
if (customFieldMap.containsKey(k)) {
if (customFieldMap.containsKey(k) && temCustomFieldsMap.containsKey(k)) {
AbstractCustomFieldValidator customFieldValidator = customFieldValidatorMap.get(temCustomFieldsMap.get(k).getType());
String value = "";
if (customFieldValidator.isKVOption) {
if (!temCustomFieldsMap.get(k).getInternal()) {
// 这里如果填的是选项值替换成选项ID保存
value = customFieldValidator.parse2Value(customFieldMap.get(k), temCustomFieldsMap.get(k)).toString();
} else {
value = customFieldMap.get(k);
}
}
ITopic preTopic = workbook.createTopic();
preTopic.setTitleText(v.concat(": ").concat(customFieldMap.get(k)));
preTopic.setTitleText(v.concat(": ").concat(value));
if (style != null) {
preTopic.setStyleId(style.getId());
}

View File

@ -1114,7 +1114,7 @@
try {
const response = await getCaseDownloadFile(currentProjectId.value, reportId.value);
const fileName = response?.headers.get('content-disposition').split('filename=')[1];
downloadByteFile(response.data, fileName);
downloadByteFile(response.data, decodeURIComponent(fileName));
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);