diff --git a/src/utils/clipboard.ts b/src/utils/clipboard.ts index 3da01565..eb9bd388 100644 --- a/src/utils/clipboard.ts +++ b/src/utils/clipboard.ts @@ -68,5 +68,31 @@ export const pasteExcelClipboardString = (text: string): string[][] | 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 } \ No newline at end of file diff --git a/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue b/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue index d93b11ed..ea8623f1 100644 --- a/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue +++ b/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue @@ -95,7 +95,7 @@ import { computed, onMounted, onUnmounted, ref } from 'vue' import type { ChartData, ChartType } from '@/types/slides' import { KEYS } from '@/configs/hotkey' import { CHART_TYPE_MAP } from '@/configs/chart' -import { pasteCustomClipboardString, pasteExcelClipboardString } from '@/utils/clipboard' +import { pasteCustomClipboardString, pasteExcelClipboardString, pasteHTMLTableClipboardString } from '@/utils/clipboard' import Button from '@/components/Button.vue' import Popover from '@/components/Popover.vue' import PopoverMenuItem from '@/components/PopoverMenuItem.vue' @@ -265,6 +265,18 @@ const clear = () => { } } +const fillTableData = (data: string[][], rowIndex: number, colIndex: number) => { + const maxRow = rowIndex + data.length + const maxCol = colIndex + data[0].length + for (let i = rowIndex; i < maxRow; i++) { + for (let j = colIndex; j < maxCol; j++) { + const inputRef = document.querySelector(`#cell-${i}-${j}`) as HTMLInputElement + if (!inputRef) continue + inputRef.value = data[i - rowIndex][j - colIndex] + } + } +} + // 自定义粘贴事件(尝试读取剪贴板中的表格数据) const handlePaste = (e: ClipboardEvent, rowIndex: number, colIndex: number) => { e.preventDefault() @@ -273,24 +285,22 @@ const handlePaste = (e: ClipboardEvent, rowIndex: number, colIndex: number) => { const clipboardDataFirstItem = e.clipboardData.items[0] - if (clipboardDataFirstItem && clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') { - clipboardDataFirstItem.getAsString(text => { - const clipboardData = pasteCustomClipboardString(text) - if (typeof clipboardData === 'object') return - - const excelData = pasteExcelClipboardString(text) - if (excelData) { - const maxRow = rowIndex + excelData.length - const maxCol = colIndex + excelData[0].length - for (let i = rowIndex; i < maxRow; i++) { - for (let j = colIndex; j < maxCol; j++) { - const inputRef = document.querySelector(`#cell-${i}-${j}`) as HTMLInputElement - if (!inputRef) continue - inputRef.value = excelData[i - rowIndex][j - colIndex] - } - } - } - }) + if (clipboardDataFirstItem && clipboardDataFirstItem.kind === 'string') { + if (clipboardDataFirstItem.type === 'text/plain') { + clipboardDataFirstItem.getAsString(text => { + const clipboardData = pasteCustomClipboardString(text) + if (typeof clipboardData === 'object') return + + const excelData = pasteExcelClipboardString(text) + if (excelData) fillTableData(excelData, rowIndex, colIndex) + }) + } + else if (clipboardDataFirstItem.type === 'text/html') { + clipboardDataFirstItem.getAsString(html => { + const htmlData = pasteHTMLTableClipboardString(html) + if (htmlData) fillTableData(htmlData, rowIndex, colIndex) + }) + } } } diff --git a/src/views/components/element/TableElement/CustomTextarea.vue b/src/views/components/element/TableElement/CustomTextarea.vue index f0dad954..5061a633 100644 --- a/src/views/components/element/TableElement/CustomTextarea.vue +++ b/src/views/components/element/TableElement/CustomTextarea.vue @@ -12,7 +12,7 @@