<script lang="ts" setup>
|
import type { MesHomeApi } from '#/api/mes/home';
|
import type { EchartsUIType } from '@vben/plugins/echarts';
|
|
import { onMounted, ref } from 'vue';
|
|
import { CountTo } from '@vben/common-ui';
|
import { IconifyIcon } from '@vben/icons';
|
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
|
import { Spin } from 'ant-design-vue';
|
|
import { getWorkOrderStatusDistribution } from '#/api/mes/home';
|
|
defineOptions({ name: 'DashboardAlertPanel' });
|
|
const props = defineProps<{
|
andonActiveCount: number;
|
repairActiveCount: number;
|
}>();
|
|
const emit = defineEmits<{
|
navigate: [name: string];
|
}>();
|
|
const chartRef = ref<EchartsUIType>();
|
const { renderEcharts } = useEcharts(chartRef);
|
const loading = ref(false);
|
|
async function loadStatus() {
|
loading.value = true;
|
try {
|
const data = await getWorkOrderStatusDistribution();
|
if (data.length > 0) {
|
renderEcharts({
|
legend: { bottom: 0, textStyle: { fontSize: 11 } },
|
series: [
|
{
|
animationDuration: 1200,
|
animationEasing: 'cubicOut',
|
color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444', '#ec4899'],
|
data: data.map((d: MesHomeApi.WorkOrderStatus) => ({ name: d.statusName, value: d.count })),
|
emphasis: {
|
itemStyle: { shadowBlur: 20, shadowColor: 'rgba(0,0,0,0.2)', shadowOffsetX: 0 },
|
scaleSize: 8,
|
},
|
itemStyle: { borderRadius: 6, borderColor: 'transparent', borderWidth: 3 },
|
label: { show: false },
|
name: '工单状态',
|
radius: ['50%', '75%'],
|
type: 'pie',
|
},
|
],
|
tooltip: { trigger: 'item' },
|
});
|
}
|
} finally {
|
loading.value = false;
|
}
|
}
|
|
onMounted(() => {
|
loadStatus();
|
});
|
</script>
|
|
<template>
|
<div class="space-y-4">
|
<!-- 预警卡片行 -->
|
<div class="grid grid-cols-2 gap-3">
|
<div
|
class="glass-tilt group cursor-pointer overflow-hidden rounded-2xl border-0 p-4"
|
@click="emit('navigate', 'MesProAndon')"
|
>
|
<div class="relative z-10 flex items-center gap-3">
|
<div class="flex size-10 items-center justify-center rounded-lg bg-red-50 text-red-600 shadow-sm dark:bg-red-500/15 dark:text-red-400">
|
<IconifyIcon class="size-5" icon="lucide:alert-triangle" />
|
</div>
|
<div>
|
<div class="text-xs text-gray-500 dark:text-gray-400">安灯呼叫</div>
|
<div class="flex items-baseline gap-1">
|
<CountTo class="text-xl font-bold text-red-600 dark:text-red-400" :end-val="andonActiveCount" :duration="1000" />
|
<span class="text-xs text-gray-400">未处置</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div
|
class="glass-tilt group cursor-pointer overflow-hidden rounded-2xl border-0 p-4"
|
@click="emit('navigate', 'MesProRepair')"
|
>
|
<div class="relative z-10 flex items-center gap-3">
|
<div class="flex size-10 items-center justify-center rounded-lg bg-amber-50 text-amber-600 shadow-sm dark:bg-amber-500/15 dark:text-amber-400">
|
<IconifyIcon class="size-5" icon="lucide:wrench" />
|
</div>
|
<div>
|
<div class="text-xs text-gray-500 dark:text-gray-400">维修工单</div>
|
<div class="flex items-baseline gap-1">
|
<CountTo class="text-xl font-bold text-amber-600 dark:text-amber-400" :end-val="repairActiveCount" :duration="1000" />
|
<span class="text-xs text-gray-400">待处理</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 工单状态图 -->
|
<div class="glass-tilt rounded-2xl p-5">
|
<h4 class="mb-3 text-sm font-semibold text-gray-800 dark:text-gray-100">
|
工单状态分布
|
</h4>
|
<Spin :spinning="loading">
|
<EchartsUI ref="chartRef" class="!h-[200px]" />
|
</Spin>
|
</div>
|
</div>
|
</template>
|
|
<style scoped>
|
.glass-tilt {
|
background: linear-gradient(135deg, rgba(255,255,255,0.85), rgba(255,255,255,0.55));
|
backdrop-filter: blur(20px);
|
-webkit-backdrop-filter: blur(20px);
|
border: 1px solid rgba(255,255,255,0.6);
|
box-shadow:
|
0 4px 24px rgba(0,0,0,0.04),
|
0 1px 4px rgba(0,0,0,0.02),
|
inset 0 1px 0 rgba(255,255,255,0.8);
|
}
|
|
.dark .glass-tilt {
|
background: linear-gradient(135deg, rgba(30,30,55,0.75), rgba(20,20,40,0.5));
|
border: 1px solid rgba(255,255,255,0.08);
|
box-shadow:
|
0 4px 24px rgba(0,0,0,0.3),
|
0 1px 4px rgba(0,0,0,0.2),
|
inset 0 1px 0 rgba(255,255,255,0.04);
|
}
|
</style>
|