diff --git a/dashboard/src/components/ClickToCopyField.vue b/dashboard/src/components/ClickToCopyField.vue index c4c12cf..e635412 100644 --- a/dashboard/src/components/ClickToCopyField.vue +++ b/dashboard/src/components/ClickToCopyField.vue @@ -44,15 +44,50 @@ export default { }; }, methods: { - copyTextContentToClipboard() { - const clipboard = window.navigator.clipboard; - clipboard.writeText(this.textContent).then(() => { - this.copied = true; - setTimeout(() => { - this.copied = false; - }, 4000); - toast.success(this.$t('Copied to clipboard!')); - }); + async copyTextContentToClipboard() { + try { + // 优先使用现代的 Clipboard API + if (navigator.clipboard && navigator.clipboard.writeText) { + await navigator.clipboard.writeText(this.textContent); + this.showCopySuccess(); + } else { + // 降级方案:使用传统的 execCommand 方法 + this.fallbackCopyTextToClipboard(this.textContent); + } + } catch (error) { + // 如果 Clipboard API 失败,尝试降级方案 + this.fallbackCopyTextToClipboard(this.textContent); + } + }, + fallbackCopyTextToClipboard(text) { + const textArea = document.createElement('textarea'); + textArea.value = text; + textArea.style.position = 'fixed'; + textArea.style.left = '-999999px'; + textArea.style.top = '-999999px'; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + try { + const successful = document.execCommand('copy'); + if (successful) { + this.showCopySuccess(); + } else { + toast.error(this.$t('Copy failed, please copy manually')); + } + } catch (err) { + toast.error(this.$t('Copy failed, please copy manually')); + } finally { + document.body.removeChild(textArea); + } + }, + showCopySuccess() { + this.copied = true; + setTimeout(() => { + this.copied = false; + }, 4000); + toast.success(this.$t('Copied to clipboard!')); } } };