// clipboard.ts — 统一剪贴板复制(Clipboard API + execCommand 回退)// Logan.Li /** 复制文本到剪贴板,兼容 HTTP / 非安全上下文 // Logan.Li */ export async function copyToClipboard(text: string): Promise { if (!text) return false; // 优先使用 Clipboard API try { if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) { await navigator.clipboard.writeText(text); return true; } } catch { /* 回退 execCommand */ } // execCommand 回退(参考 AgentWizard)// Logan.Li if (typeof document === 'undefined') return false; const textArea = document.createElement('textarea'); textArea.value = text; textArea.style.position = 'fixed'; textArea.style.top = '0'; textArea.style.left = '0'; textArea.style.width = '2em'; textArea.style.height = '2em'; textArea.style.padding = '0'; textArea.style.border = 'none'; textArea.style.outline = 'none'; textArea.style.boxShadow = 'none'; textArea.style.background = 'transparent'; textArea.style.opacity = '0'; textArea.style.pointerEvents = 'none'; textArea.style.zIndex = '-1'; textArea.style.fontSize = '16px'; textArea.contentEditable = 'true'; textArea.readOnly = true; document.body.appendChild(textArea); textArea.focus(); textArea.select(); if (textArea.setSelectionRange) { textArea.setSelectionRange(0, text.length); } let success = false; try { success = document.execCommand('copy'); } catch { success = false; } document.body.removeChild(textArea); return success; } /** 从剪贴板读取文本;非 HTTPS / 无权限时返回 null,由调用方走手动粘贴回退 // Logan.Li */ export async function readFromClipboard(): Promise { try { if (typeof navigator !== 'undefined' && navigator.clipboard?.readText) { return await navigator.clipboard.readText(); } } catch { return null; } return null; }