feat(工作台): 工作台卡片增加骨架屏loading
This commit is contained in:
parent
4039bab50e
commit
2c40fc7757
|
@ -1,53 +1,60 @@
|
|||
<template>
|
||||
<div class="card-wrapper card-min-height">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<div class="case-count-wrapper">
|
||||
<div class="case-count-item">
|
||||
<div v-for="(ele, index) of executionTimeValue" :key="index" class="case-count-item-content">
|
||||
<div class="case-count-item-title">{{ ele.name }}</div>
|
||||
<div class="case-count-item-number">{{ hasPermission ? addCommasToNumber(ele.count as number) : '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="case-count-item">
|
||||
<div v-for="(ele, index) of apiCountValue" :key="index" class="case-count-item-content">
|
||||
<div class="case-count-item-title">{{ ele.name }}</div>
|
||||
<div class="case-count-item-number">{{ hasPermission ? addCommasToNumber(ele.count as number) : '-' }}</div>
|
||||
</div>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="case-ratio-wrapper mt-[16px]">
|
||||
<div class="case-ratio-item">
|
||||
<RatioPie
|
||||
:has-permission="hasPermission"
|
||||
:loading="loading"
|
||||
:data="coverData"
|
||||
:rate-config="coverTitleConfig"
|
||||
/>
|
||||
<div class="mt-[16px]">
|
||||
<div class="case-count-wrapper">
|
||||
<div class="case-count-item">
|
||||
<div v-for="(ele, index) of executionTimeValue" :key="index" class="case-count-item-content">
|
||||
<div class="case-count-item-title">{{ ele.name }}</div>
|
||||
<div class="case-count-item-number">
|
||||
{{ hasPermission ? addCommasToNumber(ele.count as number) : '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="case-count-item">
|
||||
<div v-for="(ele, index) of apiCountValue" :key="index" class="case-count-item-content">
|
||||
<div class="case-count-item-title">{{ ele.name }}</div>
|
||||
<div class="case-count-item-number">
|
||||
{{ hasPermission ? addCommasToNumber(ele.count as number) : '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="case-ratio-item">
|
||||
<RatioPie :has-permission="hasPermission" :data="caseExecuteData" :rate-config="executeTitleConfig" />
|
||||
</div>
|
||||
<div class="case-ratio-item">
|
||||
<RatioPie :has-permission="hasPermission" :data="casePassData" :rate-config="casePassTitleConfig" />
|
||||
<div class="case-ratio-wrapper mt-[16px]">
|
||||
<div class="case-ratio-item">
|
||||
<RatioPie
|
||||
:has-permission="hasPermission"
|
||||
:loading="loading"
|
||||
:data="coverData"
|
||||
:rate-config="coverTitleConfig"
|
||||
/>
|
||||
</div>
|
||||
<div class="case-ratio-item">
|
||||
<RatioPie :has-permission="hasPermission" :data="caseExecuteData" :rate-config="executeTitleConfig" />
|
||||
</div>
|
||||
<div class="case-ratio-item">
|
||||
<RatioPie :has-permission="hasPermission" :data="casePassData" :rate-config="casePassTitleConfig" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -62,6 +69,7 @@
|
|||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
import RatioPie from './ratioPie.vue';
|
||||
|
||||
import { workApiCaseCountDetail, workApiCountCoverRage, workScenarioCaseCountDetail } from '@/api/modules/workbench';
|
||||
|
@ -244,8 +252,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function initApiOrScenarioCount() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
coverData.value = cloneDeep(initCoverRate);
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
|
||||
|
@ -292,6 +303,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,47 +1,50 @@
|
|||
<template>
|
||||
<div class="card-wrapper card-min-height">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<MsBaseTable
|
||||
v-bind="propsRes"
|
||||
:action-config="{
|
||||
baseAction: [],
|
||||
moreAction: [],
|
||||
}"
|
||||
class="mt-[16px]"
|
||||
v-on="propsEvent"
|
||||
>
|
||||
<template #num="{ record }">
|
||||
<MsButton type="text" @click="openDetail(record)">{{ record.num || '-' }}</MsButton>
|
||||
</template>
|
||||
<template v-if="isNoPermission" #empty>
|
||||
<div class="w-full">
|
||||
<slot name="empty">
|
||||
<div class="flex h-[40px] flex-col items-center justify-center">
|
||||
<span class="text-[14px] text-[var(--color-text-4)]">{{ t('common.noResource') }}</span>
|
||||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<MsBaseTable
|
||||
v-bind="propsRes"
|
||||
:action-config="{
|
||||
baseAction: [],
|
||||
moreAction: [],
|
||||
}"
|
||||
class="mt-[16px]"
|
||||
v-on="propsEvent"
|
||||
>
|
||||
<template #num="{ record }">
|
||||
<MsButton type="text" @click="openDetail(record)">{{ record.num || '-' }}</MsButton>
|
||||
</template>
|
||||
<template v-if="isNoPermission" #empty>
|
||||
<div class="w-full">
|
||||
<slot name="empty">
|
||||
<div class="flex h-[40px] flex-col items-center justify-center">
|
||||
<span class="text-[14px] text-[var(--color-text-4)]">{{ t('common.noResource') }}</span>
|
||||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -58,6 +61,7 @@
|
|||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
|
||||
import { workApiChangeList } from '@/api/modules/workbench';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
@ -168,7 +172,9 @@
|
|||
}
|
||||
|
||||
const isNoPermission = ref<boolean>(false);
|
||||
const showSkeleton = ref(false);
|
||||
async function initData() {
|
||||
showSkeleton.value = true;
|
||||
try {
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
setLoadListParams({
|
||||
|
@ -185,6 +191,8 @@
|
|||
isNoPermission.value = error === 'no_project_permission';
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,39 +1,42 @@
|
|||
<template>
|
||||
<div class="card-wrapper api-count-wrapper card-min-height">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-[16px]">
|
||||
<TabCard :content-tab-list="apiCountTabList" not-has-padding hidden-border min-width="296px">
|
||||
<template #item="{ item: tabItem }">
|
||||
<PassRatePie
|
||||
:tooltip-text="tabItem.tooltip"
|
||||
:options="tabItem.options"
|
||||
:size="60"
|
||||
:loading="tabItem.value === 'cover' ? loading : undefined"
|
||||
:has-permission="hasPermission"
|
||||
:value-list="tabItem.valueList"
|
||||
/>
|
||||
</template>
|
||||
</TabCard>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="apiCountOptions" />
|
||||
<div class="my-[16px]">
|
||||
<TabCard :content-tab-list="apiCountTabList" not-has-padding hidden-border min-width="296px">
|
||||
<template #item="{ item: tabItem }">
|
||||
<PassRatePie
|
||||
:tooltip-text="tabItem.tooltip"
|
||||
:options="tabItem.options"
|
||||
:size="60"
|
||||
:loading="tabItem.value === 'cover' ? loading : undefined"
|
||||
:has-permission="hasPermission"
|
||||
:value-list="tabItem.valueList"
|
||||
/>
|
||||
</template>
|
||||
</TabCard>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="apiCountOptions" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -47,6 +50,7 @@
|
|||
|
||||
import MsChart from '@/components/pure/chart/index.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
import PassRatePie from './passRatePie.vue';
|
||||
import TabCard from './tabCard.vue';
|
||||
|
||||
|
@ -144,8 +148,6 @@
|
|||
coverOptions.value = { ...covOptions };
|
||||
}
|
||||
async function initApiCountRate() {
|
||||
console.log(hasPermission.value);
|
||||
|
||||
try {
|
||||
loading.value = true;
|
||||
const detail = await workApiCountCoverRage(projectId.value);
|
||||
|
@ -158,8 +160,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function initApiCount() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const detail = await workApiCountDetail({
|
||||
current: 1,
|
||||
|
@ -187,6 +193,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<template>
|
||||
<a-skeleton v-if="props.showSkeleton" :loading="props.showSkeleton" :animation="true">
|
||||
<div class="flex gap-[16px]">
|
||||
<div class="flex-1">
|
||||
<a-skeleton-line :rows="1" :line-height="props.skeletonLine" />
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<a-skeleton-line :rows="1" :line-height="props.skeletonLine" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div v-for="index in props.showLineNumber" :key="index" class="mt-[16px] flex flex-col">
|
||||
<div class="flex gap-4">
|
||||
<div :style="{ width: `${index * 12}%` }">
|
||||
<a-skeleton-line :rows="1" :line-height="props.skeletonLine" />
|
||||
</div>
|
||||
<div :style="{ width: `calc(100% - ${index * 12}%)` }">
|
||||
<a-skeleton-line :rows="1" :line-height="props.skeletonLine" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-skeleton>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
showSkeleton: boolean;
|
||||
skeletonLine?: number;
|
||||
showLineNumber?: number;
|
||||
}>(),
|
||||
{
|
||||
skeletonLine: 24,
|
||||
showLineNumber: 7,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -1,40 +1,43 @@
|
|||
<template>
|
||||
<div class="card-wrapper card-min-height">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<TabCard :content-tab-list="caseCountTabList" not-has-padding hidden-border min-width="270px">
|
||||
<template #item="{ item: tabItem }">
|
||||
<div class="w-full">
|
||||
<PassRatePie
|
||||
:options="tabItem.options"
|
||||
:tooltip-text="tabItem.tooltip"
|
||||
:size="60"
|
||||
:value-list="tabItem.valueList"
|
||||
:has-permission="hasPermission"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</TabCard>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="caseCountOptions" />
|
||||
<div class="mt-[16px]">
|
||||
<TabCard :content-tab-list="caseCountTabList" not-has-padding hidden-border min-width="270px">
|
||||
<template #item="{ item: tabItem }">
|
||||
<div class="w-full">
|
||||
<PassRatePie
|
||||
:options="tabItem.options"
|
||||
:tooltip-text="tabItem.tooltip"
|
||||
:size="60"
|
||||
:value-list="tabItem.valueList"
|
||||
:has-permission="hasPermission"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</TabCard>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="caseCountOptions" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -48,6 +51,7 @@
|
|||
|
||||
import MsChart from '@/components/pure/chart/index.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
import PassRatePie from './passRatePie.vue';
|
||||
import TabCard from './tabCard.vue';
|
||||
|
||||
|
@ -114,9 +118,11 @@
|
|||
const hasPermission = ref<boolean>(false);
|
||||
|
||||
const caseCountOptions = ref<Record<string, any>>({});
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function initCaseCount() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const params = {
|
||||
current: 1,
|
||||
|
@ -152,6 +158,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,41 @@
|
|||
<template>
|
||||
<div class="card-wrapper card-min-height">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<div class="case-count-wrapper mb-[16px]">
|
||||
<div class="case-count-item">
|
||||
<PassRatePie
|
||||
:options="options"
|
||||
tooltip-text="workbench.homePage.caseReviewCoverRateTooltip"
|
||||
:size="60"
|
||||
:value-list="coverValueList"
|
||||
:has-permission="hasPermission"
|
||||
/>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="caseReviewCountOptions" />
|
||||
<div class="mt-[16px]">
|
||||
<div class="case-count-wrapper mb-[16px]">
|
||||
<div class="case-count-item">
|
||||
<PassRatePie
|
||||
:options="options"
|
||||
tooltip-text="workbench.homePage.caseReviewCoverRateTooltip"
|
||||
:size="60"
|
||||
:value-list="coverValueList"
|
||||
:has-permission="hasPermission"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="caseReviewCountOptions" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -46,6 +49,7 @@
|
|||
|
||||
import MsChart from '@/components/pure/chart/index.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
import PassRatePie from './passRatePie.vue';
|
||||
|
||||
import { workCaseReviewDetail } from '@/api/modules/workbench';
|
||||
|
@ -101,19 +105,22 @@
|
|||
const caseReviewCountOptions = ref<Record<string, any>>({});
|
||||
|
||||
const hasPermission = ref<boolean>(false);
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function initReviewCount() {
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const params = {
|
||||
current: 1,
|
||||
pageSize: 5,
|
||||
startTime: dayNumber ? null : startTime,
|
||||
endTime: dayNumber ? null : endTime,
|
||||
dayNumber: dayNumber ?? null,
|
||||
projectIds: innerProjectIds.value,
|
||||
organizationId: appStore.currentOrgId,
|
||||
handleUsers: [],
|
||||
};
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const params = {
|
||||
current: 1,
|
||||
pageSize: 5,
|
||||
startTime: dayNumber ? null : startTime,
|
||||
endTime: dayNumber ? null : endTime,
|
||||
dayNumber: dayNumber ?? null,
|
||||
projectIds: innerProjectIds.value,
|
||||
organizationId: appStore.currentOrgId,
|
||||
handleUsers: [],
|
||||
};
|
||||
const detail: PassRateDataType = await workCaseReviewDetail(params);
|
||||
|
||||
hasPermission.value = detail.errorCode !== 109001;
|
||||
|
@ -130,6 +137,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,41 @@
|
|||
<template>
|
||||
<div class="card-wrapper card-min-height">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<div class="case-count-wrapper">
|
||||
<div class="case-count-item mb-[16px]">
|
||||
<PassRatePie
|
||||
:has-permission="hasPermission"
|
||||
:tooltip-text="tooltip"
|
||||
:options="legacyOptions"
|
||||
:size="60"
|
||||
:value-list="legacyValueList"
|
||||
/>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="countOptions" />
|
||||
<div class="mt-[16px]">
|
||||
<div class="case-count-wrapper">
|
||||
<div class="case-count-item mb-[16px]">
|
||||
<PassRatePie
|
||||
:has-permission="hasPermission"
|
||||
:tooltip-text="tooltip"
|
||||
:options="legacyOptions"
|
||||
:size="60"
|
||||
:value-list="legacyValueList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="countOptions" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -46,6 +49,7 @@
|
|||
|
||||
import MsChart from '@/components/pure/chart/index.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
import PassRatePie from './passRatePie.vue';
|
||||
|
||||
import {
|
||||
|
@ -115,8 +119,11 @@
|
|||
}[props.item.key as SelectedBugCountKeys];
|
||||
|
||||
const hasPermission = ref<boolean>(false);
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function initCount() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const params = {
|
||||
current: 1,
|
||||
|
@ -161,6 +168,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,41 +1,44 @@
|
|||
<template>
|
||||
<div class="card-wrapper">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
<MsSelect
|
||||
:key="props.refreshKey"
|
||||
v-model:model-value="innerHandleUsers"
|
||||
:options="memberOptions"
|
||||
allow-clear
|
||||
allow-search
|
||||
:search-keys="['label']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.staff')"
|
||||
:multiple="true"
|
||||
:has-all-select="true"
|
||||
:default-all-select="innerHandleUsers.length === 0"
|
||||
@change="changeMember"
|
||||
>
|
||||
</MsSelect>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
<MsSelect
|
||||
:key="props.refreshKey"
|
||||
v-model:model-value="innerHandleUsers"
|
||||
:options="memberOptions"
|
||||
allow-clear
|
||||
allow-search
|
||||
:search-keys="['label']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.staff')"
|
||||
:multiple="true"
|
||||
:has-all-select="true"
|
||||
:default-all-select="innerHandleUsers.length === 0"
|
||||
@change="changeMember"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<MsChart height="260px" :options="options" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<MsChart height="260px" :options="options" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -48,6 +51,7 @@
|
|||
|
||||
import MsChart from '@/components/pure/chart/index.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
|
||||
import { workBugHandlerDetail, workHandleUserOptions } from '@/api/modules/workbench';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
@ -142,9 +146,11 @@
|
|||
});
|
||||
options.value.yAxis[0].max = maxAxis < 100 ? 50 : maxAxis + 50;
|
||||
}
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function getDefectMemberDetail() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const detail = await workBugHandlerDetail({
|
||||
current: 1,
|
||||
|
@ -161,6 +167,8 @@
|
|||
handleData(detail);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,41 @@
|
|||
<template>
|
||||
<div class="card-wrapper">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="innerProjectIds"
|
||||
:options="appStore.projectList"
|
||||
allow-clear
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
:multiple="true"
|
||||
:has-all-select="true"
|
||||
:default-all-select="innerSelectAll"
|
||||
:at-least-one="true"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-[16px]">
|
||||
<TabCard
|
||||
:content-tab-list="cardModuleList"
|
||||
:no-permission-text="hasPermission ? '' : 'workbench.homePage.notHasResPermission'"
|
||||
/>
|
||||
</div>
|
||||
<!-- 概览图 -->
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div>
|
||||
<MsChart height="280px" :options="options" />
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="innerProjectIds"
|
||||
:options="appStore.projectList"
|
||||
allow-clear
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
:multiple="true"
|
||||
:has-all-select="true"
|
||||
:default-all-select="innerSelectAll"
|
||||
:at-least-one="true"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-[16px]">
|
||||
<TabCard
|
||||
:content-tab-list="cardModuleList"
|
||||
:no-permission-text="hasPermission ? '' : 'workbench.homePage.notHasResPermission'"
|
||||
/>
|
||||
</div>
|
||||
<!-- 概览图 -->
|
||||
<div>
|
||||
<MsChart height="280px" :options="options" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -45,6 +48,7 @@
|
|||
|
||||
import MsChart from '@/components/pure/chart/index.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
import TabCard from './tabCard.vue';
|
||||
|
||||
import { workMyCreatedDetail, workProOverviewDetail } from '@/api/modules/workbench';
|
||||
|
@ -190,9 +194,12 @@
|
|||
});
|
||||
options.value.yAxis[0].max = maxAxis < 100 ? 100 : maxAxis + 50;
|
||||
}
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function initOverViewDetail() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const params = {
|
||||
current: 1,
|
||||
|
@ -217,6 +224,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
const isInit = ref(true);
|
||||
|
|
|
@ -1,45 +1,48 @@
|
|||
<template>
|
||||
<div class="card-wrapper">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
|
||||
<MsSelect
|
||||
:key="props.refreshKey"
|
||||
v-model:model-value="innerHandleUsers"
|
||||
:options="memberOptions"
|
||||
allow-search
|
||||
allow-clear
|
||||
value-key="value"
|
||||
label-key="label"
|
||||
:search-keys="['label']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.staff')"
|
||||
:multiple="true"
|
||||
:has-all-select="true"
|
||||
:default-all-select="innerHandleUsers.length === 0"
|
||||
@change="changeMember"
|
||||
>
|
||||
</MsSelect>
|
||||
<MsSelect
|
||||
:key="props.refreshKey"
|
||||
v-model:model-value="innerHandleUsers"
|
||||
:options="memberOptions"
|
||||
allow-search
|
||||
allow-clear
|
||||
value-key="value"
|
||||
label-key="label"
|
||||
:search-keys="['label']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.staff')"
|
||||
:multiple="true"
|
||||
:has-all-select="true"
|
||||
:default-all-select="innerHandleUsers.length === 0"
|
||||
@change="changeMember"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 概览图 -->
|
||||
<div class="mt-[16px]">
|
||||
<MsChart height="300px" :options="options" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 概览图 -->
|
||||
<div class="mt-[16px]">
|
||||
<MsChart height="300px" :options="options" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -52,6 +55,7 @@
|
|||
|
||||
import MsChart from '@/components/pure/chart/index.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
|
||||
import { workMemberViewDetail, workProjectMemberOptions } from '@/api/modules/workbench';
|
||||
import { contentTabList } from '@/config/workbench';
|
||||
|
@ -148,9 +152,12 @@
|
|||
});
|
||||
options.value.yAxis[0].max = maxAxis < 100 ? 100 : maxAxis + 50;
|
||||
}
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function initOverViewMemberDetail() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const params = {
|
||||
current: 1,
|
||||
|
@ -168,6 +175,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +1,36 @@
|
|||
<template>
|
||||
<div :class="`card-wrapper ${props.item.fullScreen ? '' : 'card-min-height'}`">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<div class="case-count-wrapper">
|
||||
<div class="case-count-item">
|
||||
<PassRatePie
|
||||
:options="relatedOptions"
|
||||
:has-permission="hasPermission"
|
||||
tooltip-text="workbench.homePage.associateCaseCoverRateTooltip"
|
||||
:size="60"
|
||||
:value-list="coverRateValueList"
|
||||
/>
|
||||
<div class="mt-[16px]">
|
||||
<div class="case-count-wrapper">
|
||||
<div class="case-count-item">
|
||||
<PassRatePie
|
||||
:options="relatedOptions"
|
||||
:has-permission="hasPermission"
|
||||
tooltip-text="workbench.homePage.associateCaseCoverRateTooltip"
|
||||
:size="60"
|
||||
:value-list="coverRateValueList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -41,6 +44,7 @@
|
|||
import { ref } from 'vue';
|
||||
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
import PassRatePie from './passRatePie.vue';
|
||||
|
||||
import { workAssociateCaseDetail } from '@/api/modules/workbench';
|
||||
|
@ -95,8 +99,11 @@
|
|||
},
|
||||
]);
|
||||
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function getRelatedCaseCount() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const detail: PassRateDataType = await workAssociateCaseDetail({
|
||||
current: 1,
|
||||
|
@ -123,6 +130,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,39 +1,42 @@
|
|||
<template>
|
||||
<div class="card-wrapper card-min-height">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<TabCard :content-tab-list="testPlanTabList" not-has-padding hidden-border min-width="290px">
|
||||
<template #item="{ item: tabItem }">
|
||||
<div class="w-full">
|
||||
<PassRatePie
|
||||
:has-permission="hasPermission"
|
||||
:options="tabItem.options"
|
||||
:size="60"
|
||||
:value-list="tabItem.valueList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</TabCard>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="testPlanCountOptions" />
|
||||
<div class="mt-[16px]">
|
||||
<TabCard :content-tab-list="testPlanTabList" not-has-padding hidden-border min-width="290px">
|
||||
<template #item="{ item: tabItem }">
|
||||
<div class="w-full">
|
||||
<PassRatePie
|
||||
:has-permission="hasPermission"
|
||||
:options="tabItem.options"
|
||||
:size="60"
|
||||
:value-list="tabItem.valueList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</TabCard>
|
||||
<div class="h-[148px]">
|
||||
<MsChart :options="testPlanCountOptions" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -47,6 +50,7 @@
|
|||
|
||||
import MsChart from '@/components/pure/chart/index.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
import PassRatePie from './passRatePie.vue';
|
||||
import TabCard from './tabCard.vue';
|
||||
|
||||
|
@ -119,8 +123,12 @@
|
|||
const testPlanCountOptions = ref({});
|
||||
// 测试计划权限
|
||||
const hasPermission = ref<boolean>(false);
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function initTestPlanCount() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
const params: WorkTestPlanDetail = {
|
||||
startTime: dayNumber ? null : startTime,
|
||||
|
@ -212,6 +220,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,87 +1,92 @@
|
|||
<template>
|
||||
<div class="card-wrapper">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<MsBaseTable
|
||||
v-bind="propsRes"
|
||||
:action-config="{
|
||||
baseAction: [],
|
||||
moreAction: [],
|
||||
}"
|
||||
class="mt-[16px]"
|
||||
v-on="propsEvent"
|
||||
>
|
||||
<template #num="{ record }">
|
||||
<a-tooltip :content="`${record.num}`">
|
||||
<a-button type="text" class="px-0 !text-[14px] !leading-[22px]" @click="openDetail(record.id)">
|
||||
<div class="one-line-text max-w-[168px]">{{ record.num }}</div>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template #passRateColumn>
|
||||
<div class="flex items-center text-[var(--color-text-3)]">
|
||||
{{ t('caseManagement.caseReview.passRate') }}
|
||||
<a-tooltip :content="t('caseManagement.caseReview.passRateTip')" position="right">
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<template #passRate="{ record }">
|
||||
<div class="mr-[8px] w-[100px]">
|
||||
<passRateLine :review-detail="record" height="5px" />
|
||||
</div>
|
||||
<div class="text-[var(--color-text-1)]">
|
||||
{{ `${record.passRate}%` }}
|
||||
</div>
|
||||
</template>
|
||||
<template #reviewPassRule="{ record }">
|
||||
<a-tag
|
||||
:color="record.reviewPassRule === 'SINGLE' ? 'rgb(var(--success-2))' : 'rgb(var(--link-2))'"
|
||||
:class="record.reviewPassRule === 'SINGLE' ? '!text-[rgb(var(--success-6))]' : '!text-[rgb(var(--link-6))]'"
|
||||
<CardSkeleton v-if="showSkeleton" :show-skeleton="showSkeleton" />
|
||||
<div v-else>
|
||||
<div class="flex items-center justify-between">
|
||||
<a-tooltip :content="t(props.item.label)" position="tl">
|
||||
<div class="title one-line-text"> {{ t(props.item.label) }} </div>
|
||||
</a-tooltip>
|
||||
<div>
|
||||
<MsSelect
|
||||
v-model:model-value="projectId"
|
||||
:options="appStore.projectList"
|
||||
allow-search
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
:search-keys="['name']"
|
||||
class="!w-[200px]"
|
||||
:prefix="t('workbench.homePage.project')"
|
||||
@change="changeProject"
|
||||
>
|
||||
{{
|
||||
record.reviewPassRule === 'SINGLE'
|
||||
? t('caseManagement.caseReview.single')
|
||||
: t('caseManagement.caseReview.multi')
|
||||
}}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #createUserName="{ record }">
|
||||
<a-tooltip :content="`${record.createUserName}`" position="tl">
|
||||
<div class="one-line-text">{{ record.createUserName }}</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-if="isNoPermission" #empty>
|
||||
<div class="w-full">
|
||||
<slot name="empty">
|
||||
<div class="flex h-[40px] flex-col items-center justify-center">
|
||||
<span class="text-[14px] text-[var(--color-text-4)]">{{ t('common.noResource') }}</span>
|
||||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
</MsSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<MsBaseTable
|
||||
v-bind="propsRes"
|
||||
:action-config="{
|
||||
baseAction: [],
|
||||
moreAction: [],
|
||||
}"
|
||||
class="mt-[16px]"
|
||||
v-on="propsEvent"
|
||||
>
|
||||
<template #num="{ record }">
|
||||
<a-tooltip :content="`${record.num}`">
|
||||
<a-button type="text" class="px-0 !text-[14px] !leading-[22px]" @click="openDetail(record.id)">
|
||||
<div class="one-line-text max-w-[168px]">{{ record.num }}</div>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template #passRateColumn>
|
||||
<div class="flex items-center text-[var(--color-text-3)]">
|
||||
{{ t('caseManagement.caseReview.passRate') }}
|
||||
<a-tooltip :content="t('caseManagement.caseReview.passRateTip')" position="right">
|
||||
<icon-question-circle
|
||||
class="ml-[4px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<template #passRate="{ record }">
|
||||
<div class="mr-[8px] w-[100px]">
|
||||
<passRateLine :review-detail="record" height="5px" />
|
||||
</div>
|
||||
<div class="text-[var(--color-text-1)]">
|
||||
{{ `${record.passRate}%` }}
|
||||
</div>
|
||||
</template>
|
||||
<template #reviewPassRule="{ record }">
|
||||
<a-tag
|
||||
:color="record.reviewPassRule === 'SINGLE' ? 'rgb(var(--success-2))' : 'rgb(var(--link-2))'"
|
||||
:class="
|
||||
record.reviewPassRule === 'SINGLE' ? '!text-[rgb(var(--success-6))]' : '!text-[rgb(var(--link-6))]'
|
||||
"
|
||||
>
|
||||
{{
|
||||
record.reviewPassRule === 'SINGLE'
|
||||
? t('caseManagement.caseReview.single')
|
||||
: t('caseManagement.caseReview.multi')
|
||||
}}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #createUserName="{ record }">
|
||||
<a-tooltip :content="`${record.createUserName}`" position="tl">
|
||||
<div class="one-line-text">{{ record.createUserName }}</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-if="isNoPermission" #empty>
|
||||
<div class="w-full">
|
||||
<slot name="empty">
|
||||
<div class="flex h-[40px] flex-col items-center justify-center">
|
||||
<span class="text-[14px] text-[var(--color-text-4)]">{{ t('common.noResource') }}</span>
|
||||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -96,6 +101,7 @@
|
|||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import CardSkeleton from './cardSkeleton.vue';
|
||||
import passRateLine from '@/views/case-management/caseReview/components/passRateLine.vue';
|
||||
|
||||
import { workReviewList } from '@/api/modules/workbench';
|
||||
|
@ -192,9 +198,11 @@
|
|||
});
|
||||
|
||||
const isNoPermission = ref<boolean>(false);
|
||||
const showSkeleton = ref(false);
|
||||
|
||||
async function initData() {
|
||||
try {
|
||||
showSkeleton.value = true;
|
||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||
setLoadListParams({
|
||||
startTime: dayNumber ? null : startTime,
|
||||
|
@ -209,6 +217,8 @@
|
|||
} catch (error) {
|
||||
isNoPermission.value = error === 'no_project_permission';
|
||||
// eslint-disable-next-line no-console
|
||||
} finally {
|
||||
showSkeleton.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue