feat(缺陷管理): 详情保存

This commit is contained in:
RubyLiu 2024-02-06 14:49:32 +08:00 committed by Craftsman
parent 1d71ba51d2
commit e3730b3bba
3 changed files with 87 additions and 81 deletions

View File

@ -88,7 +88,13 @@
<template #title>
{{ t('bugManagement.detail.detail') }}
</template>
<BugDetailTab :allow-edit="true" :detail-info="detailInfo" @update-success="updateSuccess" />
<BugDetailTab
ref="bugDetailTabRef"
:form-item="formItem"
:allow-edit="true"
:detail-info="detailInfo"
@update-success="updateSuccess"
/>
</a-tab-pane>
<a-tab-pane key="case">
<template #title>
@ -118,7 +124,7 @@
:form-rule="formRules"
class="w-full"
:option="options"
@change="handleOK"
@change="handelFormCreateChange"
/>
<!-- 自定义字段结束 -->
<div class="baseItem">
@ -154,6 +160,7 @@
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { Message } from '@arco-design/web-vue';
import { debounce } from 'lodash-es';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue';
@ -175,7 +182,6 @@
followBug,
getBugDetail,
getTemplateById,
updateBug,
} from '@/api/modules/bug-management/index';
import useFullScreen from '@/hooks/useFullScreen';
import { useI18n } from '@/hooks/useI18n';
@ -212,6 +218,7 @@
const formItem = ref<FormRuleItem[]>([]); //
const currentProjectId = computed(() => appStore.currentProjectId);
const showDrawerVisible = defineModel<boolean>('visible', { default: false });
const bugDetailTabRef = ref();
const activeTab = ref<string | number>('detail');
@ -219,7 +226,7 @@
const tags = ref([]);
//
const getFormRules = (arr: BugEditCustomField[]) => {
const getFormRules = (arr: BugEditCustomField[], valueObj: BugEditFormObject) => {
formRules.value = [];
if (Array.isArray(arr) && arr.length) {
formRules.value = arr.map((item) => {
@ -227,11 +234,11 @@
type: item.type,
name: item.fieldId,
label: item.fieldName,
value: item.value,
value: valueObj[item.fieldId],
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
required: item.required as boolean,
props: {
modelValue: item.value,
modelValue: valueObj[item.fieldId],
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
},
};
@ -239,11 +246,11 @@
}
};
const templateChange = async (v: SelectValue) => {
const templateChange = async (v: SelectValue, valueObj: BugEditFormObject) => {
if (v) {
try {
const res = await getTemplateById({ projectId: appStore.currentProjectId, id: v });
getFormRules(res.customFields);
getFormRules(res.customFields, valueObj);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
@ -255,16 +262,14 @@
const { templateId } = detail;
// tag
tags.value = detail.tags || [];
//
await templateChange(templateId);
const tmpObj = {};
if (detail.customFields && Array.isArray(detail.customFields)) {
detail.customFields.forEach((item) => {
tmpObj[item.id] = item.value;
});
}
//
fApi.value.setValue(tmpObj);
//
await templateChange(templateId, tmpObj);
}
const editLoading = ref<boolean>(false);
@ -333,24 +338,9 @@
});
}
const handleOK = async () => {
const values = await fApi.value.validate();
if (values) {
const params = {
id: detailInfo.value.id,
projectId: currentProjectId.value,
...values,
};
try {
await updateBug(params);
Message.success(t('common.editSuccess'));
detailDrawerRef.value?.initDetail();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
};
const handelFormCreateChange = debounce(() => {
bugDetailTabRef.value?.handleSave();
}, 300);
//
const options = {

View File

@ -1,36 +1,36 @@
<template>
<div class="p-[16px]">
<div class="relative p-[16px] pb-[16px]">
<div class="header">
<div class="header-title">{{ t('bugManagement.edit.content') }}</div>
<div v-if="!contentEditAble" v-permission="['PROJECT_BUG:READ+UPDATE']" class="header-action">
<a-button type="text" @click="contentEditAble = true">
<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>
{{ t('bugManagement.edit.contentEdit') }}
</a-button>
</div>
</div>
<div class="mt-[8]" :class="{ 'max-h-[260px]': contentEditAble }">
<div class="mt-[16px]" :class="{ 'max-h-[260px]': contentEditAble }">
<MsRichText
v-if="contentEditAble"
v-model:raw="form.content"
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?.content || '-'" class="text-[var(--color-text-3)]"></div>
<div v-else v-dompurify-html="form?.description || '-'" class="text-[var(--color-text-3)]"></div>
</div>
<div v-if="contentEditAble" class="flex justify-end">
<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">
<a-button class="ml-[12px]" type="primary" :loading="confirmLoading" @click="handleSave">
{{ t('common.save') }}
</a-button></div
>
<div v-if="props.allowEdit">
<div class="font-medium text-[var(--color-text-1)]">
<div class="mt-[16px] font-medium text-[var(--color-text-1)]">
{{ t('bugManagement.edit.file') }}
</div>
<div class="mb-1">
<div class="mt-[16px] pb-[4px]">
<a-dropdown position="tr" trigger="hover">
<a-button v-permission="['PROJECT_BUG:READ+UPDATE']" type="outline">
<template #icon> <icon-plus class="text-[14px]" /> </template
@ -162,6 +162,7 @@
import { Message } from '@arco-design/web-vue';
import MsButton from '@/components/pure/ms-button/index.vue';
import { FormRuleItem } from '@/components/pure/ms-form-create/types';
import MsIconfont from '@/components/pure/ms-icon-font/index.vue';
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
import MsFileList from '@/components/pure/ms-upload/fileList.vue';
@ -171,6 +172,7 @@
import {
checkFileIsUpdateRequest,
createOrUpdateBug,
deleteFileOrCancelAssociation,
downloadFileRequest,
editorUploadFile,
@ -180,14 +182,12 @@
updateFile,
uploadOrAssociationFile,
} from '@/api/modules/bug-management';
import { updateCaseRequest } from '@/api/modules/case-management/featureCase';
import { getModules, getModulesCount } from '@/api/modules/project-management/fileManagement';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
import { downloadByteFile, sleep } from '@/utils';
import { scrollIntoView } from '@/utils/dom';
import { BugEditFormObject } from '@/models/bug-management';
import { BugEditCustomFieldItem, BugEditFormObject } from '@/models/bug-management';
import { AssociatedList, AttachFileInfo } from '@/models/caseManagement/featureCase';
import { TableQueryParams } from '@/models/common';
@ -197,6 +197,7 @@
const props = defineProps<{
detailInfo: BugEditFormObject;
formItem: FormRuleItem[];
allowEdit?: boolean; //
}>();
@ -224,7 +225,7 @@
},
});
const form = ref({
content: '',
description: '',
deleteLocalFileIds: [] as string[],
unLinkRefIds: [] as string[],
linkFileIds: [] as string[],
@ -251,36 +252,17 @@
}
};
const confirmLoading = ref<boolean>(false);
const initCurrentDetail = async (detail: BugEditFormObject) => {
const { attachments, description } = detail;
form.value.description = description;
handleFileFunc(attachments);
};
function handleCancel() {
contentEditAble.value = false;
}
const confirmLoading = ref<boolean>(false);
// function handleOK() {
// caseFormRef.value?.validate().then(async (res: any) => {
// if (!res) {
// try {
// confirmLoading.value = true;
// await updateCaseRequest();
// Message.success(t('caseManagement.featureCase.editSuccess'));
// handleCancel();
// emit('updateSuccess');
// } catch (error) {
// // eslint-disable-next-line no-console
// console.log(error);
// } finally {
// confirmLoading.value = false;
// }
// }
// return scrollIntoView(document.querySelector('.arco-form-item-message'), { block: 'center' });
// });
// }
const initCurrentDetail = async (detail: BugEditFormObject) => {
const { attachments, content } = detail;
form.value.content = content;
handleFileFunc(attachments);
};
//
async function deleteFileHandler(item: MsFileItem) {
@ -311,16 +293,6 @@
return Promise.resolve(true);
}
function handleChange(_fileList: MsFileItem[]) {
fileList.value = _fileList.map((e) => {
return {
...e,
enable: true, //
local: true, //
};
});
}
//
async function handlePreview(item: MsFileItem) {
try {
@ -471,10 +443,50 @@
},
{ deep: true }
);
//
async function handleSave() {
try {
confirmLoading.value = true;
const { formItem } = props;
const customFields: BugEditCustomFieldItem[] = [];
if (formItem && formItem.length) {
formItem.forEach((item: FormRuleItem) => {
customFields.push({
id: item.field as string,
name: item.title as string,
type: item.sourceType as string,
value: item.value as string,
});
});
}
const tmpObj: BugEditFormObject = {
...form.value,
id: props.detailInfo.id,
projectId: currentProjectId.value,
templateId: props.detailInfo.templateId,
customFields,
};
//
const res = await createOrUpdateBug({ request: tmpObj, fileList: fileList.value as unknown as File[] });
if (res) {
Message.success(t('common.updateSuccess'));
handleCancel();
emit('updateSuccess');
}
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
confirmLoading.value = false;
}
}
watchEffect(() => {
initCurrentDetail(props.detailInfo);
});
defineExpose({
handleSave,
});
</script>
<style lang="less" scoped>
@ -487,6 +499,9 @@
color: var(--color-text-1);
}
&-action {
position: absolute;
top: 0;
right: 6px;
color: rgb(var(--primary-7));
}
}

View File

@ -452,6 +452,7 @@
formRules.value = customFields.value.map((item: any) => {
const multipleType = ['MULTIPLE_SELECT', 'CHECKBOX', 'MULTIPLE_MEMBER', 'MULTIPLE_INPUT'];
const currentDefaultValue = multipleType.includes(item.type) ? JSON.parse(item.defaultValue) : item.defaultValue;
console.log('currentDefaultValue', currentDefaultValue);
return {
...item,
type: item.type,