refactor(测试计划): 测试计划详情-缺陷列表
This commit is contained in:
parent
6653d5497d
commit
327476108f
|
@ -163,7 +163,8 @@ export default {
|
||||||
'common.text': '文本',
|
'common.text': '文本',
|
||||||
'common.resourceDeleted': '资源已被删除',
|
'common.resourceDeleted': '资源已被删除',
|
||||||
'common.refresh': '刷新',
|
'common.refresh': '刷新',
|
||||||
'common.searchByNameAndId': '通过ID、名称或标签搜索',
|
'common.searchByIdName': '通过ID 或名称搜索',
|
||||||
|
'common.searchByIDNameTag': '通过ID、名称或标签搜索',
|
||||||
'common.archive': '归档',
|
'common.archive': '归档',
|
||||||
'common.running': '执行中',
|
'common.running': '执行中',
|
||||||
'common.unExecute': '未执行',
|
'common.unExecute': '未执行',
|
||||||
|
|
|
@ -4,9 +4,8 @@
|
||||||
<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="flex flex-nowrap items-center">
|
|
||||||
<a-tooltip :content="record.name">
|
<a-tooltip :content="record.name">
|
||||||
<div class="one-line-text max-w-[200px] flex-auto items-center"> {{ characterLimit(record.name) }}</div>
|
<div class="one-line-text max-w-[calc(100%-32px)]"> {{ record.name }}</div>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-popover class="bug-content-popover" title="" position="right" style="width: 480px">
|
<a-popover class="bug-content-popover" title="" position="right" style="width: 480px">
|
||||||
<span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span>
|
<span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span>
|
||||||
|
@ -14,7 +13,6 @@
|
||||||
<div v-dompurify-html="record.content" class="markdown-body bug-content"> </div>
|
<div v-dompurify-html="record.content" class="markdown-body bug-content"> </div>
|
||||||
</template>
|
</template>
|
||||||
</a-popover>
|
</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>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
:filter-config-list="filterConfigList"
|
:filter-config-list="filterConfigList"
|
||||||
:custom-fields-config-list="searchCustomFields"
|
:custom-fields-config-list="searchCustomFields"
|
||||||
:row-count="filterRowCount"
|
:row-count="filterRowCount"
|
||||||
:search-placeholder="t('common.searchByNameAndId')"
|
:search-placeholder="t('common.searchByIDNameTag')"
|
||||||
@keyword-search="fetchData"
|
@keyword-search="fetchData"
|
||||||
@adv-search="fetchData"
|
@adv-search="fetchData"
|
||||||
@refresh="fetchData"
|
@refresh="fetchData"
|
||||||
|
|
|
@ -1,48 +1,52 @@
|
||||||
<template>
|
<template>
|
||||||
<a-popover position="bottom" content-class="case-count-popover" @popup-visible-change="popupChange">
|
<a-popover position="br" content-class="case-count-popover" @popup-visible-change="popupChange">
|
||||||
<div class="one-line-text cursor-pointer px-0 text-[rgb(var(--primary-5))]">{{
|
<div class="one-line-text cursor-pointer px-0 text-[rgb(var(--primary-5))]">{{
|
||||||
props.record.relateCase.length
|
props.bugItem.relateCase?.length ?? 0
|
||||||
}}</div>
|
}}</div>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="w-[500px]">
|
<div class="w-[500px]">
|
||||||
<MsBaseTable v-bind="propsRes" v-on="propsEvent"></MsBaseTable>
|
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
|
||||||
|
<template #num="{ record }">
|
||||||
|
<MsButton type="text" @click="goCaseDetail(record.id)">{{ record.num }}</MsButton>
|
||||||
|
</template>
|
||||||
|
</MsBaseTable>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
import type { PlanDetailBugItem } from '@/models/testPlan/testPlan';
|
import type { PlanDetailBugItem } from '@/models/testPlan/testPlan';
|
||||||
|
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
record: PlanDetailBugItem;
|
bugItem: PlanDetailBugItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.tableColumnID',
|
title: 'caseManagement.featureCase.tableColumnID',
|
||||||
dataIndex: 'num',
|
dataIndex: 'num',
|
||||||
|
slotName: 'num',
|
||||||
width: 100,
|
width: 100,
|
||||||
showInTable: true,
|
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
showDrag: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'case.caseName',
|
title: 'case.caseName',
|
||||||
slotName: 'name',
|
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
showInTable: true,
|
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
|
@ -59,7 +63,15 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
function popupChange() {
|
function popupChange() {
|
||||||
propsRes.value.data = props.record.relateCase;
|
propsRes.value.data = props.bugItem.relateCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
function goCaseDetail(id: string) {
|
||||||
|
window.open(
|
||||||
|
`${window.location.origin}#${
|
||||||
|
router.resolve({ name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE }).fullPath
|
||||||
|
}?id=${id}&orgId=${appStore.currentOrgId}&pId=${appStore.currentProjectId}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="p-[16px]">
|
<div class="p-[16px]">
|
||||||
<div class="flex items-center justify-between">
|
<div class="mb-[16px] flex items-center justify-between">
|
||||||
<div
|
<div
|
||||||
>{{ t('testPlan.bugManagement.bug') }}
|
>{{ t('testPlan.bugManagement.bug') }}
|
||||||
<span class="!text-[var(--color-text-n4)]">({{ addCommasToNumber(count) }})</span>
|
<span class="text-[var(--color-text-4)]">({{ addCommasToNumber(count) }})</span>
|
||||||
</div>
|
</div>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
v-model:model-value="keyword"
|
v-model:model-value="keyword"
|
||||||
:placeholder="t('caseManagement.featureCase.searchByName')"
|
:placeholder="t('common.searchByIdName')"
|
||||||
allow-clear
|
allow-clear
|
||||||
class="mx-[8px] w-[240px]"
|
class="w-[240px]"
|
||||||
@search="getFetch"
|
@search="getFetch"
|
||||||
@press-enter="getFetch"
|
@press-enter="getFetch"
|
||||||
@clear="getFetch"
|
@clear="getFetch"
|
||||||
|
@ -17,23 +17,21 @@
|
||||||
</div>
|
</div>
|
||||||
<MsBaseTable ref="tableRef" v-bind="propsRes" v-on="propsEvent">
|
<MsBaseTable ref="tableRef" v-bind="propsRes" v-on="propsEvent">
|
||||||
<template #num="{ record }">
|
<template #num="{ record }">
|
||||||
<a-tooltip :content="`${record.num}`">
|
<MsButton type="text" @click="toDetail(record.id)">{{ record.num }}</MsButton>
|
||||||
<a-button type="text" class="px-0 !text-[14px] !leading-[22px]" size="mini">
|
|
||||||
<div class="one-line-text max-w-[168px]">{{ record.num }}</div>
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
</template>
|
||||||
<template #name="{ record }">
|
<template #name="{ record }">
|
||||||
<span class="one-line-text max-w-[300px]"> {{ record.name }}</span>
|
<a-tooltip :content="record.title">
|
||||||
<a-popover title="" position="right" style="width: 480px">
|
<div class="one-line-text max-w-[calc(100%-32px)]"> {{ record.title }}</div>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-popover class="bug-content-popover" title="" position="right" style="width: 480px">
|
||||||
<span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span>
|
<span class="ml-1 text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.preview') }}</span>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-dompurify-html="record.content" class="markdown-body" style="margin-left: 48px"> </div>
|
<div v-dompurify-html="record.content" class="markdown-body bug-content"> </div>
|
||||||
</template>
|
</template>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
<template #linkCase="{ record }">
|
<template #linkCase="{ record }">
|
||||||
<CaseCountPopover :record="record" />
|
<CaseCountPopover :bug-item="record" />
|
||||||
</template>
|
</template>
|
||||||
</MsBaseTable>
|
</MsBaseTable>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,31 +39,35 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import CaseCountPopover from './caseCountPopover.vue';
|
import CaseCountPopover from './caseCountPopover.vue';
|
||||||
|
|
||||||
|
import { getCustomOptionHeader } from '@/api/modules/bug-management';
|
||||||
import { planDetailBugPage } from '@/api/modules/test-plan/testPlan';
|
import { planDetailBugPage } 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 { addCommasToNumber } from '@/utils';
|
import { addCommasToNumber } from '@/utils';
|
||||||
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
|
// import { BugManagementRouteEnum } from '@/enums/routeEnum';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
|
import { makeColumns } from '@/views/case-management/caseManagementFeature/components/utils';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const route = useRoute();
|
||||||
|
// const router = useRouter();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
planId: string | undefined;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const keyword = ref<string>('');
|
const keyword = ref<string>('');
|
||||||
|
const planId = ref(route.query.id as string);
|
||||||
|
|
||||||
function getFetch() {}
|
const columns = ref<MsTableColumn>([
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
dataIndex: 'num',
|
dataIndex: 'num',
|
||||||
|
@ -80,21 +82,22 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'testPlan.bugManagement.bugName',
|
title: 'testPlan.bugManagement.bugName',
|
||||||
slotName: 'title',
|
slotName: 'name',
|
||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
showTooltip: false,
|
|
||||||
width: 300,
|
width: 300,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
showDrag: false,
|
showDrag: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'testPlan.bugManagement.defectState',
|
title: 'caseManagement.featureCase.defectState',
|
||||||
slotName: 'status',
|
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
|
filterConfig: {
|
||||||
|
options: [],
|
||||||
|
labelKey: 'text',
|
||||||
|
},
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
showTooltip: true,
|
width: 150,
|
||||||
width: 200,
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
showDrag: false,
|
showDrag: false,
|
||||||
},
|
},
|
||||||
|
@ -103,8 +106,7 @@
|
||||||
slotName: 'linkCase',
|
slotName: 'linkCase',
|
||||||
dataIndex: 'linkCase',
|
dataIndex: 'linkCase',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
showTooltip: true,
|
width: 150,
|
||||||
width: 300,
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -129,10 +131,9 @@
|
||||||
width: 200,
|
width: 200,
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(planDetailBugPage, {
|
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(planDetailBugPage, {
|
||||||
columns,
|
columns: columns.value,
|
||||||
tableKey: TableKeyEnum.TEST_PLAN_DETAIL_BUG_TABLE,
|
tableKey: TableKeyEnum.TEST_PLAN_DETAIL_BUG_TABLE,
|
||||||
scroll: { x: '100%' },
|
scroll: { x: '100%' },
|
||||||
showSelectorAll: false,
|
showSelectorAll: false,
|
||||||
|
@ -144,18 +145,40 @@
|
||||||
return propsRes.value.msPagination?.total || 0;
|
return propsRes.value.msPagination?.total || 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
function initData() {
|
function getFetch() {
|
||||||
setLoadListParams({
|
setLoadListParams({
|
||||||
planId: props.planId,
|
planId: planId.value,
|
||||||
keyword: keyword.value,
|
keyword: keyword.value,
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
});
|
});
|
||||||
loadList();
|
loadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tableRef = ref<InstanceType<typeof MsBaseTable>>();
|
||||||
|
async function initFilterOptions() {
|
||||||
|
if (hasAnyPermission(['PROJECT_BUG:READ'])) {
|
||||||
|
const res = await getCustomOptionHeader(appStore.currentProjectId);
|
||||||
|
const optionsMap: Record<string, any> = {
|
||||||
|
status: res.statusOption,
|
||||||
|
};
|
||||||
|
columns.value = makeColumns(optionsMap, columns.value);
|
||||||
|
}
|
||||||
|
tableRef.value?.initColumn(columns.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toDetail(id: string) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('id', id);
|
||||||
|
// TODO: 查看详情
|
||||||
|
// window.open(
|
||||||
|
// `${window.location.origin}#${
|
||||||
|
// router.resolve({ name: BugManagementRouteEnum.BUG_MANAGEMENT_INDEX }).fullPath
|
||||||
|
// }?id=${id}&orgId=${appStore.currentOrgId}&pId=${appStore.currentProjectId}`
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
initData();
|
initFilterOptions();
|
||||||
|
getFetch();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
|
|
|
@ -107,8 +107,7 @@
|
||||||
:can-edit="detail.status !== 'ARCHIVED'"
|
:can-edit="detail.status !== 'ARCHIVED'"
|
||||||
@refresh="initDetail"
|
@refresh="initDetail"
|
||||||
/>
|
/>
|
||||||
<!-- TODO 先不上 -->
|
<BugManagement v-if="activeTab === 'defectList'" />
|
||||||
<!-- <BugManagement v-if="activeTab === 'defectList'" :plan-id="detail.id" /> -->
|
|
||||||
</MsCard>
|
</MsCard>
|
||||||
<AssociateDrawer
|
<AssociateDrawer
|
||||||
v-model:visible="caseAssociateVisible"
|
v-model:visible="caseAssociateVisible"
|
||||||
|
@ -303,11 +302,10 @@
|
||||||
value: 'featureCase',
|
value: 'featureCase',
|
||||||
label: t('menu.caseManagement.featureCase'),
|
label: t('menu.caseManagement.featureCase'),
|
||||||
},
|
},
|
||||||
// TODO 先不上
|
{
|
||||||
// {
|
value: 'defectList',
|
||||||
// key: 'defectList',
|
label: t('caseManagement.featureCase.defectList'),
|
||||||
// title: t('caseManagement.featureCase.defectList'),
|
},
|
||||||
// },
|
|
||||||
]);
|
]);
|
||||||
const hasSelectedIds = ref<string[]>([]);
|
const hasSelectedIds = ref<string[]>([]);
|
||||||
const caseAssociateVisible = ref(false);
|
const caseAssociateVisible = ref(false);
|
||||||
|
|
|
@ -90,7 +90,6 @@ export default {
|
||||||
'testPlan.bugManagement.bug': 'Defect list',
|
'testPlan.bugManagement.bug': 'Defect list',
|
||||||
'testPlan.bugManagement.bugName': 'name',
|
'testPlan.bugManagement.bugName': 'name',
|
||||||
'testPlan.bugManagement.defectState': 'Defect state',
|
'testPlan.bugManagement.defectState': 'Defect state',
|
||||||
'testPlan.bugManagement.caseClassification': 'Classification',
|
|
||||||
'testPlan.featureCase.bugCount': 'Bug count',
|
'testPlan.featureCase.bugCount': 'Bug count',
|
||||||
'testPlan.featureCase.executor': 'Executor',
|
'testPlan.featureCase.executor': 'Executor',
|
||||||
'testPlan.featureCase.changeExecutor': 'Change executor',
|
'testPlan.featureCase.changeExecutor': 'Change executor',
|
||||||
|
|
|
@ -85,7 +85,6 @@ export default {
|
||||||
'testPlan.bugManagement.bug': '缺陷列表',
|
'testPlan.bugManagement.bug': '缺陷列表',
|
||||||
'testPlan.bugManagement.bugName': '名称',
|
'testPlan.bugManagement.bugName': '名称',
|
||||||
'testPlan.bugManagement.defectState': '缺陷状态',
|
'testPlan.bugManagement.defectState': '缺陷状态',
|
||||||
'testPlan.bugManagement.caseClassification': '用例分类',
|
|
||||||
'testPlan.featureCase.bugCount': '缺陷数',
|
'testPlan.featureCase.bugCount': '缺陷数',
|
||||||
'testPlan.featureCase.bug': '缺陷',
|
'testPlan.featureCase.bug': '缺陷',
|
||||||
'testPlan.featureCase.executor': '执行人',
|
'testPlan.featureCase.executor': '执行人',
|
||||||
|
|
Loading…
Reference in New Issue