feat(工作台): 待办/我的创建/我的关注页面展示逻辑调整
This commit is contained in:
parent
35a5b03343
commit
796ae6bb7d
|
@ -25,7 +25,7 @@
|
||||||
useDefaultArrowIcon?: boolean;
|
useDefaultArrowIcon?: boolean;
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'change', val: string): void;
|
(e: 'change', val: string, project?: ProjectListItem): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
@ -34,6 +34,14 @@
|
||||||
default: () => '',
|
default: () => '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function selectProject(
|
||||||
|
value: string | number | boolean | Record<string, any> | (string | number | boolean | Record<string, any>)[]
|
||||||
|
) {
|
||||||
|
project.value = value as string;
|
||||||
|
const _project = projectList.value.find((item) => item.id === value);
|
||||||
|
emit('change', value as string, _project);
|
||||||
|
}
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
if (!project.value) {
|
if (!project.value) {
|
||||||
project.value = appStore.currentProjectId;
|
project.value = appStore.currentProjectId;
|
||||||
|
@ -42,6 +50,7 @@
|
||||||
if (appStore.currentOrgId) {
|
if (appStore.currentOrgId) {
|
||||||
const res = await getProjectList(appStore.getCurrentOrgId);
|
const res = await getProjectList(appStore.getCurrentOrgId);
|
||||||
projectList.value = res;
|
projectList.value = res;
|
||||||
|
selectProject(project.value);
|
||||||
} else {
|
} else {
|
||||||
projectList.value = [];
|
projectList.value = [];
|
||||||
}
|
}
|
||||||
|
@ -50,12 +59,6 @@
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function selectProject(
|
|
||||||
value: string | number | boolean | Record<string, any> | (string | number | boolean | Record<string, any>)[]
|
|
||||||
) {
|
|
||||||
emit('change', value as string);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<a-popover position="bottom" content-class="p-[16px]">
|
<a-popover position="bottom" content-class="ms-color-line-popper">
|
||||||
<div class="color-bar" :style="{ borderRadius: props.radius }">
|
<div class="color-bar" :style="{ borderRadius: props.radius }">
|
||||||
<template v-for="(item, index) in colorData">
|
<template v-for="(item, index) in colorData">
|
||||||
<div v-if="item.percentage > 0" :key="index" :style="getStyle(item, index)"></div>
|
<div v-if="item.percentage > 0" :key="index" :style="getStyle(item, index)"></div>
|
||||||
|
@ -34,9 +34,21 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="less">
|
||||||
|
.ms-color-line-popper {
|
||||||
|
padding: 16px;
|
||||||
|
.arco-popover-title {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
.arco-popover-content {
|
||||||
|
@apply mt-0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
.color-bar {
|
.color-bar {
|
||||||
@apply flex w-full overflow-hidden;
|
@apply flex w-full overflow-hidden;
|
||||||
|
|
||||||
background-color: var(--color-text-n8);
|
background-color: var(--color-text-n8);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,4 +14,5 @@ export interface ProjectListItem {
|
||||||
deleteUser: string;
|
deleteUser: string;
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
moduleIds: string[];
|
moduleIds: string[];
|
||||||
|
moduleSetting: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,15 @@
|
||||||
</template>
|
</template>
|
||||||
<span v-else>-</span>
|
<span v-else>-</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template #lineNum="{ record }">
|
||||||
|
<a-tooltip
|
||||||
|
v-if="record.errorMessage || !record.lineNum"
|
||||||
|
:content="!record.lineNum ? t('ms.taskCenter.taskDetailErrorMsg') : record.errorMessage"
|
||||||
|
>
|
||||||
|
<icon-exclamation-circle-fill class="min-w-[18px] !text-[rgb(var(--warning-6))]" />
|
||||||
|
</a-tooltip>
|
||||||
|
<div v-else>{{ record.lineNum }}</div>
|
||||||
|
</template>
|
||||||
<template #action="{ record }">
|
<template #action="{ record }">
|
||||||
<MsButton
|
<MsButton
|
||||||
v-if="[ExecuteStatusEnum.RUNNING, ExecuteStatusEnum.RERUNNING].includes(record.status)"
|
v-if="[ExecuteStatusEnum.RUNNING, ExecuteStatusEnum.RERUNNING].includes(record.status)"
|
||||||
|
@ -266,6 +275,7 @@
|
||||||
{
|
{
|
||||||
title: 'ms.taskCenter.queue',
|
title: 'ms.taskCenter.queue',
|
||||||
dataIndex: 'lineNum',
|
dataIndex: 'lineNum',
|
||||||
|
slotName: 'lineNum',
|
||||||
width: 100,
|
width: 100,
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
},
|
},
|
||||||
|
@ -631,7 +641,11 @@
|
||||||
const res = await currentQueueRequest(ids);
|
const res = await currentQueueRequest(ids);
|
||||||
propsRes.value.data.forEach((item) => {
|
propsRes.value.data.forEach((item) => {
|
||||||
const queue = res[item.id];
|
const queue = res[item.id];
|
||||||
if (queue) {
|
if (item.errorMessage) {
|
||||||
|
item.lineNum = '';
|
||||||
|
} else if (queue === -1) {
|
||||||
|
item.lineNum = t('ms.taskCenter.waitQueue');
|
||||||
|
} else if (queue) {
|
||||||
item.lineNum = queue;
|
item.lineNum = queue;
|
||||||
} else if (
|
} else if (
|
||||||
[ExecuteStatusEnum.COMPLETED, ExecuteStatusEnum.STOPPED, ExecuteStatusEnum.RUNNING].includes(item.status) ||
|
[ExecuteStatusEnum.COMPLETED, ExecuteStatusEnum.STOPPED, ExecuteStatusEnum.RUNNING].includes(item.status) ||
|
||||||
|
@ -639,7 +653,7 @@
|
||||||
) {
|
) {
|
||||||
item.lineNum = '-';
|
item.lineNum = '-';
|
||||||
} else {
|
} else {
|
||||||
item.lineNum = t('ms.taskCenter.waitQueue');
|
item.lineNum = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -45,63 +45,11 @@
|
||||||
{{ t(executeMethodMap[record.triggerMode]) }}
|
{{ t(executeMethodMap[record.triggerMode]) }}
|
||||||
</template>
|
</template>
|
||||||
<template #executeRate="{ record }">
|
<template #executeRate="{ record }">
|
||||||
<a-popover
|
<executeRatePopper
|
||||||
v-model:popup-visible="record.executeRatePopVisible"
|
v-model:visible="record.executeRatePopVisible"
|
||||||
trigger="hover"
|
:record="record"
|
||||||
position="bottom"
|
:execute-task-statistics-request="currentExecuteTaskStatistics"
|
||||||
:disabled="record.caseTotal === 0 || record.status === ExecuteStatusEnum.PENDING"
|
/>
|
||||||
@popup-visible-change="($event) => handleExecuteRatePopVisibleChange($event, record)"
|
|
||||||
>
|
|
||||||
<div>{{ record.executeRate || '0.00' }}%</div>
|
|
||||||
<template #content>
|
|
||||||
<a-spin :loading="record.loading" class="flex w-[130px] flex-col gap-[8px]">
|
|
||||||
<div class="ms-taskCenter-execute-rate-item">
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-label">
|
|
||||||
{{ t('ms.taskCenter.executeFinishedRate') }}
|
|
||||||
</div>
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-value">
|
|
||||||
{{ `${record.executeRate}%` }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ms-taskCenter-execute-rate-item">
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-label">
|
|
||||||
<div
|
|
||||||
:class="`ms-taskCenter-execute-rate-item-label-point bg-[${executeFinishedRateMap.UN_EXECUTE.color}]`"
|
|
||||||
></div>
|
|
||||||
{{ t(executeFinishedRateMap.UN_EXECUTE.label) }}
|
|
||||||
</div>
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-value">{{ record.pendingCount }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="ms-taskCenter-execute-rate-item">
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-label">
|
|
||||||
<div
|
|
||||||
:class="`ms-taskCenter-execute-rate-item-label-point bg-[${executeFinishedRateMap.SUCCESS.color}]`"
|
|
||||||
></div>
|
|
||||||
{{ t(executeFinishedRateMap.SUCCESS.label) }}
|
|
||||||
</div>
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-value">{{ record.successCount }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="ms-taskCenter-execute-rate-item">
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-label">
|
|
||||||
<div
|
|
||||||
:class="`ms-taskCenter-execute-rate-item-label-point bg-[${executeFinishedRateMap.FAKE_ERROR.color}]`"
|
|
||||||
></div>
|
|
||||||
{{ t(executeFinishedRateMap.FAKE_ERROR.label) }}
|
|
||||||
</div>
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-value">{{ record.fakeErrorCount }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="ms-taskCenter-execute-rate-item">
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-label">
|
|
||||||
<div
|
|
||||||
:class="`ms-taskCenter-execute-rate-item-label-point bg-[${executeFinishedRateMap.ERROR.color}]`"
|
|
||||||
></div>
|
|
||||||
{{ t(executeFinishedRateMap.ERROR.label) }}
|
|
||||||
</div>
|
|
||||||
<div class="ms-taskCenter-execute-rate-item-value">{{ record.errorCount }}</div>
|
|
||||||
</div>
|
|
||||||
</a-spin>
|
|
||||||
</template>
|
|
||||||
</a-popover>
|
|
||||||
</template>
|
</template>
|
||||||
<template #action="{ record }">
|
<template #action="{ record }">
|
||||||
<MsButton
|
<MsButton
|
||||||
|
@ -178,6 +126,7 @@
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
import batchTaskReportDrawer from './batchTaskReportDrawer.vue';
|
import batchTaskReportDrawer from './batchTaskReportDrawer.vue';
|
||||||
import execStatus from './execStatus.vue';
|
import execStatus from './execStatus.vue';
|
||||||
|
import executeRatePopper from './executeRatePopper.vue';
|
||||||
import executionStatus from './executionStatus.vue';
|
import executionStatus from './executionStatus.vue';
|
||||||
import CaseReportDrawer from '@/views/api-test/report/component/caseReportDrawer.vue';
|
import CaseReportDrawer from '@/views/api-test/report/component/caseReportDrawer.vue';
|
||||||
import ReportDetailDrawer from '@/views/api-test/report/component/reportDetailDrawer.vue';
|
import ReportDetailDrawer from '@/views/api-test/report/component/reportDetailDrawer.vue';
|
||||||
|
@ -225,7 +174,7 @@
|
||||||
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
||||||
import { ExecuteStatusEnum, ExecuteTaskType } from '@/enums/taskCenter';
|
import { ExecuteStatusEnum, ExecuteTaskType } from '@/enums/taskCenter';
|
||||||
|
|
||||||
import { executeFinishedRateMap, executeMethodMap, executeResultMap, executeStatusMap } from './config';
|
import { executeMethodMap, executeResultMap, executeStatusMap } from './config';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
type: 'system' | 'project' | 'org';
|
type: 'system' | 'project' | 'org';
|
||||||
|
@ -538,26 +487,6 @@
|
||||||
initTaskStatistics();
|
initTaskStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleExecuteRatePopVisibleChange(visible: boolean, record: TaskCenterTaskItem) {
|
|
||||||
if (visible) {
|
|
||||||
try {
|
|
||||||
record.loading = true;
|
|
||||||
const res = await currentExecuteTaskStatistics([record.id]);
|
|
||||||
record.executeRate = res[0].executeRate;
|
|
||||||
record.pendingCount = res[0].pendingCount;
|
|
||||||
record.successCount = res[0].successCount;
|
|
||||||
record.fakeErrorCount = res[0].fakeErrorCount;
|
|
||||||
record.errorCount = res[0].errorCount;
|
|
||||||
record.caseTotal = res[0].caseTotal;
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
record.loading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showTaskDetail(id: string) {
|
function showTaskDetail(id: string) {
|
||||||
emit('goDetail', id);
|
emit('goDetail', id);
|
||||||
}
|
}
|
||||||
|
@ -816,23 +745,4 @@
|
||||||
await tableStore.initColumn(TableKeyEnum.TASK_CENTER_CASE_TASK, columns, 'drawer');
|
await tableStore.initColumn(TableKeyEnum.TASK_CENTER_CASE_TASK, columns, 'drawer');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less"></style>
|
||||||
.ms-taskCenter-execute-rate-item {
|
|
||||||
@apply flex items-center justify-between;
|
|
||||||
.ms-taskCenter-execute-rate-item-label {
|
|
||||||
@apply flex items-center;
|
|
||||||
|
|
||||||
gap: 4px;
|
|
||||||
color: var(--color-text-4);
|
|
||||||
.ms-taskCenter-execute-rate-item-label-point {
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
border-radius: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ms-taskCenter-execute-rate-item-value {
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--color-text-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
<template>
|
||||||
|
<a-popover
|
||||||
|
v-model:popup-visible="visible"
|
||||||
|
trigger="hover"
|
||||||
|
position="bottom"
|
||||||
|
:disabled="record.caseTotal === 0 || record.status === ExecuteStatusEnum.PENDING"
|
||||||
|
@popup-visible-change="($event) => handleExecuteRatePopVisibleChange($event)"
|
||||||
|
>
|
||||||
|
<div>{{ record.executeRate || '0.00' }}%</div>
|
||||||
|
<template #content>
|
||||||
|
<a-spin :loading="record.loading" class="flex w-[130px] flex-col gap-[8px]">
|
||||||
|
<div class="ms-taskCenter-execute-rate-item">
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-label">
|
||||||
|
{{ t('ms.taskCenter.executeFinishedRate') }}
|
||||||
|
</div>
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-value">
|
||||||
|
{{ `${record.executeRate}%` }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ms-taskCenter-execute-rate-item">
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-label">
|
||||||
|
<div
|
||||||
|
:class="`ms-taskCenter-execute-rate-item-label-point bg-[${executeFinishedRateMap.UN_EXECUTE.color}]`"
|
||||||
|
></div>
|
||||||
|
{{ t(executeFinishedRateMap.UN_EXECUTE.label) }}
|
||||||
|
</div>
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-value">{{ record.pendingCount }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="ms-taskCenter-execute-rate-item">
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-label">
|
||||||
|
<div
|
||||||
|
:class="`ms-taskCenter-execute-rate-item-label-point bg-[${executeFinishedRateMap.SUCCESS.color}]`"
|
||||||
|
></div>
|
||||||
|
{{ t(executeFinishedRateMap.SUCCESS.label) }}
|
||||||
|
</div>
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-value">{{ record.successCount }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="ms-taskCenter-execute-rate-item">
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-label">
|
||||||
|
<div
|
||||||
|
:class="`ms-taskCenter-execute-rate-item-label-point bg-[${executeFinishedRateMap.FAKE_ERROR.color}]`"
|
||||||
|
></div>
|
||||||
|
{{ t(executeFinishedRateMap.FAKE_ERROR.label) }}
|
||||||
|
</div>
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-value">{{ record.fakeErrorCount }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="ms-taskCenter-execute-rate-item">
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-label">
|
||||||
|
<div
|
||||||
|
:class="`ms-taskCenter-execute-rate-item-label-point bg-[${executeFinishedRateMap.ERROR.color}]`"
|
||||||
|
></div>
|
||||||
|
{{ t(executeFinishedRateMap.ERROR.label) }}
|
||||||
|
</div>
|
||||||
|
<div class="ms-taskCenter-execute-rate-item-value">{{ record.errorCount }}</div>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { TaskCenterStatisticsItem, TaskCenterTaskItem } from '@/models/taskCenter';
|
||||||
|
import { ExecuteStatusEnum } from '@/enums/taskCenter';
|
||||||
|
|
||||||
|
import { executeFinishedRateMap } from './config';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
executeTaskStatisticsRequest: (ids: string[]) => Promise<TaskCenterStatisticsItem[]>;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const visible = defineModel<boolean>('visible', {
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
const record = defineModel<TaskCenterTaskItem>('record', {
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleExecuteRatePopVisibleChange(_visible: boolean) {
|
||||||
|
if (_visible) {
|
||||||
|
try {
|
||||||
|
record.value.loading = true;
|
||||||
|
const res = await props.executeTaskStatisticsRequest([record.value.id]);
|
||||||
|
record.value.executeRate = res[0].executeRate;
|
||||||
|
record.value.pendingCount = res[0].pendingCount;
|
||||||
|
record.value.successCount = res[0].successCount;
|
||||||
|
record.value.fakeErrorCount = res[0].fakeErrorCount;
|
||||||
|
record.value.errorCount = res[0].errorCount;
|
||||||
|
record.value.caseTotal = res[0].caseTotal;
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
record.value.loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.ms-taskCenter-execute-rate-item {
|
||||||
|
@apply flex items-center justify-between;
|
||||||
|
.ms-taskCenter-execute-rate-item-label {
|
||||||
|
@apply flex items-center;
|
||||||
|
|
||||||
|
gap: 4px;
|
||||||
|
color: var(--color-text-4);
|
||||||
|
.ms-taskCenter-execute-rate-item-label-point {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ms-taskCenter-execute-rate-item-value {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -58,4 +58,5 @@ export default {
|
||||||
'ms.taskCenter.closeTaskSuccess': 'Task closed successfully',
|
'ms.taskCenter.closeTaskSuccess': 'Task closed successfully',
|
||||||
'ms.taskCenter.waitQueue': 'Waiting in line',
|
'ms.taskCenter.waitQueue': 'Waiting in line',
|
||||||
'ms.taskCenter.caseName': 'Case name',
|
'ms.taskCenter.caseName': 'Case name',
|
||||||
|
'ms.taskCenter.taskDetailErrorMsg': 'The resource pool is unavailable/restarted, please restart the task execution',
|
||||||
};
|
};
|
||||||
|
|
|
@ -58,4 +58,5 @@ export default {
|
||||||
'ms.taskCenter.closeTaskSuccess': '任务关闭成功',
|
'ms.taskCenter.closeTaskSuccess': '任务关闭成功',
|
||||||
'ms.taskCenter.waitQueue': '等待排队',
|
'ms.taskCenter.waitQueue': '等待排队',
|
||||||
'ms.taskCenter.caseName': '用例名称',
|
'ms.taskCenter.caseName': '用例名称',
|
||||||
|
'ms.taskCenter.taskDetailErrorMsg': '资源池不可用/重启,请重新发起任务执行',
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<template>
|
||||||
|
<a-popover position="bottom" content-class="testPlanTable-caseCount-popper" :disabled="getFunctionalCount(id) < 1">
|
||||||
|
<div>{{ getFunctionalCount(id) }}</div>
|
||||||
|
<template #content>
|
||||||
|
<table class="min-w-[140px] max-w-[176px]">
|
||||||
|
<tr>
|
||||||
|
<td class="popover-label-td !pt-0">
|
||||||
|
<div>{{ t('testPlan.testPlanIndex.TotalCases') }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="popover-value-td !pt-0">
|
||||||
|
{{ defaultCountDetailMap[id]?.caseTotal ?? '0' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="popover-label-td">
|
||||||
|
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.functionalUseCase') }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="popover-value-td">
|
||||||
|
{{ defaultCountDetailMap[id]?.functionalCaseCount ?? '0' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="popover-label-td">
|
||||||
|
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.apiCase') }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="popover-value-td">
|
||||||
|
{{ defaultCountDetailMap[id]?.apiCaseCount ?? '0' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="popover-label-td">
|
||||||
|
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.apiScenarioCase') }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="popover-value-td">
|
||||||
|
{{ defaultCountDetailMap[id]?.apiScenarioCount ?? '0' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { PassRateCountDetail } from '@/models/testPlan/testPlan';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: string;
|
||||||
|
defaultCountDetailMap: Record<string, PassRateCountDetail>;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
function getFunctionalCount(id: string) {
|
||||||
|
return props.defaultCountDetailMap[id]?.caseTotal ?? 0;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.testPlanTable-caseCount-popper {
|
||||||
|
padding: 16px;
|
||||||
|
.arco-popover-title {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
.arco-popover-content {
|
||||||
|
@apply mt-0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.popover-label-td {
|
||||||
|
@apply flex items-center;
|
||||||
|
|
||||||
|
padding: 8px 8px 0 0;
|
||||||
|
color: var(--color-text-4);
|
||||||
|
}
|
||||||
|
.popover-value-td {
|
||||||
|
@apply text-right font-medium;
|
||||||
|
|
||||||
|
padding-top: 8px;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -179,45 +179,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #functionalCaseCount="{ record }">
|
<template #functionalCaseCount="{ record }">
|
||||||
<a-popover position="bottom" content-class="p-[16px]" :disabled="getFunctionalCount(record.id) < 1">
|
<caseCountPopper :id="record.id" :default-count-detail-map="defaultCountDetailMap" />
|
||||||
<div>{{ getFunctionalCount(record.id) }}</div>
|
|
||||||
<template #content>
|
|
||||||
<table class="min-w-[140px] max-w-[176px]">
|
|
||||||
<tr>
|
|
||||||
<td class="popover-label-td">
|
|
||||||
<div>{{ t('testPlan.testPlanIndex.TotalCases') }}</div>
|
|
||||||
</td>
|
|
||||||
<td class="popover-value-td">
|
|
||||||
{{ defaultCountDetailMap[record.id]?.caseTotal ?? '0' }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="popover-label-td">
|
|
||||||
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.functionalUseCase') }}</div>
|
|
||||||
</td>
|
|
||||||
<td class="popover-value-td">
|
|
||||||
{{ defaultCountDetailMap[record.id]?.functionalCaseCount ?? '0' }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="popover-label-td">
|
|
||||||
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.apiCase') }}</div>
|
|
||||||
</td>
|
|
||||||
<td class="popover-value-td">
|
|
||||||
{{ defaultCountDetailMap[record.id]?.apiCaseCount ?? '0' }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="popover-label-td">
|
|
||||||
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.apiScenarioCase') }}</div>
|
|
||||||
</td>
|
|
||||||
<td class="popover-value-td">
|
|
||||||
{{ defaultCountDetailMap[record.id]?.apiScenarioCount ?? '0' }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</template>
|
|
||||||
</a-popover>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
|
@ -384,6 +346,7 @@
|
||||||
import ActionModal from './actionModal.vue';
|
import ActionModal from './actionModal.vue';
|
||||||
import BatchEditModal from './batchEditModal.vue';
|
import BatchEditModal from './batchEditModal.vue';
|
||||||
import BatchMoveOrCopy from './batchMoveOrCopy.vue';
|
import BatchMoveOrCopy from './batchMoveOrCopy.vue';
|
||||||
|
import caseCountPopper from './caseCountPopper.vue';
|
||||||
import ScheduledModal from './scheduledModal.vue';
|
import ScheduledModal from './scheduledModal.vue';
|
||||||
import StatusProgress from './statusProgress.vue';
|
import StatusProgress from './statusProgress.vue';
|
||||||
import PlanExpandRow from '@/views/test-plan/testPlan/components/planExpandRow.vue';
|
import PlanExpandRow from '@/views/test-plan/testPlan/components/planExpandRow.vue';
|
||||||
|
@ -1745,16 +1708,4 @@
|
||||||
:deep(.arco-table-cell-align-left) > span:first-child {
|
:deep(.arco-table-cell-align-left) > span:first-child {
|
||||||
padding-left: 0 !important;
|
padding-left: 0 !important;
|
||||||
}
|
}
|
||||||
.popover-label-td {
|
|
||||||
@apply flex items-center;
|
|
||||||
|
|
||||||
padding: 8px 8px 0 0;
|
|
||||||
color: var(--color-text-4);
|
|
||||||
}
|
|
||||||
.popover-value-td {
|
|
||||||
@apply text-right font-medium;
|
|
||||||
|
|
||||||
padding-top: 8px;
|
|
||||||
color: var(--color-text-1);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
<template #popoverContent>
|
<template #popoverContent>
|
||||||
<table class="min-w-[144px]">
|
<table class="min-w-[144px]">
|
||||||
<tr v-if="props.type === testPlanTypeEnum.TEST_PLAN">
|
<tr v-if="props.type === testPlanTypeEnum.TEST_PLAN">
|
||||||
<td class="popover-label-td">
|
<td class="popover-label-td !pt-0">
|
||||||
<div>{{ t('testPlan.testPlanIndex.threshold') }}</div>
|
<div>{{ t('testPlan.testPlanIndex.threshold') }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="popover-value-td"> {{ detailCount.passThreshold }}% </td>
|
<td class="popover-value-td !pt-0"> {{ detailCount.passThreshold }}% </td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="popover-label-td">
|
<td class="popover-label-td">
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { FeatureEnum } from '@/enums/workbenchEnum';
|
||||||
|
|
||||||
|
export const featuresMap = {
|
||||||
|
[FeatureEnum.API_CASE]: 'apiTest',
|
||||||
|
[FeatureEnum.API_SCENARIO]: 'apiTest',
|
||||||
|
[FeatureEnum.CASE_REVIEW]: 'caseManagement',
|
||||||
|
[FeatureEnum.TEST_CASE]: 'caseManagement',
|
||||||
|
[FeatureEnum.TEST_PLAN]: 'testPlan',
|
||||||
|
[FeatureEnum.BUG]: 'bugManagement',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {};
|
|
@ -74,45 +74,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #functionalCaseCount="{ record }">
|
<template #functionalCaseCount="{ record }">
|
||||||
<a-popover position="bottom" content-class="p-[16px]" :disabled="getFunctionalCount(record.id) < 1">
|
<caseCountPopper :id="record.id" :default-count-detail-map="defaultCountDetailMap" />
|
||||||
<div>{{ getFunctionalCount(record.id) }}</div>
|
|
||||||
<template #content>
|
|
||||||
<table class="min-w-[140px] max-w-[176px]">
|
|
||||||
<tr>
|
|
||||||
<td class="popover-label-td">
|
|
||||||
<div>{{ t('testPlan.testPlanIndex.TotalCases') }}</div>
|
|
||||||
</td>
|
|
||||||
<td class="popover-value-td">
|
|
||||||
{{ defaultCountDetailMap[record.id]?.caseTotal ?? '0' }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="popover-label-td">
|
|
||||||
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.functionalUseCase') }}</div>
|
|
||||||
</td>
|
|
||||||
<td class="popover-value-td">
|
|
||||||
{{ defaultCountDetailMap[record.id]?.functionalCaseCount ?? '0' }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="popover-label-td">
|
|
||||||
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.apiCase') }}</div>
|
|
||||||
</td>
|
|
||||||
<td class="popover-value-td">
|
|
||||||
{{ defaultCountDetailMap[record.id]?.apiCaseCount ?? '0' }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="popover-label-td">
|
|
||||||
<div class="text-[var(--color-text-1)]">{{ t('testPlan.testPlanIndex.apiScenarioCase') }}</div>
|
|
||||||
</td>
|
|
||||||
<td class="popover-value-td">
|
|
||||||
{{ defaultCountDetailMap[record.id]?.apiScenarioCount ?? '0' }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</template>
|
|
||||||
</a-popover>
|
|
||||||
</template>
|
</template>
|
||||||
</MsBaseTable>
|
</MsBaseTable>
|
||||||
</MsCard>
|
</MsCard>
|
||||||
|
@ -126,6 +88,7 @@
|
||||||
import { MsTableColumn, MsTableProps } from '@/components/pure/ms-table/type';
|
import { MsTableColumn, MsTableProps } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsStatusTag from '@/components/business/ms-status-tag/index.vue';
|
import MsStatusTag from '@/components/business/ms-status-tag/index.vue';
|
||||||
|
import caseCountPopper from '@/views/test-plan/testPlan/components/caseCountPopper.vue';
|
||||||
import PlanExpandRow from '@/views/test-plan/testPlan/components/planExpandRow.vue';
|
import PlanExpandRow from '@/views/test-plan/testPlan/components/planExpandRow.vue';
|
||||||
import StatusProgress from '@/views/test-plan/testPlan/components/statusProgress.vue';
|
import StatusProgress from '@/views/test-plan/testPlan/components/statusProgress.vue';
|
||||||
|
|
||||||
|
@ -158,10 +121,6 @@
|
||||||
|
|
||||||
const defaultCountDetailMap = ref<Record<string, PassRateCountDetail>>({});
|
const defaultCountDetailMap = ref<Record<string, PassRateCountDetail>>({});
|
||||||
|
|
||||||
function getFunctionalCount(id: string) {
|
|
||||||
return defaultCountDetailMap.value[id]?.caseTotal ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStatus(id: string) {
|
function getStatus(id: string) {
|
||||||
return defaultCountDetailMap.value[id]?.status;
|
return defaultCountDetailMap.value[id]?.status;
|
||||||
}
|
}
|
||||||
|
@ -325,4 +284,8 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped>
|
||||||
|
:deep(.arco-table-cell-expand-icon .arco-table-cell-inline-icon) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
:has-all-select="true"
|
:has-all-select="true"
|
||||||
:default-all-select="true"
|
:default-all-select="true"
|
||||||
/>
|
/>
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[10px]" @click="handleRefresh">
|
<a-button type="outline" class="arco-btn-outline--secondary p-[10px]" @click="() => handleRefresh()">
|
||||||
<MsIcon type="icon-icon_reset_outlined" size="14" />
|
<MsIcon type="icon-icon_reset_outlined" size="14" />
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -70,6 +70,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { SelectOptionData } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
import MsProjectSelect from '@/components/business/ms-project-select/index.vue';
|
import MsProjectSelect from '@/components/business/ms-project-select/index.vue';
|
||||||
import MsSelect from '@/components/business/ms-select';
|
import MsSelect from '@/components/business/ms-select';
|
||||||
|
@ -85,20 +87,31 @@
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { getGenerateId } from '@/utils';
|
import { getGenerateId } from '@/utils';
|
||||||
|
|
||||||
|
import { ProjectListItem } from '@/models/setting/project';
|
||||||
import { FeatureEnum } from '@/enums/workbenchEnum';
|
import { FeatureEnum } from '@/enums/workbenchEnum';
|
||||||
|
|
||||||
|
import { featuresMap } from '../components/config';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const currentProject = ref(appStore.currentProjectId);
|
const currentProject = ref(appStore.currentProjectId);
|
||||||
const features = ref<FeatureEnum[]>(Object.values(FeatureEnum));
|
const features = ref<FeatureEnum[]>([]);
|
||||||
const featureOptions = Object.keys(FeatureEnum).map((key) => ({
|
const fullFeaturesOptions = Object.keys(FeatureEnum).map((key) => ({
|
||||||
label: t(`ms.workbench.myFollowed.feature.${key}`),
|
label: t(`ms.workbench.myFollowed.feature.${key}`),
|
||||||
value: key as FeatureEnum,
|
value: key as FeatureEnum,
|
||||||
}));
|
}));
|
||||||
|
const featureOptions = ref<SelectOptionData[]>([]);
|
||||||
const refreshId = ref('');
|
const refreshId = ref('');
|
||||||
|
|
||||||
function handleRefresh() {
|
function handleRefresh(val?: string, _project?: ProjectListItem) {
|
||||||
|
if (_project) {
|
||||||
|
const _currentProjectFeatures = JSON.parse(_project.moduleSetting);
|
||||||
|
featureOptions.value = fullFeaturesOptions.filter((item) =>
|
||||||
|
_currentProjectFeatures.includes(featuresMap[item.value])
|
||||||
|
);
|
||||||
|
features.value = featureOptions.value.map((item) => item.value as FeatureEnum);
|
||||||
|
}
|
||||||
refreshId.value = getGenerateId();
|
refreshId.value = getGenerateId();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
:has-all-select="true"
|
:has-all-select="true"
|
||||||
:default-all-select="true"
|
:default-all-select="true"
|
||||||
/>
|
/>
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[10px]" @click="handleRefresh">
|
<a-button type="outline" class="arco-btn-outline--secondary p-[10px]" @click="() => handleRefresh()">
|
||||||
<MsIcon type="icon-icon_reset_outlined" size="14" />
|
<MsIcon type="icon-icon_reset_outlined" size="14" />
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -69,6 +69,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { SelectOptionData } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
import MsProjectSelect from '@/components/business/ms-project-select/index.vue';
|
import MsProjectSelect from '@/components/business/ms-project-select/index.vue';
|
||||||
import MsSelect from '@/components/business/ms-select';
|
import MsSelect from '@/components/business/ms-select';
|
||||||
|
@ -84,20 +86,31 @@
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { getGenerateId } from '@/utils';
|
import { getGenerateId } from '@/utils';
|
||||||
|
|
||||||
|
import { ProjectListItem } from '@/models/setting/project';
|
||||||
import { FeatureEnum } from '@/enums/workbenchEnum';
|
import { FeatureEnum } from '@/enums/workbenchEnum';
|
||||||
|
|
||||||
|
import { featuresMap } from '../components/config';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const currentProject = ref(appStore.currentProjectId);
|
const currentProject = ref(appStore.currentProjectId);
|
||||||
const features = ref<FeatureEnum[]>(Object.values(FeatureEnum));
|
const features = ref<FeatureEnum[]>([]);
|
||||||
const featureOptions = Object.keys(FeatureEnum).map((key) => ({
|
const fullFeaturesOptions = Object.keys(FeatureEnum).map((key) => ({
|
||||||
label: t(`ms.workbench.myFollowed.feature.${key}`),
|
label: t(`ms.workbench.myFollowed.feature.${key}`),
|
||||||
value: key as FeatureEnum,
|
value: key as FeatureEnum,
|
||||||
}));
|
}));
|
||||||
|
const featureOptions = ref<SelectOptionData[]>([]);
|
||||||
const refreshId = ref('');
|
const refreshId = ref('');
|
||||||
|
|
||||||
function handleRefresh() {
|
function handleRefresh(val?: string, _project?: ProjectListItem) {
|
||||||
|
if (_project) {
|
||||||
|
const _currentProjectFeatures = JSON.parse(_project.moduleSetting);
|
||||||
|
featureOptions.value = fullFeaturesOptions.filter((item) =>
|
||||||
|
_currentProjectFeatures.includes(featuresMap[item.value])
|
||||||
|
);
|
||||||
|
features.value = featureOptions.value.map((item) => item.value as FeatureEnum);
|
||||||
|
}
|
||||||
refreshId.value = getGenerateId();
|
refreshId.value = getGenerateId();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -2,7 +2,12 @@
|
||||||
<div class="flex flex-col gap-[16px]">
|
<div class="flex flex-col gap-[16px]">
|
||||||
<template v-if="appStore.projectList.length > 0">
|
<template v-if="appStore.projectList.length > 0">
|
||||||
<div class="flex items-center justify-end gap-[12px]">
|
<div class="flex items-center justify-end gap-[12px]">
|
||||||
<MsProjectSelect v-model:project="currentProject" class="w-[240px]" use-default-arrow-icon>
|
<MsProjectSelect
|
||||||
|
v-model:project="currentProject"
|
||||||
|
class="w-[240px]"
|
||||||
|
use-default-arrow-icon
|
||||||
|
@change="handleRefresh"
|
||||||
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
{{ t('menu.projectManagementShort') }}
|
{{ t('menu.projectManagementShort') }}
|
||||||
</template>
|
</template>
|
||||||
|
@ -18,7 +23,7 @@
|
||||||
:has-all-select="true"
|
:has-all-select="true"
|
||||||
:default-all-select="true"
|
:default-all-select="true"
|
||||||
/>
|
/>
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary p-[10px]" @click="handleRefresh">
|
<a-button type="outline" class="arco-btn-outline--secondary p-[10px]" @click="() => handleRefresh()">
|
||||||
<MsIcon type="icon-icon_reset_outlined" size="14" />
|
<MsIcon type="icon-icon_reset_outlined" size="14" />
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -47,6 +52,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { SelectOptionData } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
import MsProjectSelect from '@/components/business/ms-project-select/index.vue';
|
import MsProjectSelect from '@/components/business/ms-project-select/index.vue';
|
||||||
import MsSelect from '@/components/business/ms-select';
|
import MsSelect from '@/components/business/ms-select';
|
||||||
|
@ -59,22 +66,33 @@
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { getGenerateId } from '@/utils';
|
import { getGenerateId } from '@/utils';
|
||||||
|
|
||||||
|
import { ProjectListItem } from '@/models/setting/project';
|
||||||
import { FeatureEnum } from '@/enums/workbenchEnum';
|
import { FeatureEnum } from '@/enums/workbenchEnum';
|
||||||
|
|
||||||
|
import { featuresMap } from '../components/config';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const currentProject = ref(appStore.currentProjectId);
|
const currentProject = ref(appStore.currentProjectId);
|
||||||
const features = ref<FeatureEnum[]>(Object.values(FeatureEnum));
|
const features = ref<FeatureEnum[]>([]);
|
||||||
const featureOptions = Object.keys(FeatureEnum)
|
const fullFeaturesOptions = Object.keys(FeatureEnum)
|
||||||
.filter((e) => [FeatureEnum.TEST_PLAN, FeatureEnum.CASE_REVIEW, FeatureEnum.BUG].includes(e as FeatureEnum))
|
.filter((e) => [FeatureEnum.TEST_PLAN, FeatureEnum.CASE_REVIEW, FeatureEnum.BUG].includes(e as FeatureEnum))
|
||||||
.map((key) => ({
|
.map((key) => ({
|
||||||
label: t(`ms.workbench.myFollowed.feature.${key}`),
|
label: t(`ms.workbench.myFollowed.feature.${key}`),
|
||||||
value: key as FeatureEnum,
|
value: key as FeatureEnum,
|
||||||
}));
|
}));
|
||||||
|
const featureOptions = ref<SelectOptionData[]>([]);
|
||||||
const refreshId = ref('');
|
const refreshId = ref('');
|
||||||
|
|
||||||
function handleRefresh() {
|
function handleRefresh(val?: string, _project?: ProjectListItem) {
|
||||||
|
if (_project) {
|
||||||
|
const _currentProjectFeatures = JSON.parse(_project.moduleSetting);
|
||||||
|
featureOptions.value = fullFeaturesOptions.filter((item) =>
|
||||||
|
_currentProjectFeatures.includes(featuresMap[item.value])
|
||||||
|
);
|
||||||
|
features.value = featureOptions.value.map((item) => item.value as FeatureEnum);
|
||||||
|
}
|
||||||
refreshId.value = getGenerateId();
|
refreshId.value = getGenerateId();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue