From b909dd693e8c2559fb1bc855491c75dbb20e33a8 Mon Sep 17 00:00:00 2001 From: zhouxiaofeng <2946471396@qq.com> Date: Tue, 14 Jul 2026 13:09:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=8C=E6=96=87=E6=9C=AC=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/TemplateRichTextEditor.vue | 97 +++++++++++++++++-- 1 file changed, 88 insertions(+), 9 deletions(-) diff --git a/src/views/contract/launch/components/TemplateRichTextEditor.vue b/src/views/contract/launch/components/TemplateRichTextEditor.vue index 9b090ec..ed39f48 100644 --- a/src/views/contract/launch/components/TemplateRichTextEditor.vue +++ b/src/views/contract/launch/components/TemplateRichTextEditor.vue @@ -52,6 +52,7 @@ :title="disabled ? '富文本宽屏查看' : '富文本宽屏编辑'" width="96vw" :footer="null" + centered :mask-closable="false" :body-style="{ padding: '0', height: '82vh', overflow: 'hidden' }" @update:open="handleFullscreenVisibleChange" @@ -177,11 +178,11 @@ const toolbarGroups = [ { key: 'insertUnorderedList', label: '无序列表', command: 'insertUnorderedList' }, { key: 'insertOrderedList', label: '有序列表', command: 'insertOrderedList' }, ], - [ - { key: 'insertTable', label: '插入表格', type: 'insertTable' }, - { key: 'undo', label: '撤销', command: 'undo' }, - { key: 'redo', label: '重做', command: 'redo' }, - ], + // [ + // { key: 'insertTable', label: '插入表格', type: 'insertTable' }, + // { key: 'undo', label: '撤销', command: 'undo' }, + // { key: 'redo', label: '重做', command: 'redo' }, + // ], ] const savedRanges = { @@ -357,6 +358,10 @@ function handleToolbarAction(action, targetSurface = '') { insertDefaultTable(targetSurface) return } + if (['justifyLeft', 'justifyCenter', 'justifyRight'].includes(action.command)) { + applyTextAlignment(action.command, targetSurface) + return + } runDocumentCommand(action.command, action.value, targetSurface) } @@ -396,6 +401,9 @@ function insertHtmlAtCursor(html, targetSurface = '') { const editor = getEditorElement(surface) insertHtmlByRange(editor, html) } + if (/]/i.test(html)) { + focusFirstTableCell(surface) + } captureSelection(surface) handleEditorInput(surface) } @@ -435,10 +443,10 @@ function insertHtmlByRange(editor, html) { function buildDefaultTableHtml(rows = 4, cols = 4) { const minWidth = Math.max(640, cols * 140) const rowHtml = Array.from({ length: rows }, () => { - const cellHtml = Array.from({ length: cols }, () => '
').join('') + const cellHtml = Array.from({ length: cols }, () => ' ').join('') return `${cellHtml}` }).join('') - return `${rowHtml}


` + return `${rowHtml}


` } function handlePaste(event, surface) { @@ -586,6 +594,7 @@ function applyNormalizedCellStyle(sourceCell, targetCell) { targetCell.style.wordBreak = 'keep-all' targetCell.style.overflowWrap = 'break-word' targetCell.style.whiteSpace = 'pre-wrap' + targetCell.style.lineHeight = '1.7' targetCell.style.minWidth = '120px' if (textAlign) { @@ -678,13 +687,81 @@ function buildPlainTextTableHtml(text) { .map((cells) => { const cellHtml = Array.from({ length: columnCount }, (_, index) => { const value = escapeHtml(String(cells[index] || '').trim()) - return `${value || '
'}` + return `${value || ' '}` }).join('') return `${cellHtml}` }) .join('') - return `${rowHtml}


` + return `${rowHtml}


` +} + +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() { @@ -833,6 +910,7 @@ function escapeHtml(text) { margin: 8px 0; border-collapse: collapse; table-layout: auto; + border: 1px solid #1f2937; background: #fff; } @@ -845,6 +923,7 @@ function escapeHtml(text) { word-break: keep-all; overflow-wrap: break-word; white-space: pre-wrap; + line-height: 1.7; } .editor-surface th {