|
|
@@ -582,6 +582,45 @@ export default {
|
|
|
return tempDiv.innerHTML
|
|
|
},
|
|
|
|
|
|
+ // 保证替换内容为内联且不换行:将 div/p 等块级标签转换为 span,并强制 white-space: nowrap
|
|
|
+ ensureInlineNoWrap(html) {
|
|
|
+ if (!html) return ''
|
|
|
+ try {
|
|
|
+ const wrapper = document.createElement('div')
|
|
|
+ wrapper.innerHTML = html
|
|
|
+
|
|
|
+ // 将所有 div/p 转为 span,保留原有内联样式
|
|
|
+ wrapper.querySelectorAll('div, p').forEach(block => {
|
|
|
+ const span = document.createElement('span')
|
|
|
+ // 复制子内容
|
|
|
+ while (block.firstChild) {
|
|
|
+ span.appendChild(block.firstChild)
|
|
|
+ }
|
|
|
+ // 合并样式并强制不换行与内联显示
|
|
|
+ const style = (block.getAttribute('style') || '')
|
|
|
+ span.setAttribute('style', `${style}${style.endsWith(';') ? '' : ';'} display: inline; white-space: nowrap;`)
|
|
|
+ // 替换节点
|
|
|
+ block.parentNode.replaceChild(span, block)
|
|
|
+ })
|
|
|
+
|
|
|
+ // 确保所有顶层文本不含多余换行或制表符
|
|
|
+ const normalizeTextNodes = (node) => {
|
|
|
+ node.childNodes && Array.from(node.childNodes).forEach(child => {
|
|
|
+ if (child.nodeType === Node.TEXT_NODE) {
|
|
|
+ child.textContent = child.textContent.replace(/[\t\r\n\f\v]+/g, ' ')
|
|
|
+ } else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
|
+ normalizeTextNodes(child)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ normalizeTextNodes(wrapper)
|
|
|
+
|
|
|
+ return wrapper.innerHTML
|
|
|
+ } catch (e) {
|
|
|
+ return typeof html === 'string' ? html : ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
// 更新导出方法
|
|
|
async exportDocumentWithHtmlDocx(template) {
|
|
|
const res = await searchlistDocTemplate({
|
|
|
@@ -2293,14 +2332,15 @@ export default {
|
|
|
if (matchedContent?.content) {
|
|
|
// 构建替换内容
|
|
|
const cleanContent = matchedContent.content.trim() // 清理前后空格
|
|
|
+ const inlineContent = this.ensureInlineNoWrap(cleanContent) // 转为内联且不换行
|
|
|
const chineseDescription = matchedContent.chinese_description || '' // 获取中文释义,如果有的话 !important
|
|
|
const formattedReplacement = `
|
|
|
<span
|
|
|
class="replacement-content"
|
|
|
data-code="${currentCode}"
|
|
|
title="${chineseDescription}"
|
|
|
- style="background-color: #ffff00 !important; padding: 2px 4px; border-radius: 2px; display: inline-block;"
|
|
|
- >${cleanContent}${chineseDescription ? `<span class="chinese-desc" style="color: #67c23a; margin-left: 4px; font-size: 0.9em;">(${chineseDescription})</span>` : ''}</span>`.trim()
|
|
|
+ style="background-color: #ffff00 !important; padding: 2px 4px; border-radius: 2px; display: inline; white-space: nowrap;"
|
|
|
+ >${inlineContent}${chineseDescription ? `<span class="chinese-desc" style="color: #67c23a; margin-left: 4px; font-size: 0.9em;">(${chineseDescription})</span>` : ''}</span>`.trim()
|
|
|
|
|
|
// 处理表格和其他内容
|
|
|
updatedContent = this.processTableContent(
|
|
|
@@ -2354,6 +2394,8 @@ export default {
|
|
|
if (!content || !searchItem) return content
|
|
|
|
|
|
try {
|
|
|
+ // 确保传入 replacement 内部不包含导致换行的块级元素
|
|
|
+ replacement = this.ensureInlineNoWrap(replacement)
|
|
|
// 提取搜索项中的编号
|
|
|
const getCodeFromItem = (item) => {
|
|
|
const cleanItem = item.replace(/[\[\]【】]/g, '')
|
|
|
@@ -2453,6 +2495,37 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 在替换点前后去除多余空白并避免自动换行
|
|
|
+ tempDiv.querySelectorAll('span.replacement-content').forEach(span => {
|
|
|
+ // 去除包裹点两侧的多余空白文本节点
|
|
|
+ const trimSideWhitespace = (node, direction) => {
|
|
|
+ let sibling = direction === 'prev' ? node.previousSibling : node.nextSibling
|
|
|
+ while (sibling && sibling.nodeType === Node.TEXT_NODE) {
|
|
|
+ const trimmed = sibling.textContent.replace(/[\t\f\v\u00A0\u200B]+/g, ' ').replace(/\s+/g, ' ')
|
|
|
+ // 如果纯空白或只有一个空格,进一步根据上下文裁剪
|
|
|
+ if (!trimmed.trim()) {
|
|
|
+ const toRemove = sibling
|
|
|
+ sibling = direction === 'prev' ? sibling.previousSibling : sibling.nextSibling
|
|
|
+ toRemove.parentNode.removeChild(toRemove)
|
|
|
+ } else {
|
|
|
+ sibling.textContent = trimmed
|
|
|
+ // 剔除与替换点相邻的首尾空格,避免出现额外空格
|
|
|
+ if (direction === 'prev') sibling.textContent = sibling.textContent.replace(/[\s\u00A0]+$/, '')
|
|
|
+ else sibling.textContent = sibling.textContent.replace(/^[\s\u00A0]+/, '')
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ trimSideWhitespace(span, 'prev')
|
|
|
+ trimSideWhitespace(span, 'next')
|
|
|
+
|
|
|
+ // 强制不自动换行(若父元素限制导致换行,此设置可最大程度避免)
|
|
|
+ const currentStyle = span.getAttribute('style') || ''
|
|
|
+ if (!/white-space\s*:\s*nowrap/i.test(currentStyle)) {
|
|
|
+ span.setAttribute('style', `${currentStyle}${currentStyle.endsWith(';') ? '' : ';'} white-space: nowrap; display: inline;`)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
// 处理最终结果中的所有表格,确保自适应行高
|
|
|
tempDiv.querySelectorAll('table').forEach(table => {
|
|
|
// 添加自适应样式类
|