<script lang="ts" setup>
|
import { computed } from 'vue';
|
import { useRouter } from 'vue-router';
|
|
import { Page } from '@vben/common-ui';
|
|
import { Col, Row } from 'ant-design-vue';
|
|
import KpiCards from './modules/kpi-cards.vue';
|
import QuickActions from './modules/quick-actions.vue';
|
import RecentApplications from './modules/recent-applications.vue';
|
import TodoPanel from './modules/todo-panel.vue';
|
|
defineOptions({ name: 'DashboardAnalytics' });
|
|
// vite.config.ts 注入的公司 Logo 路径
|
declare const __APP_LOGO__: string;
|
const brandLogo = __APP_LOGO__ || '/logos/JSSM.svg';
|
|
const router = useRouter();
|
|
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 });
|
}
|
</script>
|
|
<template>
|
<Page auto-content-height>
|
<!-- 欢迎栏:藏青底 + 金色描边 -->
|
<div class="elite-hero mb-6">
|
<img alt="" class="elite-hero-mark" :src="brandLogo" />
|
<div class="relative z-10 flex flex-wrap items-center justify-between gap-4">
|
<div>
|
<h1 class="elite-hero-title">{{ greeting }},欢迎回来</h1>
|
<p class="elite-hero-date">{{ today }}</p>
|
</div>
|
<div class="elite-status">
|
<span class="elite-status-dot"></span>
|
系统运行中
|
</div>
|
</div>
|
</div>
|
|
<!-- 系统指标 -->
|
<KpiCards @navigate="handleNavigate" />
|
|
<!-- 待办 + 快捷入口 -->
|
<Row :gutter="16" class="mb-4">
|
<Col :lg="14" :md="24" :sm="24" :xl="14" :xs="24" class="mb-4">
|
<TodoPanel @navigate="handleNavigate" />
|
</Col>
|
<Col :lg="10" :md="24" :sm="24" :xl="10" :xs="24" class="mb-4">
|
<QuickActions @navigate="handleNavigate" />
|
</Col>
|
</Row>
|
|
<!-- 最近课题申报 -->
|
<RecentApplications @navigate="handleNavigate" />
|
</Page>
|
</template>
|
|
<style scoped>
|
/* ===== 欢迎栏 ===== */
|
.elite-hero {
|
position: relative;
|
overflow: hidden;
|
border-radius: 12px;
|
padding: 30px 34px;
|
background:
|
radial-gradient(circle at 88% 12%, rgba(212, 175, 55, 0.08), transparent 50%),
|
linear-gradient(135deg, #123156 0%, #0f2440 58%, #0b1c33 100%);
|
border: 1px solid rgba(212, 175, 55, 0.24);
|
box-shadow: 0 4px 18px rgba(15, 36, 64, 0.12);
|
}
|
|
/* 右侧淡淡的徽标水印 */
|
.elite-hero-mark {
|
position: absolute;
|
top: 50%;
|
right: 168px;
|
width: 118px;
|
height: 118px;
|
pointer-events: none;
|
opacity: 0.05;
|
transform: translateY(-50%);
|
}
|
|
.elite-hero-title {
|
margin: 0;
|
font-size: 22px;
|
font-weight: 600;
|
letter-spacing: 2px;
|
color: #f5f0e4;
|
}
|
|
.elite-hero-date {
|
margin: 8px 0 0;
|
font-size: 13px;
|
letter-spacing: 1px;
|
color: rgba(212, 175, 55, 0.85);
|
}
|
|
.elite-status {
|
display: inline-flex;
|
align-items: center;
|
gap: 8px;
|
padding: 7px 16px;
|
font-size: 12.5px;
|
letter-spacing: 1px;
|
color: #f0e2b8;
|
background: rgba(212, 175, 55, 0.12);
|
border: 1px solid rgba(212, 175, 55, 0.38);
|
border-radius: 999px;
|
}
|
|
/* 静态状态点,不做脉冲动画 */
|
.elite-status-dot {
|
display: inline-flex;
|
width: 7px;
|
height: 7px;
|
border-radius: 999px;
|
background: #d4af37;
|
}
|
</style>
|