265 lines
6.5 KiB
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> |