富文本优化
This commit is contained in:
@@ -52,6 +52,7 @@
|
|||||||
:title="disabled ? '富文本宽屏查看' : '富文本宽屏编辑'"
|
:title="disabled ? '富文本宽屏查看' : '富文本宽屏编辑'"
|
||||||
width="96vw"
|
width="96vw"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
|
centered
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
:body-style="{ padding: '0', height: '82vh', overflow: 'hidden' }"
|
:body-style="{ padding: '0', height: '82vh', overflow: 'hidden' }"
|
||||||
@update:open="handleFullscreenVisibleChange"
|
@update:open="handleFullscreenVisibleChange"
|
||||||
@@ -177,11 +178,11 @@ const toolbarGroups = [
|
|||||||
{ key: 'insertUnorderedList', label: '无序列表', command: 'insertUnorderedList' },
|
{ key: 'insertUnorderedList', label: '无序列表', command: 'insertUnorderedList' },
|
||||||
{ key: 'insertOrderedList', label: '有序列表', command: 'insertOrderedList' },
|
{ key: 'insertOrderedList', label: '有序列表', command: 'insertOrderedList' },
|
||||||
],
|
],
|
||||||
[
|
// [
|
||||||
{ key: 'insertTable', label: '插入表格', type: 'insertTable' },
|
// { key: 'insertTable', label: '插入表格', type: 'insertTable' },
|
||||||
{ key: 'undo', label: '撤销', command: 'undo' },
|
// { key: 'undo', label: '撤销', command: 'undo' },
|
||||||
{ key: 'redo', label: '重做', command: 'redo' },
|
// { key: 'redo', label: '重做', command: 'redo' },
|
||||||
],
|
// ],
|
||||||
]
|
]
|
||||||
|
|
||||||
const savedRanges = {
|
const savedRanges = {
|
||||||
@@ -357,6 +358,10 @@ function handleToolbarAction(action, targetSurface = '') {
|
|||||||
insertDefaultTable(targetSurface)
|
insertDefaultTable(targetSurface)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (['justifyLeft', 'justifyCenter', 'justifyRight'].includes(action.command)) {
|
||||||
|
applyTextAlignment(action.command, targetSurface)
|
||||||
|
return
|
||||||
|
}
|
||||||
runDocumentCommand(action.command, action.value, targetSurface)
|
runDocumentCommand(action.command, action.value, targetSurface)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,6 +401,9 @@ function insertHtmlAtCursor(html, targetSurface = '') {
|
|||||||
const editor = getEditorElement(surface)
|
const editor = getEditorElement(surface)
|
||||||
insertHtmlByRange(editor, html)
|
insertHtmlByRange(editor, html)
|
||||||
}
|
}
|
||||||
|
if (/<table[\s>]/i.test(html)) {
|
||||||
|
focusFirstTableCell(surface)
|
||||||
|
}
|
||||||
captureSelection(surface)
|
captureSelection(surface)
|
||||||
handleEditorInput(surface)
|
handleEditorInput(surface)
|
||||||
}
|
}
|
||||||
@@ -435,10 +443,10 @@ function insertHtmlByRange(editor, html) {
|
|||||||
function buildDefaultTableHtml(rows = 4, cols = 4) {
|
function buildDefaultTableHtml(rows = 4, cols = 4) {
|
||||||
const minWidth = Math.max(640, cols * 140)
|
const minWidth = Math.max(640, cols * 140)
|
||||||
const rowHtml = Array.from({ length: rows }, () => {
|
const rowHtml = Array.from({ length: rows }, () => {
|
||||||
const cellHtml = Array.from({ length: cols }, () => '<td><br></td>').join('')
|
const cellHtml = Array.from({ length: cols }, () => '<td> </td>').join('')
|
||||||
return `<tr>${cellHtml}</tr>`
|
return `<tr>${cellHtml}</tr>`
|
||||||
}).join('')
|
}).join('')
|
||||||
return `<table style="width:100%;min-width:${minWidth}px;border-collapse:collapse;table-layout:auto;margin:8px 0;">${rowHtml}</table><p><br></p>`
|
return `<table style="width:100%;min-width:${minWidth}px;border-collapse:collapse;table-layout:auto;margin:8px 0;border:1px solid #1f2937;">${rowHtml}</table><p><br></p>`
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePaste(event, surface) {
|
function handlePaste(event, surface) {
|
||||||
@@ -586,6 +594,7 @@ function applyNormalizedCellStyle(sourceCell, targetCell) {
|
|||||||
targetCell.style.wordBreak = 'keep-all'
|
targetCell.style.wordBreak = 'keep-all'
|
||||||
targetCell.style.overflowWrap = 'break-word'
|
targetCell.style.overflowWrap = 'break-word'
|
||||||
targetCell.style.whiteSpace = 'pre-wrap'
|
targetCell.style.whiteSpace = 'pre-wrap'
|
||||||
|
targetCell.style.lineHeight = '1.7'
|
||||||
targetCell.style.minWidth = '120px'
|
targetCell.style.minWidth = '120px'
|
||||||
|
|
||||||
if (textAlign) {
|
if (textAlign) {
|
||||||
@@ -678,13 +687,81 @@ function buildPlainTextTableHtml(text) {
|
|||||||
.map((cells) => {
|
.map((cells) => {
|
||||||
const cellHtml = Array.from({ length: columnCount }, (_, index) => {
|
const cellHtml = Array.from({ length: columnCount }, (_, index) => {
|
||||||
const value = escapeHtml(String(cells[index] || '').trim())
|
const value = escapeHtml(String(cells[index] || '').trim())
|
||||||
return `<td>${value || '<br>'}</td>`
|
return `<td>${value || ' '}</td>`
|
||||||
}).join('')
|
}).join('')
|
||||||
return `<tr>${cellHtml}</tr>`
|
return `<tr>${cellHtml}</tr>`
|
||||||
})
|
})
|
||||||
.join('')
|
.join('')
|
||||||
|
|
||||||
return `<table style="width:100%;min-width:${minWidth}px;border-collapse:collapse;table-layout:auto;margin:8px 0;">${rowHtml}</table><p><br></p>`
|
return `<table style="width:100%;min-width:${minWidth}px;border-collapse:collapse;table-layout:auto;margin:8px 0;border:1px solid #1f2937;">${rowHtml}</table><p><br></p>`
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTextAlignment(command, targetSurface = '') {
|
||||||
|
if (props.disabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const surface = resolveTargetSurface(targetSurface)
|
||||||
|
activeSurface.value = surface
|
||||||
|
restoreSelection(surface)
|
||||||
|
const editor = getEditorElement(surface)
|
||||||
|
if (!editor) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const alignValue = resolveAlignValue(command)
|
||||||
|
if (!alignValue) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const selection = window.getSelection()
|
||||||
|
if (!selection || !selection.rangeCount) {
|
||||||
|
editor.style.textAlign = alignValue
|
||||||
|
handleEditorInput(surface)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const range = selection.getRangeAt(0)
|
||||||
|
const block = findAlignmentTarget(range.startContainer, editor)
|
||||||
|
;(block || editor).style.textAlign = alignValue
|
||||||
|
captureSelection(surface)
|
||||||
|
handleEditorInput(surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveAlignValue(command) {
|
||||||
|
if (command === 'justifyLeft') return 'left'
|
||||||
|
if (command === 'justifyCenter') return 'center'
|
||||||
|
if (command === 'justifyRight') return 'right'
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function findAlignmentTarget(node, editor) {
|
||||||
|
let current = node?.nodeType === Node.ELEMENT_NODE ? node : node?.parentElement || null
|
||||||
|
while (current && current !== editor) {
|
||||||
|
const tag = String(current.tagName || '').toLowerCase()
|
||||||
|
if (['p', 'div', 'li', 'td', 'th'].includes(tag)) {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
current = current.parentElement
|
||||||
|
}
|
||||||
|
return editor
|
||||||
|
}
|
||||||
|
|
||||||
|
function focusFirstTableCell(surface) {
|
||||||
|
const editor = getEditorElement(surface)
|
||||||
|
if (!editor) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const firstCell = editor.querySelector('td, th')
|
||||||
|
if (!firstCell) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const selection = window.getSelection()
|
||||||
|
if (!selection) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const range = document.createRange()
|
||||||
|
range.selectNodeContents(firstCell)
|
||||||
|
range.collapse(true)
|
||||||
|
selection.removeAllRanges()
|
||||||
|
selection.addRange(range)
|
||||||
|
savedRanges[surface] = range.cloneRange()
|
||||||
}
|
}
|
||||||
|
|
||||||
function openFullscreen() {
|
function openFullscreen() {
|
||||||
@@ -833,6 +910,7 @@ function escapeHtml(text) {
|
|||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
table-layout: auto;
|
table-layout: auto;
|
||||||
|
border: 1px solid #1f2937;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -845,6 +923,7 @@ function escapeHtml(text) {
|
|||||||
word-break: keep-all;
|
word-break: keep-all;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
line-height: 1.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-surface th {
|
.editor-surface th {
|
||||||
|
|||||||
Reference in New Issue
Block a user