Files
moc/src/views/factoryOverview/index.vue
T

203 lines
8.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import { getColorWithOpacity } from '@/utils/common';
import RingChart from './modules/ringChart.vue';
import ColumnChart from './modules/columnChart.vue';
import ColumnChart2 from './modules/columnChart2.vue';
import { factoryStatisticsApi } from '@/service/api/statistics';
const themeStore = useThemeStore();
const DEFAULT_EXPORTS = ["变更数量统计", "变更周期分析", "超期预警报表", "风险分析执行", "PSSR 与验收", "关闭及时率"];
const loading = ref<boolean>(false);
const homeData = ref<any>(null);
// 导出数据
const exportData = (type: string) => {
window.$message?.info('还差接口')
}
// 获取数据
const getData = async () => {
loading.value = true;
const {data,error} = await factoryStatisticsApi({
from: null,
to: null,
});
if(!error){
homeData.value = data;
}
loading.value = false;
}
onMounted(() => {
getData();
});
</script>
<template>
<NSpace vertical :size="16">
<!-- 卡片数据 -->
<NGrid cols="s:1 m:4 l:4" responsive="screen" :x-gap="16" :y-gap="16" :style="{'--theme-color': themeStore.themeColor,'--theme-bg': getColorWithOpacity(themeStore.themeColor, 0.1)}">
<NGi>
<div
class="bg-white px-16px py-12px text-[#94a3b8]"
:style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }"
>
<p class="text-12px font-600 text-center">按期关闭率</p>
<div class="flex justify-center py-2.5">
<NProgress type="circle" :percentage="homeData?.gauges?.ontime_close_rate || 0" :offset-degree="180">
<div class="flex flex-col items-center mt-2">
<p class="flex items-end text-2xl font-bold leading-none text-[#1D2129]">
{{homeData?.gauges?.ontime_close_rate || 0}}<span class="text-sm font-semibold">%</span>
</p>
</div>
</NProgress>
</div>
<p class="text-12px text-center">近一年 · 全厂</p>
</div>
</NGi>
<NGi>
<div
class="bg-white px-16px py-12px text-[#94a3b8]"
:style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }"
>
<p class="text-12px font-600 text-center">PSSR 完成率</p>
<div class="flex justify-center py-2.5">
<NProgress type="circle" :percentage="homeData?.gauges?.pssr_rate || 0" :offset-degree="180" status="success">
<div class="flex flex-col items-center mt-2">
<p class="flex items-end text-2xl font-bold leading-none text-[#1D2129]">
{{homeData?.gauges?.pssr_rate || 0}}<span class="text-sm font-semibold">%</span>
</p>
</div>
</NProgress>
</div>
<p class="text-12px text-center">近一年 · 全厂</p>
</div>
</NGi>
<NGi>
<div
class="bg-white px-16px py-12px text-[#94a3b8] flex flex-col justify-center items-center"
:style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }"
>
<p class="text-12px font-600 text-center">当月临时变更数量</p>
<p class="mt-2 text-[40px] font-bold leading-none text-[#1D2129] text-center">{{homeData?.gauges?.month_created || 0}}</p>
<p class="text-12px text-center mt-1">近一年 · 全厂</p>
</div>
</NGi>
<NGi>
<div
class="bg-white px-16px py-12px text-[#94a3b8] flex flex-col justify-center items-center"
:style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }"
>
<p class="text-12px font-600 text-center">平均关闭时长</p>
<p class="mt-2 text-[40px] font-bold leading-none text-[#1D2129] text-center">{{homeData?.gauges?.avg_close_days || 0}}</p>
<p class="text-12px text-center mt-1">天 · 优于行业均值</p>
</div>
</NGi>
</NGrid>
<NGrid :x-gap="16" :y-gap="16" responsive="screen" item-responsive>
<NGi span="24 s:24 m:24 l:12">
<NCard :bordered="true" size="small" :content-style="{padding: 0}" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
<p class=" text-base font-semibold border-b border-slate-100 p-3">月度变更数量</p>
<div class="py-3 px-4">
<ColumnChart v-if="homeData" :data="homeData?.monthly_counts || []" />
</div>
</NCard>
</NGi>
<NGi span="24 s:24 m:24 l:6">
<NCard :bordered="true" size="small" :content-style="{padding: 0}" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更类型分布</p>
<div class="py-3 px-4">
<RingChart v-if="homeData" :data="homeData?.type_dist || []" />
</div>
</NCard>
</NGi>
<NGi span="24 s:24 m:24 l:6">
<NCard :bordered="true" size="small" :content-style="{padding: 0}"
:style="{
borderRadius: themeStore.themeRadius + 'px',
height: '100%',
'--theme-color': themeStore.themeColor,
'--warning-color': themeStore.otherColor.warning,
'--error-color': themeStore.otherColor.error,
}"
>
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更效率指标</p>
<div class="py-3 px-4">
<div class="space-y-5">
<div>
<div class="flex items-baseline gap-2">
<span class="text-2xl font-bold text-[#1D2129]">{{homeData?.eff?.ontime_use_rate || 0}}<span class="text-sm font-semibold">%</span></span>
<span class="text-xs text-slate-400">按期投用率</span>
</div>
<div class="mt-1.5 h-1 w-full overflow-hidden rounded-full bg-slate-100">
<div class="h-full rounded-full bg-[var(--theme-color)]" :style="{ width: `${homeData?.eff?.ontime_use_rate || 0}%` }"></div>
</div>
</div>
<div>
<div class="flex items-baseline gap-2">
<span class="text-2xl font-bold text-[#1D2129]">{{homeData?.eff?.train_upload_rate || 0}}<span class="text-sm font-semibold">%</span></span>
<span class="text-xs text-slate-400">培训按期完成率</span>
</div>
<div class="mt-1.5 h-1 w-full overflow-hidden rounded-full bg-slate-100">
<div class="h-full rounded-full bg-[var(--warning-color)]" :style="{ width: `${homeData?.eff?.train_upload_rate || 0}%` }"></div>
</div>
</div>
<div>
<div class="flex items-baseline gap-2">
<span class="text-2xl font-bold text-[#1D2129]">{{homeData?.eff?.overdue_rate || 0}}<span class="text-sm font-semibold">%</span></span>
<span class="text-xs text-slate-400">超期变更占比</span>
</div>
<div class="mt-1.5 h-1 w-full overflow-hidden rounded-full bg-slate-100">
<div class="h-full rounded-full bg-[var(--error-color)]" :style="{ width: `${homeData?.eff?.overdue_rate || 0}%` }"></div>
</div>
</div>
<div class="text-[11px] text-slate-400">近一年 · 全厂口径 · 超期占比越低越好</div>
</div>
</div>
</NCard>
</NGi>
</NGrid>
<NGrid :x-gap="16" :y-gap="16" responsive="screen" item-responsive>
<NGi span="24 s:24 m:24 l:16">
<NCard :bordered="true" size="small" :content-style="{padding: 0}" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
<p class=" text-base font-semibold border-b border-slate-100 p-3">平均审批周期趋势(天)</p>
<div class="py-3 px-4">
<ColumnChart2 v-if="homeData" :data="homeData?.cycle_trend || []" />
</div>
</NCard>
</NGi>
<NGi span="24 s:24 m:24 l:8">
<NCard :bordered="true" size="small" :content-style="{padding: 0}"
:style="{
borderRadius: themeStore.themeRadius + 'px',
height: '100%',
'--theme-color': themeStore.themeColor,
'--theme-bg': getColorWithOpacity(themeStore.themeColor, 0.1),
}"
>
<p class=" text-base font-semibold border-b border-slate-100 p-3">报表导出</p>
<div class="py-3 px-4">
<div class="grid grid-cols-2 gap-2">
<div v-for="r in DEFAULT_EXPORTS" :key="r" @click="exportData(r)"
class="cursor-pointer flex items-center gap-2 rounded-lg border px-3 py-2.5 text-sm hover:border-[var(--theme-color)] hover:bg-[var(--theme-bg)]">
<Icon icon="akar-icons:file" class="size-16px text-slate-400" />
{{ r }}
</div>
</div>
</div>
</NCard>
</NGi>
</NGrid>
</NSpace>
</template>
<style scoped></style>