You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

170 lines
4.6 KiB

<script setup lang="ts">
import { cmdNameMap } from 'libs/utils'
import { useSystemStore } from 'stores/systemStore'
import { computed, nextTick, ref, watch } from 'vue'
defineProps({
visible: {
type: Boolean,
default: false,
},
})
const systemStore = useSystemStore()
const title = computed(() => {
return cmdNameMap[systemStore.systemList[0]?.command as keyof typeof cmdNameMap] || systemStore.systemList[0]?.command
})
const maskBodyRef = ref<HTMLElement | null>(null)
const maskRef = ref<HTMLElement | null>(null)
const maskHeaderRef = ref<HTMLElement | null>(null)
const statusMap = {
info: 'info',
error: 'danger',
warn: 'warning',
success: 'success',
finish: 'primary',
SEND: 'primary',
receive: 'primary',
start: 'primary',
result: 'primary',
}
watch(
() => systemStore.systemList,
async () => {
await nextTick()
if (maskBodyRef.value) {
maskBodyRef.value.scrollTop = maskBodyRef.value.scrollHeight
}
},
{ deep: true },
)
// 拖拽相关逻辑
let isDragging = false
let offsetX = 0
let offsetY = 0
const handleMouseDown = (event: MouseEvent | TouchEvent) => {
if (maskRef.value && maskHeaderRef.value) {
isDragging = true
const clientX = 'clientX' in event ? event.clientX : event.touches[0].clientX
const clientY = 'clientY' in event ? event.clientY : event.touches[0].clientY
offsetX = clientX - maskRef.value.offsetLeft
offsetY = clientY - maskRef.value.offsetTop
document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
document.addEventListener('touchmove', handleMouseMove)
document.addEventListener('touchend', handleMouseUp)
}
}
const handleMouseMove = (event: MouseEvent | TouchEvent) => {
if (maskRef.value && isDragging) {
const clientX = 'clientX' in event ? event.clientX : event.touches[0].clientX
const clientY = 'clientY' in event ? event.clientY : event.touches[0].clientY
// 获取 body 的宽度和高度
const bodyWidth = document.body.clientWidth
const bodyHeight = document.body.clientHeight
// 计算新的位置,并确保不会超出 body 的范围
const newLeft = Math.max(0, Math.min(clientX - offsetX, bodyWidth - maskRef.value.offsetWidth))
const newTop = Math.max(0, Math.min(clientY - offsetY, bodyHeight - maskRef.value.offsetHeight))
maskRef.value.style.left = `${newLeft}px`
maskRef.value.style.top = `${newTop}px`
}
}
const handleMouseUp = () => {
isDragging = false
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
document.removeEventListener('touchmove', handleMouseMove)
document.removeEventListener('touchend', handleMouseUp)
}
</script>
<template>
<teleport to="body">
<!-- 使用 transition 组件包裹 mask 元素 -->
<transition name="mask-fade">
<div
v-if="visible && systemStore.isDebug"
ref="maskRef"
class="mask"
>
<div
ref="maskHeaderRef" class="mask-header" @mousedown="handleMouseDown"
@touchstart="handleMouseDown"
>
<p>{{ title }}</p>
<el-icon @click="systemStore.updateStreamVisible(false)">
<Close />
</el-icon>
</div>
<div ref="maskBodyRef" class="mask-body">
<el-timeline>
<el-timeline-item
v-for="item in systemStore.systemList" :key="item"
:timestamp="JSON.stringify(item.content)"
>
<el-tag :type="statusMap[item.level as keyof typeof statusMap]" class="mask-tag">
{{ item.title }}
</el-tag>
</el-timeline-item>
</el-timeline>
</div>
</div>
</transition>
</teleport>
</template>
<style scoped lang="scss">
.mask {
width: 350px;
height: 200px;
padding: 5px 10px;
background: #fff;
box-shadow: var(--el-box-shadow-light);
position: absolute;
bottom: 20px;
right: 20px;
border-radius: 8px;
font-size: 30px;
.mask-header {
display: flex;
justify-content: space-between;
align-items: center;
height: 30px;
font-size: 16px;
border-bottom: 1px solid #ddd;
cursor: move; // 添加鼠标指针样式
.el-icon svg{
width: 18px;
cursor: pointer;
}
}
.mask-body {
padding: 5px 2px;
height: calc(100% - 31px);
overflow: auto;
}
}
/* 定义过渡效果 */
.mask-fade-enter-active, .mask-fade-leave-active {
transition: transform 0.5s ease;
}
.mask-fade-enter-from {
transform: translateX(100%);
}
.mask-fade-leave-to {
transform: translateX(100%);
}
</style>