Files
jiangmingzhao-daily-report/frontend/src/layout/components/ScrollPane.vue
jiangmingzhao 9b9ee273fc 初始提交:企业级日报系统完整代码
功能特性:
-  JWT用户认证系统
-  日报CRUD管理
-  三级权限控制
-  多维度搜索过滤
-  统计分析功能
-  评论互动系统
-  响应式Cool Admin界面
-  暗色主题支持

 技术栈:
- 后端:Django 4.2.7 + DRF + SimpleJWT
- 前端:Vue 3 + Element Plus + Pinia
- 数据库:SQLite/PostgreSQL
- 部署:Docker + Nginx

 包含内容:
- 完整的后端API代码
- 现代化前端界面
- 数据库迁移文件
- 部署脚本和文档
- 演示页面和测试工具
2025-09-13 14:35:15 +08:00

109 lines
2.5 KiB
Vue

<template>
<div
ref="scrollContainer"
class="scroll-container"
@wheel.prevent="handleScroll"
>
<div ref="scrollWrapper" class="scroll-wrapper">
<slot />
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
const emit = defineEmits(['scroll'])
const scrollContainer = ref()
const scrollWrapper = ref()
let scrollLeft = 0
let scrollTop = 0
const handleScroll = (e) => {
const eventDelta = e.wheelDelta || -e.deltaY * 40
const $container = scrollContainer.value
const $containerWidth = $container.offsetWidth
const $wrapper = scrollWrapper.value
const $wrapperWidth = $wrapper.offsetWidth
if (eventDelta > 0) {
scrollLeft = Math.max(0, scrollLeft - 50)
} else {
if ($containerWidth - 50 < $wrapperWidth) {
if (scrollLeft < $wrapperWidth - $containerWidth + 50) {
scrollLeft += 50
}
}
}
$wrapper.style.left = scrollLeft * -1 + 'px'
emit('scroll')
}
const moveToTarget = (currentTag) => {
const $container = scrollContainer.value
const $containerWidth = $container.offsetWidth
const $wrapper = scrollWrapper.value
if (!currentTag) {
return
}
const tagList = $wrapper.querySelectorAll('.tags-view-item')
let firstTag = null
let lastTag = null
if (tagList.length > 0) {
firstTag = tagList[0]
lastTag = tagList[tagList.length - 1]
}
if (firstTag === currentTag) {
scrollLeft = 0
} else if (lastTag === currentTag) {
scrollLeft = $wrapper.offsetWidth - $containerWidth
} else {
const tagListArray = [...tagList]
const currentIndex = tagListArray.findIndex(item => item === currentTag)
const prevTag = tagListArray[currentIndex - 1]
const nextTag = tagListArray[currentIndex + 1]
const afterNextTagOffsetLeft = nextTag ? nextTag.offsetLeft + nextTag.offsetWidth + 4 : 0
const beforePrevTagOffsetLeft = prevTag ? prevTag.offsetLeft - 4 : 0
if (afterNextTagOffsetLeft > scrollLeft + $containerWidth) {
scrollLeft = afterNextTagOffsetLeft - $containerWidth
} else if (beforePrevTagOffsetLeft < scrollLeft) {
scrollLeft = beforePrevTagOffsetLeft
}
}
$wrapper.style.left = scrollLeft * -1 + 'px'
}
// 暴露方法
defineExpose({
moveToTarget
})
</script>
<style lang="scss" scoped>
.scroll-container {
white-space: nowrap;
position: relative;
overflow: hidden;
width: 100%;
.scroll-wrapper {
position: absolute;
top: 0px;
height: 100%;
transition: left 0.3s ease-in-out;
}
}
</style>