|
|
@@ -514,39 +514,72 @@ function getTocBullet(level) {
|
|
|
return bullets[Math.min(level - 1, bullets.length - 1)]
|
|
|
}
|
|
|
|
|
|
+// 规范化文本(移除多余空格、特殊字符)
|
|
|
+function normalizeText(text) {
|
|
|
+ if (!text) return ''
|
|
|
+ return text
|
|
|
+ .replace(/\s+/g, ' ') // 多个空格变一个
|
|
|
+ .replace(/[\u00A0]/g, ' ') // 不间断空格转普通空格
|
|
|
+ .trim()
|
|
|
+}
|
|
|
+
|
|
|
// 滚动到指定章节(通过标题元素匹配)
|
|
|
function scrollToHeading(item) {
|
|
|
- const titleText = item.title || item.text
|
|
|
+ const titleText = normalizeText(item.title || item.text)
|
|
|
if (!titleText) return
|
|
|
|
|
|
- // 在文档内容区域中查找标题元素 (h1, h2, h3, h4, h5, h6)
|
|
|
+ // 在文档内容区域中查找标题元素
|
|
|
const editorContent = document.querySelector('.editor-content')
|
|
|
if (!editorContent) return
|
|
|
|
|
|
- // 查找所有标题元素
|
|
|
+ // 1. 先查找 h1-h6 标题元素
|
|
|
const headings = editorContent.querySelectorAll('h1, h2, h3, h4, h5, h6')
|
|
|
|
|
|
+ // 精确匹配
|
|
|
for (const heading of headings) {
|
|
|
- // 获取标题的纯文本内容(去除空格比较)
|
|
|
- const headingText = heading.textContent?.trim()
|
|
|
- if (headingText && headingText === titleText.trim()) {
|
|
|
- // 滚动到标题元素
|
|
|
+ const headingText = normalizeText(heading.textContent)
|
|
|
+ if (headingText === titleText) {
|
|
|
heading.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
|
highlightElement(heading)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 如果精确匹配失败,尝试包含匹配
|
|
|
+ // 包含匹配(标题包含目录文本,或目录文本包含标题)
|
|
|
for (const heading of headings) {
|
|
|
- const headingText = heading.textContent?.trim()
|
|
|
- if (headingText && headingText.includes(titleText.trim())) {
|
|
|
+ const headingText = normalizeText(heading.textContent)
|
|
|
+ if (headingText && (headingText.includes(titleText) || titleText.includes(headingText))) {
|
|
|
heading.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
|
highlightElement(heading)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 2. 如果 h1-h6 没找到,尝试查找带粗体样式的段落(可能是标题)
|
|
|
+ const boldSpans = editorContent.querySelectorAll('span[style*="font-weight:bold"], strong, b')
|
|
|
+ for (const span of boldSpans) {
|
|
|
+ const spanText = normalizeText(span.textContent)
|
|
|
+ if (spanText === titleText || spanText.includes(titleText) || titleText.includes(spanText)) {
|
|
|
+ const parent = span.closest('p, div, h1, h2, h3, h4, h5, h6') || span
|
|
|
+ parent.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
|
+ highlightElement(parent)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 最后尝试全文搜索
|
|
|
+ const allElements = editorContent.querySelectorAll('p, div, span')
|
|
|
+ for (const el of allElements) {
|
|
|
+ const elText = normalizeText(el.textContent)
|
|
|
+ // 检查元素直接包含的文本(不是子元素的文本)
|
|
|
+ if (elText === titleText) {
|
|
|
+ el.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
|
+ highlightElement(el)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ console.warn('未找到章节:', titleText)
|
|
|
ElMessage.warning('未找到对应章节')
|
|
|
}
|
|
|
|