This commit is contained in:
amb
2026-09-02 07:57:39 +08:00
parent 2d42b0e73d
commit 410bd30b2e
5 changed files with 90 additions and 7 deletions
+37
View File
@@ -0,0 +1,37 @@
/**
* 兼容所有浏览器的复制到剪贴板函数
* 解决 iOS Safari 不支持 navigator.clipboard.writeText() 的问题
*/
export async function copyToClipboard(text) {
// 方法1: 现代 Clipboard APIChrome/Firefox/Edge 桌面端)
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
try {
await navigator.clipboard.writeText(text);
return true;
}
catch {
// Safari 可能抛出 NotAllowedError,继续尝试 fallback
}
}
// 方法2: 传统 execCommandiOS Safari 兼容方案)
try {
const textarea = document.createElement('textarea');
textarea.value = text;
// 防止页面滚动
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
textarea.style.top = '-9999px';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
// iOS Safari 需要设置 selection range
textarea.focus();
textarea.select();
textarea.setSelectionRange(0, textarea.value.length);
const success = document.execCommand('copy');
document.body.removeChild(textarea);
return success;
}
catch {
return false;
}
}
+40
View File
@@ -0,0 +1,40 @@
/**
* 兼容所有浏览器的复制到剪贴板函数
* 解决 iOS Safari 不支持 navigator.clipboard.writeText() 的问题
*/
export async function copyToClipboard(text: string): Promise<boolean> {
// 方法1: 现代 Clipboard APIChrome/Firefox/Edge 桌面端)
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
try {
await navigator.clipboard.writeText(text)
return true
} catch {
// Safari 可能抛出 NotAllowedError,继续尝试 fallback
}
}
// 方法2: 传统 execCommandiOS Safari 兼容方案)
try {
const textarea = document.createElement('textarea')
textarea.value = text
// 防止页面滚动
textarea.style.position = 'fixed'
textarea.style.left = '-9999px'
textarea.style.top = '-9999px'
textarea.style.opacity = '0'
document.body.appendChild(textarea)
// iOS Safari 需要设置 selection range
textarea.focus()
textarea.select()
textarea.setSelectionRange(0, textarea.value.length)
const success = document.execCommand('copy')
document.body.removeChild(textarea)
return success
} catch {
return false
}
}
+6 -3
View File
@@ -3,6 +3,7 @@ import { ref, onMounted, computed } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import apiClient from '@/api/client'
import { copyToClipboard } from '@/utils/clipboard'
const route = useRoute()
const kbId = route.params.id as string
@@ -173,10 +174,12 @@ async function handleReprocess(doc: any) {
}
async function handleCopyLink() {
try {
await navigator.clipboard.writeText(aiUrl.value)
const success = await copyToClipboard(aiUrl.value)
if (success) {
ElMessage.success('AI 链接已复制!')
} catch { /* ignore */ }
} else {
ElMessage.error('复制失败,请手动长按复制。')
}
}
// 重新生成 AI 链接
+6 -3
View File
@@ -2,6 +2,7 @@ import { ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { ElMessage, ElMessageBox } from 'element-plus';
import apiClient from '@/api/client';
import { copyToClipboard } from '@/utils/clipboard';
const route = useRoute();
const kbId = route.params.id;
const isMobile = ref(window.innerWidth <= 768);
@@ -162,11 +163,13 @@ async function handleReprocess(doc) {
catch { /* ignore */ }
}
async function handleCopyLink() {
try {
await navigator.clipboard.writeText(aiUrl.value);
const success = await copyToClipboard(aiUrl.value);
if (success) {
ElMessage.success('AI 链接已复制!');
}
catch { /* ignore */ }
else {
ElMessage.error('复制失败,请手动长按复制。');
}
}
// 重新生成 AI 链接
async function handleRegenerateLink() {
+1 -1
View File
@@ -1 +1 @@
{"root":["./src/env.d.ts","./src/main.ts","./src/api/client.ts","./src/router/index.ts","./src/stores/user.ts","./src/app.vue","./src/layouts/defaultlayout.vue","./src/views/dashboard.vue","./src/views/kbdetail.vue","./src/views/knowledgebases.vue","./src/views/login.vue","./src/views/register.vue","./src/views/settings.vue"],"version":"5.9.3"}
{"root":["./src/env.d.ts","./src/main.ts","./src/api/client.ts","./src/router/index.ts","./src/stores/user.ts","./src/utils/clipboard.ts","./src/app.vue","./src/layouts/defaultlayout.vue","./src/views/dashboard.vue","./src/views/kbdetail.vue","./src/views/knowledgebases.vue","./src/views/login.vue","./src/views/register.vue","./src/views/settings.vue"],"version":"5.9.3"}