mirror of
https://gitee.com/fit2cloud-feizhiyun/MeterSphere.git
synced 2024-12-02 20:19:16 +08:00
feat(缺陷管理): 支持Jira默认模板
--bug=1036246 --user=宋昌昌 【缺陷管理】使用JIRA默认模板创建缺陷失败 https://www.tapd.cn/55049933/s/1473618
This commit is contained in:
parent
effb35b4e1
commit
c5602b2033
@ -13,4 +13,6 @@ public class PlatformCustomFieldItemDTO extends PlatformCustomFieldDTO {
|
||||
private String defaultValue;
|
||||
private Boolean supportSearch;
|
||||
private String searchMethod;
|
||||
private String placeHolder;
|
||||
private Boolean systemField;
|
||||
}
|
||||
|
@ -8,70 +8,69 @@ public enum PlatformCustomFieldType {
|
||||
/**
|
||||
* 输入框
|
||||
*/
|
||||
INPUT(false, "input"),
|
||||
INPUT(false),
|
||||
/**
|
||||
* 文本框
|
||||
*/
|
||||
TEXTAREA(false, "textarea"),
|
||||
TEXTAREA(false),
|
||||
/**
|
||||
* 单选下拉框框
|
||||
*/
|
||||
SELECT(true, "select"),
|
||||
SELECT(true),
|
||||
/**
|
||||
* 多选下拉框框
|
||||
*/
|
||||
MULTIPLE_SELECT(true, "multipleSelect"),
|
||||
MULTIPLE_SELECT(true),
|
||||
/**
|
||||
* 单选框
|
||||
*/
|
||||
RADIO(true, "radio"),
|
||||
RADIO(true),
|
||||
/**
|
||||
* 复选框
|
||||
*/
|
||||
CHECKBOX(true, "checkbox"),
|
||||
CHECKBOX(true),
|
||||
/**
|
||||
* 单选成员
|
||||
*/
|
||||
MEMBER(true, "member"),
|
||||
MEMBER(true),
|
||||
/**
|
||||
* 多选成员
|
||||
*/
|
||||
MULTIPLE_MEMBER(true, "multipleMember"),
|
||||
MULTIPLE_MEMBER(true),
|
||||
/**
|
||||
* 日期
|
||||
*/
|
||||
DATE(false, "date"),
|
||||
DATE(false),
|
||||
/**
|
||||
* 日期时间
|
||||
*/
|
||||
DATETIME(false, "datetime"),
|
||||
DATETIME(false),
|
||||
/**
|
||||
* 整型
|
||||
*/
|
||||
INT(false, "int"),
|
||||
INT(false),
|
||||
/**
|
||||
* 浮点型
|
||||
*/
|
||||
FLOAT(false, "float"),
|
||||
FLOAT(false),
|
||||
/**
|
||||
* 多值输入框(标签输入框)
|
||||
*/
|
||||
MULTIPLE_INPUT(false, "multipleInput"),
|
||||
MULTIPLE_INPUT(false),
|
||||
|
||||
// (第三方平台单独的自定义类型)
|
||||
/**
|
||||
* 级联选择
|
||||
*/
|
||||
CASCADE_SELECT(true, "cascadingSelect"),
|
||||
CASCADER(true),
|
||||
/**
|
||||
* 富文本
|
||||
*/
|
||||
RICH_TEXT(false, "richText");
|
||||
RICH_TEXT(false);
|
||||
|
||||
private final Boolean hasOption;
|
||||
|
||||
private final String type;
|
||||
|
||||
PlatformCustomFieldType(Boolean hasOption, String type) {
|
||||
PlatformCustomFieldType(Boolean hasOption) {
|
||||
this.hasOption = hasOption;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
@ -8,73 +8,65 @@ public enum CustomFieldType {
|
||||
/**
|
||||
* 输入框
|
||||
*/
|
||||
INPUT(false, "input"),
|
||||
INPUT(false),
|
||||
/**
|
||||
* 文本框
|
||||
*/
|
||||
TEXTAREA(false, "textarea"),
|
||||
TEXTAREA(false),
|
||||
/**
|
||||
* 单选下拉框框
|
||||
*/
|
||||
SELECT(true, "select"),
|
||||
SELECT(true),
|
||||
/**
|
||||
* 多选下拉框框
|
||||
*/
|
||||
MULTIPLE_SELECT(true, "multipleSelect"),
|
||||
MULTIPLE_SELECT(true),
|
||||
/**
|
||||
* 单选框
|
||||
*/
|
||||
RADIO(true, "radio"),
|
||||
RADIO(true),
|
||||
/**
|
||||
* 复选框
|
||||
*/
|
||||
CHECKBOX(true, "checkbox"),
|
||||
CHECKBOX(true),
|
||||
/**
|
||||
* 单选成员
|
||||
*/
|
||||
MEMBER(true, "member"),
|
||||
MEMBER(true),
|
||||
/**
|
||||
* 多选成员
|
||||
*/
|
||||
MULTIPLE_MEMBER(true, "multipleMember"),
|
||||
MULTIPLE_MEMBER(true),
|
||||
/**
|
||||
* 日期
|
||||
*/
|
||||
DATE(false, "date"),
|
||||
DATE(false),
|
||||
/**
|
||||
* 日期时间
|
||||
*/
|
||||
DATETIME(false, "datetime"),
|
||||
DATETIME(false),
|
||||
/**
|
||||
* 整型
|
||||
*/
|
||||
INT(false, "int"),
|
||||
INT(false),
|
||||
/**
|
||||
* 浮点型
|
||||
*/
|
||||
FLOAT(false, "float"),
|
||||
FLOAT(false),
|
||||
/**
|
||||
* 多值输入框(标签输入框)
|
||||
*/
|
||||
MULTIPLE_INPUT(false, "multipleInput");
|
||||
MULTIPLE_INPUT(false);
|
||||
|
||||
private final Boolean hasOption;
|
||||
|
||||
private final String type;
|
||||
|
||||
CustomFieldType(Boolean hasOption, String type) {
|
||||
CustomFieldType(Boolean hasOption) {
|
||||
this.hasOption = hasOption;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Boolean getHasOption() {
|
||||
return this.hasOption;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public static Set<String> getHasOptionValueSet() {
|
||||
return Arrays.stream(CustomFieldType.values())
|
||||
.filter(CustomFieldType::getHasOption)
|
||||
|
@ -413,16 +413,16 @@
|
||||
</if>
|
||||
select api_id from api_definition_custom_field where field_id = #{custom.id}
|
||||
<choose>
|
||||
<when test="custom.type == 'richText' or custom.type == 'textarea' or custom.operator == 'current user'">
|
||||
<when test="custom.type == 'TEXTAREA' or custom.operator == 'current user'">
|
||||
and `value`
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
</include>
|
||||
</when>
|
||||
<when test="custom.type == 'multipleMember' or custom.type == 'checkbox' or custom.type == 'multipleSelect'">
|
||||
<when test="custom.type == 'MULTIPLE_MEMBER' or custom.type == 'CHECKBOX' or custom.type == 'MULTIPLE_SELECT'">
|
||||
and ${custom.value}
|
||||
</when>
|
||||
<when test="custom.type == 'date' or custom.type == 'datetime'">
|
||||
<when test="custom.type == 'DATE' or custom.type == 'DATETIME'">
|
||||
and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13)
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
|
@ -266,16 +266,16 @@
|
||||
</if>
|
||||
select api_id from api_definition_custom_field where field_id = #{custom.id}
|
||||
<choose>
|
||||
<when test="custom.type == 'richText' or custom.type == 'textarea' or custom.operator == 'current user'">
|
||||
<when test="custom.type == 'TEXTAREA' or custom.operator == 'current user'">
|
||||
and `value`
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
</include>
|
||||
</when>
|
||||
<when test="custom.type == 'multipleMember' or custom.type == 'checkbox' or custom.type == 'multipleSelect'">
|
||||
<when test="custom.type == 'MULTIPLE_MEMBER' or custom.type == 'CHECKBOX' or custom.type == 'MULTIPLE_SELECT'">
|
||||
and ${custom.value}
|
||||
</when>
|
||||
<when test="custom.type == 'date' or custom.type == 'datetime'">
|
||||
<when test="custom.type == 'DATE' or custom.type == 'DATETIME'">
|
||||
and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13)
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
|
@ -314,16 +314,16 @@
|
||||
</if>
|
||||
select api_id from api_definition_custom_field where field_id = #{custom.id}
|
||||
<choose>
|
||||
<when test="custom.type == 'richText' or custom.type == 'textarea' or custom.operator == 'current user'">
|
||||
<when test="custom.type == 'TEXTAREA' or custom.operator == 'current user'">
|
||||
and `value`
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
</include>
|
||||
</when>
|
||||
<when test="custom.type == 'multipleMember' or custom.type == 'checkbox' or custom.type == 'multipleSelect'">
|
||||
<when test="custom.type == 'MULTIPLE_MEMBER' or custom.type == 'CHECKBOX' or custom.type == 'MULTIPLE_SELECT'">
|
||||
and ${custom.value}
|
||||
</when>
|
||||
<when test="custom.type == 'date' or custom.type == 'datetime'">
|
||||
<when test="custom.type == 'DATE' or custom.type == 'DATETIME'">
|
||||
and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13)
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
|
@ -944,13 +944,13 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
||||
Map<String, Object> custom = new HashMap<>();
|
||||
custom.put("id", "test_field");
|
||||
custom.put("operator", "in");
|
||||
custom.put("type", "multipleSelect");
|
||||
custom.put("type", "MULTIPLE_SELECT");
|
||||
custom.put("value", JSON.toJSONString(List.of("test", "default")));
|
||||
customs.add(custom);
|
||||
Map<String, Object> currentUserCustom = new HashMap<>();
|
||||
currentUserCustom.put("id", "test_field");
|
||||
currentUserCustom.put("operator", "current user");
|
||||
currentUserCustom.put("type", "multipleMember");
|
||||
currentUserCustom.put("type", "MULTIPLE_MEMBER");
|
||||
currentUserCustom.put("value", "current user");
|
||||
customs.add(currentUserCustom);
|
||||
map.put("customs", customs);
|
||||
|
@ -259,9 +259,9 @@ public class BugService {
|
||||
detail.setPlatformDefault(template.getPlatformDefault());
|
||||
detail.setStatus(bug.getStatus());
|
||||
detail.setPlatformBugId(bug.getPlatformBugId());
|
||||
detail.setTitle(bug.getTitle());
|
||||
if (!detail.getPlatformDefault()) {
|
||||
// 非平台默认模板 {标题, 内容, 标签, 自定义字段: 处理人, 状态}
|
||||
detail.setTitle(bug.getTitle());
|
||||
// 非平台默认模板 {内容, 标签, 自定义字段: 处理人, 状态}
|
||||
BugContent bugContent = bugContentMapper.selectByPrimaryKey(id);
|
||||
detail.setDescription(bugContent.getDescription());
|
||||
detail.setTags(bug.getTags());
|
||||
@ -286,7 +286,7 @@ public class BugService {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 平台默认模板
|
||||
// 平台默认模板 {自定义字段}
|
||||
allCustomFields.forEach(field -> template.getCustomFields().stream().filter(templateField -> StringUtils.equals(templateField.getFieldId(), field.getId())).findFirst().ifPresent(templateField -> {
|
||||
field.setName(templateField.getFieldName());
|
||||
field.setType(templateField.getType());
|
||||
@ -697,7 +697,7 @@ public class BugService {
|
||||
handleUserField.setFieldId(BugTemplateCustomField.HANDLE_USER.getId());
|
||||
handleUserField.setFieldName(BugTemplateCustomField.HANDLE_USER.getName());
|
||||
handleUserField.setFieldKey(BugTemplateCustomField.HANDLE_USER.getId());
|
||||
handleUserField.setType(CustomFieldType.SELECT.getType());
|
||||
handleUserField.setType(CustomFieldType.SELECT.name());
|
||||
List<SelectOption> localHandlerOption = bugCommonService.getLocalHandlerOption(projectId);
|
||||
handleUserOption = localHandlerOption.stream().map(user -> {
|
||||
CustomFieldOption option = new CustomFieldOption();
|
||||
@ -713,7 +713,7 @@ public class BugService {
|
||||
// 成员类型的自定义字段, 选项值与处理人选项保持一致
|
||||
final List<CustomFieldOption> memberOption = handleUserOption;
|
||||
templateDTO.getCustomFields().forEach(field -> {
|
||||
if (StringUtils.equalsAny(field.getType(), CustomFieldType.MEMBER.getType(), CustomFieldType.MULTIPLE_MEMBER.getType())) {
|
||||
if (StringUtils.equalsAny(field.getType(), CustomFieldType.MEMBER.name(), CustomFieldType.MULTIPLE_MEMBER.name())) {
|
||||
field.setPlatformOptionJson(JSON.toJSONString(memberOption));
|
||||
}
|
||||
});
|
||||
@ -737,7 +737,7 @@ public class BugService {
|
||||
statusField.setFieldId(BugTemplateCustomField.STATUS.getId());
|
||||
statusField.setFieldName(BugTemplateCustomField.STATUS.getName());
|
||||
statusField.setFieldKey(BugTemplateCustomField.STATUS.getId());
|
||||
statusField.setType(CustomFieldType.SELECT.getType());
|
||||
statusField.setType(CustomFieldType.SELECT.name());
|
||||
List<SelectOption> statusOption = bugStatusService.getToStatusItemOption(projectId, fromStatusId, platformBugKey);
|
||||
List<CustomFieldOption> statusCustomOption = statusOption.stream().map(option -> {
|
||||
CustomFieldOption customFieldOption = new CustomFieldOption();
|
||||
@ -1252,6 +1252,8 @@ public class BugService {
|
||||
customField.setFieldId(platformCustomField.getId());
|
||||
customField.setFieldName(platformCustomField.getName());
|
||||
customField.setPlatformOptionJson(platformCustomField.getOptions());
|
||||
customField.setPlatformPlaceHolder(platformCustomField.getPlaceHolder());
|
||||
customField.setPlatformSystemField(platformCustomField.getSystemField());
|
||||
return customField;
|
||||
}).collect(Collectors.toList());
|
||||
template.setCustomFields(customFields);
|
||||
|
@ -588,7 +588,7 @@ public class BugControllerTests extends BaseTest {
|
||||
BugCustomFieldDTO summary = new BugCustomFieldDTO();
|
||||
summary.setId("summary");
|
||||
summary.setName("摘要");
|
||||
summary.setType("input");
|
||||
summary.setType("INPUT");
|
||||
summary.setValue("这是一个系统Jira模板创建的缺陷");
|
||||
addRequest.getCustomFields().add(summary);
|
||||
MultiValueMap<String, Object> addParam3 = getMultiPartParam(addRequest, null);
|
||||
@ -667,7 +667,7 @@ public class BugControllerTests extends BaseTest {
|
||||
field.setId("test_field");
|
||||
field.setName("test");
|
||||
field.setValue("test");
|
||||
field.setType("multipleSelect");
|
||||
field.setType("MULTIPLE_SELECT");
|
||||
bugService.transferCustomToPlatformField(null, List.of(field), true);
|
||||
// 添加没有配置自定义映射字段的Jira缺陷
|
||||
removeApiFieldTmp();
|
||||
@ -694,8 +694,6 @@ public class BugControllerTests extends BaseTest {
|
||||
this.requestMultipart(BUG_ADD, addParam).andExpect(status().is5xxServerError());
|
||||
// 获取禅道模板(删除默认项目模板)
|
||||
bugService.attachTemplateStatusField(null, null, null, null);
|
||||
// 获取处理人选项
|
||||
this.requestGetWithOk(BUG_HEADER_COLUMNS_OPTION + "/default-project-for-bug");
|
||||
// 批量删除
|
||||
BugBatchRequest request = new BugBatchRequest();
|
||||
request.setProjectId("default-project-for-bug");
|
||||
|
@ -66,7 +66,7 @@ INSERT INTO project_application (project_id, type, type_value) VALUES
|
||||
|
||||
INSERT INTO service_integration(`id`, `plugin_id`, `enable`, `configuration`, `organization_id`) VALUES
|
||||
('621103810617344', 'jira', true, 0x504B0304140008080800BC517657000000000000000000000000030000007A6970258DC10EC2201044FF65CF06D2C498D89347B5574FBD6D8158222CD85D6268E3BF4BE3F5CDBC990DD0DAC531430FB348E65EEBE06B41AAA9289480CC1E4991130D07C022F3A366D7DA13B2373B32261592469AF1572FCF883E289362CB735BF8A4C5EE073474C3CB8E59A6F85EEFF12AE676EC4E67F8FE00504B0708384DA4307800000087000000504B01021400140008080800BC517657384DA43078000000870000000300000000000000000000000000000000007A6970504B0506000000000100010031000000A90000000000, '100001'),
|
||||
('652096294625281', 'zentao', true, 0x504B03041400080808003B939C57000000000000000000000000030000007A6970AB564A4C49294A2D2E56B252CA282929B0D2D7373437D23334D33334D03333D3AF4ACD2B49CCD757D2514A4C4ECE2FCD2B01AA4B4CC9CDCC038A1424161797E717A500859C1373F2F3D21D8C0C0C4D811245A985A5A9C525219505A940B900C7108F784F3F377FA55A00504B07081BBBB5766A0000006E000000504B010214001400080808003B939C571BBBB5766A0000006E0000000300000000000000000000000000000000007A6970504B05060000000001000100310000009B0000000000, '100001');
|
||||
('652096294625281', 'zentao', true, 0x504B030414000808080093756458000000000000000000000000030000007A6970AB564A4C49294A2D2E56B252CA282929B0D2D7373437D23334D3333230D033B3B4B230B0B050D2514A4C4ECE2FCD2B01AA4A4CC9CDCC038A1424161797E717A500859C1373F2F3D21D8C0C0C4D811245A985A5A9C525219505A940B900C7108F784F3F377FA55A00504B07088A813510680000006C000000504B01021400140008080800937564588A813510680000006C0000000300000000000000000000000000000000007A6970504B0506000000000100010031000000990000000000, '100001');
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
@ -33,9 +33,6 @@ public class TemplateCustomFieldDTO {
|
||||
@Schema(title = "选项值")
|
||||
private List<CustomFieldOption> options;
|
||||
|
||||
@Schema(title = "平台选项值")
|
||||
private String platformOptionJson;
|
||||
|
||||
@Schema(title = "是否支持搜索")
|
||||
private Boolean supportSearch;
|
||||
|
||||
@ -44,4 +41,16 @@ public class TemplateCustomFieldDTO {
|
||||
|
||||
@Schema(description = "是否内置字段")
|
||||
private Boolean internal;
|
||||
|
||||
/**
|
||||
* 平台字段相关属性 -- start
|
||||
*/
|
||||
@Schema(title = "平台选项值")
|
||||
private String platformOptionJson;
|
||||
|
||||
@Schema(description = "平台字段占位提示")
|
||||
private String platformPlaceHolder;
|
||||
|
||||
@Schema(description = "是否平台系统字段")
|
||||
private Boolean platformSystemField;
|
||||
}
|
||||
|
@ -69,8 +69,8 @@ public class CustomFieldUtils {
|
||||
String fieldType = custom.get(COMBINE_CUSTOM_FIELD_TYPE).toString();
|
||||
String fieldValue = custom.get(COMBINE_CUSTOM_FIELD_VALUE).toString();
|
||||
|
||||
if (StringUtils.equalsAny(fieldType, CustomFieldType.MULTIPLE_MEMBER.getType(),
|
||||
CustomFieldType.CHECKBOX.getType(), CustomFieldType.MULTIPLE_SELECT.getType()) && StringUtils.isNotEmpty(fieldValue)) {
|
||||
if (StringUtils.equalsAny(fieldType, CustomFieldType.MULTIPLE_MEMBER.name(),
|
||||
CustomFieldType.CHECKBOX.name(), CustomFieldType.MULTIPLE_SELECT.name()) && StringUtils.isNotEmpty(fieldValue)) {
|
||||
List<String> customValues = JSON.parseArray(fieldValue, String.class);
|
||||
List<String> jsonValues = customValues.stream().map(item -> "JSON_CONTAINS(`value`, '[\"".concat(item).concat("\"]')")).toList();
|
||||
custom.put(COMBINE_CUSTOM_FIELD_VALUE, "(".concat(StringUtils.join(jsonValues, " OR ")).concat(")"));
|
||||
|
@ -38,13 +38,13 @@ class CustomFieldTests extends BaseTest {
|
||||
Map<String, Object> custom = new HashMap<>();
|
||||
custom.put("id", "test_field");
|
||||
custom.put("operator", "in");
|
||||
custom.put("type", "multipleSelect");
|
||||
custom.put("type", "MULTIPLE_SELECT");
|
||||
custom.put("value", JSON.toJSONString(List.of("test", "default")));
|
||||
customs.add(custom);
|
||||
Map<String, Object> currentUserCustom = new HashMap<>();
|
||||
currentUserCustom.put("id", "test_field");
|
||||
currentUserCustom.put("operator", "current user");
|
||||
currentUserCustom.put("type", "multipleMember");
|
||||
currentUserCustom.put("type", "MULTIPLE_MEMBER");
|
||||
currentUserCustom.put("value", "current user");
|
||||
customs.add(currentUserCustom);
|
||||
currentUserCustom.put("value", "");
|
||||
|
@ -180,6 +180,16 @@ export const PASSWORD = {
|
||||
},
|
||||
};
|
||||
|
||||
export const CASCADER = {
|
||||
type: 'cascader',
|
||||
field: 'fieldName',
|
||||
title: '',
|
||||
value: [],
|
||||
props: {
|
||||
'allow-clear': true,
|
||||
},
|
||||
};
|
||||
|
||||
export const FieldTypeFormRules: Record<string, FormRule> = {
|
||||
INPUT,
|
||||
SELECT,
|
||||
@ -196,4 +206,5 @@ export const FieldTypeFormRules: Record<string, FormRule> = {
|
||||
TEXTAREA,
|
||||
JIRAKEY,
|
||||
PASSWORD,
|
||||
CASCADER,
|
||||
};
|
||||
|
@ -16,9 +16,8 @@
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
import type { FormItem } from './types';
|
||||
import { FormRuleItem } from './types';
|
||||
import formCreate, { Rule } from '@form-create/arco-design';
|
||||
import { FormItem, FormRuleItem } from './types';
|
||||
import formCreate from '@form-create/arco-design';
|
||||
|
||||
defineOptions({ name: 'MsFormCreate' });
|
||||
|
||||
@ -147,6 +146,20 @@
|
||||
formItems.value = formItems.value.filter((item: FormItem) => !item.displayConditions?.field);
|
||||
}
|
||||
|
||||
function mapOption(options: any[]) {
|
||||
return options.map((optionsItem) => {
|
||||
const mappedItem: any = {
|
||||
label: optionsItem.text,
|
||||
value: optionsItem.value,
|
||||
};
|
||||
|
||||
if (optionsItem.children) {
|
||||
mappedItem.children = mapOption(optionsItem.children);
|
||||
}
|
||||
return mappedItem;
|
||||
});
|
||||
}
|
||||
|
||||
function convertItem(item: FormItem) {
|
||||
// 当前类型
|
||||
let fieldType;
|
||||
@ -162,12 +175,7 @@
|
||||
fieldType = FieldTypeFormRules[currentTypeForm].type;
|
||||
}
|
||||
const options = item?.options;
|
||||
const currentOptions = options?.map((optionsItem: any) => {
|
||||
return {
|
||||
label: optionsItem.text,
|
||||
value: optionsItem.value,
|
||||
};
|
||||
});
|
||||
const currentOptions = mapOption(options || []);
|
||||
const ruleItem: any = {
|
||||
type: fieldType, // 表单类型
|
||||
field: item.name, // 字段
|
||||
@ -206,6 +214,10 @@
|
||||
tooltip: item.tooltip,
|
||||
},
|
||||
};
|
||||
// 如果存在placeholder, 替换掉默认的placeholder
|
||||
if (item.platformPlaceHolder) {
|
||||
ruleItem.props.placeholder = item.platformPlaceHolder;
|
||||
}
|
||||
// 如果不存在关联name删除link关联属性
|
||||
if (!ruleItem.link.filter((ink: string) => ink).length) {
|
||||
delete ruleItem.link;
|
||||
|
@ -18,6 +18,7 @@ export type FormItemType =
|
||||
| 'FLOAT'
|
||||
| 'NUMBER'
|
||||
| 'PassWord'
|
||||
| 'CASCADER'
|
||||
| undefined;
|
||||
|
||||
// 表单选项
|
||||
@ -64,6 +65,7 @@ export interface FormItem {
|
||||
inputSearch?: boolean; // 是否支持远程搜索
|
||||
tooltip?: string; // 表单后边的提示info
|
||||
instructionsIcon?: ''; // 是否有图片在表单后边展示
|
||||
platformPlaceHolder?: string; // 平台表单项占位符
|
||||
optionMethod?: string; // 请求检索的方法 两个参数 表单项的所有值
|
||||
options?: FormItemDefaultOptions[];
|
||||
required: boolean;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {FormItemType} from '@/components/pure/ms-form-create/types';
|
||||
import { FormItemType } from '@/components/pure/ms-form-create/types';
|
||||
|
||||
import {BatchApiParams} from './common';
|
||||
import { BatchApiParams } from './common';
|
||||
|
||||
export interface BugListItem {
|
||||
id: string; // 缺陷id
|
||||
@ -47,6 +47,8 @@ export interface BugEditCustomField {
|
||||
required: boolean;
|
||||
isMutiple?: boolean;
|
||||
options?: any[];
|
||||
defaultValue: string;
|
||||
platformSystemField: boolean;
|
||||
}
|
||||
export interface BugEditFormObject {
|
||||
[key: string]: any;
|
||||
@ -54,7 +56,7 @@ export interface BugEditFormObject {
|
||||
export interface BugEditCustomFieldItem {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
type: string | undefined;
|
||||
value: string;
|
||||
}
|
||||
export type BugBatchUpdateFiledType = 'single_select' | 'multiple_select' | 'tags' | 'input' | 'user_selector' | 'date';
|
||||
@ -104,6 +106,6 @@ export interface OperationFile {
|
||||
}
|
||||
|
||||
export interface BugTemplateRequest {
|
||||
fromStatusId: string; // 缺陷当前状态
|
||||
platformBugKey: string; // 缺陷第三方平台Key
|
||||
fromStatusId: string; // 缺陷当前状态
|
||||
platformBugKey: string; // 缺陷第三方平台Key
|
||||
}
|
||||
|
29
frontend/src/utils/recursion.ts
Normal file
29
frontend/src/utils/recursion.ts
Normal file
@ -0,0 +1,29 @@
|
||||
export interface Option {
|
||||
label: string;
|
||||
value: string;
|
||||
children?: Option[];
|
||||
}
|
||||
|
||||
// 递归函数,获取所有父级元素
|
||||
export function findParents(data: Option[], targetId: string, parents: string[] = []) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const current = data[i];
|
||||
if (current.value === targetId) {
|
||||
// 第一层级, 直接返回
|
||||
parents.push(current.value);
|
||||
return parents;
|
||||
}
|
||||
if (current.children && current.children.length > 0) {
|
||||
// 多层级, 递归查找
|
||||
parents.push(current.value);
|
||||
const result = findParents(current.children, targetId, parents);
|
||||
if (result) {
|
||||
// 子元素中有匹配的, 返回结果
|
||||
return result;
|
||||
}
|
||||
// 子元素中没有匹配的, 队尾元素删除, 继续查找相邻元素
|
||||
parents.pop();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
@ -100,6 +100,8 @@
|
||||
:form-item="formItem"
|
||||
:allow-edit="true"
|
||||
:detail-info="detailInfo"
|
||||
:is-platform-default-template="isPlatformDefaultTemplate"
|
||||
:platform-system-fields="platformSystemFields"
|
||||
@update-success="updateSuccess"
|
||||
/>
|
||||
|
||||
@ -118,7 +120,11 @@
|
||||
</template>
|
||||
<template #second>
|
||||
<div class="rightWrapper p-[24px]">
|
||||
<div class="mb-4 font-medium">{{ t('bugManagement.detail.basicInfo') }}</div>
|
||||
<div class="mb-4 font-medium">
|
||||
<strong>
|
||||
{{ t('bugManagement.detail.basicInfo') }}
|
||||
</strong>
|
||||
</div>
|
||||
<!-- 自定义字段开始 -->
|
||||
<MsFormCreate
|
||||
v-if="formRules.length"
|
||||
@ -131,7 +137,8 @@
|
||||
@change="handelFormCreateChange"
|
||||
/>
|
||||
<!-- 自定义字段结束 -->
|
||||
<div class="baseItem">
|
||||
<!-- 内置基础信息开始 -->
|
||||
<div v-if="!isPlatformDefaultTemplate" class="baseItem">
|
||||
<a-form-item field="tags" :label="t('system.orgTemplate.tags')">
|
||||
<MsTagsInput v-model:model-value="tags" />
|
||||
</a-form-item>
|
||||
@ -140,6 +147,7 @@
|
||||
<!-- <MsTag v-for="item of tags" :key="item"> {{ item }} </MsTag>-->
|
||||
<!-- </span>-->
|
||||
</div>
|
||||
<!-- 内置基础信息结束 -->
|
||||
</div>
|
||||
</template>
|
||||
</MsSplitBox>
|
||||
@ -226,17 +234,19 @@
|
||||
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||
const showDrawerVisible = defineModel<boolean>('visible', { default: false });
|
||||
const bugDetailTabRef = ref();
|
||||
const isPlatformDefaultTemplate = ref(false);
|
||||
|
||||
const activeTab = ref<string>('detail');
|
||||
|
||||
const detailInfo = ref<Record<string, any>>({ match: [] }); // 存储当前详情信息,通过loadBug 获取
|
||||
const tags = ref([]);
|
||||
const platformSystemFields = ref<BugEditCustomField[]>([]); // 平台系统字段
|
||||
|
||||
// 处理表单格式
|
||||
const getFormRules = (arr: BugEditCustomField[], valueObj: BugEditFormObject) => {
|
||||
formRules.value = [];
|
||||
if (Array.isArray(arr) && arr.length) {
|
||||
formRules.value = arr.map((item) => {
|
||||
formRules.value = arr.map((item: any) => {
|
||||
return {
|
||||
type: item.type,
|
||||
name: item.fieldId,
|
||||
@ -244,6 +254,7 @@
|
||||
value: valueObj[item.fieldId],
|
||||
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
|
||||
required: item.required as boolean,
|
||||
platformPlaceHolder: item.platformPlaceHolder,
|
||||
props: {
|
||||
modelValue: valueObj[item.fieldId],
|
||||
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
|
||||
@ -262,7 +273,14 @@
|
||||
fromStatusId: request.fromStatusId,
|
||||
platformBugKey: request.platformBugKey,
|
||||
});
|
||||
getFormRules(res.customFields, valueObj);
|
||||
platformSystemFields.value = res.customFields.filter((field) => field.platformSystemField);
|
||||
platformSystemFields.value.forEach((item) => {
|
||||
item.defaultValue = valueObj[item.fieldId];
|
||||
});
|
||||
getFormRules(
|
||||
res.customFields.filter((field) => !field.platformSystemField),
|
||||
valueObj
|
||||
);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
@ -272,16 +290,24 @@
|
||||
async function loadedBug(detail: BugEditFormObject) {
|
||||
detailInfo.value = { ...detail };
|
||||
const { templateId } = detail;
|
||||
// tag 赋值
|
||||
|
||||
// 是否平台默认模板
|
||||
isPlatformDefaultTemplate.value = detail.platformDefault;
|
||||
// TAG 赋值
|
||||
tags.value = detail.tags || [];
|
||||
caseCount.value = detail.linkCaseCount;
|
||||
const tmpObj = {};
|
||||
const tmpObj = { status: detail.status };
|
||||
if (detail.customFields && Array.isArray(detail.customFields)) {
|
||||
detail.customFields.forEach((item) => {
|
||||
if (item.type === 'MULTIPLE_SELECT') {
|
||||
if (item.type === 'MULTIPLE_SELECT' || item.type === 'MULTIPLE_INPUT' || item.type === 'CHECKBOX') {
|
||||
tmpObj[item.id] = JSON.parse(item.value);
|
||||
} else if (item.type === 'INT') {
|
||||
tmpObj[item.id] = Number(item.value);
|
||||
} else if (item.type === 'CASCADER') {
|
||||
const arr = JSON.parse(item.value);
|
||||
if (arr && arr instanceof Array && arr.length > 0) {
|
||||
tmpObj[item.id] = arr[arr.length - 1];
|
||||
}
|
||||
} else {
|
||||
tmpObj[item.id] = item.value;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="relative p-[16px] pb-[16px]">
|
||||
<div class="header">
|
||||
<div class="header-title">{{ t('bugManagement.edit.content') }}</div>
|
||||
<div v-permission="['PROJECT_BUG:READ+UPDATE']" class="header-action">
|
||||
<a-button type="text" @click="contentEditAble = !contentEditAble">
|
||||
<template #icon> <MsIconfont type="icon-icon_edit_outlined" /> </template>
|
||||
@ -9,24 +8,53 @@
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]" :class="{ 'max-h-[260px]': contentEditAble }">
|
||||
<MsRichText
|
||||
v-if="contentEditAble"
|
||||
v-model:raw="form.description"
|
||||
v-model:filed-ids="fileIds"
|
||||
:disabled="!contentEditAble"
|
||||
:placeholder="t('bugManagement.edit.contentPlaceholder')"
|
||||
:upload-image="handleUploadImage"
|
||||
/>
|
||||
<div v-else v-dompurify-html="form?.description || '-'" class="markdown-body"></div>
|
||||
<!-- 左侧布局默认内容(非平台默认模板时默认展示) -->
|
||||
<div v-if="!isPlatformDefaultTemplate" class="default-content">
|
||||
<div class="header-title">{{ t('bugManagement.edit.content') }}</div>
|
||||
<div class="mb-4 mt-[16px]" :class="{ 'max-h-[260px]': contentEditAble }">
|
||||
<MsRichText
|
||||
v-if="contentEditAble"
|
||||
v-model:raw="form.description"
|
||||
v-model:filed-ids="fileIds"
|
||||
:disabled="!contentEditAble"
|
||||
:placeholder="t('bugManagement.edit.contentPlaceholder')"
|
||||
:upload-image="handleUploadImage"
|
||||
/>
|
||||
<div v-else v-dompurify-html="form?.description || '-'" class="markdown-body"></div>
|
||||
</div>
|
||||
<div v-if="contentEditAble" class="mt-[8px] flex justify-end">
|
||||
<a-button type="secondary" @click="handleCancel">{{ t('common.cancel') }}</a-button>
|
||||
<a-button class="ml-[12px]" type="primary" :loading="confirmLoading" @click="handleSave">
|
||||
{{ t('common.save') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="contentEditAble" class="mt-[8px] flex justify-end">
|
||||
<a-button type="secondary" @click="handleCancel">{{ t('common.cancel') }}</a-button>
|
||||
<a-button class="ml-[12px]" type="primary" :loading="confirmLoading" @click="handleSave">
|
||||
{{ t('common.save') }}
|
||||
</a-button>
|
||||
<!-- 特殊布局内容(平台默认模板时展示) -->
|
||||
<div v-if="isPlatformDefaultTemplate" class="special-content">
|
||||
<div v-for="(item, index) in platformSystemFields" :key="index">
|
||||
<div v-if="item.fieldId !== 'summary'">
|
||||
<h1 class="header-title">
|
||||
<strong>{{ item.fieldName }}</strong>
|
||||
</h1>
|
||||
<div class="mb-4 mt-[16px]" :class="{ 'max-h-[260px]': contentEditAble }">
|
||||
<MsRichText
|
||||
v-if="contentEditAble"
|
||||
v-model:raw="item.defaultValue"
|
||||
:disabled="!contentEditAble"
|
||||
:placeholder="t('bugManagement.edit.contentPlaceholder')"
|
||||
/>
|
||||
<div v-else v-dompurify-html="item?.defaultValue || '-'" class="markdown-body"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="contentEditAble" class="mt-[8px] flex justify-end">
|
||||
<a-button type="secondary" @click="handleCancel">{{ t('common.cancel') }}</a-button>
|
||||
<a-button class="ml-[12px]" type="primary" :loading="confirmLoading" @click="handleSave">
|
||||
{{ t('common.save') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 20px">
|
||||
<div class="mt-4">
|
||||
<AddAttachment v-model:file-list="fileList" @link-file="associatedFile" />
|
||||
</div>
|
||||
<MsFileList
|
||||
@ -180,8 +208,9 @@
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useAppStore } from '@/store';
|
||||
import { downloadByteFile, sleep } from '@/utils';
|
||||
import { findParents, Option } from '@/utils/recursion';
|
||||
|
||||
import { BugEditCustomFieldItem, BugEditFormObject } from '@/models/bug-management';
|
||||
import { BugEditCustomField, BugEditCustomFieldItem, BugEditFormObject } from '@/models/bug-management';
|
||||
import { AssociatedList, AttachFileInfo } from '@/models/caseManagement/featureCase';
|
||||
import { TableQueryParams } from '@/models/common';
|
||||
|
||||
@ -197,6 +226,8 @@
|
||||
detailInfo: BugEditFormObject;
|
||||
formItem: FormRuleItem[];
|
||||
allowEdit?: boolean; // 是否允许编辑
|
||||
isPlatformDefaultTemplate: boolean; // 是否是平台默认模板
|
||||
platformSystemFields: BugEditCustomField[]; // 平台系统字段
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
@ -401,21 +432,42 @@
|
||||
const customFields: BugEditCustomFieldItem[] = [];
|
||||
if (formItem && formItem.length) {
|
||||
formItem.forEach((item: FormRuleItem) => {
|
||||
let itemVal = item.value;
|
||||
if (item.sourceType === 'CASCADER') {
|
||||
itemVal = findParents(item.options as Option[], item.value as string, []);
|
||||
}
|
||||
customFields.push({
|
||||
id: item.field as string,
|
||||
name: item.title as string,
|
||||
type: item.sourceType as string,
|
||||
value: Array.isArray(item.value) ? JSON.stringify(item.value) : (item.value as string),
|
||||
value: Array.isArray(itemVal) ? JSON.stringify(itemVal) : (itemVal as string),
|
||||
});
|
||||
});
|
||||
}
|
||||
if (props.isPlatformDefaultTemplate) {
|
||||
// 平台系统默认字段插入自定义集合
|
||||
props.platformSystemFields.forEach((item) => {
|
||||
customFields.push({
|
||||
id: item.fieldId,
|
||||
name: item.fieldName,
|
||||
type: item.type,
|
||||
value: item.defaultValue,
|
||||
});
|
||||
});
|
||||
}
|
||||
const tmpObj: BugEditFormObject = {
|
||||
...form.value,
|
||||
id: props.detailInfo.id,
|
||||
projectId: currentProjectId.value,
|
||||
templateId: props.detailInfo.templateId,
|
||||
deleteLocalFileIds: form.value.deleteLocalFileIds,
|
||||
unLinkRefIds: form.value.unLinkRefIds,
|
||||
linkFileIds: form.value.linkFileIds,
|
||||
customFields,
|
||||
};
|
||||
if (!props.isPlatformDefaultTemplate) {
|
||||
tmpObj.description = form.value.description;
|
||||
tmpObj.title = form.value.title;
|
||||
}
|
||||
// 执行保存操作。 保存成功后将富文本内容赋值给默认值
|
||||
const res = await createOrUpdateBug({ request: tmpObj, fileList: [] as unknown as File[] });
|
||||
if (res) {
|
||||
|
@ -24,7 +24,9 @@
|
||||
<a-form ref="formRef" :model="form" layout="vertical">
|
||||
<div class="flex flex-row">
|
||||
<div class="left mt-[16px] min-w-[732px] grow pl-[24px]">
|
||||
<!-- 平台默认模板不展示缺陷名称, 描述 -->
|
||||
<a-form-item
|
||||
v-if="!isPlatformDefaultTemplate"
|
||||
field="title"
|
||||
:label="t('bugManagement.bugName')"
|
||||
:rules="[{ required: true, message: t('bugManagement.edit.nameIsRequired') }]"
|
||||
@ -32,13 +34,38 @@
|
||||
>
|
||||
<a-input v-model="form.title" :max-length="255" />
|
||||
</a-form-item>
|
||||
<a-form-item field="description" :label="t('bugManagement.edit.content')">
|
||||
<a-form-item v-if="!isPlatformDefaultTemplate" field="description" :label="t('bugManagement.edit.content')">
|
||||
<MsRichText
|
||||
v-model:raw="form.description"
|
||||
v-model:filed-ids="richTextFileIds"
|
||||
:upload-image="handleUploadImage"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- 平台默认模板展示字段, 暂时支持输入框, 富文本类型 -->
|
||||
<div v-if="isPlatformDefaultTemplate">
|
||||
<a-form-item
|
||||
v-for="(value, key) in form.platformSystemFields"
|
||||
:key="key"
|
||||
:field="'platformSystemFields.' + key"
|
||||
:label="platformSystemFieldMap[key].fieldName"
|
||||
:rules="[
|
||||
{
|
||||
required: platformSystemFieldMap[key].required,
|
||||
message: `${platformSystemFieldMap[key].fieldName}` + t('bugManagement.edit.cannotBeNull'),
|
||||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
v-if="platformSystemFieldMap[key].type === 'INPUT'"
|
||||
v-model="form.platformSystemFields[key]"
|
||||
:max-length="255"
|
||||
/>
|
||||
<MsRichText
|
||||
v-if="platformSystemFieldMap[key].type === 'RICH_TEXT'"
|
||||
v-model:raw="form.platformSystemFields[key]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<a-form-item field="attachment">
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-1">
|
||||
@ -124,7 +151,8 @@
|
||||
<div class="right mt-[16px] max-w-[433px] grow pr-[24px]">
|
||||
<div style="min-width: 250px; overflow: auto">
|
||||
<MsFormCreate ref="formCreateRef" v-model:formItem="formItem" v-model:api="fApi" :form-rule="formRules" />
|
||||
<a-form-item field="tag" :label="t('bugManagement.tag')">
|
||||
<!-- 平台默认模板不展示标签, 与第三方保持一致 -->
|
||||
<a-form-item v-if="!isPlatformDefaultTemplate" field="tag" :label="t('bugManagement.tag')">
|
||||
<MsTagsInput
|
||||
v-model:model-value="form.tags"
|
||||
:placeholder="t('bugManagement.edit.tagPlaceholder')"
|
||||
@ -200,6 +228,7 @@
|
||||
import { useAppStore } from '@/store';
|
||||
import { downloadByteFile } from '@/utils';
|
||||
import { scrollIntoView } from '@/utils/dom';
|
||||
import { findParents, Option } from '@/utils/recursion';
|
||||
|
||||
import {
|
||||
BugEditCustomField,
|
||||
@ -237,8 +266,13 @@
|
||||
deleteLocalFileIds: [],
|
||||
unLinkRefIds: [],
|
||||
linkFileIds: [],
|
||||
// 平台默认模板系统字段
|
||||
platformSystemFields: {},
|
||||
});
|
||||
|
||||
// 平台默认模板系统字段
|
||||
const platformSystemFieldMap = {};
|
||||
|
||||
const getListFunParams = ref<TableQueryParams>({
|
||||
combine: {
|
||||
hiddenIds: [],
|
||||
@ -262,6 +296,7 @@
|
||||
const bugId = computed(() => route.query.id || '');
|
||||
const isEditOrCopy = computed(() => !!bugId.value);
|
||||
const isCopy = computed(() => route.params.mode === 'copy');
|
||||
const isPlatformDefaultTemplate = ref(false);
|
||||
const imageUrl = ref('');
|
||||
const previewVisible = ref<boolean>(false);
|
||||
const richTextFileIds = ref<string[]>([]);
|
||||
@ -323,6 +358,7 @@
|
||||
value: item.defaultValue,
|
||||
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
|
||||
required: item.required as boolean,
|
||||
platformPlaceHolder: item.platformPlaceHolder,
|
||||
props: {
|
||||
modelValue: item.defaultValue,
|
||||
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
|
||||
@ -335,12 +371,22 @@
|
||||
const templateChange = async (v: SelectValue, request?: BugTemplateRequest) => {
|
||||
if (v) {
|
||||
try {
|
||||
loading.value = true;
|
||||
let param = { projectId: appStore.currentProjectId, id: v };
|
||||
if (request) {
|
||||
param = { ...param, ...request };
|
||||
}
|
||||
const res = await getTemplateById(param);
|
||||
getFormRules(res.customFields);
|
||||
isPlatformDefaultTemplate.value = res.platformDefault;
|
||||
if (isPlatformDefaultTemplate.value) {
|
||||
const systemFields = res.customFields.filter((field) => field.platformSystemField);
|
||||
systemFields.forEach((field) => {
|
||||
form.value.platformSystemFields[field.fieldId] = field.defaultValue;
|
||||
platformSystemFieldMap[field.fieldId] = field;
|
||||
});
|
||||
}
|
||||
getFormRules(res.customFields.filter((field) => !field.platformSystemField));
|
||||
loading.value = false;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
@ -461,6 +507,9 @@
|
||||
const customFields: BugEditCustomFieldItem[] = [];
|
||||
if (formItem.value && formItem.value.length) {
|
||||
formItem.value.forEach((item: FormRuleItem) => {
|
||||
if (item.sourceType === 'CASCADER') {
|
||||
item.value = findParents(item.options as Option[], item.value as string, []);
|
||||
}
|
||||
customFields.push({
|
||||
id: item.field as string,
|
||||
name: item.title as string,
|
||||
@ -469,6 +518,21 @@
|
||||
});
|
||||
});
|
||||
}
|
||||
if (isPlatformDefaultTemplate.value && form.value.platformSystemFields) {
|
||||
Object.keys(form.value.platformSystemFields).forEach((key) => {
|
||||
customFields.push({
|
||||
id: platformSystemFieldMap[key].fieldId,
|
||||
name: platformSystemFieldMap[key].fieldName,
|
||||
type: platformSystemFieldMap[key].type,
|
||||
value: form.value.platformSystemFields[key],
|
||||
});
|
||||
});
|
||||
delete form.value.platformSystemFields;
|
||||
// 平台默认模板不传递名称, 描述, 标签等参数
|
||||
delete form.value.title;
|
||||
delete form.value.description;
|
||||
delete form.value.tags;
|
||||
}
|
||||
// 过滤出复制的附件
|
||||
const copyFileList = fileList.value.filter((item) => item.isCopyFlag);
|
||||
let copyFiles: { refId: string; fileId: string; local: boolean }[] = [];
|
||||
@ -550,6 +614,7 @@
|
||||
};
|
||||
// 获取详情
|
||||
const getDetailInfo = async () => {
|
||||
loading.value = true;
|
||||
const id = route.query.id as string;
|
||||
if (!id) return;
|
||||
const res = await getBugDetail(id);
|
||||
@ -580,16 +645,24 @@
|
||||
});
|
||||
}
|
||||
|
||||
const tmpObj = {};
|
||||
let tmpObj = {};
|
||||
if (isEdit.value) {
|
||||
tmpObj = { status: res.status };
|
||||
}
|
||||
if (customFields && Array.isArray(customFields)) {
|
||||
customFields.forEach((item) => {
|
||||
if (item.id === 'status' && isCopy.value) {
|
||||
// 复制时, 状态赋值为空
|
||||
tmpObj[item.id] = '';
|
||||
} else if (item.type === 'MULTIPLE_SELECT') {
|
||||
} else if (item.type === 'MULTIPLE_SELECT' || item.type === 'MULTIPLE_INPUT' || item.type === 'CHECKBOX') {
|
||||
tmpObj[item.id] = JSON.parse(item.value);
|
||||
} else if (item.type === 'INT') {
|
||||
tmpObj[item.id] = Number(item.value);
|
||||
} else if (item.type === 'CASCADER') {
|
||||
const arr = JSON.parse(item.value);
|
||||
if (arr && arr instanceof Array && arr.length > 0) {
|
||||
tmpObj[item.id] = arr[arr.length - 1];
|
||||
}
|
||||
} else {
|
||||
tmpObj[item.id] = item.value;
|
||||
}
|
||||
@ -597,6 +670,13 @@
|
||||
}
|
||||
// 自定义字段赋值
|
||||
fApi.value.setValue(tmpObj);
|
||||
// 平台默认模板系统字段单独处理
|
||||
if (isPlatformDefaultTemplate && form.value.platformSystemFields) {
|
||||
Object.keys(form.value.platformSystemFields).forEach((key) => {
|
||||
form.value.platformSystemFields[key] = tmpObj[key];
|
||||
});
|
||||
}
|
||||
const { platformSystemFields } = form.value;
|
||||
// 表单赋值
|
||||
form.value = {
|
||||
id: res.id,
|
||||
@ -605,7 +685,9 @@
|
||||
templateId: res.templateId,
|
||||
tags: res.tags,
|
||||
projectId: res.projectId,
|
||||
platformSystemFields,
|
||||
};
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const initDefaultFields = async () => {
|
||||
|
@ -378,7 +378,7 @@
|
||||
{
|
||||
title: 'bugManagement.status',
|
||||
dataIndex: 'statusName',
|
||||
width: 84,
|
||||
width: 100,
|
||||
slotName: 'status',
|
||||
titleSlotName: 'statusFilter',
|
||||
showDrag: true,
|
||||
@ -390,7 +390,7 @@
|
||||
slotName: 'handleUser',
|
||||
showTooltip: true,
|
||||
titleSlotName: 'handleUserFilter',
|
||||
width: 75,
|
||||
width: 100,
|
||||
showDrag: true,
|
||||
showInTable: true,
|
||||
},
|
||||
@ -404,7 +404,7 @@
|
||||
},
|
||||
{
|
||||
title: 'bugManagement.belongPlatform',
|
||||
width: 135,
|
||||
width: 100,
|
||||
showDrag: true,
|
||||
dataIndex: 'platform',
|
||||
showInTable: true,
|
||||
@ -421,7 +421,7 @@
|
||||
title: 'bugManagement.creator',
|
||||
dataIndex: 'createUser',
|
||||
slotName: 'createUser',
|
||||
width: 112,
|
||||
width: 125,
|
||||
showTooltip: true,
|
||||
showDrag: true,
|
||||
titleSlotName: 'createUserFilter',
|
||||
@ -445,7 +445,7 @@
|
||||
{
|
||||
title: 'bugManagement.updateUser',
|
||||
dataIndex: 'updateUser',
|
||||
width: 112,
|
||||
width: 125,
|
||||
showTooltip: true,
|
||||
showDrag: true,
|
||||
titleSlotName: 'updateUserFilter',
|
||||
|
@ -53,6 +53,7 @@ export default {
|
||||
linkFile: 'Link file',
|
||||
contentEdit: 'Content edit',
|
||||
linkCase: 'Link case',
|
||||
cannotBeNull: 'is empty',
|
||||
},
|
||||
detail: {
|
||||
title: '【{id}】{name}',
|
||||
|
@ -53,6 +53,7 @@ export default {
|
||||
linkFile: '关联文件',
|
||||
contentEdit: '内容编辑',
|
||||
linkCase: '关联用例',
|
||||
cannotBeNull: '不能为空',
|
||||
},
|
||||
detail: {
|
||||
title: '【{id}】{name}',
|
||||
|
Loading…
Reference in New Issue
Block a user