gtsoft-snail-job-admin/src/views/home/modules/card-data.vue

341 lines
9.8 KiB
Vue
Raw Normal View History

2024-03-08 17:59:45 +08:00
<script setup lang="ts">
2024-04-12 23:46:09 +08:00
import { computed, nextTick, onUnmounted, reactive } from 'vue';
2024-03-08 17:59:45 +08:00
import { createReusableTemplate } from '@vueuse/core';
2024-05-08 11:57:58 +08:00
import { getPaletteColorByNumber } from '@sa/color';
2024-03-08 17:59:45 +08:00
import { $t } from '@/locales';
import { useThemeStore } from '@/store/modules/theme';
import { useRouterPush } from '@/hooks/common/router';
2024-03-25 09:41:48 +08:00
import DardRetryChart from './card-retry-chart.vue';
2024-03-08 17:59:45 +08:00
const { routerPushByKey } = useRouterPush();
const themeStore = useThemeStore();
2024-03-30 17:07:04 +08:00
2024-03-08 17:59:45 +08:00
defineOptions({
name: 'CardData'
});
2024-03-22 11:22:07 +08:00
interface Props {
2024-03-28 16:22:18 +08:00
modelValue?: Api.Dashboard.CardCount;
2024-03-22 11:22:07 +08:00
}
2024-04-12 23:46:09 +08:00
const state = reactive({ width: 0 });
const gridCol = computed(() => {
if (state.width >= 1600) {
return 4;
} else if (state.width >= 1024) {
return 2;
}
return 1;
});
const getState = () => {
state.width = document.documentElement.clientWidth;
};
nextTick(() => {
getState();
window.addEventListener('resize', getState);
});
onUnmounted(() => {
// 移除监听事件
window.removeEventListener('resize', getState);
});
2024-03-28 16:22:18 +08:00
const props = withDefaults(defineProps<Props>(), {
modelValue: () => ({
jobTask: {
successNum: 0,
failNum: 0,
cancelNum: 0,
stopNum: 0,
totalNum: 0,
successRate: 0
},
2024-04-13 01:23:58 +08:00
workFlowTask: {
successNum: 0,
failNum: 0,
cancelNum: 0,
stopNum: 0,
totalNum: 0,
successRate: 0
},
2024-03-28 16:22:18 +08:00
retryTask: {
totalNum: 0,
runningNum: 0,
finishNum: 0,
maxCountNum: 0,
suspendNum: 0
},
retryTaskBarList: [],
onLineService: {
total: 0,
clientTotal: 0,
serverTotal: 0
}
})
});
2024-03-22 11:22:07 +08:00
2024-03-08 17:59:45 +08:00
interface CardData {
key: string;
2024-03-08 17:59:45 +08:00
title: string;
2024-03-22 11:22:07 +08:00
tip: string;
2024-03-08 17:59:45 +08:00
value: number;
click?: () => void;
2024-03-08 17:59:45 +08:00
color: {
start: string;
end: string;
};
icon: string;
bottom: { label: string; value: number; click?: () => void }[];
2024-03-08 17:59:45 +08:00
}
2024-04-25 23:55:03 +08:00
// eslint-disable-next-line complexity
2024-03-08 17:59:45 +08:00
const cardData = computed<CardData[]>(() => [
{
key: 'job_task',
2024-05-22 14:19:16 +08:00
title: $t('page.home.jobTask'),
tip: $t('page.home.jobTaskTip'),
value: props.modelValue?.jobTask.totalNum ?? 0,
click: () => routerPushByKey('job_task'),
2024-03-08 17:59:45 +08:00
color: {
2024-05-22 14:19:16 +08:00
start: '#f5b386',
end: '#FFD6BA'
2024-03-08 17:59:45 +08:00
},
2024-05-22 14:19:16 +08:00
icon: 'ant-design:profile-outlined',
2024-03-22 11:22:07 +08:00
bottom: [
{
label: $t('common.success'),
value: props.modelValue?.jobTask.successNum ?? 0,
click: () => routerPushByKey('job_batch', { state: { taskBatchStatus: 3 } })
2024-03-22 11:22:07 +08:00
},
{
2024-05-22 14:19:16 +08:00
label: $t('common.fail'),
value: props.modelValue?.jobTask.failNum ?? 0,
click: () => routerPushByKey('job_batch', { state: { taskBatchStatus: 4 } })
2024-03-22 11:22:07 +08:00
},
{
2024-05-22 14:19:16 +08:00
label: $t('common.stop'),
value: props.modelValue?.jobTask.stopNum ?? 0,
click: () => routerPushByKey('job_batch', { state: { taskBatchStatus: 5 } })
2024-03-22 11:22:07 +08:00
},
{
2024-05-22 14:19:16 +08:00
label: $t('common.cancel'),
value: props.modelValue?.jobTask.cancelNum ?? 0,
click: () => routerPushByKey('job_batch', { state: { taskBatchStatus: 6 } })
2024-03-22 11:22:07 +08:00
}
]
2024-03-08 17:59:45 +08:00
},
{
key: 'retry_task',
title: $t('page.home.retryTask.title'),
2024-05-22 14:19:16 +08:00
tip: $t('page.home.retryTaskTip'),
value: props.modelValue?.retryTask.totalNum ?? 0,
click: () => routerPushByKey('retry_task'),
2024-05-22 14:19:16 +08:00
unit: '',
2024-03-08 17:59:45 +08:00
color: {
2024-05-22 14:19:16 +08:00
start: '#40e9c5',
end: '#BEE3DB'
2024-03-08 17:59:45 +08:00
},
2024-05-22 14:19:16 +08:00
icon: 'ant-design:schedule-outlined',
2024-03-22 11:22:07 +08:00
bottom: [
{
label: $t('common.success'),
value: props.modelValue?.retryTask.finishNum ?? 0,
click: () => routerPushByKey('retry_log', { state: { retryStatus: 1 } })
2024-03-22 11:22:07 +08:00
},
{
2024-05-22 14:19:16 +08:00
label: $t('common.running'),
value: props.modelValue?.retryTask.runningNum ?? 0,
click: () => routerPushByKey('retry_log', { state: { retryStatus: 0 } })
2024-03-22 11:22:07 +08:00
},
{
label: $t('page.home.retryTask.status.maxRetryTimes'),
value: props.modelValue?.retryTask.maxCountNum ?? 0,
click: () => routerPushByKey('retry_log', { state: { retryStatus: 2 } })
2024-03-22 11:22:07 +08:00
},
{
label: $t('page.home.retryTask.status.pauseRetry'),
value: props.modelValue?.retryTask.suspendNum ?? 0,
click: () => routerPushByKey('retry_log', { state: { retryStatus: 3 } })
2024-03-22 11:22:07 +08:00
}
]
2024-03-08 17:59:45 +08:00
},
{
key: 'workflow_task',
2024-03-22 11:22:07 +08:00
title: $t('page.home.workflow'),
tip: $t('page.home.workflowTip'),
value: props.modelValue?.workFlowTask.totalNum,
click: () => routerPushByKey('workflow_task'),
2024-03-08 17:59:45 +08:00
unit: '',
color: {
2024-03-22 11:22:07 +08:00
start: '#ec6f6f',
end: '#f99797'
2024-03-08 17:59:45 +08:00
},
2024-03-26 11:47:11 +08:00
icon: 'typcn:flow-merge',
2024-03-22 11:22:07 +08:00
bottom: [
{
label: $t('common.success'),
value: props.modelValue?.workFlowTask.successNum ?? 0,
click: () => routerPushByKey('workflow_batch', { state: { taskBatchStatus: 3 } })
2024-03-22 11:22:07 +08:00
},
{
label: $t('common.fail'),
value: props.modelValue?.workFlowTask.failNum ?? 0,
click: () => routerPushByKey('workflow_batch', { state: { taskBatchStatus: 4 } })
2024-03-22 11:22:07 +08:00
},
{
label: $t('common.stop'),
value: props.modelValue?.workFlowTask.stopNum ?? 0,
click: () => routerPushByKey('workflow_batch', { state: { taskBatchStatus: 5 } })
2024-03-22 11:22:07 +08:00
},
{
label: $t('common.cancel'),
value: props.modelValue?.workFlowTask.cancelNum ?? 0,
click: () => routerPushByKey('workflow_batch', { state: { taskBatchStatus: 6 } })
2024-04-13 01:23:58 +08:00
}
]
},
{
key: 'pods',
2024-04-13 01:23:58 +08:00
title: $t('page.home.onlineServiceCount'),
tip: $t('page.home.onlineServiceTip'),
value: props.modelValue?.onLineService.total ?? 0,
click: () => routerPushByKey('pods'),
2024-04-13 01:23:58 +08:00
unit: '',
color: {
start: '#b686d4',
end: '#c5a5d8'
},
icon: 'ant-design:database-outlined',
bottom: [
{
label: $t('page.home.machine.type.client'),
value: props.modelValue?.onLineService.clientTotal ?? 0,
click: () => routerPushByKey('pods')
2024-04-13 01:23:58 +08:00
},
{
label: $t('page.home.machine.type.server'),
value: props.modelValue?.onLineService.serverTotal ?? 0,
click: () => routerPushByKey('pods')
2024-03-22 11:22:07 +08:00
}
]
2024-03-08 17:59:45 +08:00
}
]);
interface GradientBgProps {
gradientColor: string;
}
const [DefineGradientBg, GradientBg] = createReusableTemplate<GradientBgProps>();
function getGradientColor(color: CardData['color']) {
2024-05-08 11:57:58 +08:00
const start = themeStore.darkMode ? getPaletteColorByNumber(color.start, 700) : color.start;
const end = themeStore.darkMode ? getPaletteColorByNumber(color.end, 700) : color.end;
return `linear-gradient(to bottom right, ${start}, ${end})`;
2024-03-08 17:59:45 +08:00
}
</script>
<template>
2024-03-21 10:57:53 +08:00
<NCard :bordered="false" size="small" class="card-wrapper">
2024-03-08 17:59:45 +08:00
<!-- define component start: GradientBg -->
<DefineGradientBg v-slot="{ $slots, gradientColor }">
2024-03-21 10:57:53 +08:00
<div class="rd-8px px-16px pb-4px pt-8px text-white" :style="{ backgroundImage: gradientColor }">
2024-03-08 17:59:45 +08:00
<component :is="$slots.default" />
</div>
</DefineGradientBg>
<!-- define component end: GradientBg -->
2024-04-12 23:46:09 +08:00
<NGrid :cols="gridCol" responsive="screen" :x-gap="16" :y-gap="16">
<NGi v-for="item in cardData" :key="item.key" class="home-card">
2024-03-22 11:22:07 +08:00
<NSpin :show="false">
<GradientBg :gradient-color="getGradientColor(item.color)" class="h-165px flex-1">
<div :class="item.click ? 'cursor-pointer' : null" @click="item.click">
<div class="flex justify-between">
<div class="align-center flex">
<SvgIcon :icon="item.icon" class="text-26px" />
<h3 class="ml-2 text-18px">{{ item.title }}</h3>
</div>
<NPopover trigger="hover">
<template #trigger>
<NButton text>
<SvgIcon icon="ant-design:info-circle-outlined" class="text-20px color-white" />
</NButton>
</template>
{{ item.tip }}
</NPopover>
</div>
<div class="flex">
<CountTo :start-value="0" :end-value="item.value" class="text-30px text-white" />
2024-03-22 11:22:07 +08:00
</div>
</div>
2024-03-25 09:41:48 +08:00
<NProgress
v-if="item.key === 'job_task'"
2024-03-25 09:41:48 +08:00
class="mb-24px h-20px pt-18px"
type="line"
color="#728bf9"
rail-color="#ebebeb"
:percentage="props.modelValue?.jobTask.successRate ?? 0"
indicator-text-color="#fff"
/>
2024-03-26 11:47:11 +08:00
<NProgress
v-else-if="item.key === 'workflow_task'"
2024-03-26 11:47:11 +08:00
class="mb-24px h-20px pt-18px"
type="line"
color="#728bf9"
rail-color="#ebebeb"
:percentage="props.modelValue?.workFlowTask.successRate ?? 0"
2024-03-26 11:47:11 +08:00
indicator-text-color="#fff"
/>
<DardRetryChart v-else-if="item.key === 'retry_task'" :model-value="props.modelValue?.retryTaskBarList" />
2024-03-25 09:41:48 +08:00
<div v-else class="mb-12px h-32px"></div>
2024-03-22 11:22:07 +08:00
<NDivider />
<template v-for="(bottomItem, bottomIndex) in item.bottom" :key="bottomIndex">
<NDivider v-if="bottomIndex !== 0" vertical />
<span :class="bottomItem.click ? 'cursor-pointer home-card-footer' : null" @click="bottomItem.click">
{{ bottomItem.label }}
<CountTo :start-value="0" :end-value="bottomItem.value" />
</span>
2024-03-22 11:22:07 +08:00
</template>
</GradientBg>
</NSpin>
2024-03-21 10:57:53 +08:00
</NGi>
</NGrid>
</NCard>
2024-03-08 17:59:45 +08:00
</template>
2024-03-22 11:22:07 +08:00
<style scoped>
.n-divider {
2024-03-25 09:41:48 +08:00
margin: 0px 0 6px;
2024-03-22 11:22:07 +08:00
}
.n-divider--vertical {
margin: 0 5px 0 5px;
2024-03-22 11:22:07 +08:00
}
2024-03-25 09:41:48 +08:00
:deep(.n-progress-icon--as-text) {
width: 60px !important;
2024-03-25 09:41:48 +08:00
}
.home-card {
transition: all 0.25s ease-in;
}
.home-card:hover {
transform: translateY(-8px);
box-shadow: var(--n-box-shadow);
border-radius: 8px;
}
.home-card-footer:hover {
color: #fff;
font-size: 14px;
transition: all 0.25s ease-in;
}
.home-card-footer:hover {
color: #1366ff !important;
font-size: 15px;
}
2024-03-22 11:22:07 +08:00
</style>