Commit 8f2d04a3 by wusiyi

fix: 尝试修复图片预览会留存的问题

parent 735473e1
...@@ -4,6 +4,7 @@ import { ...@@ -4,6 +4,7 @@ import {
RouteLocationNormalized, RouteLocationNormalized,
NavigationGuardNext, NavigationGuardNext,
} from 'vue-router' } from 'vue-router'
import { cleanupImagePreview } from '@/utils/hooks/useImagePreview.'
import Login from '@/views/Login.vue' import Login from '@/views/Login.vue'
import Reset from '@/views/Reset.vue' import Reset from '@/views/Reset.vue'
...@@ -341,6 +342,8 @@ router.beforeEach( ...@@ -341,6 +342,8 @@ router.beforeEach(
_from: RouteLocationNormalized, _from: RouteLocationNormalized,
next: NavigationGuardNext, next: NavigationGuardNext,
) => { ) => {
// 路由切换时清理图片预览,防止预览元素残留
cleanupImagePreview()
const token = getToken() const token = getToken()
if (to.query.factoryCode) { if (to.query.factoryCode) {
localStorage.setItem('factory_code', String(to.query.factoryCode)) localStorage.setItem('factory_code', String(to.query.factoryCode))
......
import { ref } from 'vue' import { ref, onUnmounted } from 'vue'
export default function useImagePreview() { // 单例模式:所有实例共享同一个预览元素
const show = ref(false) let previewDiv: HTMLDivElement | null = null
const div = document.createElement('div') let previewImg: HTMLImageElement | null = null
div.style.position = 'fixed' const show = ref(false)
div.style.zIndex = '9999999999999' let currentTarget: HTMLElement | null = null
div.style.display = 'none' let mousemoveHandler: ((ev: MouseEvent) => void) | null = null
const img = document.createElement('img')
img.style.width = '300px' // 初始化预览元素(只创建一次)
div.appendChild(img) function initPreviewElement() {
document.body.appendChild(div) if (previewDiv) return
let currentTarget: HTMLElement | null = null previewDiv = document.createElement('div')
previewDiv.style.position = 'fixed'
previewDiv.style.zIndex = '9999999999999'
previewDiv.style.display = 'none'
previewImg = document.createElement('img')
previewImg.style.width = '300px'
previewDiv.appendChild(previewImg)
document.body.appendChild(previewDiv)
}
const mousemoveHandler = (ev: MouseEvent) => { // 清理函数:移除事件监听器和重置状态
if (!currentTarget) return function cleanup() {
const rect = currentTarget.getBoundingClientRect() if (mousemoveHandler) {
const inOrigin = window.removeEventListener('mousemove', mousemoveHandler)
ev.clientX >= rect.left && mousemoveHandler = null
ev.clientX <= rect.right && }
ev.clientY >= rect.top && if (previewDiv) {
ev.clientY <= rect.bottom previewDiv.style.display = 'none'
}
show.value = false
currentTarget = null
}
const divRect = div.getBoundingClientRect() // 导出清理函数,供路由切换时使用
const inPreview = export function cleanupImagePreview() {
ev.clientX >= divRect.left && cleanup()
ev.clientX <= divRect.right && }
ev.clientY >= divRect.top &&
ev.clientY <= divRect.bottom
if (!inOrigin && !inPreview) { export default function useImagePreview() {
div.style.display = 'none' // 确保预览元素已初始化
show.value = false initPreviewElement()
window.removeEventListener('mousemove', mousemoveHandler)
currentTarget = null // 创建 mousemove 处理器(如果还没有)
if (!mousemoveHandler) {
mousemoveHandler = (ev: MouseEvent) => {
if (!currentTarget || !previewDiv) {
cleanup()
return
}
const rect = currentTarget.getBoundingClientRect()
const inOrigin =
ev.clientX >= rect.left &&
ev.clientX <= rect.right &&
ev.clientY >= rect.top &&
ev.clientY <= rect.bottom
const divRect = previewDiv.getBoundingClientRect()
const inPreview =
ev.clientX >= divRect.left &&
ev.clientX <= divRect.right &&
ev.clientY >= divRect.top &&
ev.clientY <= divRect.bottom
if (!inOrigin && !inPreview) {
cleanup()
}
} }
} }
...@@ -44,12 +77,13 @@ export default function useImagePreview() { ...@@ -44,12 +77,13 @@ export default function useImagePreview() {
newBorder?: boolean, newBorder?: boolean,
positionBOOTTOM?: boolean, positionBOOTTOM?: boolean,
) => { ) => {
if (!previewDiv || !previewImg) return
ev.preventDefault() ev.preventDefault()
if (show.value === true) return if (show.value === true) return
img.src = url previewImg.src = url
img.style.backgroundColor = '#eee' previewImg.style.backgroundColor = '#eee'
if (newBorder) img.style.border = '1px solid #eee' if (newBorder) previewImg.style.border = '1px solid #eee'
if (newWitdh) img.style.width = newWitdh if (newWitdh) previewImg.style.width = newWitdh
const cW = document.body.clientWidth const cW = document.body.clientWidth
const cH = document.body.clientHeight const cH = document.body.clientHeight
const cX = ev.clientX const cX = ev.clientX
...@@ -59,14 +93,15 @@ export default function useImagePreview() { ...@@ -59,14 +93,15 @@ export default function useImagePreview() {
else y = cY - 150 else y = cY - 150
if (cX + 300 >= cW) x = cX - 300 if (cX + 300 >= cW) x = cX - 300
else x = cX + 60 else x = cX + 60
img.onload = () => { previewImg.onload = () => {
div.style.left = x + 'px' if (!previewDiv || !previewImg) return
div.style.top = y + 'px' previewDiv.style.left = x + 'px'
div.style.display = 'block' previewDiv.style.top = y + 'px'
previewDiv.style.display = 'block'
if (positionBOOTTOM) { if (positionBOOTTOM) {
// 获取图片实际尺寸 // 获取图片实际尺寸
const imgWidth = img.clientWidth const imgWidth = previewImg.clientWidth
const imgHeight = img.clientHeight const imgHeight = previewImg.clientHeight
// 计算新位置(鼠标正下方) // 计算新位置(鼠标正下方)
let x = cX / 2 let x = cX / 2
...@@ -85,20 +120,26 @@ export default function useImagePreview() { ...@@ -85,20 +120,26 @@ export default function useImagePreview() {
if (y < 0) { if (y < 0) {
y = 10 y = 10
} }
div.style.left = x + 'px' previewDiv.style.left = x + 'px'
div.style.top = y + 'px' previewDiv.style.top = y + 'px'
} }
show.value = true show.value = true
currentTarget = ev.currentTarget as HTMLElement currentTarget = ev.currentTarget as HTMLElement
window.addEventListener('mousemove', mousemoveHandler) if (mousemoveHandler) {
window.addEventListener('mousemove', mousemoveHandler)
}
} }
} }
const mouseleaveImg = () => { const mouseleaveImg = () => {
if (show.value === false) return // 在 mouseleave 时也要清理事件监听器
div.style.display = 'none' cleanup()
show.value = false
} }
// 组件卸载时清理(防止内存泄漏)
onUnmounted(() => {
cleanup()
})
return { mouseoverImg, mouseleaveImg } return { mouseoverImg, mouseleaveImg }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment