feat: 增强前端clipboard功能

This commit is contained in:
shaw
2025-12-27 15:16:52 +08:00
parent f1e47291cd
commit 016d7ef645
7 changed files with 73 additions and 52 deletions

View File

@@ -1,40 +1,65 @@
import { ref } from 'vue'
import { useAppStore } from '@/stores/app'
/**
* 检测是否支持 Clipboard API需要安全上下文HTTPS/localhost
*/
function isClipboardSupported(): boolean {
return !!(navigator.clipboard && window.isSecureContext)
}
/**
* 降级方案:使用 textarea + execCommand
* 使用 textarea 而非 input以正确处理多行文本
*/
function fallbackCopy(text: string): boolean {
const textarea = document.createElement('textarea')
textarea.value = text
textarea.style.cssText = 'position:fixed;left:-9999px;top:-9999px'
document.body.appendChild(textarea)
textarea.select()
try {
return document.execCommand('copy')
} finally {
document.body.removeChild(textarea)
}
}
export function useClipboard() {
const appStore = useAppStore()
const copied = ref(false)
const copyToClipboard = async (text: string, successMessage = 'Copied to clipboard') => {
const copyToClipboard = async (
text: string,
successMessage = 'Copied to clipboard'
): Promise<boolean> => {
if (!text) return false
try {
await navigator.clipboard.writeText(text)
copied.value = true
appStore.showSuccess(successMessage)
setTimeout(() => {
copied.value = false
}, 2000)
return true
} catch {
// Fallback for older browsers
const input = document.createElement('input')
input.value = text
document.body.appendChild(input)
input.select()
document.execCommand('copy')
document.body.removeChild(input)
copied.value = true
appStore.showSuccess(successMessage)
setTimeout(() => {
copied.value = false
}, 2000)
return true
let success = false
if (isClipboardSupported()) {
try {
await navigator.clipboard.writeText(text)
success = true
} catch {
success = fallbackCopy(text)
}
} else {
success = fallbackCopy(text)
}
if (success) {
copied.value = true
appStore.showSuccess(successMessage)
setTimeout(() => {
copied.value = false
}, 2000)
} else {
appStore.showError('Copy failed')
}
return success
}
return {
copied,
copyToClipboard
}
return { copied, copyToClipboard }
}