fix(测试跟踪): 使用第三方缺陷模板,存在同名字段,无法保存

【[测试跟踪] github#24685MS集成Jira,缺陷模板选择【使用jira缺陷模板】,MS读取的Jira缺陷模板中有错误:非必填项变为必填项,并且缺陷无法保存】https://www.tapd.cn/55049933/bugtrace/bugs/view?bug_id=1155049933001026618
This commit is contained in:
chenjianxing 2023-06-05 11:06:10 +08:00 committed by fit2-zhao
parent cdbdcb931c
commit 0fb0e8c786
4 changed files with 134 additions and 18 deletions

View File

@ -4,7 +4,7 @@
<span class="custom-item" v-for="(item, j) in sortCustomFields" :key="j"> <span class="custom-item" v-for="(item, j) in sortCustomFields" :key="j">
<span v-if="j >= (i - 1)*3 && j < (i - 1)*3+3"> <span v-if="j >= (i - 1)*3 && j < (i - 1)*3+3">
<el-col :span="8" v-if="item.type !== 'richText'"> <el-col :span="8" v-if="item.type !== 'richText'">
<el-form-item :label="item.system ? $t(systemNameMap[item.name]) : item.name" :prop="item.name" <el-form-item :label="item.system ? $t(systemNameMap[item.name]) : item.name" :prop="item[formProp]"
:label-width="formLabelWidth"> :label-width="formLabelWidth">
<custom-filed-component <custom-filed-component
prop="defaultValue" prop="defaultValue"
@ -12,6 +12,7 @@
:form="form" :form="form"
:default-open="defaultOpen" :default-open="defaultOpen"
:disabled="isPublic" :disabled="isPublic"
:form-prop="formProp"
@inputSearch="handleInputSearch" @inputSearch="handleInputSearch"
ref="customFiled" ref="customFiled"
/> />
@ -21,12 +22,13 @@
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item
:label="item.system ? $t(systemNameMap[item.name]) : item.name" :label="item.system ? $t(systemNameMap[item.name]) : item.name"
:prop="item.name" :prop="item[formProp]"
:default-open="defaultOpen" :default-open="defaultOpen"
:label-width="formLabelWidth"> :label-width="formLabelWidth">
<custom-filed-component <custom-filed-component
:data="item" :data="item"
:form="form" :form="form"
:form-prop="formProp"
prop="defaultValue" prop="defaultValue"
@inputSearch="handleInputSearch" @inputSearch="handleInputSearch"
ref="customFiled"/> ref="customFiled"/>
@ -59,7 +61,11 @@ export default {
type: Boolean, type: Boolean,
default() { default() {
return false; return false;
} },
},
formProp: {
type: String,
default: 'name'
}, },
defaultOpen: { defaultOpen: {
type: String, type: String,

View File

@ -161,14 +161,18 @@ import {OPTION_LABEL_PREFIX} from "../../utils/tableUtils";
export default { export default {
name: "CustomFiledComponent", name: "CustomFiledComponent",
components: {MsMarkDownText, MsInputTag, MsTableColumn}, components: {MsMarkDownText, MsInputTag, MsTableColumn},
props: [ props: {
'data', data: Object,
'prop', prop: String,
'form', form: Object,
'disabled', disabled: Boolean,
'defaultOpen', defaultOpen: String,
'isTemplateEdit' isTemplateEdit: Boolean,
], formProp: {
type: String,
default: 'name'
}
},
data() { data() {
return { return {
memberOptions: [], memberOptions: [],
@ -223,10 +227,10 @@ export default {
return item.system ? this.$t(item.text) : item.text; return item.system ? this.$t(item.text) : item.text;
}, },
handleChange() { handleChange() {
if (this.form) {
this.$set(this.form, this.data.name, this.data[this.prop]); this.setFormData();
}
this.$emit('change', this.data.name); this.$emit('change', this.data[this.formProp]);
this.$forceUpdate(); this.$forceUpdate();
if (this.data.inputSearch) { if (this.data.inputSearch) {
// optionLabel // optionLabel
@ -285,7 +289,7 @@ export default {
}, },
setFormData() { setFormData() {
if (this.form && this.data && this.data[this.prop]) { if (this.form && this.data && this.data[this.prop]) {
this.$set(this.form, this.data.name, this.data[this.prop]); this.$set(this.form, this.data[this.formProp], this.data[this.prop]);
} }
} }
} }

View File

@ -111,6 +111,111 @@ export function parseCustomField(data, template, rules, oldFields) {
return customFieldForm; return customFieldForm;
} }
/**
*
* 原本的 parseCustomField form key 是字段名这里改成 IDjira 存在相同字段名的情况
* 设置默认值添加自定义校验
* @param data 原表单值
* @param template 模板
* @param rules 自定义表单的校验规则
* @param oldFields 用于兼容旧版本数据
*/
export function parseCustomFieldForId(data, template, rules, oldFields) {
let hasOldData = false;
if (!data.fields) {
// 旧数据
hasOldData = true;
data.fields = [];
}
let customFieldForm = {};
// 设置页面显示的默认值
template.customFields.forEach((item) => {
if (item.defaultValue && !item.hasParse) {
let val = item.defaultValue;
try {
val = JSON.parse(item.defaultValue);
} catch (e) {
//
}
if (
item.name === "责任人" &&
item.system &&
val &&
val === "CURRENT_USER"
) {
val = '';
const {id, userGroups} = getCurrentUser();
if (userGroups) {
// CURRENT_USER是否是当前项目下的成员
let index = userGroups.findIndex(ug => ug.sourceId === getCurrentProjectID());
if (index !== -1) {
val = id;
}
}
}
setDefaultValue(item, val);
}
// 添加自定义字段必填校验
if (item.required) {
let msg =
(item.system ? i18n.t(SYSTEM_FIELD_NAME_MAP[item.name]) : item.name) +
i18n.t("commons.cannot_be_null");
if (rules) {
rules[item.id] = [{ required: true, message: msg, trigger: "blur" }];
}
}
if (hasOldData && oldFields) {
// 兼容旧数据
for (const key of oldFields.keys()) {
if (item.name === key) {
if (oldFields.get(key)) {
setDefaultValue(item, oldFields.get(key));
}
}
}
}
// 将保存的值赋值给template
if (data.fields instanceof Array) {
for (let i = 0; i < data.fields.length; i++) {
let customField = data.fields[i];
if (customField.id === item.id) {
try {
if (item.type === "textarea" || item.type === "richText") {
setDefaultValue(item, customField.textValue);
} else {
setDefaultValue(item, customField.value);
}
parseCustomFieldOptionLabel(customField, item);
item.isEdit = true;
} catch (e) {
console.error("JSON parse custom field value error.", e);
}
break;
}
}
} else if (data.fields instanceof Object) {
// todo
// 兼容旧的存储方式
for (const key in data.fields) {
if (item.name === key) {
if (data.fields[key]) {
setDefaultValue(item, JSON.parse(data.fields[key]));
}
}
}
}
customFieldForm[item.id] = item.defaultValue;
});
return customFieldForm;
}
export function isMultipleField(type) { export function isMultipleField(type) {
if (type.startsWith('multiple') || type === 'checkbox') { if (type.startsWith('multiple') || type === 'checkbox') {
return true; return true;

View File

@ -43,6 +43,7 @@
:default-open="richTextDefaultOpen" :default-open="richTextDefaultOpen"
:form-label-width="formLabelWidth" :form-label-width="formLabelWidth"
:issue-template="issueTemplate" :issue-template="issueTemplate"
form-prop="id"
@inputSearch="handleInputSearch" @inputSearch="handleInputSearch"
ref="customFieldItem" ref="customFieldItem"
/> />
@ -188,7 +189,7 @@
import TemplateComponentEditHeader from "@/business/plan/view/comonents/report/TemplateComponentEditHeader"; import TemplateComponentEditHeader from "@/business/plan/view/comonents/report/TemplateComponentEditHeader";
import MsFormDivider from "metersphere-frontend/src/components/MsFormDivider"; import MsFormDivider from "metersphere-frontend/src/components/MsFormDivider";
import FormRichTextItem from "metersphere-frontend/src/components/FormRichTextItem"; import FormRichTextItem from "metersphere-frontend/src/components/FormRichTextItem";
import {buildCustomFields, parseCustomField} from "metersphere-frontend/src/utils/custom_field"; import {buildCustomFields, parseCustomField, parseCustomFieldForId} from "metersphere-frontend/src/utils/custom_field";
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent"; import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
import TestCaseIssueList from "@/business/issue/TestCaseIssueList"; import TestCaseIssueList from "@/business/issue/TestCaseIssueList";
import IssueEditDetail from "@/business/issue/IssueEditDetail"; import IssueEditDetail from "@/business/issue/IssueEditDetail";
@ -495,7 +496,7 @@ export default {
this.form.creator = getCurrentUserId(); this.form.creator = getCurrentUserId();
} }
} }
this.customFieldForm = parseCustomField(this.form, this.issueTemplate, this.customFieldRules); this.customFieldForm = parseCustomFieldForId(this.form, this.issueTemplate, this.customFieldRules);
this.comments = []; this.comments = [];
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.testCaseIssueList) { if (this.$refs.testCaseIssueList) {