118 lines
3.3 KiB
Vue
118 lines
3.3 KiB
Vue
<template>
|
||
<div class="page-container">
|
||
<!-- 使用 Ant Design Vue 的栅格系统,PC端一行展示3个,响应式适配 -->
|
||
<a-row :gutter="[16, 16]">
|
||
<a-col :xs="24" :sm="24" :md="8" >
|
||
<RichTextCard title="本周数据概况" :html-content="weekSummary" :loading="loading" />
|
||
</a-col>
|
||
<a-col :xs="24" :sm="24" :md="8">
|
||
<RichTextCard title="本月数据概况" :html-content="monthSummary" :loading="loading" />
|
||
</a-col>
|
||
<a-col :xs="24" :sm="24" :md="8">
|
||
<RichTextCard title="本年度数据概况" :html-content="yearSummary" :loading="loading" />
|
||
</a-col>
|
||
</a-row>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted } from 'vue';
|
||
import { Spin } from 'ant-design-vue';
|
||
import RichTextCard from './components/RichTextCard.vue'; // 引入子组件
|
||
// 假设的接口请求方法
|
||
import { getAllDataSummary } from './datacenter.api';
|
||
|
||
// 定义三个富文本的响应式变量
|
||
const weekSummary = ref('');
|
||
const monthSummary = ref('');
|
||
const yearSummary = ref('');
|
||
// 初始化为 true,确保组件一开始就显示 loading
|
||
const loading = ref(true);
|
||
|
||
// 最小显示时间,确保 loading 至少显示一段时间
|
||
const MIN_LOADING_TIME = 800; // 800ms
|
||
|
||
onMounted(async () => {
|
||
const startTime = Date.now();
|
||
try {
|
||
// 模拟网络延迟(可选,用于测试)
|
||
// await new Promise(resolve => setTimeout(resolve, 1000));
|
||
|
||
const res = await getAllDataSummary();
|
||
if (res.success) {
|
||
// 根据接口实际返回的字段名进行赋值
|
||
weekSummary.value = res.result.weekHtml;
|
||
monthSummary.value = res.result.monthHtml;
|
||
yearSummary.value = res.result.yearHtml;
|
||
}
|
||
} catch (error) {
|
||
console.error('获取数据概况失败:', error);
|
||
} finally {
|
||
// 确保 loading 至少显示 MIN_LOADING_TIME 毫秒
|
||
const elapsedTime = Date.now() - startTime;
|
||
if (elapsedTime < MIN_LOADING_TIME) {
|
||
setTimeout(() => {
|
||
loading.value = false;
|
||
}, MIN_LOADING_TIME - elapsedTime);
|
||
} else {
|
||
loading.value = false;
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.page-container {
|
||
background-color: #fdfdfd;
|
||
min-height: 100vh;
|
||
padding: 16px;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
}
|
||
|
||
/* 全局 Loading 遮罩样式 */
|
||
.loading-overlay {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: rgba(255, 255, 255, 0.8);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 1000;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.page-container :deep(.ant-card) {
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||
transition: box-shadow 0.3s ease;
|
||
}
|
||
|
||
.page-container :deep(.ant-card:hover) {
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
/* 自定义卡片 loading 样式 */
|
||
.page-container :deep(.ant-spin-container) {
|
||
min-height: 200px;
|
||
}
|
||
|
||
.page-container :deep(.ant-card-loading) {
|
||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||
background-size: 200% 100%;
|
||
animation: loading-shimmer 1.5s infinite;
|
||
}
|
||
|
||
@keyframes loading-shimmer {
|
||
0% {
|
||
background-position: 200% 0;
|
||
}
|
||
100% {
|
||
background-position: -200% 0;
|
||
}
|
||
}
|
||
</style>
|