<script lang="ts" setup>
|
import { computed, onMounted, ref } from 'vue';
|
import { useRouter } from 'vue-router';
|
|
import { Page } from '@vben/common-ui';
|
|
import { Card, Col, Row } from 'ant-design-vue';
|
|
import { getHomeSummary } from '#/api/mes/home';
|
|
import { defaultSummary } from './data';
|
import AiInsights from './modules/ai-insights.vue';
|
import AlertPanel from './modules/alert-panel.vue';
|
import BizCards from './modules/biz-cards.vue';
|
import KpiCards from './modules/kpi-cards.vue';
|
import ProductionTrend from './modules/production-trend.vue';
|
import QuickActions from './modules/quick-actions.vue';
|
|
defineOptions({ name: 'DashboardAnalytics' });
|
|
const router = useRouter();
|
const summary = ref(defaultSummary);
|
|
const greeting = computed(() => {
|
const hour = new Date().getHours();
|
if (hour < 6) return '夜深了';
|
if (hour < 9) return '早上好';
|
if (hour < 12) return '上午好';
|
if (hour < 14) return '中午好';
|
if (hour < 18) return '下午好';
|
return '晚上好';
|
});
|
|
const today = computed(() => {
|
const d = new Date();
|
const weekNames = ['日', '一', '二', '三', '四', '五', '六'];
|
return `${d.getFullYear()}年${d.getMonth() + 1}月${d.getDate()}日 星期${weekNames[d.getDay()]}`;
|
});
|
|
function handleNavigate(name: string) {
|
router.push({ name });
|
}
|
|
async function loadSummary() {
|
summary.value = await getHomeSummary();
|
}
|
|
onMounted(() => {
|
loadSummary();
|
});
|
</script>
|
|
<template>
|
<Page auto-content-height>
|
<!-- 欢迎栏 -->
|
<div class="glass-card mb-6 flex items-center justify-between rounded-2xl p-6">
|
<div>
|
<h1 class="bg-gradient-to-r from-blue-600 via-purple-600 to-pink-500 bg-clip-text text-2xl font-bold text-transparent dark:from-blue-400 dark:via-purple-400 dark:to-pink-400">
|
{{ greeting }},欢迎回来
|
</h1>
|
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ today }}</p>
|
</div>
|
<div class="hidden items-center gap-2 sm:flex">
|
<div class="flex items-center gap-1.5 rounded-full bg-emerald-50 px-3 py-1.5 text-xs font-medium text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-400">
|
<span class="relative flex size-2">
|
<span class="absolute inline-flex size-full animate-ping rounded-full bg-emerald-400 opacity-75" />
|
<span class="relative inline-flex size-2 rounded-full bg-emerald-500" />
|
</span>
|
系统运行中
|
</div>
|
</div>
|
</div>
|
|
<!-- MES 生产 KPI -->
|
<KpiCards :summary="summary" @navigate="handleNavigate" />
|
|
<!-- ERP/WMS/BPM 经营 KPI -->
|
<BizCards @navigate="handleNavigate" />
|
|
<!-- AI 智能分析 -->
|
<AiInsights
|
:active-order-count="summary.workOrderActiveCount"
|
@navigate="handleNavigate"
|
/>
|
|
<!-- 生产趋势 + 预警面板 -->
|
<Row :gutter="16" class="mb-4">
|
<Col :lg="14" :md="24" :sm="24" :xl="14" :xs="24" class="mb-4">
|
<div class="glass-card rounded-2xl p-5">
|
<h3 class="mb-4 text-base font-semibold text-gray-800 dark:text-gray-100">
|
生产趋势(近7天)
|
</h3>
|
<ProductionTrend />
|
</div>
|
</Col>
|
<Col :lg="10" :md="24" :sm="24" :xl="10" :xs="24" class="mb-4">
|
<AlertPanel
|
:andon-active-count="summary.andonActiveCount"
|
:repair-active-count="summary.repairActiveCount"
|
@navigate="handleNavigate"
|
/>
|
</Col>
|
</Row>
|
|
<!-- 快捷操作 -->
|
<Row :gutter="16" class="mb-4">
|
<Col :span="24">
|
<QuickActions @navigate="handleNavigate" />
|
</Col>
|
</Row>
|
</Page>
|
</template>
|
|
<style scoped>
|
.glass-card {
|
background: linear-gradient(135deg, rgba(255,255,255,0.8), rgba(255,255,255,0.5));
|
backdrop-filter: blur(20px);
|
-webkit-backdrop-filter: blur(20px);
|
border: 1px solid rgba(255,255,255,0.6);
|
box-shadow:
|
0 8px 32px rgba(0,0,0,0.04),
|
0 2px 8px rgba(0,0,0,0.02),
|
inset 0 1px 0 rgba(255,255,255,0.8);
|
}
|
|
.dark .glass-card {
|
background: linear-gradient(135deg, rgba(30,30,50,0.7), rgba(20,20,40,0.5));
|
border: 1px solid rgba(255,255,255,0.08);
|
box-shadow:
|
0 8px 32px rgba(0,0,0,0.3),
|
0 2px 8px rgba(0,0,0,0.2),
|
inset 0 1px 0 rgba(255,255,255,0.05);
|
}
|
</style>
|