应用排名滚动

This commit is contained in:
JenniferW 2025-09-08 10:38:17 +08:00
parent f2ef475cda
commit 22f22a8c83
2 changed files with 191 additions and 37 deletions

View File

@ -0,0 +1,155 @@
<template>
<div class="scroll-ranking-container">
<ul class="ranking-list" ref="rankingList">
<li
v-for="(item, index) in extendedList"
:key="index"
class="ranking-item"
>
<span class="item-name">{{ item.name }}</span>
<span class="item-count">{{ item.count }}</span>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "ScrollRanking",
props: {
list: {
type: Array,
required: true,
default: () => [],
},
interval: {
type: Number,
default: 2000,
},
visibleCount: {
type: Number,
default: 4,
},
},
data() {
return {
scrollTimer: null,
currentPosition: 0,
itemHeight: 0, //
};
},
computed: {
extendedList() {
if (this.list.length <= this.visibleCount) {
return this.list;
}
return [...this.list, ...this.list];
},
},
mounted() {
// DOM
this.$nextTick(() => {
this.calculateItemHeight();
if (this.list.length > this.visibleCount) {
this.startScroll();
this.$refs.rankingList.addEventListener("mouseenter", this.stopScroll);
this.$refs.rankingList.addEventListener("mouseleave", this.startScroll);
}
});
},
beforeDestroy() {
this.stopScroll();
if (this.$refs.rankingList) {
this.$refs.rankingList.removeEventListener("mouseenter", this.stopScroll);
this.$refs.rankingList.removeEventListener(
"mouseleave",
this.startScroll
);
}
},
methods: {
//
calculateItemHeight() {
const firstItem = this.$refs.rankingList?.querySelector(".ranking-item");
if (firstItem) {
this.itemHeight = firstItem.offsetHeight;
//
this.$el.style.height = `${this.itemHeight * this.visibleCount}px`;
}
},
startScroll() {
this.stopScroll();
this.scrollTimer = setInterval(() => {
this.scrollDown();
}, this.interval);
},
stopScroll() {
if (this.scrollTimer) {
clearInterval(this.scrollTimer);
this.scrollTimer = null;
}
},
scrollDown() {
if (!this.itemHeight) return;
this.currentPosition++;
const rankingList = this.$refs.rankingList;
rankingList.style.transform = `translateY(-${
this.currentPosition * this.itemHeight
}px)`;
rankingList.style.transition = "transform 0.5s ease";
//
if (this.currentPosition >= this.list.length) {
setTimeout(() => {
this.currentPosition = 0;
rankingList.style.transition = "none";
rankingList.style.transform = "translateY(0)";
}, 500);
}
},
},
};
</script>
<style scoped lang="scss">
.scroll-ranking-container {
overflow: hidden;
width: 100%;
position: relative;
}
.ranking-list {
list-style: none;
padding: 0;
margin: 0;
position: relative;
}
.ranking-item {
display: flex;
justify-content: space-between;
font-size: 13px;
color: rgba(255, 255, 255, 0.8);
transition: all 0.3s ease;
padding: 6px 0; /* 增加内边距使条目高度更合适 */
&:hover {
color: #fff;
transform: translateX(3px);
}
}
.item-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 70%;
}
.item-count {
font-weight: 500;
}
</style>

View File

@ -39,12 +39,12 @@
<div class="chart-item">
<div class="chart-title">应用今日调用 TOP5</div>
<div class="chart-content">
<ul class="chart-list">
<li v-for="(item, index) in top5Apps" :key="index">
<span>{{ item.name }}</span>
<span>{{ item.count }}</span>
</li>
</ul>
<!-- 使用滚动排名组件 -->
<scroll-ranking
:list="top5Apps"
:visible-count="4"
:interval="2000"
/>
</div>
</div>
</div>
@ -54,12 +54,12 @@
<div class="chart-item">
<div class="chart-title">接口资源调用 TOP20</div>
<div class="chart-content">
<ul class="chart-list">
<li v-for="(item, index) in top20Apis" :key="index">
<span>{{ item.name }}</span>
<span>{{ item.count }}</span>
</li>
</ul>
<!-- 使用滚动排名组件 -->
<scroll-ranking
:list="top20Apis"
:visible-count="4"
:interval="2500"
/>
</div>
</div>
</div>
@ -68,7 +68,12 @@
</template>
<script>
import ScrollRanking from "@/components/ScrollRanking.vue";
export default {
components: {
ScrollRanking,
},
data() {
return {
top20Apis: [
@ -76,12 +81,29 @@ export default {
{ name: "学生人数信息", count: 193 },
{ name: "教职工科研信息", count: 127 },
{ name: "教职工基础信息", count: 231 },
{ name: "课程信息", count: 189 },
{ name: "成绩信息", count: 176 },
{ name: "图书馆借阅信息", count: 156 },
{ name: "校园卡消费信息", count: 143 },
{ name: "宿舍信息", count: 132 },
{ name: "奖学金信息", count: 121 },
{ name: "助学金信息", count: 110 },
{ name: "勤工助学信息", count: 98 },
{ name: "学生社团信息", count: 87 },
{ name: "教学计划信息", count: 76 },
{ name: "教材信息", count: 65 },
{ name: "实验室信息", count: 54 },
{ name: "科研项目信息", count: 43 },
{ name: "学术会议信息", count: 32 },
{ name: "论文发表信息", count: 21 },
{ name: "专利信息", count: 10 },
],
top5Apps: [
{ name: "人事系统", count: 209 },
{ name: "科研系统", count: 193 },
{ name: "门禁系统", count: 127 },
{ name: "学工系统", count: 231 },
{ name: "教务系统", count: 186 },
],
};
},
@ -89,6 +111,7 @@ export default {
</script>
<style scoped lang="scss">
/* 原有样式保持不变 */
.open-share-container {
display: flex;
align-items: stretch;
@ -237,30 +260,6 @@ export default {
flex: 1;
display: flex;
flex-direction: column;
ul.chart-list {
list-style: none;
padding: 0;
margin: 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-around;
li {
display: flex;
justify-content: space-between;
font-size: 13px;
color: rgba(255, 255, 255, 0.8);
transition: all 0.3s ease;
padding: 3px 0;
&:hover {
color: #fff;
transform: translateX(3px);
}
}
}
}
}
</style>
</style>