| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import Clipboard from 'clipboard'
- import { decrypt } from '@/utils/crypto'
- import { lang } from '@/main'
- // 全局隐藏的 input 元素,用于保持页面焦点
- let clipboardFocusInput: HTMLInputElement | null = null
- // 初始化隐藏的 input 元素以保持焦点
- export const initClipboardFocus = () => {
- if (clipboardFocusInput) return clipboardFocusInput
-
- clipboardFocusInput = document.createElement('input')
- clipboardFocusInput.style.cssText = 'position:fixed;left:-9999px;top:-9999px;opacity:0;pointer-events:none;'
- // clipboardFocusInput.style.cssText = 'position:fixed;left:-0;top:-0;'
- // clipboardFocusInput.setAttribute('readonly', 'readonly')
- clipboardFocusInput.setAttribute('tabindex', '-1')
- document.querySelector('.viewport-wrapper')?.appendChild(clipboardFocusInput)
-
- // 尝试聚焦
- clipboardFocusInput.focus()
- readClipboard()
- return clipboardFocusInput
- }
- /**
- * 复制文本到剪贴板
- * @param text 文本内容
- */
- export const copyText = (text: string) => {
- return new Promise((resolve, reject) => {
- const fakeElement = document.createElement('button')
- const clipboard = new Clipboard(fakeElement, {
- text: () => text,
- action: () => 'copy',
- container: document.body,
- })
- clipboard.on('success', e => {
- clipboard.destroy()
- resolve(e)
- })
- clipboard.on('error', e => {
- clipboard.destroy()
- reject(e)
- })
- document.body.appendChild(fakeElement)
- fakeElement.click()
- document.body.removeChild(fakeElement)
- })
- }
- // 读取剪贴板
- // 读取剪贴板
- export const readClipboard = (): Promise<string> => {
- return new Promise((resolve, reject) => {
- if (navigator.clipboard?.readText) {
- navigator.clipboard.readText().then(text => {
- if (!text) reject('剪贴板为空或者不包含文本')
- return resolve(text)
- })
- }
- else reject('浏览器不支持或禁止访问剪贴板,请使用快捷键 Ctrl + V')
- })
- }
- // 解析加密后的剪贴板内容
- export const pasteCustomClipboardString = (text: string) => {
- let clipboardData
- try {
- clipboardData = JSON.parse(decrypt(text))
- }
- catch {
- clipboardData = text
- }
- return clipboardData
- }
- // 尝试解析剪贴板内容是否为Excel表格(或类似的)数据格式
- export const pasteExcelClipboardString = (text: string): string[][] | null => {
- const lines: string[] = text.split('\r\n')
- if (lines[lines.length - 1] === '') lines.pop()
- let colCount = -1
- const data: string[][] = []
- for (const index in lines) {
- data[index] = lines[index].split('\t')
- if (data[index].length === 1) return null
- if (colCount === -1) colCount = data[index].length
- else if (colCount !== data[index].length) return null
- }
- return data
- }
- // 尝试解析剪贴板内容是否为HTML table代码
- export const pasteHTMLTableClipboardString = (text: string): string[][] | null => {
- const parser = new DOMParser()
- const doc = parser.parseFromString(text, 'text/html')
- const table = doc.querySelector('table')
- const data: string[][] = []
- if (!table) return data
- const rows = table.querySelectorAll('tr')
- for (const row of rows) {
- const rowData = []
- const cells = row.querySelectorAll('td, th')
- for (const cell of cells) {
- const text = cell.textContent ? cell.textContent.trim() : ''
- const colspan = parseInt(cell.getAttribute('colspan') || '1', 10)
- for (let i = 0; i < colspan; i++) {
- rowData.push(text)
- }
- }
- data.push(rowData)
- }
- return data
- }
|