提交 3327d190 authored 作者: 龙菲's avatar 龙菲

优化web端的导航组件

上级 66b75ffd
差异被折叠。
......@@ -18,6 +18,7 @@
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.3",
"sass-embedded": "^1.89.1",
"unplugin-auto-import": "^19.1.2",
"unplugin-vue-components": "^28.5.0",
"vite": "^6.2.4",
......
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
......@@ -9,10 +9,12 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
BookReader: typeof import('./components/BookReader.vue')['default']
ElBacktop: typeof import('element-plus/es')['ElBacktop']
ElButton: typeof import('element-plus/es')['ElButton']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElIcon: typeof import('element-plus/es')['ElIcon']
FileUpload: typeof import('./components/FileUpload.vue')['default']
Guide: typeof import('./components/Guide.vue')['default']
IconCommunity: typeof import('./components/icons/IconCommunity.vue')['default']
IconDocumentation: typeof import('./components/icons/IconDocumentation.vue')['default']
IconEcosystem: typeof import('./components/icons/IconEcosystem.vue')['default']
......
<template>
<el-dialog
v-model="showDirectory"
title="目录"
width="50%"
:close-on-click-modal="true"
:close-on-press-escape="true"
class="directory-dialog"
>
<div class="content">
<div class="thumbnail-grid" ref="thumbnailGrid" @scroll="handleScroll">
<div
v-for="(img, index) in directoryImages"
:key="index"
:class="['thumbnail-item', { active: currentPage == index + 2 }]"
@click="goToPage(img.pageNum)"
:ref="setThumbnailRef"
>
<img :src="img.src" :alt="`第 ${img.pageNum} 页`" />
<span class="page-number">{{ img.pageNum }}</span>
</div>
</div>
<el-button
v-show="showBackTop"
:icon="ArrowUpBold"
class="back-top"
color="#000"
circle
size="large"
type="info"
@click="scrollToTop"
></el-button>
</div>
</el-dialog>
</template>
<script setup>
import { ArrowUpBold } from "@element-plus/icons-vue";
const $emit = defineEmits(["goToPage"]);
const props = defineProps({
directoryImages: {
type: Array,
default: () => [],
},
currentPage: {
type: Number,
default: 0,
},
});
const showDirectory = ref(false);
const thumbnailGrid = ref(null); // 获取滚动容器的引用
const showBackTop = ref(false); // 控制按钮显示
const thumbnailRefs = ref([]); // 存储所有缩略图的DOM引用
const setThumbnailRef = (el) => {
if (el) {
thumbnailRefs.value.push(el);
}
};
function show() {
showDirectory.value = true;
nextTick(() => {
scrollToCurrentPage();
});
}
function scrollToCurrentPage() {
if (
props.currentPage > 0 &&
thumbnailGrid.value &&
thumbnailRefs.value.length > 0
) {
// 找到当前页码对应的缩略图索引
const currentIndex = props.directoryImages.findIndex(
(img) => img.pageNum === props.currentPage
);
if (currentIndex >= 0) {
const thumbnailElement = thumbnailRefs.value[currentIndex + 2];
if (thumbnailElement) {
// 计算滚动位置
const gridRect = thumbnailGrid.value.getBoundingClientRect();
const thumbRect = thumbnailElement.getBoundingClientRect();
const scrollTop =
thumbRect.top - gridRect.top + thumbnailGrid.value.scrollTop;
// 平滑滚动到该位置
thumbnailGrid.value.scrollTo({
top: scrollTop - 50, // 减去50px让缩略图不是紧贴顶部
behavior: "smooth",
});
}
}
}
}
function goToPage(pageNum) {
$emit("goToPage", pageNum);
showDirectory.value = false;
}
// 返回顶部函数
function scrollToTop() {
if (thumbnailGrid.value) {
thumbnailGrid.value.scrollTo({
top: 0,
behavior: "smooth", // 平滑滚动
});
}
}
// 监听滚动
function handleScroll() {
if (thumbnailGrid.value) {
showBackTop.value = thumbnailGrid.value.scrollTop > 100; // 滚动超过 100px 时显示
}
}
defineExpose({
show,
});
</script>
<style lang="scss" scoped>
.thumbnail-grid {
max-height: 70vh;
overflow-y: auto;
display: flex;
flex-wrap: wrap;
gap: 10px; /* 添加行间距和列间距 */
position: relative;
}
.content {
.back-top {
position: absolute;
bottom: 40px;
right: 40px;
}
}
.thumbnail-item {
position: relative;
cursor: pointer;
transition: transform 0.2s;
overflow: hidden;
width: calc(33.333% - 10px); /* 调整宽度,减去间距 */
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid transparent;
&:hover {
border: 1px solid #000;
}
img {
width: 100%;
height: 200px;
object-fit: contain;
}
.page-number {
font-size: 20px;
position: absolute;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.65);
width: 100%;
text-align: center;
color: #fff;
}
}
.active {
border: 1px solid #000;
.page-number {
color: var(--el-color-success);
background-color: #fff;
}
}
@media (max-width: 768px) {
.thumbnail-grid {
gap: 10px; /* 保持间距 */
}
.thumbnail-item {
width: calc(33.333% - 10px); /* 保持宽度调整 */
}
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论