refactor: 重构缺陷管理&用例管理详情页面展示
This commit is contained in:
parent
fec6cfce98
commit
12e3eae473
|
@ -222,8 +222,8 @@ export interface CaseModuleQueryParams extends TableQueryParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TabItemType {
|
export interface TabItemType {
|
||||||
key: string;
|
value: string;
|
||||||
title: string;
|
label: string;
|
||||||
canHide: boolean;
|
canHide: boolean;
|
||||||
isShow: boolean;
|
isShow: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,14 +96,22 @@
|
||||||
:class="[
|
:class="[
|
||||||
`${
|
`${
|
||||||
activeTab === 'comment' && hasAnyPermission(['PROJECT_BUG:READ+COMMENT']) && !commentInputIsActive
|
activeTab === 'comment' && hasAnyPermission(['PROJECT_BUG:READ+COMMENT']) && !commentInputIsActive
|
||||||
? 'h-[calc(100%-72px)]'
|
? 'h-[calc(100%-118px)]'
|
||||||
: commentInputIsActive
|
: commentInputIsActive
|
||||||
? 'h-[calc(100%-286px)]'
|
? 'h-[calc(100%-338px)]'
|
||||||
: 'h-full'
|
: 'h-full'
|
||||||
}`,
|
}`,
|
||||||
'bg-white',
|
'bg-white',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
|
<div class="header relative h-[48px] pl-2">
|
||||||
|
<MsTab
|
||||||
|
v-model:active-key="activeTab"
|
||||||
|
:content-tab-list="contentTabList"
|
||||||
|
:get-text-func="getTabBadge"
|
||||||
|
class="no-content relative border-b"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<MsSplitBox
|
<MsSplitBox
|
||||||
expand-direction="right"
|
expand-direction="right"
|
||||||
:size="0.8"
|
:size="0.8"
|
||||||
|
@ -115,15 +123,7 @@
|
||||||
<template #first>
|
<template #first>
|
||||||
<div class="leftWrapper h-full">
|
<div class="leftWrapper h-full">
|
||||||
<a-spin :loading="detailLoading" class="w-full">
|
<a-spin :loading="detailLoading" class="w-full">
|
||||||
<div class="header h-[50px]">
|
<div class="tab-pane-container p-4">
|
||||||
<MsTab
|
|
||||||
v-model:active-key="activeTab"
|
|
||||||
:content-tab-list="contentTabList"
|
|
||||||
:get-text-func="getTabBadge"
|
|
||||||
class="no-content relative mb-[8px]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane-container">
|
|
||||||
<BugDetailTab
|
<BugDetailTab
|
||||||
v-if="activeTab === 'detail'"
|
v-if="activeTab === 'detail'"
|
||||||
ref="bugDetailTabRef"
|
ref="bugDetailTabRef"
|
||||||
|
@ -150,65 +150,65 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #second>
|
<template #second>
|
||||||
<!-- <a-spin :loading="rightLoading" class="w-full"> -->
|
<a-spin :loading="rightLoading" class="w-full">
|
||||||
<!-- 所属平台一致, 详情展示 -->
|
<!-- 所属平台一致, 详情展示 -->
|
||||||
<div v-if="props.currentPlatform === detailInfo.platform" class="rightWrapper h-full p-[24px]">
|
<div v-if="props.currentPlatform === detailInfo.platform" class="rightWrapper h-full p-4">
|
||||||
<!-- 自定义字段开始 -->
|
<!-- 自定义字段开始 -->
|
||||||
<div class="inline-block w-full break-words">
|
<div class="inline-block w-full break-words">
|
||||||
<a-skeleton v-if="rightLoading" class="w-full" :loading="rightLoading" :animation="true">
|
<a-skeleton v-if="rightLoading" class="w-full" :loading="rightLoading" :animation="true">
|
||||||
<a-space direction="vertical" class="w-[100%]" size="large">
|
<a-space direction="vertical" class="w-[100%]" size="large">
|
||||||
<a-skeleton-line :rows="14" :line-height="30" :line-spacing="30" />
|
<a-skeleton-line :rows="14" :line-height="30" :line-spacing="30" />
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-skeleton>
|
</a-skeleton>
|
||||||
<div v-if="!rightLoading" class="mb-4 font-medium">
|
<div v-if="!rightLoading" class="mb-4 font-medium">
|
||||||
<strong>
|
<strong>
|
||||||
{{ t('bugManagement.detail.basicInfo') }}
|
{{ t('bugManagement.detail.basicInfo') }}
|
||||||
</strong>
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
<MsFormCreate
|
<MsFormCreate
|
||||||
v-if="!rightLoading"
|
v-if="!rightLoading"
|
||||||
ref="formCreateRef"
|
ref="formCreateRef"
|
||||||
v-model:form-item="formItem"
|
v-model:form-item="formItem"
|
||||||
v-model:api="fApi"
|
v-model:api="fApi"
|
||||||
:form-rule="formRules"
|
:form-rule="formRules"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:option="options"
|
:option="options"
|
||||||
@change="handelFormCreateChange"
|
@change="handelFormCreateChange"
|
||||||
/>
|
/>
|
||||||
<!-- 自定义字段结束 -->
|
<!-- 自定义字段结束 -->
|
||||||
<div
|
<div
|
||||||
v-if="!isPlatformDefaultTemplate && hasAnyPermission(['PROJECT_BUG:READ+UPDATE']) && !loading"
|
v-if="!isPlatformDefaultTemplate && hasAnyPermission(['PROJECT_BUG:READ+UPDATE']) && !loading"
|
||||||
class="baseItem"
|
class="baseItem"
|
||||||
>
|
|
||||||
<a-form
|
|
||||||
:model="{}"
|
|
||||||
:label-col-props="{
|
|
||||||
span: 9,
|
|
||||||
}"
|
|
||||||
:wrapper-col-props="{
|
|
||||||
span: 15,
|
|
||||||
}"
|
|
||||||
label-align="left"
|
|
||||||
content-class="tags-class"
|
|
||||||
>
|
>
|
||||||
<a-form-item field="tags" :label="t('system.orgTemplate.tags')">
|
<a-form
|
||||||
<MsTagsInput
|
:model="{}"
|
||||||
v-model:model-value="tags"
|
:label-col-props="{
|
||||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])"
|
span: 9,
|
||||||
@blur="changeTag"
|
}"
|
||||||
/>
|
:wrapper-col-props="{
|
||||||
</a-form-item>
|
span: 15,
|
||||||
</a-form>
|
}"
|
||||||
|
label-align="left"
|
||||||
|
content-class="tags-class"
|
||||||
|
>
|
||||||
|
<a-form-item field="tags" :label="t('system.orgTemplate.tags')">
|
||||||
|
<MsTagsInput
|
||||||
|
v-model:model-value="tags"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])"
|
||||||
|
@blur="changeTag"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 内置基础信息结束 -->
|
<!-- 内置基础信息结束 -->
|
||||||
</div>
|
</div>
|
||||||
<!-- 所属平台不一致, 详情不展示, 展示空面板 -->
|
<!-- 所属平台不一致, 详情不展示, 展示空面板 -->
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<a-empty> {{ $t('messageBox.noContent') }} </a-empty>
|
<a-empty> {{ $t('messageBox.noContent') }} </a-empty>
|
||||||
</div>
|
</div>
|
||||||
<!-- </a-spin> -->
|
</a-spin>
|
||||||
</template>
|
</template>
|
||||||
</MsSplitBox>
|
</MsSplitBox>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,89 +1,87 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="p-4">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<div class="flex items-center justify-between">
|
<a-button type="primary" :disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])" @click="handleSelect">{{
|
||||||
<a-button type="primary" :disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])" @click="handleSelect">{{
|
t('caseManagement.featureCase.linkCase')
|
||||||
t('caseManagement.featureCase.linkCase')
|
}}</a-button>
|
||||||
}}</a-button>
|
<a-input-search
|
||||||
<a-input-search
|
v-model:model-value="keyword"
|
||||||
v-model:model-value="keyword"
|
:placeholder="t('caseManagement.featureCase.searchByIdAndName')"
|
||||||
:placeholder="t('caseManagement.featureCase.searchByIdAndName')"
|
allow-clear
|
||||||
allow-clear
|
class="mx-[8px] w-[240px]"
|
||||||
class="mx-[8px] w-[240px]"
|
@search="searchCase"
|
||||||
@search="searchCase"
|
@press-enter="searchCase"
|
||||||
@press-enter="searchCase"
|
></a-input-search>
|
||||||
></a-input-search>
|
|
||||||
</div>
|
|
||||||
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
|
||||||
<template #relateCaseNum="{ record }">
|
|
||||||
<a-tooltip :content="`${record.relateCaseNum}`">
|
|
||||||
<!-- TOTO 暂时没有用例id的字段 需要后台加caseId -->
|
|
||||||
<a-button type="text" class="px-0" @click="openDetail(record.relateCaseId)">
|
|
||||||
<div class="one-line-text max-w-[168px]">{{ record.relateCaseNum }}</div>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
<template #defectName="{ record }">
|
|
||||||
<span class="one-line-text max-w[300px]"> {{ record.relateCaseName }}</span
|
|
||||||
><span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span>
|
|
||||||
</template>
|
|
||||||
<template #operation="{ record }">
|
|
||||||
<MsButton :disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])" @click="cancelLink(record)">{{
|
|
||||||
t('caseManagement.featureCase.cancelLink')
|
|
||||||
}}</MsButton>
|
|
||||||
</template>
|
|
||||||
<template v-if="(keyword || '').trim() === ''" #empty>
|
|
||||||
<div class="flex w-full items-center justify-center text-[var(--color-text-4)]">
|
|
||||||
{{ t('caseManagement.caseReview.tableNoData') }}
|
|
||||||
<MsButton class="ml-[8px]" :disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])" @click="handleSelect">
|
|
||||||
{{ t('caseManagement.featureCase.linkCase') }}
|
|
||||||
</MsButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #relatePlanTitle>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="font-medium text-[var(--color-text-3)]">
|
|
||||||
{{ t('bugManagement.detail.isPlanRelateCase') }}
|
|
||||||
</div>
|
|
||||||
<a-popover position="rt">
|
|
||||||
<icon-question-circle
|
|
||||||
class="ml-[4px] text-[var(--color-text-3)] hover:text-[rgb(var(--primary-5))]"
|
|
||||||
size="16"
|
|
||||||
/>
|
|
||||||
<template #title>
|
|
||||||
<div class="w-[300px]"> {{ t('bugManagement.detail.isPlanRelateCaseTip1') }} </div>
|
|
||||||
<br />
|
|
||||||
<div class="w-[300px]"> {{ t('bugManagement.detail.isPlanRelateCaseTip2') }} </div>
|
|
||||||
<br />
|
|
||||||
<div class="w-[300px]"> {{ t('bugManagement.detail.isPlanRelateCaseTip3') }} </div>
|
|
||||||
</template>
|
|
||||||
</a-popover>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #isRelatePlanCase="{ record }">
|
|
||||||
<span class="text-[var(--color-text-1)]">{{ record.isRelatePlanCase ? t('common.yes') : t('common.no') }}</span>
|
|
||||||
</template>
|
|
||||||
</ms-base-table>
|
|
||||||
<MsCaseAssociate
|
|
||||||
v-model:visible="innerVisible"
|
|
||||||
v-model:project-id="innerProject"
|
|
||||||
v-model:currentSelectCase="currentSelectCase"
|
|
||||||
:ok-button-disabled="associateForm.reviewers.length === 0"
|
|
||||||
:get-modules-func="getModuleTree"
|
|
||||||
:modules-params="modulesTreeParams"
|
|
||||||
:get-table-func="getUnAssociatedList"
|
|
||||||
:table-params="getTableParams"
|
|
||||||
:modules-count="modulesCount"
|
|
||||||
:module-options="caseTypeOptions"
|
|
||||||
:confirm-loading="confirmLoading"
|
|
||||||
:case-id="props.bugId"
|
|
||||||
:associated-ids="associatedIds"
|
|
||||||
:type="RequestModuleEnum.BUG_MANAGEMENT"
|
|
||||||
:is-hidden-case-level="true"
|
|
||||||
@close="emit('close')"
|
|
||||||
@save="saveHandler"
|
|
||||||
>
|
|
||||||
</MsCaseAssociate>
|
|
||||||
</div>
|
</div>
|
||||||
|
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
||||||
|
<template #relateCaseNum="{ record }">
|
||||||
|
<a-tooltip :content="`${record.relateCaseNum}`">
|
||||||
|
<!-- TOTO 暂时没有用例id的字段 需要后台加caseId -->
|
||||||
|
<a-button type="text" class="px-0" @click="openDetail(record.relateCaseId)">
|
||||||
|
<div class="one-line-text max-w-[168px]">{{ record.relateCaseNum }}</div>
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template #defectName="{ record }">
|
||||||
|
<span class="one-line-text max-w[300px]"> {{ record.relateCaseName }}</span
|
||||||
|
><span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<MsButton :disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])" @click="cancelLink(record)">{{
|
||||||
|
t('caseManagement.featureCase.cancelLink')
|
||||||
|
}}</MsButton>
|
||||||
|
</template>
|
||||||
|
<template v-if="(keyword || '').trim() === ''" #empty>
|
||||||
|
<div class="flex w-full items-center justify-center text-[var(--color-text-4)]">
|
||||||
|
{{ t('caseManagement.caseReview.tableNoData') }}
|
||||||
|
<MsButton class="ml-[8px]" :disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])" @click="handleSelect">
|
||||||
|
{{ t('caseManagement.featureCase.linkCase') }}
|
||||||
|
</MsButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #relatePlanTitle>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="font-medium text-[var(--color-text-3)]">
|
||||||
|
{{ t('bugManagement.detail.isPlanRelateCase') }}
|
||||||
|
</div>
|
||||||
|
<a-popover position="rt">
|
||||||
|
<icon-question-circle
|
||||||
|
class="ml-[4px] text-[var(--color-text-3)] hover:text-[rgb(var(--primary-5))]"
|
||||||
|
size="16"
|
||||||
|
/>
|
||||||
|
<template #title>
|
||||||
|
<div class="w-[300px]"> {{ t('bugManagement.detail.isPlanRelateCaseTip1') }} </div>
|
||||||
|
<br />
|
||||||
|
<div class="w-[300px]"> {{ t('bugManagement.detail.isPlanRelateCaseTip2') }} </div>
|
||||||
|
<br />
|
||||||
|
<div class="w-[300px]"> {{ t('bugManagement.detail.isPlanRelateCaseTip3') }} </div>
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #isRelatePlanCase="{ record }">
|
||||||
|
<span class="text-[var(--color-text-1)]">{{ record.isRelatePlanCase ? t('common.yes') : t('common.no') }}</span>
|
||||||
|
</template>
|
||||||
|
</ms-base-table>
|
||||||
|
<MsCaseAssociate
|
||||||
|
v-model:visible="innerVisible"
|
||||||
|
v-model:project-id="innerProject"
|
||||||
|
v-model:currentSelectCase="currentSelectCase"
|
||||||
|
:ok-button-disabled="associateForm.reviewers.length === 0"
|
||||||
|
:get-modules-func="getModuleTree"
|
||||||
|
:modules-params="modulesTreeParams"
|
||||||
|
:get-table-func="getUnAssociatedList"
|
||||||
|
:table-params="getTableParams"
|
||||||
|
:modules-count="modulesCount"
|
||||||
|
:module-options="caseTypeOptions"
|
||||||
|
:confirm-loading="confirmLoading"
|
||||||
|
:case-id="props.bugId"
|
||||||
|
:associated-ids="associatedIds"
|
||||||
|
:type="RequestModuleEnum.BUG_MANAGEMENT"
|
||||||
|
:is-hidden-case-level="true"
|
||||||
|
@close="emit('close')"
|
||||||
|
@save="saveHandler"
|
||||||
|
>
|
||||||
|
</MsCaseAssociate>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- 所属平台一致, 详情展示 -->
|
<!-- 所属平台一致, 详情展示 -->
|
||||||
<div v-if="props.currentPlatform === props.detailInfo.platform" class="relative p-[16px] pb-[16px]">
|
<div v-if="props.currentPlatform === props.detailInfo.platform" class="relative">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div v-permission="['PROJECT_BUG:READ+UPDATE']" class="header-action">
|
<div v-permission="['PROJECT_BUG:READ+UPDATE']" class="header-action">
|
||||||
<a-button type="text" @click="contentEditAble = !contentEditAble">
|
<a-button type="text" @click="contentEditAble = !contentEditAble">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<ms-base-table class="mt-[16px]" v-bind="propsRes" v-on="propsEvent">
|
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
||||||
<template #changeNumber="{ record }">
|
<template #changeNumber="{ record }">
|
||||||
<span>{{ record.id }}</span>
|
<span>{{ record.id }}</span>
|
||||||
<MsTag v-if="record.latest" size="small" class="ml-2">{{ t('bugManagement.history.current') }}</MsTag>
|
<MsTag v-if="record.latest" size="small" class="ml-2">{{ t('bugManagement.history.current') }}</MsTag>
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="pl-2 pt-4">
|
<div>
|
||||||
<a-scrollbar
|
<MsEmpty v-if="commentList.length === 0" />
|
||||||
:style="{
|
<MsComment
|
||||||
overflow: 'auto',
|
v-else
|
||||||
height: 'calc(100vh - 236px)',
|
:preview-url="EditorPreviewFileUrl"
|
||||||
width: '100%',
|
:comment-list="commentList"
|
||||||
}"
|
:upload-image="handleUploadImage"
|
||||||
>
|
@delete="handleDelete"
|
||||||
<MsEmpty v-if="commentList.length === 0" />
|
@update-or-add="handleUpdate"
|
||||||
<MsComment
|
/>
|
||||||
v-else
|
|
||||||
:preview-url="EditorPreviewFileUrl"
|
|
||||||
:comment-list="commentList"
|
|
||||||
:upload-image="handleUploadImage"
|
|
||||||
@delete="handleDelete"
|
|
||||||
@update-or-add="handleUpdate"
|
|
||||||
/>
|
|
||||||
</a-scrollbar>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -90,79 +90,63 @@
|
||||||
<template #default="{ loading }">
|
<template #default="{ loading }">
|
||||||
<div
|
<div
|
||||||
ref="wrapperRef"
|
ref="wrapperRef"
|
||||||
:class="[`${!commentInputIsActive ? 'h-[calc(100%-72px)]' : 'h-[calc(100%-286px)]'}`, 'bg-white']"
|
:class="[`${!commentInputIsActive ? 'h-[calc(100%-118px)]' : 'h-[calc(100%-338px)]'}`, 'bg-white']"
|
||||||
>
|
>
|
||||||
|
<div class="header relative h-[48px] pl-2">
|
||||||
|
<MsTab
|
||||||
|
v-model:active-key="activeTab"
|
||||||
|
:content-tab-list="tabSetting"
|
||||||
|
:get-text-func="getTotal"
|
||||||
|
class="no-content relative border-b"
|
||||||
|
@change="clickMenu"
|
||||||
|
/>
|
||||||
|
<span class="absolute bottom-0 right-4 top-4 my-auto text-[var(--color-text-2)]" @click="showMenuSetting">{{
|
||||||
|
t('caseManagement.featureCase.detailDisplaySetting')
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
<MsSplitBox :size="0.8" :max="0.7" :min="0.6" direction="horizontal" expand-direction="right">
|
<MsSplitBox :size="0.8" :max="0.7" :min="0.6" direction="horizontal" expand-direction="right">
|
||||||
<template #first>
|
<template #first>
|
||||||
<div class="leftWrapper h-full">
|
<div class="leftWrapper h-full">
|
||||||
<div class="header h-[50px]">
|
<div class="leftContent mt-4 w-full pl-[16px] pr-[24px]">
|
||||||
<a-menu mode="horizontal" :default-selected-keys="[activeTab || 'detail']" @menu-item-click="clickMenu">
|
<template v-if="activeTab === 'detail'">
|
||||||
<a-menu-item v-for="tab of tabSetting" :key="tab.key">
|
<TabDetail
|
||||||
<div class="flex items-center">
|
ref="tabDetailRef"
|
||||||
<span>{{ t(tab.title) }}</span>
|
:form="detailInfo"
|
||||||
<a-badge
|
:allow-edit="true"
|
||||||
v-if="getTotal(tab.key)"
|
:form-rules="formItem"
|
||||||
class="ml-1"
|
:form-api="fApi"
|
||||||
:class="activeTab === tab.key ? 'active' : ''"
|
@update-success="updateSuccess"
|
||||||
:text="getTotal(tab.key)"
|
/>
|
||||||
/> </div
|
</template>
|
||||||
></a-menu-item>
|
<template v-if="activeTab === 'requirement'">
|
||||||
<a-menu-item key="setting">
|
<TabDemand :case-id="props.detailId" />
|
||||||
<span @click="showMenuSetting">{{
|
</template>
|
||||||
t('caseManagement.featureCase.detailDisplaySetting')
|
<template v-if="activeTab === 'case'">
|
||||||
}}</span></a-menu-item
|
<TabCaseTable :case-id="props.detailId" />
|
||||||
>
|
</template>
|
||||||
</a-menu>
|
<template v-if="activeTab === 'bug'">
|
||||||
|
<TabDefect :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'dependency'">
|
||||||
|
<TabDependency :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'caseReview'">
|
||||||
|
<TabCaseReview :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'testPlan'">
|
||||||
|
<TabTestPlan />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'comments'">
|
||||||
|
<TabComment ref="commentRef" :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
|
<template v-if="activeTab === 'changeHistory'">
|
||||||
|
<TabChangeHistory :case-id="props.detailId" />
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<keep-alive>
|
|
||||||
<div class="leftContent mt-4 w-full px-[24px]">
|
|
||||||
<a-scrollbar
|
|
||||||
:style="{
|
|
||||||
overflow: 'auto',
|
|
||||||
height: 'calc(100vh - 190px)',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template v-if="activeTab === 'detail'">
|
|
||||||
<TabDetail
|
|
||||||
ref="tabDetailRef"
|
|
||||||
:form="detailInfo"
|
|
||||||
:allow-edit="true"
|
|
||||||
:form-rules="formItem"
|
|
||||||
:form-api="fApi"
|
|
||||||
@update-success="updateSuccess"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-if="activeTab === 'requirement'">
|
|
||||||
<TabDemand :case-id="props.detailId" />
|
|
||||||
</template>
|
|
||||||
<template v-if="activeTab === 'case'">
|
|
||||||
<TabCaseTable :case-id="props.detailId" />
|
|
||||||
</template>
|
|
||||||
<template v-if="activeTab === 'bug'">
|
|
||||||
<TabDefect :case-id="props.detailId" />
|
|
||||||
</template>
|
|
||||||
<template v-if="activeTab === 'dependency'">
|
|
||||||
<TabDependency :case-id="props.detailId" />
|
|
||||||
</template>
|
|
||||||
<template v-if="activeTab === 'caseReview'">
|
|
||||||
<TabCaseReview :case-id="props.detailId" />
|
|
||||||
</template>
|
|
||||||
<template v-if="activeTab === 'testPlan'">
|
|
||||||
<TabTestPlan />
|
|
||||||
</template>
|
|
||||||
<template v-if="activeTab === 'comments'">
|
|
||||||
<TabComment ref="commentRef" :case-id="props.detailId" />
|
|
||||||
</template>
|
|
||||||
<template v-if="activeTab === 'changeHistory'">
|
|
||||||
<TabChangeHistory :case-id="props.detailId" />
|
|
||||||
</template>
|
|
||||||
</a-scrollbar>
|
|
||||||
</div>
|
|
||||||
</keep-alive>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #second>
|
<template #second>
|
||||||
<div class="rightWrapper h-full p-[24px]">
|
<div class="rightWrapper h-full p-4">
|
||||||
<a-skeleton v-if="loading" class="w-full" :loading="loading" :animation="true">
|
<a-skeleton v-if="loading" class="w-full" :loading="loading" :animation="true">
|
||||||
<a-space direction="vertical" class="w-[100%]" size="large">
|
<a-space direction="vertical" class="w-[100%]" size="large">
|
||||||
<a-skeleton-line :rows="14" :line-height="30" :line-spacing="30" />
|
<a-skeleton-line :rows="14" :line-height="30" :line-spacing="30" />
|
||||||
|
@ -263,6 +247,7 @@
|
||||||
import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue';
|
import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue';
|
||||||
import type { FormItem, FormRuleItem } from '@/components/pure/ms-form-create/types';
|
import type { FormItem, FormRuleItem } from '@/components/pure/ms-form-create/types';
|
||||||
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
||||||
|
import MsTab from '@/components/pure/ms-tab/index.vue';
|
||||||
import type { MsPaginationI } from '@/components/pure/ms-table/type';
|
import type { MsPaginationI } from '@/components/pure/ms-table/type';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
||||||
|
@ -347,8 +332,9 @@
|
||||||
|
|
||||||
// const tabSetting = ref<TabItemType[]>([...tabSettingList.value]);
|
// const tabSetting = ref<TabItemType[]>([...tabSettingList.value]);
|
||||||
const tabSetting = ref<TabItemType[]>([]);
|
const tabSetting = ref<TabItemType[]>([]);
|
||||||
const activeTab = ref<string | number>('detail');
|
const activeTab = ref<string>('detail');
|
||||||
function clickMenu(key: string | number) {
|
|
||||||
|
function clickMenu(key: string) {
|
||||||
activeTab.value = key;
|
activeTab.value = key;
|
||||||
featureCaseStore.setActiveTab(key);
|
featureCaseStore.setActiveTab(key);
|
||||||
switch (activeTab.value) {
|
switch (activeTab.value) {
|
||||||
|
@ -642,39 +628,38 @@
|
||||||
|
|
||||||
const tabDefaultSettingList: TabItemType[] = [
|
const tabDefaultSettingList: TabItemType[] = [
|
||||||
{
|
{
|
||||||
key: 'detail',
|
value: 'detail',
|
||||||
title: 'caseManagement.featureCase.detail',
|
label: t('caseManagement.featureCase.detail'),
|
||||||
canHide: false,
|
canHide: false,
|
||||||
isShow: true,
|
isShow: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'case',
|
value: 'case',
|
||||||
title: 'caseManagement.featureCase.case',
|
label: t('caseManagement.featureCase.case'),
|
||||||
canHide: true,
|
|
||||||
|
|
||||||
isShow: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'dependency',
|
|
||||||
title: 'caseManagement.featureCase.dependency',
|
|
||||||
canHide: true,
|
canHide: true,
|
||||||
isShow: true,
|
isShow: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'caseReview',
|
value: 'dependency',
|
||||||
title: 'caseManagement.featureCase.caseReview',
|
label: t('caseManagement.featureCase.dependency'),
|
||||||
canHide: true,
|
canHide: true,
|
||||||
isShow: true,
|
isShow: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'comments',
|
value: 'caseReview',
|
||||||
title: 'caseManagement.featureCase.comments',
|
label: t('caseManagement.featureCase.caseReview'),
|
||||||
canHide: true,
|
canHide: true,
|
||||||
isShow: true,
|
isShow: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'changeHistory',
|
value: 'comments',
|
||||||
title: 'caseManagement.featureCase.changeHistory',
|
label: t('caseManagement.featureCase.comments'),
|
||||||
|
canHide: true,
|
||||||
|
isShow: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'changeHistory',
|
||||||
|
label: t('caseManagement.featureCase.changeHistory'),
|
||||||
canHide: true,
|
canHide: true,
|
||||||
isShow: true,
|
isShow: true,
|
||||||
},
|
},
|
||||||
|
@ -683,14 +668,14 @@
|
||||||
const moduleTabMap: Record<string, TabItemType[]> = {
|
const moduleTabMap: Record<string, TabItemType[]> = {
|
||||||
bugManagement: [
|
bugManagement: [
|
||||||
{
|
{
|
||||||
key: 'requirement',
|
value: 'requirement',
|
||||||
title: 'caseManagement.featureCase.requirement',
|
label: t('caseManagement.featureCase.requirement'),
|
||||||
canHide: true,
|
canHide: true,
|
||||||
isShow: true,
|
isShow: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'bug',
|
value: 'bug',
|
||||||
title: 'caseManagement.featureCase.bug',
|
label: t('caseManagement.featureCase.bug'),
|
||||||
canHide: true,
|
canHide: true,
|
||||||
isShow: true,
|
isShow: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -400,7 +400,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { Message, TableChangeExtra, TableColumnData, TableData } from '@arco-design/web-vue';
|
import { Message, TableChangeExtra, TableData } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import { CustomTypeMaps, MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
|
import { CustomTypeMaps, MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
|
||||||
import { FilterFormItem, FilterResult, FilterType } from '@/components/pure/ms-advance-filter/type';
|
import { FilterFormItem, FilterResult, FilterType } from '@/components/pure/ms-advance-filter/type';
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
|
|
||||||
<div class="ms-table-column-seletor">
|
<div class="ms-table-column-seletor">
|
||||||
<div class="flex-col">
|
<div class="flex-col">
|
||||||
<div v-for="item in nonCloseColumn" :key="item.key" class="column-item">
|
<div v-for="item in nonCloseColumn" :key="item.value" class="column-item">
|
||||||
<div>{{ t(item.title) }}</div>
|
<div>{{ t(item.label) }}</div>
|
||||||
<a-switch v-model="item.isShow" disabled size="small" type="line" @change="handleSwitchChange" />
|
<a-switch v-model="item.isShow" disabled size="small" type="line" @change="handleSwitchChange" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,26 +41,15 @@
|
||||||
t('project.environmental.nonClose')
|
t('project.environmental.nonClose')
|
||||||
}}</span></a-divider
|
}}</span></a-divider
|
||||||
>
|
>
|
||||||
<!-- <div>
|
|
||||||
<div class="itemTab">
|
|
||||||
<span>{{ t('caseManagement.featureCase.detail') }}</span>
|
|
||||||
<a-switch v-model="detailEnable" size="small" :disabled="true" type="line" />
|
|
||||||
</div>
|
|
||||||
<a-divider orientation="center" class="non-sort"
|
|
||||||
><span class="one-line-text text-xs text-[var(--color-text-4)]">{{
|
|
||||||
t('caseManagement.featureCase.nonClosableTab')
|
|
||||||
}}</span></a-divider
|
|
||||||
>
|
|
||||||
</div> -->
|
|
||||||
<VueDraggable
|
<VueDraggable
|
||||||
v-model="couldCloseColumn"
|
v-model="couldCloseColumn"
|
||||||
class="ms-assertion-body-left"
|
class="ms-assertion-body-left"
|
||||||
ghost-class="ghost"
|
ghost-class="ghost"
|
||||||
handle=".column-drag-item"
|
handle=".column-drag-item"
|
||||||
>
|
>
|
||||||
<div v-for="element in couldCloseColumn" :key="element.key" class="column-drag-item">
|
<div v-for="element in couldCloseColumn" :key="element.value" class="column-drag-item">
|
||||||
<div class="flex w-[90%] items-center">
|
<div class="flex w-[90%] items-center">
|
||||||
<span class="ml-[8px]">{{ t(element.title) }}</span>
|
<span class="ml-[8px]">{{ t(element.label) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<a-switch v-model="element.isShow" size="small" type="line" @change="handleSwitchChange" />
|
<a-switch v-model="element.isShow" size="small" type="line" @change="handleSwitchChange" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -123,7 +112,7 @@
|
||||||
|
|
||||||
const loadTab = async () => {
|
const loadTab = async () => {
|
||||||
const res = (await featureCaseStore.getContentTabList()) || [];
|
const res = (await featureCaseStore.getContentTabList()) || [];
|
||||||
nonCloseColumn.value = res.filter((item) => !item.canHide && item.key !== 'SETTING');
|
nonCloseColumn.value = res.filter((item) => !item.canHide);
|
||||||
couldCloseColumn.value = res.filter((item) => item.canHide);
|
couldCloseColumn.value = res.filter((item) => item.canHide);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -113,40 +113,6 @@
|
||||||
{{ t('common.save') }}
|
{{ t('common.save') }}
|
||||||
</a-button></div
|
</a-button></div
|
||||||
>
|
>
|
||||||
<!-- <a-form-item v-if="props.allowEdit" field="attachment" :label="t('caseManagement.featureCase.attachment')">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div class="mb-1">
|
|
||||||
<a-dropdown position="tr" trigger="hover">
|
|
||||||
<a-button v-permission="['FUNCTIONAL_CASE:READ+UPDATE']" type="outline">
|
|
||||||
<template #icon> <icon-plus class="text-[14px]" /> </template
|
|
||||||
>{{ t('system.orgTemplate.addAttachment') }}</a-button
|
|
||||||
>
|
|
||||||
<template #content>
|
|
||||||
<a-upload
|
|
||||||
ref="uploadRef"
|
|
||||||
v-model:file-list="fileList"
|
|
||||||
:auto-upload="false"
|
|
||||||
:show-file-list="false"
|
|
||||||
:before-upload="beforeUpload"
|
|
||||||
>
|
|
||||||
<template #upload-button>
|
|
||||||
<a-button type="text" class="!text-[var(--color-text-1)]">
|
|
||||||
<icon-upload />{{ t('caseManagement.featureCase.uploadFile') }}
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
</a-upload>
|
|
||||||
<a-button type="text" class="!text-[var(--color-text-1)]" @click="associatedFile">
|
|
||||||
<MsIcon type="icon-icon_link-copy_outlined" size="16" />
|
|
||||||
{{ t('caseManagement.featureCase.associatedFile') }}
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
</a-dropdown>
|
|
||||||
</div>
|
|
||||||
<div class="!hover:bg-[rgb(var(--primary-1))] !text-[var(--color-text-4)]">
|
|
||||||
{{ t('system.orgTemplate.addAttachmentTip') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a-form-item> -->
|
|
||||||
<div v-permission="['FUNCTIONAL_CASE:READ+UPDATE']">
|
<div v-permission="['FUNCTIONAL_CASE:READ+UPDATE']">
|
||||||
<AddAttachment v-model:file-list="fileList" multiple @change="handleChange" @link-file="associatedFile" />
|
<AddAttachment v-model:file-list="fileList" multiple @change="handleChange" @link-file="associatedFile" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -504,13 +470,14 @@
|
||||||
if (valid === true) {
|
if (valid === true) {
|
||||||
confirmLoading.value = true;
|
confirmLoading.value = true;
|
||||||
await updateCaseRequest(getParams());
|
await updateCaseRequest(getParams());
|
||||||
|
confirmLoading.value = false;
|
||||||
Message.success(t('caseManagement.featureCase.editSuccess'));
|
Message.success(t('caseManagement.featureCase.editSuccess'));
|
||||||
isEditPreposition.value = false;
|
isEditPreposition.value = false;
|
||||||
emit('updateSuccess');
|
emit('updateSuccess');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
confirmLoading.value = false;
|
confirmLoading.value = false;
|
||||||
}
|
}
|
||||||
|
@ -665,7 +632,6 @@
|
||||||
|
|
||||||
async function restartUpload() {
|
async function restartUpload() {
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
console.log('ooo');
|
|
||||||
fileListRef.value?.startUpload();
|
fileListRef.value?.startUpload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,6 +641,7 @@
|
||||||
fileId: '',
|
fileId: '',
|
||||||
local: true,
|
local: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
function transferFileHandler(item: MsFileItem) {
|
function transferFileHandler(item: MsFileItem) {
|
||||||
activeTransferFileParams.value = {
|
activeTransferFileParams.value = {
|
||||||
projectId: currentProjectId.value,
|
projectId: currentProjectId.value,
|
||||||
|
|
|
@ -37,7 +37,16 @@
|
||||||
const activeKey = ref('requestHeader');
|
const activeKey = ref('requestHeader');
|
||||||
const GlobalVariable = ref<EnvConfigItem[]>([]);
|
const GlobalVariable = ref<EnvConfigItem[]>([]);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { setIsSave } = useLeaveUnSaveTip();
|
|
||||||
|
const leaveTitle = 'common.tip';
|
||||||
|
const leaveContent = 'apiTestDebug.unsavedLeave';
|
||||||
|
|
||||||
|
const { setIsSave } = useLeaveUnSaveTip({
|
||||||
|
leaveTitle,
|
||||||
|
leaveContent,
|
||||||
|
tipType: 'warning',
|
||||||
|
});
|
||||||
|
|
||||||
setIsSave(true);
|
setIsSave(true);
|
||||||
const canSave = ref(false);
|
const canSave = ref(false);
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
:label="t('system.authorized.license')"
|
:label="t('system.authorized.license')"
|
||||||
field="licenseCode"
|
field="licenseCode"
|
||||||
asterisk-position="end"
|
asterisk-position="end"
|
||||||
required
|
:rules="[{ required: true, message: t('system.authorized.LicenseIsRequired') }]"
|
||||||
:validate-trigger="['input']"
|
:validate-trigger="['input']"
|
||||||
>
|
>
|
||||||
<MsUpload
|
<MsUpload
|
||||||
|
|
Loading…
Reference in New Issue