ts-bigscreen-vue/src/components/LiteratureOverview.vue

265 lines
6.5 KiB
Vue

<template>
<div class="literature-overview">
<div class="content">
<div class="total-info">
<div class="total-number">
{{ formatNumber(literatureData.totalLiterature) }}
</div>
<div class="label">馆藏总量</div>
</div>
<el-carousel
ref="carousel"
:interval="6000"
indicator-position="none"
height="180px"
@mouseenter="pauseCarousel"
@mouseleave="startCarousel"
>
<el-carousel-item>
<ve-histogram
ref="histogram"
:data="literatureData.chartData"
:settings="literatureData.chartSettings"
:extend="extendChartOptions"
height="200px"
:after-config="handleAfterConfig"
/>
</el-carousel-item>
<el-carousel-item>
<div class="subject-distribution">
<h4>学科分布 TOP5</h4>
<div class="distribution-list">
<div
class="distribution-item"
v-for="(item, index) in literatureData.subjectDistribution"
:key="index"
>
<span class="name">{{ item.name }}</span>
<el-progress
:percentage="item.percentage"
:color="getProgressColor(index)"
:show-text="false"
/>
<span class="value">{{ formatNumber(item.count) }}</span>
</div>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</template>
<script>
import { literatureData, chartStyles } from "../data/dashboardData";
import { formatNumber } from "../utils/format";
export default {
name: "LiteratureOverview",
components: {},
data() {
return {
literatureData,
chartStyles,
carousel: null,
};
},
computed: {
extendChartOptions() {
return {
...this.chartStyles.research.extend,
grid: {
top: "10%",
left: "3%",
right: "4%",
bottom: "8%",
containLabel: true,
},
animation: {
duration: 2000,
easing: "cubicInOut",
},
};
},
},
methods: {
formatNumber,
pauseCarousel() {
if (this.carousel) {
this.carousel.pause();
}
},
startCarousel() {
if (this.carousel) {
this.carousel.start();
}
},
handleAfterConfig(options) {
// 强制更新图表
this.$nextTick(() => {
if (this.$refs.histogram) {
this.$refs.histogram.echarts.resize();
}
});
return options;
},
getProgressColor(index) {
// 定义5种不同的颜色
const colors = [
'#4a90e2', // 亮蓝色
'#00CED1', // 天青色
'#9561e2', // 紫色
'#64B5F6', // 天蓝色
'#ff9f43' // 亮橙色
];
return colors[index % colors.length];
},
},
mounted() {
this.carousel = this.$refs.carousel;
// 确保图表在挂载后立即渲染
this.$nextTick(() => {
if (this.$refs.histogram) {
this.$refs.histogram.echarts.resize();
}
});
},
activated() {
// keep-alive 组件激活时也重新渲染图表
if (this.$refs.histogram) {
this.$refs.histogram.echarts.resize();
}
},
};
</script>
<style lang="scss" scoped>
.literature-overview {
height: 100%;
color: #fff;
.content {
height: calc(100% - 80px);
margin-top: 20px;
.total-info {
text-align: center;
margin-bottom: 15px;
margin-top: -15px;
.total-number {
font-size: 24px;
font-weight: bold;
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.label {
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
margin-top: 5px;
}
}
.subject-distribution {
padding: 0 10px;
h4 {
font-size: 14px;
margin-bottom: 15px;
color: rgba(255, 255, 255, 0.9);
font-weight: 500;
}
.distribution-list {
.distribution-item {
display: flex;
align-items: center;
margin-bottom: 12px;
transition: all 0.3s ease;
&:hover {
transform: translateX(5px);
.name {
color: rgba(255, 255, 255, 0.9);
}
.value {
background: linear-gradient(135deg, #4a90e2, #36d1dc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.name {
width: 70px;
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
transition: color 0.3s ease;
}
.el-progress {
flex: 1;
margin: 0 12px;
::v-deep .el-progress-bar__outer {
background-color: rgba(255, 255, 255, 0.1);
border-radius: 4px;
height: 12px !important;
background-image: repeating-linear-gradient(
to right,
transparent,
transparent 4px,
rgba(255, 255, 255, 0.1) 4px,
rgba(255, 255, 255, 0.1) 6px
);
}
::v-deep .el-progress-bar__inner {
border-radius: 4px;
transition: all 0.3s ease;
position: relative;
background-image: repeating-linear-gradient(
to right,
transparent,
transparent 4px,
rgba(255, 255, 255, 0.2) 4px,
rgba(255, 255, 255, 0.2) 6px
);
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: inherit;
filter: brightness(1.2);
border-radius: 4px;
opacity: 0;
transition: opacity 0.3s ease;
}
}
&:hover {
::v-deep .el-progress-bar__inner::after {
opacity: 1;
}
}
}
.value {
width: 60px;
font-size: 13px;
color: #4a90e2;
text-align: right;
transition: all 0.3s ease;
}
}
}
}
}
}
</style>