refactor(缺陷管理): 缺陷管理创建缺陷创建组件抽离&重构

This commit is contained in:
xinxin.wu 2024-08-22 11:37:34 +08:00 committed by Craftsman
parent 00f4cf449c
commit 01a912b399
5 changed files with 441 additions and 363 deletions

View File

@ -32,7 +32,7 @@ const BugManagement: AppRouteRecordRaw = {
{
path: 'detail/:mode?',
name: BugManagementRouteEnum.BUG_MANAGEMENT_DETAIL,
component: () => import('@/views/bug-management/edit.vue'),
component: () => import('@/views/bug-management/createAndEditBug.vue'),
meta: {
locale: 'bugManagement.editBug',
roles: ['PROJECT_BUG:READ+ADD', 'PROJECT_BUG:READ+UPDATE'],

View File

@ -0,0 +1,156 @@
<template>
<MsCard
has-breadcrumb
:title="title"
:loading="loading"
:is-edit="isEdit"
@save="saveHandler(false)"
@save-and-continue="saveHandler(true)"
>
<template v-if="!isEdit" #headerRight>
<a-select
v-model="bugTemplateId"
class="w-[240px]"
:options="templateOption"
allow-search
:placeholder="t('bugManagement.edit.defaultSystemTemplate')"
/>
</template>
<BugDetail ref="bugDetailRef" v-model:template-id="bugTemplateId" :bug-id="bugId" @save-params="saveParams" />
</MsCard>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router';
import { Message } from '@arco-design/web-vue';
import MsCard from '@/components/pure/ms-card/index.vue';
import BugDetail from './edit.vue';
import { createOrUpdateBug, getTemplateOption } from '@/api/modules/bug-management';
import { useI18n } from '@/hooks/useI18n';
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
import useVisit from '@/hooks/useVisit';
import router from '@/router';
import { useAppStore } from '@/store';
import { BugEditFormObject } from '@/models/bug-management';
import { BugManagementRouteEnum } from '@/enums/routeEnum';
defineOptions({ name: 'BugEditPage' });
const { setIsSave } = useLeaveUnSaveTip();
setIsSave(false);
const { t } = useI18n();
interface TemplateOption {
label: string;
value: string;
}
const appStore = useAppStore();
const route = useRoute();
const templateOption = ref<TemplateOption[]>([]);
const bugTemplateId = ref<string>('');
const loading = ref(false);
const isEdit = computed(() => !!route.query.id && route.params.mode === 'edit');
const bugId = computed(() => route.query.id as string | undefined);
const isCopy = computed(() => route.params.mode === 'copy');
const visitedKey = 'doNotNextTipCreateBug';
const { getIsVisited } = useVisit(visitedKey);
const title = computed(() => {
if (isCopy.value) {
return t('bugManagement.copyBug');
}
return isEdit.value ? t('bugManagement.editBug') : t('bugManagement.createBug');
});
const getTemplateOptions = async () => {
try {
loading.value = true;
const res = await getTemplateOption(appStore.currentProjectId);
templateOption.value = res.map((item) => {
if (item.enableDefault && !isEdit.value) {
//
bugTemplateId.value = item.id;
}
return {
label: item.name,
value: item.id,
};
});
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
loading.value = false;
}
};
const bugDetailRef = ref<InstanceType<typeof BugDetail>>();
async function saveParams(isContinue: boolean, params: { request: BugEditFormObject; fileList: File[] }) {
try {
loading.value = true;
const res = await createOrUpdateBug(params);
if (isEdit.value) {
setIsSave(true);
Message.success(t('common.updateSuccess'));
router.push({
name: BugManagementRouteEnum.BUG_MANAGEMENT_INDEX,
});
} else {
Message.success(t('common.createSuccess'));
if (isContinue) {
setIsSave(false);
bugDetailRef.value?.resetForm();
} else {
setIsSave(true);
//
if (getIsVisited()) {
router.push({
name: BugManagementRouteEnum.BUG_MANAGEMENT_INDEX,
});
return;
}
router.push({
name: BugManagementRouteEnum.BUG_MANAGEMENT_CREATE_SUCCESS,
query: {
...route.query,
id: res.data.id,
},
});
}
}
} catch (error) {
console.log(error);
} finally {
loading.value = false;
}
}
const saveHandler = async (isContinue = false) => {
bugDetailRef.value?.saveHandler(isContinue);
};
const initDefaultFields = async () => {
await getTemplateOptions();
};
onBeforeMount(() => {
initDefaultFields();
});
</script>
<style lang="less" scoped>
:deep(.arco-form-item-extra) {
font-size: 14px;
color: var(--color-text-4);
}
:deep(.arco-form-item-content) {
overflow-wrap: anywhere;
}
</style>

View File

@ -1,185 +1,161 @@
<template>
<MsCard
has-breadcrumb
:title="title"
:loading="loading"
:is-edit="isEdit"
@save="saveHandler(false)"
@save-and-continue="saveHandler(true)"
>
<template v-if="!isEdit" #headerRight>
<a-select
v-model="form.templateId"
class="w-[240px]"
:options="templateOption"
allow-search
:placeholder="t('bugManagement.edit.defaultSystemTemplate')"
@change="templateChange"
/>
</template>
<a-form ref="formRef" :model="form" layout="vertical">
<div class="flex flex-row">
<div class="left mt-[16px] w-[calc(100%-428px)] grow">
<!-- 平台默认模板不展示缺陷名称, 描述 -->
<a-form ref="formRef" :model="form" layout="vertical">
<div class="flex flex-row">
<div class="left mt-[16px] w-[calc(100%-428px)] grow">
<!-- 平台默认模板不展示缺陷名称, 描述 -->
<a-form-item
v-if="!isPlatformDefaultTemplate"
field="title"
:label="t('bugManagement.bugName')"
:rules="[{ required: true, message: t('bugManagement.edit.nameIsRequired') }]"
>
<a-input v-model="form.title" :placeholder="t('bugManagement.edit.pleaseInputBugName')" :max-length="255" />
</a-form-item>
<a-form-item v-if="!isPlatformDefaultTemplate" field="description" :label="t('bugManagement.edit.content')">
<MsRichText
v-model:raw="form.description"
v-model:filed-ids="descriptionFileIds"
:upload-image="handleUploadImage"
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
/>
</a-form-item>
<!-- 平台默认模板展示字段, 暂时支持输入框, 富文本类型 -->
<div v-if="isPlatformDefaultTemplate">
<a-form-item
v-if="!isPlatformDefaultTemplate"
field="title"
:label="t('bugManagement.bugName')"
:rules="[{ required: true, message: t('bugManagement.edit.nameIsRequired') }]"
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-model="form.title" :placeholder="t('bugManagement.edit.pleaseInputBugName')" :max-length="255" />
</a-form-item>
<a-form-item v-if="!isPlatformDefaultTemplate" field="description" :label="t('bugManagement.edit.content')">
<a-input
v-if="platformSystemFieldMap[key].type === 'INPUT'"
v-model="form.platformSystemFields[key]"
:max-length="255"
/>
<MsRichText
v-model:raw="form.description"
v-model:filed-ids="descriptionFileIds"
v-if="platformSystemFieldMap[key].type === 'RICH_TEXT'"
v-model:raw="form.platformSystemFields[key]"
v-model:filed-ids="descriptionFileIdMap[key]"
:upload-image="handleUploadImage"
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
/>
</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"
</div>
<a-form-item field="attachment">
<div class="flex flex-col">
<div class="mb-1">
<AddAttachment v-model:file-list="fileList" @change="handleChange" @link-file="associatedFile" />
</div>
</div>
</a-form-item>
<MsFileList
ref="fileListRef"
v-model:file-list="fileList"
:init-file-save-tips="t('ms.upload.waiting_save')"
mode="static"
>
<template #actions="{ item }">
<!-- 本地文件 -->
<div v-if="item.local || item.status === 'init'" class="flex flex-nowrap">
<MsButton
v-if="item.status !== 'init' && item.file.type.includes('image')"
type="button"
status="primary"
class="!mr-[4px]"
@click="handlePreview(item)"
>
{{ t('ms.upload.preview') }}
</MsButton>
<MsButton
v-if="item.status !== 'init'"
type="button"
status="primary"
class="!mr-[4px]"
@click="transferFile(item)"
>
{{ t('caseManagement.featureCase.storage') }}
</MsButton>
<SaveAsFilePopover
v-model:visible="transferVisible"
:saving-file="activeTransferFileParams"
:file-save-as-source-id="(form.id as string)"
:file-save-as-api="transferFileRequest"
:file-module-options-api="getTransferFileTree"
source-id-key="bugId"
@finish="getDetailInfo()"
/>
<MsRichText
v-if="platformSystemFieldMap[key].type === 'RICH_TEXT'"
v-model:raw="form.platformSystemFields[key]"
v-model:filed-ids="descriptionFileIdMap[key]"
:upload-image="handleUploadImage"
:preview-url="`${EditorPreviewFileUrl}/${appStore.currentProjectId}`"
<MsButton
v-if="item.status !== 'init'"
type="button"
status="primary"
class="!mr-[4px]"
@click="downloadFile(item)"
>
{{ t('common.download') }}
</MsButton>
</div>
<!-- 关联文件 -->
<div v-else class="flex flex-nowrap">
<MsButton
v-if="item.status !== 'init' && item.file.type.includes('image')"
type="button"
status="primary"
class="!mr-[4px]"
@click="handlePreview(item)"
>
{{ t('ms.upload.preview') }}
</MsButton>
<MsButton v-if="bugId" type="button" status="primary" class="!mr-[4px]" @click="downloadFile(item)">
{{ t('common.download') }}
</MsButton>
<MsButton
v-if="bugId && item.isUpdateFlag"
type="button"
status="primary"
@click="handleUpdateFile(item)"
>
{{ t('common.update') }}
</MsButton>
</div>
</template>
<template #title="{ item }">
<span v-if="item.isUpdateFlag" class="ml-4 flex items-center font-normal text-[rgb(var(--warning-6))]"
><icon-exclamation-circle-fill /> <span>{{ t('caseManagement.featureCase.fileIsUpdated') }}</span>
</span>
</template>
</MsFileList>
</div>
<a-divider class="ml-[16px]" direction="vertical" />
<div class="right mt-[16px] w-[428px] grow pr-[24px]">
<div class="min-w-[250px] overflow-auto">
<a-skeleton v-if="isLoading" :loading="isLoading" :animation="true">
<a-space direction="vertical" class="w-full" size="large">
<a-skeleton-line :rows="12" :line-height="30" :line-spacing="30" />
</a-space>
</a-skeleton>
<a-form v-else :model="form" layout="vertical">
<div style="display: inline-block; width: 100%; word-wrap: break-word">
<MsFormCreate ref="formCreateRef" v-model:formItem="formItem" v-model:api="fApi" :form-rule="formRules" />
</div>
<a-form-item v-if="!isPlatformDefaultTemplate" field="tag" :label="t('bugManagement.tag')">
<MsTagsInput
v-model:model-value="form.tags"
:placeholder="t('bugManagement.edit.tagPlaceholder')"
allow-clear
/>
</a-form-item>
</div>
<a-form-item field="attachment">
<div class="flex flex-col">
<div class="mb-1">
<AddAttachment v-model:file-list="fileList" @change="handleChange" @link-file="associatedFile" />
</div>
</div>
</a-form-item>
<MsFileList
ref="fileListRef"
v-model:file-list="fileList"
:init-file-save-tips="t('ms.upload.waiting_save')"
mode="static"
>
<template #actions="{ item }">
<!-- 本地文件 -->
<div v-if="item.local || item.status === 'init'" class="flex flex-nowrap">
<MsButton
v-if="item.status !== 'init' && item.file.type.includes('image')"
type="button"
status="primary"
class="!mr-[4px]"
@click="handlePreview(item)"
>
{{ t('ms.upload.preview') }}
</MsButton>
<MsButton
v-if="item.status !== 'init'"
type="button"
status="primary"
class="!mr-[4px]"
@click="transferFile(item)"
>
{{ t('caseManagement.featureCase.storage') }}
</MsButton>
<SaveAsFilePopover
v-model:visible="transferVisible"
:saving-file="activeTransferFileParams"
:file-save-as-source-id="(form.id as string)"
:file-save-as-api="transferFileRequest"
:file-module-options-api="getTransferFileTree"
source-id-key="bugId"
@finish="getDetailInfo()"
/>
<MsButton
v-if="item.status !== 'init'"
type="button"
status="primary"
class="!mr-[4px]"
@click="downloadFile(item)"
>
{{ t('common.download') }}
</MsButton>
</div>
<!-- 关联文件 -->
<div v-else class="flex flex-nowrap">
<MsButton
v-if="item.status !== 'init' && item.file.type.includes('image')"
type="button"
status="primary"
class="!mr-[4px]"
@click="handlePreview(item)"
>
{{ t('ms.upload.preview') }}
</MsButton>
<MsButton v-if="bugId" type="button" status="primary" class="!mr-[4px]" @click="downloadFile(item)">
{{ t('common.download') }}
</MsButton>
<MsButton
v-if="bugId && item.isUpdateFlag"
type="button"
status="primary"
@click="handleUpdateFile(item)"
>
{{ t('common.update') }}
</MsButton>
</div>
</template>
<template #title="{ item }">
<span v-if="item.isUpdateFlag" class="ml-4 flex items-center font-normal text-[rgb(var(--warning-6))]"
><icon-exclamation-circle-fill /> <span>{{ t('caseManagement.featureCase.fileIsUpdated') }}</span>
</span>
</template>
</MsFileList>
</div>
<a-divider class="ml-[16px]" direction="vertical" />
<div class="right mt-[16px] w-[428px] grow pr-[24px]">
<div class="min-w-[250px] overflow-auto">
<a-skeleton v-if="isLoading" :loading="isLoading" :animation="true">
<a-space direction="vertical" class="w-full" size="large">
<a-skeleton-line :rows="12" :line-height="30" :line-spacing="30" />
</a-space>
</a-skeleton>
<a-form v-else :model="form" layout="vertical">
<div style="display: inline-block; width: 100%; word-wrap: break-word">
<MsFormCreate
ref="formCreateRef"
v-model:formItem="formItem"
v-model:api="fApi"
:form-rule="formRules"
/>
</div>
<a-form-item v-if="!isPlatformDefaultTemplate" field="tag" :label="t('bugManagement.tag')">
<MsTagsInput
v-model:model-value="form.tags"
:placeholder="t('bugManagement.edit.tagPlaceholder')"
allow-clear
/>
</a-form-item>
</a-form>
</div>
</a-form>
</div>
</div>
</a-form>
</MsCard>
</div>
</a-form>
<div>
<MsUpload
v-model:file-list="fileList"
@ -211,7 +187,6 @@
import { Message } from '@arco-design/web-vue';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsCard from '@/components/pure/ms-card/index.vue';
import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue';
import { FormItem, FormRuleItem } from '@/components/pure/ms-form-create/types';
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
@ -225,13 +200,11 @@
import {
checkFileIsUpdateRequest,
createOrUpdateBug,
downloadFileRequest,
editorUploadFile,
getAssociatedFileList,
getBugDetail,
getTemplateById,
getTemplateOption,
previewFile,
transferFileRequest,
updateFile,
@ -240,9 +213,6 @@
import { getModules, getModulesCount } from '@/api/modules/project-management/fileManagement';
import { EditorPreviewFileUrl } from '@/api/requrls/bug-management';
import { useI18n } from '@/hooks/useI18n';
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
import useVisit from '@/hooks/useVisit';
import router from '@/router';
import { useAppStore } from '@/store';
import useUserStore from '@/store/modules/user';
import { downloadByteFile } from '@/utils';
@ -260,24 +230,29 @@
import { TableQueryParams } from '@/models/common';
import { SelectValue } from '@/models/projectManagement/menuManagement';
import type { CustomField } from '@/models/setting/template';
import { BugManagementRouteEnum } from '@/enums/routeEnum';
import { convertToFile } from '../case-management/caseManagementFeature/components/utils';
import { convertToFileByBug } from './utils';
const props = defineProps<{
bugId?: string;
templateId: string;
}>();
const emit = defineEmits<{
(e: 'saveParams', isContinue: boolean, params: { request: BugEditFormObject; fileList: File[] }): void;
}>();
const innerTemplateId = defineModel<string>('templateId', {
required: true,
});
defineOptions({ name: 'BugEditPage' });
const { setIsSave } = useLeaveUnSaveTip();
setIsSave(false);
const { t } = useI18n();
interface TemplateOption {
label: string;
value: string;
}
const appStore = useAppStore();
const route = useRoute();
const templateOption = ref<TemplateOption[]>([]);
const form = ref<BugEditFormObject>({
projectId: appStore.currentProjectId,
title: '',
@ -314,7 +289,7 @@
const acceptType = ref('none'); // -
const userStore = useUserStore();
const isEdit = computed(() => !!route.query.id && route.params.mode === 'edit');
const bugId = computed(() => route.query.id || '');
const bugId = ref<string | undefined>(props.bugId);
const isEditOrCopy = computed(() => !!bugId.value);
const isCopy = computed(() => route.params.mode === 'copy');
const isPlatformDefaultTemplate = ref(false);
@ -324,15 +299,7 @@
const descriptionFileIds = ref<string[]>([]);
// -/ID
const descriptionFileIdMap = ref<Record<string, string[]>>({});
const visitedKey = 'doNotNextTipCreateBug';
const { getIsVisited } = useVisit(visitedKey);
const title = computed(() => {
if (isCopy.value) {
return t('bugManagement.copyBug');
}
return isEdit.value ? t('bugManagement.editBug') : t('bugManagement.createBug');
});
const isLoading = ref<boolean>(true);
const rowLength = ref<number>(0);
@ -462,29 +429,6 @@
}
};
const getTemplateOptions = async () => {
try {
loading.value = true;
const res = await getTemplateOption(appStore.currentProjectId);
templateOption.value = res.map((item) => {
if (item.enableDefault && !isEdit.value) {
//
form.value.templateId = item.id;
templateChange(item.id);
}
return {
label: item.name,
value: item.id,
};
});
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
loading.value = false;
}
};
//
async function handlePreview(item: MsFileItem) {
try {
@ -568,120 +512,94 @@
return fileIds;
}
function makeParams() {
//
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,
type: item.sourceType as string,
value: Array.isArray(item.value) ? JSON.stringify(item.value) : (item.value as string),
});
});
}
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 }[] = [];
if (copyFileList.length > 0) {
copyFiles = copyFileList.map((file) => {
return {
refId: file.associateId,
fileId: file.uid,
local: file.local,
bugId: bugId.value as string,
fileName: file.name,
};
});
}
const tmpObj: BugEditFormObject = {
...form.value,
customFields,
copyFiles,
richTextTmpFileIds: isPlatformDefaultTemplate.value ? getDescriptionFileId() : descriptionFileIds.value,
};
if (isCopy.value) {
delete tmpObj.id;
delete tmpObj.richTextTmpFileIds;
}
//
const localFiles = fileList.value.filter((item) => item.local && item.status === 'init');
return {
request: tmpObj,
fileList: localFiles as unknown as File[],
};
}
async function resetForm() {
//
const { templateId } = form.value;
//
form.value = {
projectId: appStore.currentProjectId, // id
title: '',
description: '',
templateId,
tags: [],
platformSystemFields: {},
};
await templateChange(templateId);
//
fileList.value = [];
}
//
const saveHandler = async (isContinue = false) => {
formRef.value.validate((error: any) => {
if (!error) {
fApi.value.validate(async (valid: any) => {
if (valid === true) {
try {
loading.value = true;
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,
type: item.sourceType as string,
value: Array.isArray(item.value) ? JSON.stringify(item.value) : (item.value as string),
});
});
}
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 }[] = [];
if (copyFileList.length > 0) {
copyFiles = copyFileList.map((file) => {
return {
refId: file.associateId,
fileId: file.uid,
local: file.local,
bugId: bugId.value as string,
fileName: file.name,
};
});
}
const tmpObj: BugEditFormObject = {
...form.value,
customFields,
copyFiles,
richTextTmpFileIds: isPlatformDefaultTemplate.value ? getDescriptionFileId() : descriptionFileIds.value,
};
if (isCopy.value) {
delete tmpObj.id;
delete tmpObj.richTextTmpFileIds;
}
//
const localFiles = fileList.value.filter((item) => item.local && item.status === 'init');
//
const res = await createOrUpdateBug({ request: tmpObj, fileList: localFiles as unknown as File[] });
if (isEdit.value) {
setIsSave(true);
Message.success(t('common.updateSuccess'));
router.push({
name: BugManagementRouteEnum.BUG_MANAGEMENT_INDEX,
});
} else {
Message.success(t('common.createSuccess'));
if (isContinue) {
setIsSave(false);
//
const { templateId } = form.value;
//
form.value = {
projectId: appStore.currentProjectId, // id
title: '',
description: '',
templateId,
tags: [],
platformSystemFields: {},
};
await templateChange(templateId);
//
fileList.value = [];
} else {
setIsSave(true);
//
if (getIsVisited()) {
router.push({
name: BugManagementRouteEnum.BUG_MANAGEMENT_INDEX,
});
return;
}
router.push({
name: BugManagementRouteEnum.BUG_MANAGEMENT_CREATE_SUCCESS,
query: {
...route.query,
id: res.data.id,
},
});
}
}
} catch (err) {
// eslint-disable-next-line no-console
console.log(err);
} finally {
loading.value = false;
}
emit('saveParams', isContinue, makeParams());
}
});
}
@ -812,10 +730,6 @@
loading.value = false;
};
const initDefaultFields = async () => {
await getTemplateOptions();
};
// formCreate
watch(
() => formRules.value,
@ -846,12 +760,29 @@
return data;
}
onMounted(async () => {
await initDefaultFields();
if (isEditOrCopy.value) {
//
await getDetailInfo();
watch(
() => innerTemplateId.value,
(val) => {
if (val) {
form.value.templateId = val;
templateChange(val);
}
},
{
immediate: true,
}
);
onMounted(() => {
if (isEditOrCopy.value) {
//
getDetailInfo();
}
});
defineExpose({
saveHandler,
resetForm,
});
</script>

View File

@ -18,7 +18,8 @@
@loaded="loadedCase"
>
<template #titleName>
<div :class="`case-title flex items-center ${isEditTitle ? 'w-full' : ''}`">
<div :class="`case-title flex items-center gap-[8px] ${isEditTitle ? 'w-full' : ''}`">
<div v-if="!isEditTitle" class="flex items-center"><caseLevel :case-level="caseLevels" /></div>
<a-input
v-if="isEditTitle"
v-model="titleName"
@ -30,7 +31,7 @@
@keydown.enter="handleEditName"
/>
<div v-else class="flex items-center">
<div> {{ detailInfo?.num }} </div>
<div> [ {{ detailInfo?.num }} ] </div>
<div
:class="`${
hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE']) ? 'hover-title-name' : ''
@ -41,9 +42,6 @@
</div>
</div>
</template>
<template #titleLeft>
<div v-if="!isEditTitle" class="flex items-center"><caseLevel :case-level="caseLevels" /></div>
</template>
<template #titleRight="{ loading }">
<div class="rightButtons flex items-center">
<MsButton

View File

@ -1,7 +1,23 @@
<template>
<div>
<div class="flex items-center justify-between">
<div v-if="showType === 'link'" class="flex">
<div class="mb-[16px] flex items-center justify-between">
<div>
<a-radio-group v-model:model-value="showType" type="button" size="medium">
<a-radio value="link">{{ t('caseManagement.featureCase.directLink') }}</a-radio>
<a-radio value="testPlan">{{ t('caseManagement.featureCase.testPlan') }}</a-radio>
</a-radio-group>
<a-input-search
v-model:model-value="keyword"
:placeholder="t('caseManagement.featureCase.searchByName')"
allow-clear
class="mx-[8px] w-[240px]"
@search="getFetch"
@press-enter="getFetch"
@clear="resetFetch"
@input="changeHandler"
></a-input-search>
</div>
<div v-if="showType === 'link'" class="flex items-center">
<a-tooltip v-if="!total">
<template #content>
{{ t('caseManagement.featureCase.noAssociatedDefect') }}
@ -32,29 +48,6 @@
>{{ t('testPlan.featureCase.noBugDataNewBug') }}
</a-button>
</div>
<div v-else v-permission="['FUNCTIONAL_CASE:READ+UPDATE']" class="font-medium">{{
t('caseManagement.featureCase.testPlanLinkList')
}}</div>
<div class="mb-4">
<a-radio-group v-model:model-value="showType" type="button" class="file-show-type ml-[4px]">
<a-radio value="link" class="show-type-icon p-[2px]">{{
t('caseManagement.featureCase.directLink')
}}</a-radio>
<a-radio value="testPlan" class="show-type-icon p-[2px]">{{
t('caseManagement.featureCase.testPlan')
}}</a-radio>
</a-radio-group>
<a-input-search
v-model:model-value="keyword"
:placeholder="t('caseManagement.featureCase.searchByName')"
allow-clear
class="mx-[8px] w-[240px]"
@search="getFetch"
@press-enter="getFetch"
@clear="resetFetch"
@input="changeHandler"
></a-input-search>
</div>
</div>
<BugList
v-if="showType === 'link'"