|
|
@@ -501,30 +501,41 @@ const tocItems = computed(() => {
|
|
|
if (!blocks.value || blocks.value.length === 0) return items
|
|
|
|
|
|
for (const block of blocks.value) {
|
|
|
- // 检查是否是目录块
|
|
|
- if (block.type === 'toc' && block.tocEntries) {
|
|
|
- for (const entry of block.tocEntries) {
|
|
|
- items.push({
|
|
|
- level: entry.level || 1,
|
|
|
- text: entry.title || entry.text,
|
|
|
- page: entry.page,
|
|
|
- blockId: block.id
|
|
|
- })
|
|
|
+ // 遍历块中的元素,查找 toc_item 类型
|
|
|
+ if (block.elements && Array.isArray(block.elements)) {
|
|
|
+ for (const el of block.elements) {
|
|
|
+ if (el.type === 'toc_item') {
|
|
|
+ const text = el.content || el.text || ''
|
|
|
+ if (text.trim()) {
|
|
|
+ // 从文本中推断层级(根据开头数字格式)
|
|
|
+ const level = detectTocLevel(text.trim())
|
|
|
+ items.push({
|
|
|
+ level: level,
|
|
|
+ text: text.trim(),
|
|
|
+ page: el.style?.tocPageNum || '',
|
|
|
+ blockId: block.id
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- // 检查是否是标题块 (type: heading1, heading2, heading3...)
|
|
|
- else if (block.type && block.type.startsWith('heading')) {
|
|
|
+
|
|
|
+ // 也检查标题块作为备用 (type: heading1, heading2, heading3...)
|
|
|
+ if (block.type && block.type.startsWith('heading')) {
|
|
|
const levelMatch = block.type.match(/heading(\d+)/)
|
|
|
const level = levelMatch ? parseInt(levelMatch[1]) : 1
|
|
|
- // 只提取1-3级标题
|
|
|
if (level <= 3) {
|
|
|
const text = block.plainText || getBlockPlainText(block)
|
|
|
if (text && text.trim()) {
|
|
|
- items.push({
|
|
|
- level: level,
|
|
|
- text: text.trim(),
|
|
|
- blockId: block.id
|
|
|
- })
|
|
|
+ // 避免重复添加(如果已经从 toc_item 中添加过)
|
|
|
+ const exists = items.some(item => item.text === text.trim())
|
|
|
+ if (!exists) {
|
|
|
+ items.push({
|
|
|
+ level: level,
|
|
|
+ text: text.trim(),
|
|
|
+ blockId: block.id
|
|
|
+ })
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -532,6 +543,24 @@ const tocItems = computed(() => {
|
|
|
return items
|
|
|
})
|
|
|
|
|
|
+// 检测目录项层级(根据编号格式推断)
|
|
|
+function detectTocLevel(text) {
|
|
|
+ // 一级标题:1 xxx, 第一章 xxx
|
|
|
+ if (/^(\d+)\s+[^\d]/.test(text) || /^第[一二三四五六七八九十\d]+[章节部篇]/.test(text)) {
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ // 二级标题:1.1 xxx, 1-1 xxx
|
|
|
+ if (/^\d+\.\d+\s+/.test(text) || /^\d+-\d+\s+/.test(text)) {
|
|
|
+ return 2
|
|
|
+ }
|
|
|
+ // 三级标题:1.1.1 xxx
|
|
|
+ if (/^\d+\.\d+\.\d+\s+/.test(text)) {
|
|
|
+ return 3
|
|
|
+ }
|
|
|
+ // 默认一级
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
// 获取块的纯文本内容
|
|
|
function getBlockPlainText(block) {
|
|
|
if (!block.elements) return ''
|