fix(测试用例&测试计划): 用例详情-修复自动下一条顺序不对的缺陷
--bug=1045034 --user=吕梦园 https://www.tapd.cn/55049933/bugtrace/bugs/view/1155049933001045034
This commit is contained in:
parent
48897e83ac
commit
d82745cd98
|
@ -86,192 +86,195 @@
|
|||
</a-spin>
|
||||
</div>
|
||||
<a-spin :loading="caseDetailLoading" class="relative flex flex-1 flex-col overflow-hidden">
|
||||
<div class="content-center">
|
||||
<div class="rounded-[var(--border-radius-small)] bg-[var(--color-text-n9)] p-[16px]">
|
||||
<div class="mb-[12px] flex items-center">
|
||||
<div class="mr-[16px] flex-1 overflow-hidden">
|
||||
<a-tooltip :content="`【${caseDetail.num}】${caseDetail.name}`">
|
||||
<div
|
||||
class="one-line-text w-[fit-content] max-w-[100%] cursor-pointer font-medium text-[rgb(var(--primary-5))]"
|
||||
@click="goCaseDetail"
|
||||
>
|
||||
【{{ caseDetail.num }}】{{ caseDetail.name }}
|
||||
<MsEmpty v-if="!caseList.length" />
|
||||
<template v-else>
|
||||
<div class="content-center">
|
||||
<div class="rounded-[var(--border-radius-small)] bg-[var(--color-text-n9)] p-[16px]">
|
||||
<div class="mb-[12px] flex items-center">
|
||||
<div class="mr-[16px] flex-1 overflow-hidden">
|
||||
<a-tooltip :content="`【${caseDetail.num}】${caseDetail.name}`">
|
||||
<div
|
||||
class="one-line-text w-[fit-content] max-w-[100%] cursor-pointer font-medium text-[rgb(var(--primary-5))]"
|
||||
@click="goCaseDetail"
|
||||
>
|
||||
【{{ caseDetail.num }}】{{ caseDetail.name }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-button
|
||||
v-permission="['FUNCTIONAL_CASE:READ+UPDATE']"
|
||||
type="outline"
|
||||
size="mini"
|
||||
class="arco-btn-outline--secondary"
|
||||
@click="editCaseVisible = true"
|
||||
>
|
||||
{{ t('common.edit') }}
|
||||
</a-button>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<MsIcon type="icon-icon_folder_filled1" class="mr-[4px] text-[var(--color-text-4)]" />
|
||||
<a-tooltip :content="caseDetail.moduleName || t('common.root')">
|
||||
<div class="one-line-text mr-[8px] max-w-[300px] font-medium text-[var(--color-text-000)]">
|
||||
{{ caseDetail.moduleName || t('common.root') }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-button
|
||||
v-permission="['FUNCTIONAL_CASE:READ+UPDATE']"
|
||||
type="outline"
|
||||
size="mini"
|
||||
class="arco-btn-outline--secondary"
|
||||
@click="editCaseVisible = true"
|
||||
>
|
||||
{{ t('common.edit') }}
|
||||
</a-button>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<MsIcon type="icon-icon_folder_filled1" class="mr-[4px] text-[var(--color-text-4)]" />
|
||||
<a-tooltip :content="caseDetail.moduleName || t('common.root')">
|
||||
<div class="one-line-text mr-[8px] max-w-[300px] font-medium text-[var(--color-text-000)]">
|
||||
{{ caseDetail.moduleName || t('common.root') }}
|
||||
<div class="case-detail-label">
|
||||
{{ t('caseManagement.caseReview.caseLevel') }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
<div class="case-detail-label">
|
||||
{{ t('caseManagement.caseReview.caseLevel') }}
|
||||
</div>
|
||||
<div class="case-detail-value">
|
||||
<caseLevel :case-level="caseDetailLevel" />
|
||||
</div>
|
||||
<!-- <div class="case-detail-label">
|
||||
<div class="case-detail-value">
|
||||
<caseLevel :case-level="caseDetailLevel" />
|
||||
</div>
|
||||
<!-- <div class="case-detail-label">
|
||||
{{ t('caseManagement.caseReview.caseVersion') }}
|
||||
</div>
|
||||
<div class="case-detail-value">
|
||||
<MsIcon type="icon-icon_version" size="13" class="mr-[4px]" />
|
||||
{{ caseDetail.versionName }}
|
||||
</div> -->
|
||||
<div class="case-detail-label">
|
||||
{{ t('caseManagement.caseReview.reviewResult') }}
|
||||
</div>
|
||||
<div class="case-detail-value">
|
||||
<ReviewStatusTrigger v-if="reviewDetail.reviewPassRule === 'MULTIPLE'" ref="reviewStatusTriggerRef" />
|
||||
<div
|
||||
v-if="reviewResultMap[activeCaseReviewStatus as ReviewResult] && reviewDetail.reviewPassRule !== 'MULTIPLE'"
|
||||
class="flex items-center gap-[4px]"
|
||||
>
|
||||
<MsIcon
|
||||
:type="reviewResultMap[activeCaseReviewStatus as ReviewResult].icon"
|
||||
:style="{
|
||||
<div class="case-detail-label">
|
||||
{{ t('caseManagement.caseReview.reviewResult') }}
|
||||
</div>
|
||||
<div class="case-detail-value">
|
||||
<ReviewStatusTrigger v-if="reviewDetail.reviewPassRule === 'MULTIPLE'" ref="reviewStatusTriggerRef" />
|
||||
<div
|
||||
v-if="reviewResultMap[activeCaseReviewStatus as ReviewResult] && reviewDetail.reviewPassRule !== 'MULTIPLE'"
|
||||
class="flex items-center gap-[4px]"
|
||||
>
|
||||
<MsIcon
|
||||
:type="reviewResultMap[activeCaseReviewStatus as ReviewResult].icon"
|
||||
:style="{
|
||||
color: reviewResultMap[activeCaseReviewStatus as ReviewResult].color,
|
||||
}"
|
||||
/>
|
||||
{{ t(reviewResultMap[activeCaseReviewStatus as ReviewResult].label) }}
|
||||
/>
|
||||
{{ t(reviewResultMap[activeCaseReviewStatus as ReviewResult].label) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-tabs v-model:active-key="showTab" class="no-content">
|
||||
<a-tab-pane :key="tabList[0].key" :title="tabList[0].title" />
|
||||
<a-tab-pane :key="tabList[1].key" :title="tabList[1].title" />
|
||||
<a-tab-pane :key="tabList[2].key">
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
{{ tabList[2].title }}
|
||||
<div
|
||||
v-if="caseDetail.demandCount > 0"
|
||||
style="min-width: 16px; text-align: center; align-content: center"
|
||||
:class="`ml-[4px] h-[16px] rounded-full ${
|
||||
showTab === tabList[2].key
|
||||
? 'bg-[rgb(var(--primary-9))] text-[rgb(var(--primary-5))]'
|
||||
: 'bg-[var(--color-text-brand)] text-white'
|
||||
} px-[4px] text-[12px]`"
|
||||
>
|
||||
{{ caseDetail.demandCount > 99 ? '99+' : caseDetail.demandCount }}
|
||||
<a-tabs v-model:active-key="showTab" class="no-content">
|
||||
<a-tab-pane :key="tabList[0].key" :title="tabList[0].title" />
|
||||
<a-tab-pane :key="tabList[1].key" :title="tabList[1].title" />
|
||||
<a-tab-pane :key="tabList[2].key">
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
{{ tabList[2].title }}
|
||||
<div
|
||||
v-if="caseDetail.demandCount > 0"
|
||||
style="min-width: 16px; text-align: center; align-content: center"
|
||||
:class="`ml-[4px] h-[16px] rounded-full ${
|
||||
showTab === tabList[2].key
|
||||
? 'bg-[rgb(var(--primary-9))] text-[rgb(var(--primary-5))]'
|
||||
: 'bg-[var(--color-text-brand)] text-white'
|
||||
} px-[4px] text-[12px]`"
|
||||
>
|
||||
{{ caseDetail.demandCount > 99 ? '99+' : caseDetail.demandCount }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane :key="tabList[3].key" :title="tabList[3].title" />
|
||||
</a-tabs>
|
||||
<a-divider class="my-0" />
|
||||
<MsDescription
|
||||
v-if="showTab === 'baseInfo'"
|
||||
:descriptions="descriptions"
|
||||
label-width="90px"
|
||||
class="mt-[16px]"
|
||||
/>
|
||||
<div v-else-if="showTab === 'detail'" class="mt-[16px] h-full">
|
||||
<caseTabDetail :form="caseDetail" :allow-edit="false" />
|
||||
</div>
|
||||
<div v-else-if="showTab === 'demand'">
|
||||
<div class="mt-[16px] flex items-center justify-between">
|
||||
{{ t('caseManagement.caseReview.demandCases') }}
|
||||
<a-input-search
|
||||
v-model="demandKeyword"
|
||||
:placeholder="t('caseManagement.caseReview.demandSearchPlaceholder')"
|
||||
allow-clear
|
||||
class="w-[300px]"
|
||||
@press-enter="searchDemand"
|
||||
@search="searchDemand"
|
||||
@clear="searchDemand"
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane :key="tabList[3].key" :title="tabList[3].title" />
|
||||
</a-tabs>
|
||||
<a-divider class="my-0" />
|
||||
<MsDescription
|
||||
v-if="showTab === 'baseInfo'"
|
||||
:descriptions="descriptions"
|
||||
label-width="90px"
|
||||
class="mt-[16px]"
|
||||
/>
|
||||
<div v-else-if="showTab === 'detail'" class="mt-[16px] h-full">
|
||||
<caseTabDetail :form="caseDetail" :allow-edit="false" />
|
||||
</div>
|
||||
<div v-else-if="showTab === 'demand'">
|
||||
<div class="mt-[16px] flex items-center justify-between">
|
||||
{{ t('caseManagement.caseReview.demandCases') }}
|
||||
<a-input-search
|
||||
v-model="demandKeyword"
|
||||
:placeholder="t('caseManagement.caseReview.demandSearchPlaceholder')"
|
||||
allow-clear
|
||||
class="w-[300px]"
|
||||
@press-enter="searchDemand"
|
||||
@search="searchDemand"
|
||||
@clear="searchDemand"
|
||||
/>
|
||||
</div>
|
||||
<caseTabDemand
|
||||
ref="caseDemandRef"
|
||||
:fun-params="{ projectId: appStore.currentProjectId, caseId: activeCaseId, keyword: demandKeyword }"
|
||||
:show-empty="false"
|
||||
/>
|
||||
</div>
|
||||
<caseTabDemand
|
||||
ref="caseDemandRef"
|
||||
:fun-params="{ projectId: appStore.currentProjectId, caseId: activeCaseId, keyword: demandKeyword }"
|
||||
:show-empty="false"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="flex flex-1 flex-col overflow-hidden pl-[16px] pt-[16px]">
|
||||
<div class="ms-comment-list">
|
||||
<a-spin :loading="reviewHistoryListLoading" class="h-full w-full">
|
||||
<div v-for="item of reviewHistoryList" :key="item.id" class="ms-comment-list-item">
|
||||
<MSAvatar :avatar="item.userLogo" />
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<a-tooltip :content="item.userName">
|
||||
<div
|
||||
class="one-line-text w-[fit-content] max-w-[100%] font-medium text-[var(--color-text-1)]"
|
||||
>
|
||||
{{ item.userName }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
<div v-else class="flex flex-1 flex-col overflow-hidden pl-[16px] pt-[16px]">
|
||||
<div class="ms-comment-list">
|
||||
<a-spin :loading="reviewHistoryListLoading" class="h-full w-full">
|
||||
<div v-for="item of reviewHistoryList" :key="item.id" class="ms-comment-list-item">
|
||||
<MSAvatar :avatar="item.userLogo" />
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<a-tooltip :content="item.userName">
|
||||
<div
|
||||
class="one-line-text w-[fit-content] max-w-[100%] font-medium text-[var(--color-text-1)]"
|
||||
>
|
||||
{{ item.userName }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div v-if="item.status === 'PASS'" class="flex items-center">
|
||||
<MsIcon type="icon-icon_succeed_filled" class="mr-[4px] text-[rgb(var(--success-6))]" />
|
||||
{{ t('caseManagement.caseReview.pass') }}
|
||||
</div>
|
||||
<div v-else-if="item.status === 'UN_PASS'" class="flex items-center">
|
||||
<MsIcon type="icon-icon_close_filled" class="mr-[4px] text-[rgb(var(--danger-6))]" />
|
||||
{{ t('caseManagement.caseReview.fail') }}
|
||||
</div>
|
||||
<div v-else-if="item.status === 'UNDER_REVIEWED'" class="flex items-center">
|
||||
<MsIcon type="icon-icon_warning_filled" class="mr-[4px] text-[rgb(var(--warning-6))]" />
|
||||
{{ t('caseManagement.caseReview.suggestion') }}
|
||||
</div>
|
||||
<div v-else-if="item.status === 'RE_REVIEWED'" class="flex items-center">
|
||||
<MsIcon type="icon-icon_resubmit_filled" class="mr-[4px] text-[rgb(var(--warning-6))]" />
|
||||
{{ t('caseManagement.caseReview.reReview') }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.status === 'PASS'" class="flex items-center">
|
||||
<MsIcon type="icon-icon_succeed_filled" class="mr-[4px] text-[rgb(var(--success-6))]" />
|
||||
{{ t('caseManagement.caseReview.pass') }}
|
||||
<div class="markdown-body ml-[48px]" v-html="item.contentText"></div>
|
||||
<div class="mt-[8px] text-[12px] leading-[16px] text-[var(--color-text-4)]">
|
||||
{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</div>
|
||||
<div v-else-if="item.status === 'UN_PASS'" class="flex items-center">
|
||||
<MsIcon type="icon-icon_close_filled" class="mr-[4px] text-[rgb(var(--danger-6))]" />
|
||||
{{ t('caseManagement.caseReview.fail') }}
|
||||
</div>
|
||||
<div v-else-if="item.status === 'UNDER_REVIEWED'" class="flex items-center">
|
||||
<MsIcon type="icon-icon_warning_filled" class="mr-[4px] text-[rgb(var(--warning-6))]" />
|
||||
{{ t('caseManagement.caseReview.suggestion') }}
|
||||
</div>
|
||||
<div v-else-if="item.status === 'RE_REVIEWED'" class="flex items-center">
|
||||
<MsIcon type="icon-icon_resubmit_filled" class="mr-[4px] text-[rgb(var(--warning-6))]" />
|
||||
{{ t('caseManagement.caseReview.reReview') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="markdown-body ml-[48px]" v-html="item.contentText"></div>
|
||||
<div class="mt-[8px] text-[12px] leading-[16px] text-[var(--color-text-4)]">
|
||||
{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<MsEmpty v-if="reviewHistoryList.length === 0" />
|
||||
</a-spin>
|
||||
<MsEmpty v-if="reviewHistoryList.length === 0" />
|
||||
</a-spin>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-footer">
|
||||
<div class="mb-[12px] flex items-center justify-between">
|
||||
<div class="font-medium text-[var(--color-text-1)]">
|
||||
{{ t('caseManagement.caseReview.startReview') }}
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<a-switch v-model:model-value="autoNext" class="mx-[8px]" size="small" type="line" />
|
||||
<div class="text-[var(--color-text-4)]">{{ t('caseManagement.caseReview.autoNext') }}</div>
|
||||
<a-tooltip position="right">
|
||||
<template #content>
|
||||
<div>{{ t('caseManagement.caseReview.autoNextTip1') }}</div>
|
||||
<div>{{ t('caseManagement.caseReview.autoNextTip2') }}</div>
|
||||
</template>
|
||||
<icon-question-circle
|
||||
class="mb-[2px] ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<div class="content-footer">
|
||||
<div class="mb-[12px] flex items-center justify-between">
|
||||
<div class="font-medium text-[var(--color-text-1)]">
|
||||
{{ t('caseManagement.caseReview.startReview') }}
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<a-switch v-model:model-value="autoNext" class="mx-[8px]" size="small" type="line" />
|
||||
<div class="text-[var(--color-text-4)]">{{ t('caseManagement.caseReview.autoNext') }}</div>
|
||||
<a-tooltip position="right">
|
||||
<template #content>
|
||||
<div>{{ t('caseManagement.caseReview.autoNextTip1') }}</div>
|
||||
<div>{{ t('caseManagement.caseReview.autoNextTip2') }}</div>
|
||||
</template>
|
||||
<icon-question-circle
|
||||
class="mb-[2px] ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<reviewForm
|
||||
:review-id="reviewId"
|
||||
:case-id="activeCaseId"
|
||||
:review-pass-rule="reviewDetail.reviewPassRule"
|
||||
@done="reviewDone"
|
||||
/>
|
||||
</div>
|
||||
<reviewForm
|
||||
:review-id="reviewId"
|
||||
:case-id="activeCaseId"
|
||||
:review-pass-rule="reviewDetail.reviewPassRule"
|
||||
@done="reviewDone"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</a-spin>
|
||||
</div>
|
||||
</MsCard>
|
||||
|
@ -524,6 +527,7 @@
|
|||
watch(
|
||||
() => activeCaseId.value,
|
||||
() => {
|
||||
console.log('🤔️ =>', activeCaseId.value);
|
||||
loadCaseDetail();
|
||||
initReviewerAndStatus();
|
||||
initReviewHistoryList();
|
||||
|
@ -546,10 +550,28 @@
|
|||
);
|
||||
}
|
||||
|
||||
async function reviewDone() {
|
||||
async function reviewDone(status: string) {
|
||||
if (autoNext.value) {
|
||||
// 自动下一个,更改激活的 id会刷新详情
|
||||
const index = caseList.value.findIndex((e) => e.caseId === activeCaseId.value);
|
||||
|
||||
// 如果过滤的状态和评审状态不一样,则这条将从当前列表排除
|
||||
const oneMissingCase = type.value !== '' && status !== type.value;
|
||||
if (oneMissingCase) {
|
||||
if ((pageNation.value.current - 1) * pageNation.value.pageSize + index + 1 < pageNation.value.total) {
|
||||
// 不是最后一个
|
||||
await loadCaseList();
|
||||
activeCaseId.value = caseList.value[index].caseId;
|
||||
} else {
|
||||
// 是最后一个,如果列表还有其他数据,则选中第一条;如果没有其他数据,则显示暂无数据
|
||||
await loadCaseList();
|
||||
if (caseList.value.length > 1) {
|
||||
activeCaseId.value = caseList.value[0].caseId;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < caseList.value.length - 1) {
|
||||
await loadCaseList();
|
||||
activeCaseId.value = caseList.value[index + 1].caseId;
|
||||
|
|
|
@ -178,7 +178,7 @@
|
|||
if (typeof done === 'function') {
|
||||
done(true);
|
||||
}
|
||||
emit('done');
|
||||
emit('done', params.status);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
|
|
|
@ -59,151 +59,156 @@
|
|||
</div>
|
||||
<!-- 右侧 -->
|
||||
<a-spin :loading="caseDetailLoading" class="relative flex h-full flex-1 flex-col overflow-hidden">
|
||||
<div class="flex px-[16px] pt-[16px]">
|
||||
<div class="mr-[24px] flex flex-1 items-center overflow-hidden">
|
||||
<MsStatusTag :status="caseDetail.lastExecuteResult || 'PREPARED'" />
|
||||
<div class="ml-[8px] mr-[2px] cursor-pointer font-medium text-[rgb(var(--primary-5))]" @click="goCaseDetail"
|
||||
>[{{ caseDetail.num }}]</div
|
||||
>
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<a-tooltip :content="caseDetail.name">
|
||||
<div class="one-line-text w-[fit-content] max-w-[100%] font-medium">
|
||||
{{ caseDetail.name }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
<MsEmpty v-if="!caseList.length" />
|
||||
<template v-else>
|
||||
<div class="flex px-[16px] pt-[16px]">
|
||||
<div class="mr-[24px] flex flex-1 items-center overflow-hidden">
|
||||
<MsStatusTag :status="caseDetail.lastExecuteResult || 'PREPARED'" />
|
||||
<div
|
||||
class="ml-[8px] mr-[2px] cursor-pointer font-medium text-[rgb(var(--primary-5))]"
|
||||
@click="goCaseDetail"
|
||||
>[{{ caseDetail.num }}]</div
|
||||
>
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<a-tooltip :content="caseDetail.name">
|
||||
<div class="one-line-text w-[fit-content] max-w-[100%] font-medium">
|
||||
{{ caseDetail.name }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-button
|
||||
v-if="canEdit && hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE'])"
|
||||
type="outline"
|
||||
@click="editCaseVisible = true"
|
||||
>{{ t('common.edit') }}</a-button
|
||||
>
|
||||
</div>
|
||||
<MsTab
|
||||
v-model:active-key="activeTab"
|
||||
:content-tab-list="contentTabList"
|
||||
no-content
|
||||
:get-text-func="getTotal"
|
||||
class="relative mx-[16px] border-b"
|
||||
/>
|
||||
<div :class="[' flex-1', activeTab !== 'detail' ? 'tab-content' : 'overflow-hidden']">
|
||||
<MsDescription v-if="activeTab === 'baseInfo'" :descriptions="descriptions" :column="2" one-line-value>
|
||||
<template #value="{ item }">
|
||||
<template v-if="item.key === 'reviewStatus'">
|
||||
<MsIcon
|
||||
:type="statusIconMap[item.value as keyof typeof statusIconMap]?.icon || ''"
|
||||
class="mr-1"
|
||||
:class="[statusIconMap[item.value as keyof typeof statusIconMap].color]"
|
||||
></MsIcon>
|
||||
<span>{{ statusIconMap[item.value as keyof typeof statusIconMap]?.statusText || '' }} </span>
|
||||
</template>
|
||||
</template>
|
||||
</MsDescription>
|
||||
<div v-else-if="activeTab === 'detail'" class="align-content-start flex h-full flex-col">
|
||||
<CaseTabDetail ref="caseTabDetailRef" is-test-plan :form="caseDetail" :is-disabled-test-plan="!canEdit" />
|
||||
<!-- 开始执行 -->
|
||||
<div
|
||||
v-if="canEdit && hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
class="z-[101] px-[16px] py-[8px] shadow-[0_-1px_4px_rgba(2,2,2,0.1)]"
|
||||
<a-button
|
||||
v-if="canEdit && hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE'])"
|
||||
type="outline"
|
||||
@click="editCaseVisible = true"
|
||||
>{{ t('common.edit') }}</a-button
|
||||
>
|
||||
<div class="mb-[12px] flex items-center justify-between">
|
||||
<div class="font-medium text-[var(--color-text-1)]">
|
||||
{{ t('testPlan.featureCase.startExecution') }}
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<a-switch v-model:model-value="autoNext" size="small" />
|
||||
<div class="mx-[8px]">{{ t('caseManagement.caseReview.autoNext') }}</div>
|
||||
<a-tooltip position="top">
|
||||
<template #content>
|
||||
<div>{{ t('testPlan.featureCase.autoNextTip1') }}</div>
|
||||
<div>{{ t('testPlan.featureCase.autoNextTip2') }}</div>
|
||||
</template>
|
||||
<icon-question-circle
|
||||
class="text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-4))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<MsTag type="danger" theme="light" size="medium" class="ml-4">
|
||||
<MsIcon type="icon-icon_defect" class="!text-[14px] text-[rgb(var(--danger-6))]" size="16" />
|
||||
<span class="ml-1 text-[rgb(var(--danger-6))]"> {{ t('testPlan.featureCase.bug') }}</span>
|
||||
<span class="ml-1 text-[rgb(var(--danger-6))]">{{ caseDetail.bugListCount }}</span>
|
||||
</MsTag>
|
||||
<a-dropdown @select="handleSelect">
|
||||
<a-button
|
||||
v-if="hasAllPermission(['PROJECT_BUG:READ', 'PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
type="outline"
|
||||
size="small"
|
||||
class="ml-1"
|
||||
>
|
||||
<template #icon> <icon-plus class="text-[12px]" /> </template>
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption
|
||||
v-permission="['PROJECT_BUG:READ+ADD']"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
|
||||
value="new"
|
||||
>{{ t('common.newCreate') }}</a-doption
|
||||
</div>
|
||||
<MsTab
|
||||
v-model:active-key="activeTab"
|
||||
:content-tab-list="contentTabList"
|
||||
no-content
|
||||
:get-text-func="getTotal"
|
||||
class="relative mx-[16px] border-b"
|
||||
/>
|
||||
<div :class="[' flex-1', activeTab !== 'detail' ? 'tab-content' : 'overflow-hidden']">
|
||||
<MsDescription v-if="activeTab === 'baseInfo'" :descriptions="descriptions" :column="2" one-line-value>
|
||||
<template #value="{ item }">
|
||||
<template v-if="item.key === 'reviewStatus'">
|
||||
<MsIcon
|
||||
:type="statusIconMap[item.value as keyof typeof statusIconMap]?.icon || ''"
|
||||
class="mr-1"
|
||||
:class="[statusIconMap[item.value as keyof typeof statusIconMap].color]"
|
||||
></MsIcon>
|
||||
<span>{{ statusIconMap[item.value as keyof typeof statusIconMap]?.statusText || '' }} </span>
|
||||
</template>
|
||||
</template>
|
||||
</MsDescription>
|
||||
<div v-else-if="activeTab === 'detail'" class="align-content-start flex h-full flex-col">
|
||||
<CaseTabDetail ref="caseTabDetailRef" is-test-plan :form="caseDetail" :is-disabled-test-plan="!canEdit" />
|
||||
<!-- 开始执行 -->
|
||||
<div
|
||||
v-if="canEdit && hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
class="z-[101] px-[16px] py-[8px] shadow-[0_-1px_4px_rgba(2,2,2,0.1)]"
|
||||
>
|
||||
<div class="mb-[12px] flex items-center justify-between">
|
||||
<div class="font-medium text-[var(--color-text-1)]">
|
||||
{{ t('testPlan.featureCase.startExecution') }}
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<a-switch v-model:model-value="autoNext" size="small" />
|
||||
<div class="mx-[8px]">{{ t('caseManagement.caseReview.autoNext') }}</div>
|
||||
<a-tooltip position="top">
|
||||
<template #content>
|
||||
<div>{{ t('testPlan.featureCase.autoNextTip1') }}</div>
|
||||
<div>{{ t('testPlan.featureCase.autoNextTip2') }}</div>
|
||||
</template>
|
||||
<icon-question-circle
|
||||
class="text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-4))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<MsTag type="danger" theme="light" size="medium" class="ml-4">
|
||||
<MsIcon type="icon-icon_defect" class="!text-[14px] text-[rgb(var(--danger-6))]" size="16" />
|
||||
<span class="ml-1 text-[rgb(var(--danger-6))]"> {{ t('testPlan.featureCase.bug') }}</span>
|
||||
<span class="ml-1 text-[rgb(var(--danger-6))]">{{ caseDetail.bugListCount }}</span>
|
||||
</MsTag>
|
||||
<a-dropdown @select="handleSelect">
|
||||
<a-button
|
||||
v-if="hasAllPermission(['PROJECT_BUG:READ', 'PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
type="outline"
|
||||
size="small"
|
||||
class="ml-1"
|
||||
>
|
||||
<a-doption
|
||||
v-if="createdBugCount > 0 && hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
value="link"
|
||||
>{{ t('common.associated') }}</a-doption
|
||||
>
|
||||
<a-popover v-else title="" position="left">
|
||||
<template #icon> <icon-plus class="text-[12px]" /> </template>
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption
|
||||
v-if="createdBugCount < 1 && hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
v-permission="['PROJECT_BUG:READ+ADD']"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
|
||||
value="new"
|
||||
>{{ t('common.newCreate') }}</a-doption
|
||||
>
|
||||
<a-doption
|
||||
v-if="createdBugCount > 0 && hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
value="link"
|
||||
>{{ t('common.associated') }}</a-doption
|
||||
>
|
||||
<template #content>
|
||||
<div class="flex items-center text-[14px]">
|
||||
<span class="text-[var(--color-text-4)]">{{
|
||||
t('testPlan.featureCase.noBugDataTooltip')
|
||||
}}</span>
|
||||
<MsButton
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
|
||||
type="text"
|
||||
@click="handleSelect('new')"
|
||||
>
|
||||
{{ t('testPlan.featureCase.noBugDataNewBug') }}
|
||||
</MsButton>
|
||||
</div>
|
||||
</template>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
<a-popover v-else title="" position="left">
|
||||
<a-doption
|
||||
v-if="createdBugCount < 1 && hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ'])"
|
||||
value="link"
|
||||
>{{ t('common.associated') }}</a-doption
|
||||
>
|
||||
<template #content>
|
||||
<div class="flex items-center text-[14px]">
|
||||
<span class="text-[var(--color-text-4)]">{{
|
||||
t('testPlan.featureCase.noBugDataTooltip')
|
||||
}}</span>
|
||||
<MsButton
|
||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
|
||||
type="text"
|
||||
@click="handleSelect('new')"
|
||||
>
|
||||
{{ t('testPlan.featureCase.noBugDataNewBug') }}
|
||||
</MsButton>
|
||||
</div>
|
||||
</template>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<ExecuteSubmit
|
||||
:id="activeId"
|
||||
:case-id="activeCaseId"
|
||||
:test-plan-id="route.query.id as string"
|
||||
:step-execution-result="stepExecutionResult"
|
||||
@done="executeDone"
|
||||
/>
|
||||
</div>
|
||||
<ExecuteSubmit
|
||||
:id="activeId"
|
||||
:case-id="activeCaseId"
|
||||
:test-plan-id="route.query.id as string"
|
||||
:step-execution-result="stepExecutionResult"
|
||||
@done="executeDone"
|
||||
/>
|
||||
</div>
|
||||
<BugList
|
||||
v-if="activeTab === 'defectList'"
|
||||
ref="bugRef"
|
||||
:case-id="activeCaseId"
|
||||
:test-plan-case-id="activeId"
|
||||
:can-edit="canEdit && hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
@link="linkDefect"
|
||||
@new="addBug"
|
||||
@update-count="loadCaseDetail()"
|
||||
/>
|
||||
<ExecutionHistory
|
||||
v-if="activeTab === 'executionHistory'"
|
||||
:execute-list="executeHistoryList"
|
||||
:loading="executeLoading"
|
||||
height="h-[calc(100vh-240px)]"
|
||||
show-step-detail-trigger
|
||||
/>
|
||||
</div>
|
||||
<BugList
|
||||
v-if="activeTab === 'defectList'"
|
||||
ref="bugRef"
|
||||
:case-id="activeCaseId"
|
||||
:test-plan-case-id="activeId"
|
||||
:can-edit="canEdit && hasAnyPermission(['PROJECT_TEST_PLAN:READ+EXECUTE'])"
|
||||
@link="linkDefect"
|
||||
@new="addBug"
|
||||
@update-count="loadCaseDetail()"
|
||||
/>
|
||||
<ExecutionHistory
|
||||
v-if="activeTab === 'executionHistory'"
|
||||
:execute-list="executeHistoryList"
|
||||
:loading="executeLoading"
|
||||
height="h-[calc(100vh-240px)]"
|
||||
show-step-detail-trigger
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</a-spin>
|
||||
</div>
|
||||
</MsCard>
|
||||
|
@ -451,10 +456,30 @@
|
|||
});
|
||||
});
|
||||
const autoNext = ref(true);
|
||||
async function executeDone() {
|
||||
async function executeDone(status: LastExecuteResults) {
|
||||
if (autoNext.value) {
|
||||
// 自动下一个,更改激活的 id会刷新详情
|
||||
const index = caseList.value.findIndex((e) => e.id === activeId.value);
|
||||
|
||||
// 如果过滤的状态和执行状态不一样,则这条将从当前列表排除
|
||||
const oneMissingCase = lastExecResult.value !== '' && status !== lastExecResult.value;
|
||||
if (oneMissingCase) {
|
||||
if ((pageNation.value.current - 1) * pageNation.value.pageSize + index + 1 < pageNation.value.total) {
|
||||
// 不是最后一个
|
||||
await loadCaseList();
|
||||
activeCaseId.value = caseList.value[index].caseId;
|
||||
activeId.value = caseList.value[index].id;
|
||||
} else {
|
||||
// 是最后一个,如果列表还有其他数据,则选中第一条;如果没有其他数据,则显示暂无数据
|
||||
await loadCaseList();
|
||||
if (caseList.value.length > 1) {
|
||||
activeCaseId.value = caseList.value[0].caseId;
|
||||
activeId.value = caseList.value[0].id;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < caseList.value.length - 1) {
|
||||
await loadCaseList();
|
||||
activeCaseId.value = caseList.value[index + 1].caseId;
|
||||
|
|
Loading…
Reference in New Issue