clipboard.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import Clipboard from 'clipboard'
  2. import { decrypt } from '@/utils/crypto'
  3. /**
  4. * 复制文本到剪贴板
  5. * @param text 文本内容
  6. */
  7. export const copyText = (text: string) => {
  8. return new Promise((resolve, reject) => {
  9. const fakeElement = document.createElement('button')
  10. const clipboard = new Clipboard(fakeElement, {
  11. text: () => text,
  12. action: () => 'copy',
  13. container: document.body,
  14. })
  15. clipboard.on('success', e => {
  16. clipboard.destroy()
  17. resolve(e)
  18. })
  19. clipboard.on('error', e => {
  20. clipboard.destroy()
  21. reject(e)
  22. })
  23. document.body.appendChild(fakeElement)
  24. fakeElement.click()
  25. document.body.removeChild(fakeElement)
  26. })
  27. }
  28. // 读取剪贴板
  29. export const readClipboard = (): Promise<string> => {
  30. return new Promise((resolve, reject) => {
  31. if (navigator.clipboard?.readText) {
  32. navigator.clipboard.readText().then(text => {
  33. if (!text) reject('剪贴板为空或者不包含文本')
  34. return resolve(text)
  35. })
  36. }
  37. else reject('浏览器不支持或禁止访问剪贴板,请使用快捷键 Ctrl + V')
  38. })
  39. }
  40. // 解析加密后的剪贴板内容
  41. export const pasteCustomClipboardString = (text: string) => {
  42. let clipboardData
  43. try {
  44. clipboardData = JSON.parse(decrypt(text))
  45. }
  46. catch {
  47. clipboardData = text
  48. }
  49. return clipboardData
  50. }
  51. // 尝试解析剪贴板内容是否为Excel表格(或类似的)数据格式
  52. export const pasteExcelClipboardString = (text: string): string[][] | null => {
  53. const lines: string[] = text.split('\r\n')
  54. if (lines[lines.length - 1] === '') lines.pop()
  55. let colCount = -1
  56. const data: string[][] = []
  57. for (const index in lines) {
  58. data[index] = lines[index].split('\t')
  59. if (data[index].length === 1) return null
  60. if (colCount === -1) colCount = data[index].length
  61. else if (colCount !== data[index].length) return null
  62. }
  63. return data
  64. }
  65. // 尝试解析剪贴板内容是否为HTML table代码
  66. export const pasteHTMLTableClipboardString = (text: string): string[][] | null => {
  67. const parser = new DOMParser()
  68. const doc = parser.parseFromString(text, 'text/html')
  69. const table = doc.querySelector('table')
  70. const data: string[][] = []
  71. if (!table) return data
  72. const rows = table.querySelectorAll('tr')
  73. for (const row of rows) {
  74. const rowData = []
  75. const cells = row.querySelectorAll('td, th')
  76. for (const cell of cells) {
  77. const text = cell.textContent ? cell.textContent.trim() : ''
  78. const colspan = parseInt(cell.getAttribute('colspan') || '1', 10)
  79. for (let i = 0; i < colspan; i++) {
  80. rowData.push(text)
  81. }
  82. }
  83. data.push(rowData)
  84. }
  85. return data
  86. }