feat: 新增 PC 端粘贴图片上传功能(hover 区域检测 + 网页图片链接自动填入)
This commit is contained in:
81
inventory-web/src/hooks/usePasteUpload.ts
Normal file
81
inventory-web/src/hooks/usePasteUpload.ts
Normal file
@ -0,0 +1,81 @@
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
export function usePasteUpload(
|
||||
customUpload: Function,
|
||||
targetField: string,
|
||||
containerSelector: string,
|
||||
onLinkFound?: (link: string, field: string) => void
|
||||
) {
|
||||
const isHovering = ref(false)
|
||||
|
||||
const handleMouseMove = (event: MouseEvent) => {
|
||||
const target = event.target as Element
|
||||
if (!target) return
|
||||
const isInsideTarget = !!target.closest(containerSelector)
|
||||
if (isInsideTarget !== isHovering.value) {
|
||||
isHovering.value = isInsideTarget
|
||||
}
|
||||
}
|
||||
|
||||
const handleGlobalPaste = (event: ClipboardEvent) => {
|
||||
if (!isHovering.value) return
|
||||
|
||||
const activeElement = document.activeElement
|
||||
const activeTag = activeElement?.tagName.toLowerCase()
|
||||
if (activeTag === 'input' || activeTag === 'textarea') return
|
||||
|
||||
const clipboardData = event.clipboardData
|
||||
if (!clipboardData) return
|
||||
|
||||
// 1. 优先获取真实文件(本地截图/复制文件)
|
||||
let imageFile: File | null = null
|
||||
for (let i = 0; i < clipboardData.items.length; i++) {
|
||||
if (clipboardData.items[i].type.indexOf('image') !== -1) {
|
||||
const rawFile = clipboardData.items[i].getAsFile()
|
||||
if (rawFile) {
|
||||
const extension = rawFile.type.split('/')[1] || 'png'
|
||||
const fileName = `paste_${targetField}_${new Date().getTime()}.${extension}`
|
||||
imageFile = new File([rawFile], fileName, { type: rawFile.type })
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imageFile) {
|
||||
event.preventDefault()
|
||||
customUpload({ file: imageFile, onSuccess: () => {}, onError: () => {} }, targetField)
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 没有真实文件时,解析 HTML 或文本里的图片 URL(网页复制场景)
|
||||
const htmlData = clipboardData.getData('text/html')
|
||||
const textData = clipboardData.getData('text/plain')
|
||||
|
||||
let imgUrl = ''
|
||||
if (htmlData) {
|
||||
const match = htmlData.match(/<img[^>]+src="([^">]+)"/)
|
||||
if (match && match[1]) imgUrl = match[1]
|
||||
}
|
||||
if (!imgUrl && textData && textData.startsWith('http')) {
|
||||
imgUrl = textData
|
||||
}
|
||||
|
||||
if (imgUrl && onLinkFound) {
|
||||
event.preventDefault()
|
||||
ElMessage.success('检测到网页图片,已自动填入外部链接')
|
||||
onLinkFound(imgUrl, targetField)
|
||||
} else if (!imgUrl) {
|
||||
ElMessage.warning('剪贴板中未检测到有效图片或链接')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('mousemove', handleMouseMove)
|
||||
document.addEventListener('paste', handleGlobalPaste)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('mousemove', handleMouseMove)
|
||||
document.removeEventListener('paste', handleGlobalPaste)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user