fix: 修改优先级中和低的bugs

This commit is contained in:
xinxin.wu 2024-05-24 19:38:22 +08:00 committed by Craftsman
parent 4e2b49a6e3
commit 5cca0ba48d
21 changed files with 201 additions and 128 deletions

View File

@ -134,6 +134,7 @@
no-disable no-disable
class="mt-[16px]" class="mt-[16px]"
v-on="propsEvent" v-on="propsEvent"
@filter-change="filterChange"
> >
<template #num="{ record }"> <template #num="{ record }">
<a-tooltip :content="`${record.num}`"> <a-tooltip :content="`${record.num}`">
@ -149,6 +150,10 @@
<ExecuteStatusTag v-if="record.lastExecuteResult" :execute-result="record.lastExecuteResult" /> <ExecuteStatusTag v-if="record.lastExecuteResult" :execute-result="record.lastExecuteResult" />
<span v-else>-</span> <span v-else>-</span>
</template> </template>
<!-- 用例等级 -->
<template #[FilterSlotNameEnum.CASE_MANAGEMENT_CASE_LEVEL]="{ filterContent }">
<caseLevel :case-level="filterContent.value" />
</template>
<!-- 评审结果 --> <!-- 评审结果 -->
<template #reviewStatus="{ record }"> <template #reviewStatus="{ record }">
<MsIcon <MsIcon
@ -219,6 +224,7 @@
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum'; import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
import { initGetModuleCountFunc, type RequestModuleEnum } from './utils'; import { initGetModuleCountFunc, type RequestModuleEnum } from './utils';
import { casePriorityOptions } from '@/views/api-test/components/config';
import { executionResultMap, statusIconMap } from '@/views/case-management/caseManagementFeature/components/utils'; import { executionResultMap, statusIconMap } from '@/views/case-management/caseManagementFeature/components/utils';
const router = useRouter(); const router = useRouter();
@ -385,7 +391,11 @@
title: 'ms.case.associate.caseLevel', title: 'ms.case.associate.caseLevel',
dataIndex: 'caseLevel', dataIndex: 'caseLevel',
slotName: 'caseLevel', slotName: 'caseLevel',
width: 90, width: 150,
filterConfig: {
options: casePriorityOptions,
filterSlotName: FilterSlotNameEnum.CASE_MANAGEMENT_CASE_LEVEL,
},
}, },
]; ];
} }
@ -676,6 +686,7 @@
sourceType: caseType.value, sourceType: caseType.value,
...props.tableParams, ...props.tableParams,
...props.moduleCountParams, ...props.moduleCountParams,
filter: propsRes.value.filter,
}; };
modulesCount.value = await initGetModuleCountFunc(props.type, params); modulesCount.value = await initGetModuleCountFunc(props.type, params);
} catch (error) { } catch (error) {
@ -814,6 +825,10 @@
} }
); );
function filterChange() {
initModuleCount();
}
defineExpose({ defineExpose({
initModules, initModules,
}); });

View File

@ -8,7 +8,7 @@
> >
<slot> <slot>
<div :class="['ms-more-action-trigger-content', visible ? 'ms-more-action-trigger-content--focus' : '']"> <div :class="['ms-more-action-trigger-content', visible ? 'ms-more-action-trigger-content--focus' : '']">
<MsButton type="text" size="mini" class="more-icon-btn" @click="visible = !visible"> <MsButton v-if="isHasAllPermission" type="text" size="mini" class="more-icon-btn" @click="visible = !visible">
<MsIcon type="icon-icon_more_outlined" size="16" class="text-[var(--color-text-4)]" /> <MsIcon type="icon-icon_more_outlined" size="16" class="text-[var(--color-text-4)]" />
</MsButton> </MsButton>
</div> </div>
@ -91,6 +91,11 @@
return result; return result;
}); });
//
const isHasAllPermission = computed(() => {
return props.list.some((item: ActionsItem) => hasAnyPermission(item.permission || []));
});
function selectHandler(value: SelectedValue) { function selectHandler(value: SelectedValue) {
const item = props.list.find((e: ActionsItem) => e.eventTag === value); const item = props.list.find((e: ActionsItem) => e.eventTag === value);
emit('select', item); emit('select', item);

View File

@ -52,7 +52,7 @@ const TestPlan: AppRouteRecordRaw = {
}, },
{ {
name: TestPlanRouteEnum.TEST_PLAN_REPORT_DETAIL, name: TestPlanRouteEnum.TEST_PLAN_REPORT_DETAIL,
locale: 'menu.testPlan.testPlanDetail', locale: 'menu.apiTest.reportDetail',
}, },
], ],
}, },

View File

@ -52,6 +52,7 @@
@change="changeHandler" @change="changeHandler"
@module-change="initData" @module-change="initData"
@cell-click="handleCellClick" @cell-click="handleCellClick"
@filter-change="filterChange"
> >
<template #num="{ record }"> <template #num="{ record }">
<span type="text" class="one-line-text cursor-pointer px-0 text-[rgb(var(--primary-5))]"> <span type="text" class="one-line-text cursor-pointer px-0 text-[rgb(var(--primary-5))]">
@ -885,6 +886,7 @@
...tableParams, ...tableParams,
current: propsRes.value.msPagination?.current, current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize, pageSize: propsRes.value.msPagination?.pageSize,
filter: propsRes.value.filter,
}); });
} }
@ -1466,6 +1468,10 @@
} }
}); });
function filterChange() {
emitTableParams();
}
onMounted(async () => { onMounted(async () => {
if (route.query.id) { if (route.query.id) {
showCaseDetail(route.query.id as string, 0); showCaseDetail(route.query.id as string, 0);

View File

@ -16,6 +16,7 @@
<a-form ref="formRef" :model="form" layout="vertical"> <a-form ref="formRef" :model="form" layout="vertical">
<a-form-item <a-form-item
field="title" field="title"
asterisk-position="end"
:label="t('bugManagement.bugName')" :label="t('bugManagement.bugName')"
:rules="[{ required: true, message: t('bugManagement.edit.nameIsRequired') }]" :rules="[{ required: true, message: t('bugManagement.edit.nameIsRequired') }]"
:placeholder="t('bugManagement.edit.pleaseInputBugName')" :placeholder="t('bugManagement.edit.pleaseInputBugName')"

View File

@ -4,13 +4,15 @@
<span type="text" class="one-line-text cursor-pointer px-0 text-[rgb(var(--primary-5))]">{{ record.num }}</span> <span type="text" class="one-line-text cursor-pointer px-0 text-[rgb(var(--primary-5))]">{{ record.num }}</span>
</template> </template>
<template #name="{ record }"> <template #name="{ record }">
<div class="one-line-text flex max-w-[150px] flex-nowrap items-center"> {{ characterLimit(record.name) }}</div> <div class="flex flex-nowrap items-center">
<a-popover title="" position="right" style="width: 480px"> <div class="one-line-text max-w-[200px] flex-auto items-center"> {{ characterLimit(record.name) }}</div>
<div class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</div> <a-popover class="bug-content-popover" title="" position="right" style="width: 480px">
<template #content> <span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span>
<div v-dompurify-html="record.content" class="markdown-body" style="margin-left: 48px"> </div> <template #content>
</template> <div v-dompurify-html="record.content" class="markdown-body bug-content"> </div>
</a-popover> </template>
</a-popover>
</div>
</template> </template>
<template #statusName="{ record }"> <template #statusName="{ record }">
<div class="one-line-text">{{ record.statusName || '-' }}</div> <div class="one-line-text">{{ record.statusName || '-' }}</div>
@ -149,4 +151,12 @@
}); });
</script> </script>
<style scoped></style> <style lang="less">
.bug-content-popover {
.arco-popover-content {
overflow: auto;
max-height: 400px;
.ms-scroll-bar();
}
}
</style>

View File

@ -38,13 +38,17 @@
v-on="propsEvent" v-on="propsEvent"
> >
<template #name="{ record }"> <template #name="{ record }">
<span class="one-line-text max-w-[300px]"> {{ record.name }}</span> <div class="flex flex-nowrap items-center">
<a-popover title="" position="right" style="width: 480px"> <div class="one-line-text max-w-[200px] flex-auto items-center"> {{ characterLimit(record.name) }}</div>
<span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span> <a-popover class="bug-content-popover" title="" position="right" style="width: 480px">
<template #content> <div class="ml-1 flex-auto text-[rgb(var(--primary-5))]">{{
<div v-dompurify-html="record.content" class="markdown-body" style="margin-left: 48px"> </div> t('caseManagement.featureCase.preview')
</template> }}</div>
</a-popover> <template #content>
<div v-dompurify-html="record.content" class="markdown-body"> </div>
</template>
</a-popover>
</div>
</template> </template>
</ms-base-table> </ms-base-table>
</div> </div>
@ -62,6 +66,7 @@
import { getDrawerDebugPage } from '@/api/modules/case-management/featureCase'; import { getDrawerDebugPage } from '@/api/modules/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store'; import { useAppStore } from '@/store';
import { characterLimit } from '@/utils';
import { TableKeyEnum } from '@/enums/tableEnum'; import { TableKeyEnum } from '@/enums/tableEnum';
@ -77,7 +82,7 @@
visible: boolean; visible: boolean;
caseId: string; caseId: string;
drawerLoading: boolean; drawerLoading: boolean;
showSelectorAll: boolean; showSelectorAll?: boolean;
}>(), }>(),
{ {
showSelectorAll: true, showSelectorAll: true,
@ -101,7 +106,7 @@
dataIndex: 'name', dataIndex: 'name',
showInTable: true, showInTable: true,
showTooltip: true, showTooltip: true,
width: 200, width: 300,
ellipsis: true, ellipsis: true,
showDrag: false, showDrag: false,
}, },
@ -157,6 +162,7 @@
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable( const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
getDrawerDebugPage, getDrawerDebugPage,
{ {
scroll: { x: 'auto' },
columns, columns,
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_DEFECT, tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_DEFECT,
selectable: true, selectable: true,
@ -229,4 +235,12 @@
); );
</script> </script>
<style scoped></style> <style lang="less">
.bug-content-popover {
.arco-popover-content {
overflow: auto;
max-height: 400px;
.ms-scroll-bar();
}
}
</style>

View File

@ -205,7 +205,7 @@
dataIndex: 'name', dataIndex: 'name',
showInTable: true, showInTable: true,
showTooltip: false, showTooltip: false,
width: 250, width: 300,
ellipsis: true, ellipsis: true,
showDrag: false, showDrag: false,
}, },

View File

@ -65,7 +65,7 @@
> >
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div <div
><span class="font-medium">{{ getPlatName() }}</span ><span class="font-medium">{{ platName }}</span
><span class="ml-1 text-[var(--color-text-4)]">({{ propsRes?.msPagination?.total || 0 }})</span></div ><span class="ml-1 text-[var(--color-text-4)]">({{ propsRes?.msPagination?.total || 0 }})</span></div
> >
<a-input-search <a-input-search
@ -126,6 +126,8 @@
import type { CreateOrUpdateDemand, DemandItem } from '@/models/caseManagement/featureCase'; import type { CreateOrUpdateDemand, DemandItem } from '@/models/caseManagement/featureCase';
import { TableKeyEnum } from '@/enums/tableEnum'; import { TableKeyEnum } from '@/enums/tableEnum';
import { getPlatName } from '@/views/case-management/caseManagementFeature/components/utils';
const { t } = useI18n(); const { t } = useI18n();
const appStore = useAppStore(); const appStore = useAppStore();
const currentProjectId = computed(() => appStore.currentProjectId); const currentProjectId = computed(() => appStore.currentProjectId);
@ -207,7 +209,7 @@
scroll: { x: '100%' }, scroll: { x: '100%' },
heightUsed: 290, heightUsed: 290,
selectable: true, selectable: true,
showSelectorAll: true, showSelectorAll: false,
showSetting: false, showSetting: false,
}); });
@ -411,32 +413,9 @@
initPlatform(); initPlatform();
}); });
// watch( const platName = computed(() => {
// () => activeTab.value, return getPlatName(platformInfo.value.platform_key);
// async (val) => { });
// if (val === 'requirement') {
// try {
// const result = await getCaseRelatedInfo(currentProjectId.value);
// if (result && result.platform_key) {
// platformInfo.value = { ...result };
// }
// } catch (error) {
// console.log(error);
// }
// }
// }
// );
function getPlatName() {
switch (platformInfo.value.platform_key) {
case 'zentao':
return t('caseManagement.featureCase.zentao');
case 'jira':
return t('caseManagement.featureCase.jira');
default:
break;
}
}
</script> </script>
<style scoped></style> <style scoped></style>

View File

@ -14,7 +14,7 @@
> >
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div <div
><span class="font-medium">{{ getPlatName() }}</span ><span class="font-medium">{{ platName }}</span
><span class="ml-1 text-[var(--color-text-4)]">({{ propsRes?.msPagination?.total || 0 }})</span></div ><span class="ml-1 text-[var(--color-text-4)]">({{ propsRes?.msPagination?.total || 0 }})</span></div
> >
<a-input-search <a-input-search
@ -58,6 +58,8 @@
import type { CreateOrUpdateDemand, DemandItem } from '@/models/caseManagement/featureCase'; import type { CreateOrUpdateDemand, DemandItem } from '@/models/caseManagement/featureCase';
import { TableKeyEnum } from '@/enums/tableEnum'; import { TableKeyEnum } from '@/enums/tableEnum';
import { getPlatName } from '@/views/case-management/caseManagementFeature/components/utils';
const { t } = useI18n(); const { t } = useI18n();
const appStore = useAppStore(); const appStore = useAppStore();
const currentProjectId = computed(() => appStore.currentProjectId); const currentProjectId = computed(() => appStore.currentProjectId);
@ -138,16 +140,9 @@
return filteredData; return filteredData;
}); });
function getPlatName() { const platName = computed(() => {
switch (props.platformInfo.platform_key) { return getPlatName(props.platformInfo.value.platform_key);
case 'zentao': });
return t('caseManagement.featureCase.zentao');
case 'jira':
return t('caseManagement.featureCase.jira');
default:
break;
}
}
async function handleDrawerConfirm() { async function handleDrawerConfirm() {
const demandList = tableSelected.value.map((item) => { const demandList = tableSelected.value.map((item) => {

View File

@ -449,6 +449,7 @@
function getParams() { function getParams() {
const steps = stepData.value.map((item, index) => { const steps = stepData.value.map((item, index) => {
return { return {
id: item.id,
num: index, num: index,
desc: item.step, desc: item.step,
result: item.expected, result: item.expected,

View File

@ -280,10 +280,6 @@ export function initFormCreate(customFields: CustomAttributes[], permission: str
} }
export function makeColumns(optionsMap: Record<string, any>, columnData: MsTableColumn) { export function makeColumns(optionsMap: Record<string, any>, columnData: MsTableColumn) {
// const optionsMap: Record<string, any> = {
// status: statusFilterOptions.value,
// handleUser: handleUserFilterOptions.value,
// };
return columnData.map((e) => { return columnData.map((e) => {
if (Object.prototype.hasOwnProperty.call(optionsMap, e.dataIndex as string)) { if (Object.prototype.hasOwnProperty.call(optionsMap, e.dataIndex as string)) {
return { return {
@ -297,3 +293,14 @@ export function makeColumns(optionsMap: Record<string, any>, columnData: MsTable
return { ...e }; return { ...e };
}); });
} }
export function getPlatName(platformKey: string) {
switch (platformKey) {
case 'zentao':
return t('caseManagement.featureCase.zentao');
case 'jira':
return t('caseManagement.featureCase.jira');
default:
break;
}
}

View File

@ -264,6 +264,7 @@ export default {
'caseManagement.featureCase.sortSuccess': 'Sort successfully', 'caseManagement.featureCase.sortSuccess': 'Sort successfully',
'caseManagement.featureCase.zentao': 'ZenTao', 'caseManagement.featureCase.zentao': 'ZenTao',
'caseManagement.featureCase.jira': 'JIRA', 'caseManagement.featureCase.jira': 'JIRA',
'caseManagement.featureCase.tapd': 'TAPD',
'caseManagement.featureCase.searchPlaceholder': 'Search by ID, name, or tag', 'caseManagement.featureCase.searchPlaceholder': 'Search by ID, name, or tag',
'caseManagement.featureCase.ModuleOwned': 'Module owned', 'caseManagement.featureCase.ModuleOwned': 'Module owned',
'caseManagement.featureCase.excelImportTip': 'Only xls/xlsx files are supported', 'caseManagement.featureCase.excelImportTip': 'Only xls/xlsx files are supported',

View File

@ -260,6 +260,7 @@ export default {
'caseManagement.featureCase.sortSuccess': '排序成功', 'caseManagement.featureCase.sortSuccess': '排序成功',
'caseManagement.featureCase.zentao': '禅道', 'caseManagement.featureCase.zentao': '禅道',
'caseManagement.featureCase.jira': 'JIRA', 'caseManagement.featureCase.jira': 'JIRA',
'caseManagement.featureCase.tapd': 'TAPD',
'caseManagement.featureCase.searchPlaceholder': '通过ID、名称或标签搜索', 'caseManagement.featureCase.searchPlaceholder': '通过ID、名称或标签搜索',
'caseManagement.featureCase.ModuleOwned': '所属模块', 'caseManagement.featureCase.ModuleOwned': '所属模块',
'caseManagement.featureCase.excelImportTip': '仅支持 xls/xlsx 格式的文件', 'caseManagement.featureCase.excelImportTip': '仅支持 xls/xlsx 格式的文件',

View File

@ -72,7 +72,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { FormInstance } from '@arco-design/web-vue'; import { FormInstance, Message } from '@arco-design/web-vue';
import MsDrawer from '@/components/pure/ms-drawer/index.vue'; import MsDrawer from '@/components/pure/ms-drawer/index.vue';
import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue'; import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue';
@ -168,6 +168,7 @@
{ ...form, DEMAND_PLATFORM_CONFIG: JSON.stringify(formData) }, { ...form, DEMAND_PLATFORM_CONFIG: JSON.stringify(formData) },
currentProjectId.value currentProjectId.value
); );
Message.success(t('common.linkSuccess'));
handleCancel(true); handleCancel(true);
emit('ok'); emit('ok');
} catch (error) { } catch (error) {

View File

@ -47,6 +47,7 @@
:selectable="hasOperationPermission" :selectable="hasOperationPermission"
v-on="propsEvent" v-on="propsEvent"
@batch-action="handleTableBatch" @batch-action="handleTableBatch"
@filter-change="filterChange"
> >
<!-- :expanded-keys="expandedKeys" --> <!-- :expanded-keys="expandedKeys" -->
<template #num="{ record }"> <template #num="{ record }">
@ -624,18 +625,15 @@
currentSelectCount: 0, currentSelectCount: 0,
}); });
const conditionParams = ref({ const conditionParams = computed(() => {
keyword: '', return {
filter: {},
combine: {},
});
async function initTableParams(isSetDefaultKey = false) {
conditionParams.value = {
keyword: keyword.value, keyword: keyword.value,
filter: propsRes.value.filter, filter: propsRes.value.filter,
combine: batchParams.value.condition, combine: batchParams.value.condition,
}; };
});
async function initTableParams(isSetDefaultKey = false) {
let moduleIds = let moduleIds =
props.activeFolder && props.activeFolder !== 'all' ? [props.activeFolder, ...props.offspringIds] : []; props.activeFolder && props.activeFolder !== 'all' ? [props.activeFolder, ...props.offspringIds] : [];
if (isSetDefaultKey) { if (isSetDefaultKey) {
@ -671,6 +669,7 @@
...tableParams, ...tableParams,
current: propsRes.value.msPagination?.current, current: propsRes.value.msPagination?.current,
pageSize: propsRes.value.msPagination?.pageSize, pageSize: propsRes.value.msPagination?.pageSize,
filter: propsRes.value.filter,
}); });
} }
@ -1026,6 +1025,10 @@
} }
); );
function filterChange() {
emitTableParams();
}
defineExpose({ defineExpose({
fetchData, fetchData,
emitTableParams, emitTableParams,

View File

@ -47,7 +47,13 @@
@confirm="addSubModule" @confirm="addSubModule"
@cancel="resetFocusNodeKey" @cancel="resetFocusNodeKey"
> >
<MsButton type="icon" size="mini" class="ms-tree-node-extra__btn !mr-0" @click="setFocusKey(nodeData)"> <MsButton
v-if="hasAnyPermission(['PROJECT_TEST_PLAN:READ+ADD'])"
type="icon"
size="mini"
class="ms-tree-node-extra__btn !mr-0"
@click="setFocusKey(nodeData)"
>
<MsIcon type="icon-icon_add_outlined" size="14" class="text-[var(--color-text-4)]" /> <MsIcon type="icon-icon_add_outlined" size="14" class="text-[var(--color-text-4)]" />
</MsButton> </MsButton>
</MsPopConfirm> </MsPopConfirm>
@ -134,11 +140,13 @@
{ {
label: 'caseManagement.featureCase.rename', label: 'caseManagement.featureCase.rename',
eventTag: 'rename', eventTag: 'rename',
permission: ['PROJECT_TEST_PLAN:READ+UPDATE'],
}, },
{ {
label: 'caseManagement.featureCase.delete', label: 'caseManagement.featureCase.delete',
eventTag: 'delete', eventTag: 'delete',
danger: true, danger: true,
permission: ['PROJECT_TEST_PLAN:READ+DELETE'],
}, },
]; ];

View File

@ -1,51 +1,62 @@
<template> <template>
<div> <div>
<div class="mb-4 flex items-center justify-between"> <div class="mb-4 grid grid-cols-3">
<a-dropdown-button <div>
v-if="hasAnyPermission(['PROJECT_BUG:READ']) && total" <a-dropdown-button
type="primary" v-if="hasAnyPermission(['PROJECT_BUG:READ']) && total"
@click="handleSelect('associated')" type="primary"
> @click="handleSelect('associated')"
{{ t('common.associated') }} >
<template #icon> {{ t('common.associated') }}
<icon-down /> <template #icon>
</template> <icon-down />
<template #content> </template>
<a-doption v-permission="['PROJECT_BUG:READ+ADD']" value="new" @click="handleSelect('new')"> <template #content>
{{ t('common.newCreate') }} <a-doption :disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])" value="new" @click="handleSelect('new')">
</a-doption> {{ t('common.newCreate') }}
</template>
</a-dropdown-button>
<a-dropdown-button
v-if="hasAnyPermission(['PROJECT_BUG:READ+ADD']) && !total"
type="primary"
@click="handleSelect('new')"
>
{{ t('common.newCreate') }}
<template #icon>
<icon-down />
</template>
<template #content>
<a-popover title="" position="right">
<a-doption value="associated" :disabled="!total" @click="handleSelect('associated')">
{{ t('common.associated') }}
</a-doption> </a-doption>
<template #content> </template>
<div class="flex items-center text-[14px]"> </a-dropdown-button>
<span class="text-[var(--color-text-4)]">{{ t('testPlan.featureCase.noBugDataTooltip') }}</span> <a-dropdown-button
<MsButton type="text" @click="handleSelect('new')"> v-if="hasAnyPermission(['PROJECT_BUG:READ+ADD']) && !total"
{{ t('testPlan.featureCase.noBugDataNewBug') }} type="primary"
</MsButton> @click="handleSelect('new')"
</div> >
</template> {{ t('common.newCreate') }}
</a-popover> <template #icon>
</template> <icon-down />
</a-dropdown-button> </template>
<template #content>
<a-popover title="" position="right">
<a-doption
value="associated"
:disabled="!total && !hasAnyPermission(['PROJECT_BUG:READ'])"
@click="handleSelect('associated')"
>
{{ 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-button>
</div>
<a-input-search <a-input-search
v-model:model-value="keyword" v-model:model-value="keyword"
:placeholder="t('caseManagement.featureCase.searchByName')" :placeholder="t('caseManagement.featureCase.searchByName')"
allow-clear allow-clear
class="mx-[8px] w-[240px]" class="col-span-2 col-end-7 mx-[8px] w-[240px]"
@search="initData" @search="initData"
@press-enter="initData" @press-enter="initData"
@clear="resetHandler" @clear="resetHandler"

View File

@ -127,20 +127,26 @@
<span class="ml-1 text-[rgb(var(--danger-6))]">{{ caseDetail.bugListCount }}</span> <span class="ml-1 text-[rgb(var(--danger-6))]">{{ caseDetail.bugListCount }}</span>
</MsTag> </MsTag>
<a-dropdown @select="handleSelect"> <a-dropdown @select="handleSelect">
<a-button type="outline" size="mini" class="ml-1"> <a-button v-if="hasAnyPermission(['PROJECT_BUG:READ'])" type="outline" size="mini" class="ml-1">
<template #icon> <icon-plus class="text-[12px]" /> </template> <template #icon> <icon-plus class="text-[12px]" /> </template>
</a-button> </a-button>
<template #content> <template #content>
<a-doption v-permission="['PROJECT_BUG:READ+ADD']" value="new">{{ <a-doption
t('common.newCreate') v-permission="['PROJECT_BUG:READ+ADD']"
}}</a-doption> :disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
<a-doption v-if="createdBugCount > 0 && hasAnyPermission(['PROJECT_BUG:READ'])" value="link">{{ value="new"
t('common.associated') >{{ t('common.newCreate') }}</a-doption
}}</a-doption> >
<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"> <a-popover v-else title="" position="left">
<a-doption <a-doption
v-if="createdBugCount < 1 && hasAnyPermission(['PROJECT_BUG:READ'])" v-if="createdBugCount < 1 && hasAnyPermission(['PROJECT_BUG:READ'])"
:disabled="true" :disabled="!hasAnyPermission(['PROJECT_BUG:READ'])"
value="link" value="link"
>{{ t('common.associated') }}</a-doption >{{ t('common.associated') }}</a-doption
> >
@ -149,7 +155,11 @@
<span class="text-[var(--color-text-4)]">{{ <span class="text-[var(--color-text-4)]">{{
t('testPlan.featureCase.noBugDataTooltip') t('testPlan.featureCase.noBugDataTooltip')
}}</span> }}</span>
<MsButton type="text" @click="handleSelect('new')"> <MsButton
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+ADD'])"
type="text"
@click="handleSelect('new')"
>
{{ t('testPlan.featureCase.noBugDataNewBug') }} {{ t('testPlan.featureCase.noBugDataNewBug') }}
</MsButton> </MsButton>
</div> </div>
@ -238,7 +248,7 @@
import { testPlanDefaultDetail } from '@/config/testPlan'; import { testPlanDefaultDetail } from '@/config/testPlan';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import { hasAnyPermission } from '@/utils/permission'; import { hasAllPermission, hasAnyPermission } from '@/utils/permission';
import type { TableQueryParams } from '@/models/common'; import type { TableQueryParams } from '@/models/common';
import type { PlanDetailFeatureCaseItem, TestPlanDetail } from '@/models/testPlan/testPlan'; import type { PlanDetailFeatureCaseItem, TestPlanDetail } from '@/models/testPlan/testPlan';

View File

@ -56,7 +56,11 @@
/> />
{{ t(detail.followFlag ? 'common.forked' : 'common.fork') }} {{ t(detail.followFlag ? 'common.forked' : 'common.fork') }}
</MsButton> </MsButton>
<MsTableMoreAction :list="moreAction" @select="handleMoreSelect"> <MsButton v-if="detail.status === 'ARCHIVED'" status="danger" type="button" @click="deleteHandler">
<MsIcon type="icon-icon_delete-trash_outlined" class="mr-[8px] text-[rgb(var(--danger-6))]" />
<span class="text-[rgb(var(--danger-6))]"> {{ t('common.delete') }}</span>
</MsButton>
<MsTableMoreAction v-else :list="moreAction" @select="handleMoreSelect">
<MsButton v-permission="['PROJECT_TEST_PLAN:READ+DELETE']" type="button" status="default"> <MsButton v-permission="['PROJECT_TEST_PLAN:READ+DELETE']" type="button" status="default">
<MsIcon type="icon-icon_more_outlined" class="mr-[8px]" /> <MsIcon type="icon-icon_more_outlined" class="mr-[8px]" />
{{ t('common.more') }} {{ t('common.more') }}

View File

@ -50,7 +50,7 @@
}" }"
@confirm="confirmHandler" @confirm="confirmHandler"
> >
<MsButton type="icon" class="!mr-0 p-[2px]"> <MsButton v-permission="['PROJECT_TEST_PLAN:READ+ADD']" type="icon" class="!mr-0 p-[2px]">
<MsIcon <MsIcon
type="icon-icon_create_planarity" type="icon-icon_create_planarity"
size="18" size="18"
@ -119,6 +119,7 @@
import { createPlanModuleTree, getPlanModulesCount } from '@/api/modules/test-plan/testPlan'; import { createPlanModuleTree, getPlanModulesCount } from '@/api/modules/test-plan/testPlan';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app'; import useAppStore from '@/store/modules/app';
import { hasAnyPermission } from '@/utils/permission';
import type { CreateOrUpdateModule } from '@/models/caseManagement/featureCase'; import type { CreateOrUpdateModule } from '@/models/caseManagement/featureCase';
import { ModuleTreeNode, TableQueryParams } from '@/models/common'; import { ModuleTreeNode, TableQueryParams } from '@/models/common';