Files
GEAR-OA/gear-ui3/src/components/StickyDragContainer/index.vue
砂糖 42f6f83c3a feat: 新增物料管理看板功能及多项优化
新增物料管理看板功能,包含统计卡片和图表展示
优化物料选择器组件,支持分页和搜索功能
重构物料详情展示组件,支持动态加载数据
添加多个ECharts图表组件用于数据可视化
完善出入库和采购单相关功能,增加在途数量显示
修复若干界面显示问题和交互逻辑
2026-01-31 14:21:49 +08:00

149 lines
4.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- @/components/StickyDragContainer/index.vue -->
<template>
<div class="sticky-drag-wrapper" :style="wrapperStyle">
<!-- 拖拽条 -->
<div class="drag-bar" ref="dragBarRef" @mousedown="handleDragStart"></div>
<!-- 高度可调节+内部滚动容器 -->
<div
class="content-scroll-container"
ref="scrollContainerRef"
:style="{ height: `${containerHeight}px` }"
>
<!-- 默认插槽接收外部传入的任意内容 -->
<slot></slot>
</div>
</div>
</template>
<script setup name="StickyDragContainer">
import { ref, onMounted, onUnmounted, defineProps, watch, nextTick } from 'vue'
// 新增接收父容器Ref必传用于获取父容器布局信息
const props = defineProps({
parentRef: { // 父容器的Ref对象外部传入
type: Object,
required: true
},
initialHeight: { // 容器初始高度px
type: Number,
default: 300
},
minHeight: { // 容器最小高度px
type: Number,
default: 200
},
zIndex: { // 容器层级
type: Number,
default: 99
}
})
// 响应式变量
const dragBarRef = ref(null)
const scrollContainerRef = ref(null)
const startY = ref(0)
const startHeight = ref(props.initialHeight)
const containerHeight = ref(props.initialHeight)
// 新增组件外层样式动态绑定宽度、左侧偏移、z-index等
const wrapperStyle = ref({
zIndex: props.zIndex,
width: '0px',
left: '0px'
})
// 核心方法:更新组件布局(宽度/左侧偏移),与父容器保持一致
const updateContainerLayout = () => {
nextTick(() => {
// 校验父容器Ref是否有效
console.log(props.parentRef)
if (!props.parentRef) {
console.warn('StickyDragContainer传入的parentRef无效请确保绑定了正确的DOM Ref')
return
}
// 获取父容器的实际布局信息(相对于视口的位置、宽度)
const parentRect = props.parentRef.getBoundingClientRect()
// 动态设置组件宽度(与父容器完全一致)、左侧偏移(与父容器左对齐)
wrapperStyle.value = {
zIndex: props.zIndex,
width: `${parentRect.width}px`, // 继承父容器宽度
left: `${parentRect.left}px` // 与父容器左对齐
}
})
}
// 拖拽相关方法(保持不变)
const handleDragStart = (e) => {
e.preventDefault()
startY.value = e.clientY
startHeight.value = scrollContainerRef.value?.getBoundingClientRect().height || containerHeight.value
document.addEventListener('mousemove', handleDragMove)
document.addEventListener('mouseup', handleDragEnd)
}
const handleDragMove = (e) => {
e.preventDefault()
const diffY = startY.value - e.clientY
const newHeight = Math.max(props.minHeight, startHeight.value + diffY)
containerHeight.value = newHeight
}
const handleDragEnd = () => {
document.removeEventListener('mousemove', handleDragMove)
document.removeEventListener('mouseup', handleDragEnd)
}
// 生命周期:初始化+监听窗口缩放
onMounted(() => {
containerHeight.value = props.initialHeight
updateContainerLayout() // 初始化时适配父容器布局
// 新增:监听窗口缩放,父容器宽度变化时同步更新组件布局
window.addEventListener('resize', updateContainerLayout)
})
onUnmounted(() => {
// 解绑所有事件,防止内存泄漏
document.removeEventListener('mousemove', handleDragMove)
document.removeEventListener('mouseup', handleDragEnd)
window.removeEventListener('resize', updateContainerLayout) // 解绑窗口监听
})
// 监听props变化动态更新
watch([() => props.initialHeight, () => props.zIndex], () => {
containerHeight.value = props.initialHeight
wrapperStyle.value.zIndex = props.zIndex
}, { immediate: true })
// 新增如果父容器Ref变化重新适配布局
watch(() => props.parentRef, () => {
updateContainerLayout()
}, { deep: true, immediate: true })
</script>
<style scoped>
/* 吸底外层容器移除left/right:0改为动态绑定保留fixed+bottom:0核心吸底 */
.sticky-drag-wrapper {
position: fixed;
bottom: 0; /* 仅保留吸底,宽度/左侧偏移由JS动态设置 */
background: #ffffff;
border-top: 1px solid #e6e6e6;
box-sizing: border-box;
transition: all 0.1s ease; /* 宽度/高度变化平滑过渡 */
}
/* 拖拽条样式(保持不变) */
.drag-bar {
height: 6px;
background-color: #e6e6e6;
cursor: n-resize;
transition: background-color 0.2s ease;
}
.drag-bar:hover {
background-color: #409eff;
}
/* 内容滚动容器样式(保持不变) */
.content-scroll-container {
width: 100%; /* 继承外层wrapper的宽度即父容器宽度 */
overflow: auto;
box-sizing: border-box;
transition: height 0.1s ease;
}
</style>