@angineer/docs-ui
v0.3.1
Published
Vue 3 知识库文档工作台组件库:PDF 查看器、结构化索引(索引树/索引图)、知识树、对话与检索 composables。
Readme
angineer-docs-ui
Vue 3 知识库文档工作台组件库:PDF 查看器、结构化索引(索引树/索引图)、知识树、对话与检索 composables。
安装
已发布到 npm registry:
pnpm add @angineer/docs-uidocs-ui 依赖
@angineer/smartree,从 npm 安装时作为传递依赖自动解析(^0.1.1);从 GitHub 钉 tag 安装时需一并安装@angineer/smartree(github:0mao0/angineer-smartree-ui#v0.1.2)。
环境要求:peer 依赖 [email protected]、[email protected]、@ant-design/[email protected]。包为源码分发(无构建产物),宿主需用 Vite + @vitejs/plugin-vue 与 less 编译。
使用
import { PDF_Viewer, PDFParsedWorkspace, KnowledgeTree } from '@angineer/docs-ui'
import '@angineer/docs-ui/style' // 可选:.docs-component 基础排版(组件颜色均走 CSS 变量,不导入也可渲染)导出
- 组件:
SmartTree(桥接@angineer/smartree)、KnowledgeTree、PDFParsedWorkspace、PDFParsedViewerCombo、PDF_Viewer、Preview_Markdown - Composables:
useKnowledgeTree、useDocBlocksGraph、useParsedPdfViewer、useParsedPdfIndexTree、useWorkspaceLinkage、useWorkspacePreview、useKnowledgeCitation、useKnowledgeParse、useKnowledgeStructuredIndex、useRefAnchor、useResourceAdapter等 - 子路径导出:
@angineer/docs-ui/style
主题定制
组件颜色经 CSS 变量解析且使用处自带 fallback:查看器私有 --dp-* → 包级 --docs-* → 内置默认值的三层链(PDF_Viewer 另有 --dp-*-override 层供单实例覆盖);同时引用宿主语义变量(--text-secondary、--primary-color 等)跟随 dark/light 主题,宿主在 :root / [data-theme="dark"] 定义同名变量即可。
测试
pnpm --filter @angineer/docs-ui test # 31 个用例(tsx + node:test,含 Vite ssr 集成用例)
pnpm --filter @angineer/docs-ui typecheck # vue-tsc仓库说明
本仓库为独立发布仓,代码唯一真相源在 AnGIneer monorepo 的 packages/docs-ui,经 scripts/sync-standalone.ps1 同步;版本以 git tag(vx.y.z)与 npm registry(@angineer/docs-ui)同步发布。变更历史见 CHANGELOG.md。
内部架构说明(A/B/C/D/U 分层)
本文档用于 packages/docs-ui 的后续改造与日常阅读,目标是统一分层认知、调用边界和文件职责。
1. 分层定义
A 层:可视层(Components + Styles)
- 只负责 UI 展示、交互触发、事件透传。
- 不直接实现重业务流程,不直接持久化数据。
- 允许存在局部 UI 状态(弹窗开关、hover、tab)。
B 层:逻辑层(Composables)
- 负责业务流程编排、状态联动、副作用控制。
- 管理运行时状态(
ref/computed/watch)。 - 调用 D 层接口并把结果映射为 A 层可消费状态。
C 层:契约层(Types)
- 负责类型契约、结构约束、跨层参数统一。
- 不承载运行时状态,不包含副作用。
D 层:数据层(API / Storage / Data Source)
- 前端视角:HTTP API(
/api/*)是 D 层入口。 - 后端视角:文件系统/JSON/DB/第三方解析服务是 D 层落点。
U 层:工具层(Utils,跨层纯函数)
- 纯函数、无状态、无组件上下文依赖。
- 用于格式化、映射、解析、渲染转换等可复用逻辑。
2. 当前目录映射(docs-ui)
src/
├─ components/ # A 层
│ ├─ common/
│ │ ├─ PDFParsedWorkspace.vue
│ │ ├─ PDFParsedViewerCombo.vue
│ │ ├─ PDF_Viewer.vue
│ │ ├─ Preview_Markdown.vue
│ │ ├─ Preview_IndexTree.vue
│ │ ├─ Preview_IndexGraph.vue
│ │ ├─ SmartTree.vue
│ │ ├─ SOPTree.vue
│ └─ index.ts
├─ composables/ # B 层
│ ├─ useWorkspacePreview.ts
│ ├─ useWorkspaceLinkage.ts
│ ├─ useWorkspaceIngest.ts
│ ├─ useParsedPdfViewer.ts
│ ├─ useDocBlocksGraph.ts
│ ├─ useKnowledgeTree.ts
│ ├─ useKnowledgeChat.ts
│ ├─ useSopTree.ts
│ ├─ useDocument.ts
│ ├─ useQuery.ts
│ ├─ useRefAnchor.ts
│ ├─ useResourceAdapter.ts
│ └─ index.ts
├─ types/ # C 层
│ ├─ knowledge.ts
│ ├─ tree.ts
│ ├─ document.ts
│ ├─ reference.ts
│ ├─ resource.ts
│ ├─ table.ts
│ └─ index.ts
├─ utils/ # U 层
│ ├─ knowledge.ts
│ └─ index.ts
├─ styles/ # A 层样式
│ ├─ index.less
│ └─ variables.less
└─ index.ts # 包出口3. 层间调用规则(硬约束)
- A -> B:允许(组件调用 composable)。
- A -> C:允许(组件 import type)。
- A -> U:允许(纯函数辅助展示)。
- B -> C:允许(逻辑层依赖类型契约)。
- B -> U:允许(业务流程中使用纯函数)。
- B -> D:允许(fetch/API 调用)。
- C 不依赖 A/B/D(只做契约)。
- U 不依赖 A/B 的运行时上下文(只做纯函数)。
- 禁止 A 直接写 D(组件不直接做复杂数据写入流程,统一由 B 收口)。
4. 关键调用关系(主流程)
4.1 Workspace 解析/预览链路
- A 层入口:
PDFParsedWorkspace.vue - 该组件组合调用:
useWorkspacePreview(预览状态与滚动同步)useWorkspaceIngest(入库状态与策略)useWorkspaceLinkage(左右联动高亮)
- 右侧编排组件
PDFParsedViewerCombo.vue再调用useParsedPdfViewer管理索引展示、树图状态、分页与视口。 - 左侧
PDF_Viewer.vue/ 右侧Preview_*子组件通过事件进行双向联动。
4.2 结构化索引重建(入库)链路
- 用户在 A 层触发入库(
trigger-ingest)。 PDFParsedWorkspace.vue调用 B 层useWorkspaceIngest.triggerIngest。- 校验通过后触发
emit('rebuild-structured', strategy)给宿主应用。 - 宿主应用调用 D 层接口(后端
POST /parse/structured-index)执行重建。 - 返回结果后回填到
structuredItems / structuredStats / graphData,A 层自动重渲染。
4.3 左右联动链路(高亮/定位)
- 左侧选中高亮:
PDF_Viewer触发select-highlight。 - A 层容器交给
useWorkspaceLinkage.onSelectHighlightFromLeft。 - B 层解析
graphData + structuredItems + markdownContent映射关系,得到:activeLeftHighlightIdactiveLinkedLineRange
- 右侧
Preview_Markdown根据行号滚动定位,必要时更新pdfPage。
4.4 SmartTree 交互链路
SmartTree.vue只发业务事件(如add-file、add-folder、drop、search)。- 上层容器接收事件后进入 B 层逻辑(如
useKnowledgeTree或宿主逻辑)。 - B 层调用 D 层 API / 存储后更新状态,A 层回显。
5. A 层文件清单(组件职责 + 事件契约)
5.1 组件总览
| 文件 | 角色 | 对外事件(核心) | 主要下游依赖 |
|---|---|---|---|
| PDFParsedWorkspace.vue | 文档解析工作区编排器(左侧 PDF + 可折叠解析面板) | parse save-content change-strategy query-structured rebuild-structured update:sidePanelOpen | useWorkspacePreview useWorkspaceIngest useWorkspaceLinkage |
| PDFParsedViewerCombo.vue | 右侧 pane 编排器 | update:activeTab update:editableContent save-markdown cancel-markdown strategy-change trigger-ingest content-scroll hover-item select-item toggle-tree-expand toggle-graph-expand update-graph-viewport select-line | useParsedPdfViewer + Preview_* |
| PDF_Viewer.vue | 左侧文件预览/高亮层,支持通用可折叠侧栏插槽 | download text-scroll hover-highlight select-highlight update:sidePanelOpen | 由 Workspace 注入数据 |
| Preview_Markdown.vue | Markdown 编辑/预览 | update:editableContent select-line | 被 PDFParsedViewerCombo 使用 |
| Preview_IndexTree.vue | 索引树视图 | toggle select edit toggle-check context-action | 虚拟滚动树容器(原 IndexTreeFlatRow 行渲染已并入) |
| Preview_IndexGraph.vue | 索引图视图 | toggle select update-viewport | 内聚图算法+交互(已合并原 DocBlocksGraph) |
| SmartTree.vue | 通用资源树组件 | select rename add-folder add-file delete view drop search file-drop drop-invalid drop-root | types/tree |
| SOPTree.vue | 经验库语义树组件 | select view search | useSopTree |
5.2 Workspace 核心编排函数(DocumentParsedWorkspace.vue)
saveMarkdown:把右侧编辑内容回传为save-content。cancelMarkdownEdit:回滚编辑缓存并复位 dirty 状态。triggerIngest:调用requestIngest后触发rebuild-structured。onStrategyChange:同步策略并发出change-strategy。openIndexFromIngestModal:切换到索引 tab 并关闭 modal。
6. B 层文件清单(函数/状态与职责)
6.1 composables 导出总表
| 文件 | 导出函数 | 核心职责 |
|---|---|---|
| useWorkspacePreview.ts | useWorkspacePreview | 文件类型识别、预览 URL、左右滚动同步、PDF 页码映射 |
| useWorkspaceIngest.ts | useWorkspaceIngest | 入库弹窗状态、策略切换、入库可用性校验、统计聚合 |
| useWorkspaceLinkage.ts | useWorkspaceLinkage | structured item 与 graph node 映射、左/右选择联动、行号与页码同步 |
| useParsedPdfViewer.ts | useParsedPdfViewer | 右侧索引列表/树/图的统一状态、分页、展开、视口持久 |
| useDocBlocksGraph.ts | useDocBlocksGraph | 图结构状态容器(nodeMap/childrenMap/roots)与视图模式控制 |
| useKnowledgeTree.ts | useKnowledgeTree | 知识树运行时状态与节点操作(选中、状态更新、上传任务) |
| useKnowledgeChat.ts | useKnowledgeChat | 对话流式发送、上下文窗口管理、终止/清空、token 估算 |
| useSopTree.ts | useSopTree | 经验库树默认数据、查找与选中状态管理 |
| useDocument.ts | useDocument | 文档/库查询、块查询 |
| useQuery.ts | useQuery | 表查询与语义查询、历史记录 |
| useRefAnchor.ts | useRefAnchor | 引用上下文管理、引用拉取、复制 |
| useResourceAdapter.ts | createResourceNodeFrom* createOpenResourcePayload | 资源结构适配与工作台打开 payload 构建 |
6.2 关键函数清单(按文件)
useWorkspacePreview.ts
- 状态:
textContentleftScrollPercentrightScrollPercentpdfPage - 计算:
isPdfisOfficeisImageisTextfileUrlpdfViewerUrlinferredPdfPageCount - 方法:
onRightPaneScrollPercentonLeftTextScrollPercentdownloadFileresetPreviewState
useWorkspaceIngest.ts
- 状态:
ingestModalVisibleselectedStrategy - 计算:
ingestProgressStatusingestStageTextstrategyValuestructuredTotalindexSummaryStatsingestButtonTextcanIngest - 方法:
onStrategyChangetriggerIngestopenIngestModalcloseIngestModal
useWorkspaceLinkage.ts
- 状态:
activeLinkedItemIdhighlightLinkEnabled - 计算:
linkedHighlightsshowHighlightToggleactiveLeftHighlightIdactiveLinkedLineRange - 方法:
onHoverLinkedItemonSelectHighlightFromLeftonSelectItemFromRightonSelectLineFromRighttoggleHighlightLinkresetLinkageState
useParsedPdfViewer.ts
- 状态:
indexCurrentPageexpandedNodeIdsexpandedGraphNodeIdsgraphViewportState - 计算:
flatIndexItemsnodeMapchildrenMaprootsactiveNodeIdForGraphTree - 方法:
onTabChangeonIndexPageChangeonTreeToggleonGraphToggleonNodeSelectonViewportUpdateexpandAncestorssetViewMode
useDocBlocksGraph.ts
- 状态:
graphactiveNodeIdexpandedNodeIdsexpandedGraphNodeIdsviewModeviewportState - 方法:
loadGraphsetActiveNodetoggleExpandtoggleGraphExpandexpandAllcollapseAllsetViewModesetViewportState - 查询:
getAncestorsexpandAncestorsgetNodeLevelgetNodeTextgetChildren
useKnowledgeTree.ts
- 状态:
treeDataselectedKeysexpandedKeysselectedNodeuploadTasks - 方法:
buildTreefindNodegetChildCountgetFolderNameselectNodeupdateNodeStatusaddUploadTaskupdateUploadTasksetTreeData
useKnowledgeChat.ts
- 状态:
messagesinputTextloadingcurrentStreamContent - 方法:
sendMessagestopGenerationclearMessagesgetContextTokensgetContextRoundsgenerateMessageId - 类型:
KnowledgeChatMessageKnowledgeChatRequestKnowledgeChatStreamEventKnowledgeChatContextConfig
useDocument.ts
- 状态:
documentloadingerror - 方法:
fetchDocumentfetchLibrarysearchDocumentsgetBlockgetBlocksByType
useQuery.ts
- 状态:
resultloadingerrorhistory - 方法:
queryTablesemanticQueryclearHistory
useRefAnchor.ts
- 状态:
contextItemsloading - 方法:
addContextremoveContextclearContextfetchReferencecopyReferencegetContextText
useResourceAdapter.ts
- 适配函数:
createResourceNodeFromKnowledgecreateResourceNodeFromProjectcreateResourceNodeFromSop - 跳转函数:
createOpenResourcePayload
7. C 层契约清单(types)
7.1 types/knowledge.ts
KnowledgeStrategy = 'doc_blocks_graph_v1'IngestStatus = 'idle' | 'processing' | 'completed' | 'failed'ParseTaskInfoStructuredIndexItemStructuredStatsDocumentStorageManifestDocBlockNodeDocBlockEdgeDocBlocksGraphDocBlocksGraphState
7.2 types/tree.ts
SmartTreeNodeTreeNodeAction
7.3 其他契约
types/document.ts:DocumentDocumentBlockBlockLocationDocumentMetadataLibrarytypes/resource.ts:ResourceTypeWorkbenchTabTypeResourceNodeOpenResourcePayloadtypes/reference.ts:ReferenceReferenceLocationReferenceContextCrossReferencetypes/table.ts:TableDataTableTypeTableDimensionValueRangeTableOutputTableRuleTableQueryResult
8. U 层工具清单(utils)
utils/knowledge.ts
getFileExtension(path):扩展名提取getPreviewFileType(node):预览类型映射(pdf/word/markdown/image/text/file)mapNodeStatusText(status):节点状态文案映射renderMarkdownToHtml(content, sourceFilePath):Markdown + KaTeX 渲染为 HTML,并处理资源路径
工具层定位:可在 A/B 任意层调用,但保持“纯函数、无运行时状态”。
9. D 层数据源映射(当前项目实际)
docs-ui前端通过/api/*与后端交互;数据持久化和解析产物在services/docs-core完成。
9.1 前端调用入口(B -> D)
useDocument.ts:/api/docs/documents/*/api/docs/libraries/*/api/docs/searchuseQuery.ts:/api/docs/tables/*/query/api/docs/query/semanticuseRefAnchor.ts:/api/docs/references/*useKnowledgeChat.ts:/api/chat- 预览文件:
/api/files?path=...
9.2 后端解析/存储关键点(D 层落盘)
- 解析任务接口:
services/docs-api/docs_routes.pyPOST /parseGET /parse/{task_id}POST /parse/structured-index
- 存储实现:
services/docs-core/src/docs_core/storage/document_storage.py- 根目录:
data/knowledge_base - 文档目录:
libraries/{library_id}/documents/{doc_id}/ - 关键文件:
parsed/content.mdparsed/doc_blocks_graph.jsonlparsed/doc_blocks_graph_meta.jsonparsed/mineru_blocks.jsonparsed/raw/*edited/current.md
- 根目录:
10. 包出口与使用建议
10.1 出口文件
src/index.ts:聚合导出 components/composables/types/utilssrc/components/index.ts:导出SmartTreeKnowledgeTreePDFParsedWorkspacePDFParsedViewerComboPDF_ViewerPreview_MarkdownPDF_Viewer支持side-panel插槽与sidePanelOpen/showSidePanelToggle/sidePanelWidthprops;PDFParsedWorkspace支持sidePanelOpen/sidePanelDefaultOpen/sidePanelWidth/defaultParsedTabprops,可控制解析面板展开/收起、宽度与默认 Tab。PDFParsedWorkspace支持fileUrlResolverprop,可自定义文件地址拼接规则;不传时默认使用/api/files?path=...。src/composables/index.ts:导出全部 composables 及关键类型src/types/index.ts:导出所有契约类型src/utils/index.ts:导出工具函数
10.2 新功能放置规范(改造准则)
- 新 UI:优先放 A 层
components/common/*,样式仅放本组件所需。 - 新业务流程:优先放 B 层 composable,组件只消费状态与方法。
- 新数据结构:先定义到 C 层 type/interface,再落逻辑实现。
- 新纯算法/映射:放 U 层 utils,保持无副作用。
- 新 API/存储交互:统一由 B 层发起,不从 A 层直接发起复杂流程。
11. 改造检查清单(提交前自检)
- 是否把流程逻辑从组件下沉到 composable。
- 是否存在组件直接处理复杂 API/落盘流程(应避免)。
- 类型是否先在 C 层定义,再被 A/B 复用。
- utils 是否仍保持纯函数,不引入状态/副作用。
- 事件命名是否保持语义一致(
select-*、toggle-*、update:*)。 - Workspace 是否继续作为编排器,而非逻辑堆积点。
12. 逐文件外部依赖与调用矩阵(细化)
这一节聚焦“文件 -> 引用谁 -> 对外暴露什么 -> 在分层里承担什么角色”。
12.1 A 层组件矩阵(common)
| 文件 | 直接引用的外部 TS/函数 | 对外事件(emit) | 分层结论 |
|---|---|---|---|
| DocumentParsedWorkspace.vue | useWorkspacePreview useWorkspaceIngest useWorkspaceLinkage renderMarkdownToHtml KnowledgeTreeNode KnowledgeStrategy/IngestStatus/Structured* | parse save-content change-strategy query-structured rebuild-structured | A 层编排器,强依赖 B/C/U,合理 |
| ParsedPDF_Viewer.vue | useParsedPdfViewer PreviewMode KnowledgeStrategy StructuredIndexItem DocBlocksGraph | update:activeTab update:editableContent save-markdown cancel-markdown strategy-change trigger-ingest content-scroll hover-item select-item toggle-tree-expand toggle-graph-expand update-graph-viewport select-line | A 层二级编排器,依赖 B/C |
| PDF_Viewer.vue | KnowledgeTreeNode(来自 types/tree) | download text-scroll hover-highlight select-highlight | A 层渲染组件,轻依赖 C |
| Preview_Markdown.vue | 无项目外部 TS(仅 Vue) | update:editableContent select-line | A 层纯展示 |
| Preview_IndexTree.vue | DocBlockNode(C) | toggle select edit toggle-check context-action | A 层虚拟滚动树组件(内聚交互) |
| Preview_IndexGraph.vue | DocBlockNode(C) | toggle select update-viewport | A 层图组件(内聚交互) |
| SmartTree.vue | SmartTreeNode(C) TreeProps useTheme | select rename add-folder add-file delete view drop search file-drop drop-invalid drop-root | A 层通用组件,不直接做 D 层写入 |
| SOPTree.vue | SOPTreeNode(C) + SmartTree | select view search | A 层经验库树语义包装 |
12.2 B 层 composables 矩阵
| 文件 | 主要输入 | 主要输出(状态/函数) | 是否直接触达 D 层 |
|---|---|---|---|
| useWorkspacePreview.ts | node/filePath/graphData | isPdf/isOffice/... fileUrl pdfViewerUrl onRightPaneScrollPercent onLeftTextScrollPercent | 否(仅读取文件 URL) |
| useWorkspaceIngest.ts | node/content/isContentDirty/ingestStatus/structuredStats | ingestModalVisible strategyValue canIngest triggerIngest | 否 |
| useWorkspaceLinkage.ts | graphData/structuredItems/markdownContent/isPdf/pdfPage/rightScrollPercent | linkedHighlights activeLinkedLineRange onSelect* | 否 |
| useParsedPdfViewer.ts | 右侧 pane props + emit | flatIndexItems/nodeMap/childrenMap onTabChange onTreeToggle | 否 |
| useDocBlocksGraph.ts | DocBlocksGraph | nodeMap/childrenMap/roots toggleExpand setViewMode | 否 |
| useKnowledgeTree.ts | 运行时树数据 | treeData/selectedNode buildTree/selectNode/updateNodeStatus | 否 |
| useKnowledgeChat.ts | 对话参数与上下文配置 | messages/loading/sendMessage/stopGeneration | 是(/api/chat)已废弃,请使用 ui-kit 的 useAIChat |
| useSopTree.ts | 经验库树数据 | treeData/selectedNode/resetToDefaultTree/findNode | 否 |
| useDocument.ts | docId/libraryId/query | document/loading/error fetchDocument searchDocuments | 是(/api/docs/*) |
| useQuery.ts | tableId/params/question | result/history/queryTable/semanticQuery | 是(/api/docs/*) |
| useRefAnchor.ts | blockId/reference | contextItems fetchReference copyReference | 是(/api/docs/references/*) |
| useResourceAdapter.ts | SmartTreeNode/ProjectItem/SopItem | ResourceNode/OpenResourcePayload | 否(纯适配) |
12.3 C 层契约文件矩阵
| 文件 | 核心契约 |
|---|---|
| types/knowledge.ts | KnowledgeStrategy IngestStatus StructuredIndexItem StructuredStats DocBlockNode DocBlocksGraph |
| types/tree.ts | SmartTreeNode TreeNodeAction |
| types/document.ts | Document DocumentBlock Library |
| types/reference.ts | Reference ReferenceContext |
| types/resource.ts | ResourceNode OpenResourcePayload |
| types/table.ts | TableQueryResult 等表结构契约 |
12.4 U 层工具函数矩阵
| 文件 | 函数 | 常见调用方 |
|---|---|---|
| utils/knowledge.ts | getFileExtension getPreviewFileType | A/B 层文件类型识别 |
| utils/knowledge.ts | mapNodeStatusText | A 层状态文案展示 |
| utils/knowledge.ts | renderMarkdownToHtml | DocumentParsedWorkspace.vue |
13. 架构演进建议(按触发条件)
13.1 何时引入 Pinia Store(非强制)
满足任意两条时建议引入:
- 同一份状态被 3 个以上页面/区域复用。
- A 层出现明显 props drilling(多级透传)。
- 同一逻辑在多个 composable 重复实现。
- 需要跨页面缓存、乐观更新、统一回滚。
- 需要统一收口 websocket/polling 增量数据。
13.2 推荐的最小 Store 切入点
可先落一个 knowledgeWorkspaceStore,仅收口这三类状态:
activeDocId/activeTabstructuredItems/graphDataingestStatus/ingestStage
其余状态继续留在 composables,避免一次性大迁移。
13.3 保持稳定的边界规则
- Store 持有“跨组件共享状态”,不持有重展示逻辑。
- Composable 负责“流程与副作用”,可读写 store。
- Utils 继续保持纯函数,不依赖 store。
- Types 始终先于实现定义,作为改造护栏。
14. 架构关系图(3 张)
14.1 分层总览图(A/B/C/D/U)
flowchart TD
U[U 工具层\nutils/*.ts\n纯函数]
C[C 契约层\ntypes/*.ts\n类型约束]
A[A 可视层\ncomponents + styles]
B[B 逻辑层\ncomposables/*.ts]
D[D 数据层\nAPI/Storage/DB/JSON]
A -->|调用 composable| B
A -->|import type| C
A -->|调用纯函数| U
B -->|import type| C
B -->|调用纯函数| U
B -->|fetch/api| D14.2 Workspace 运行时调用图(你当前主链路)
sequenceDiagram
participant User as 用户
participant W as DocumentParsedWorkspace(A)
participant P as useWorkspacePreview(B)
participant I as useWorkspaceIngest(B)
participant L as useWorkspaceLinkage(B)
participant R as ParsedPDF_Viewer(A)
participant API as /api + docs-core(D)
User->>W: 点击操作(入库/切换/选中)
W->>P: 预览与滚动同步
W->>I: triggerIngest / onStrategyChange
W->>L: onSelectHighlightFromLeft / onSelectItemFromRight
W->>R: 传递 activeTab/content/highlight
R-->>W: 事件回传(update:activeTab, select-line...)
W->>API: rebuild-structured / parse / query
API-->>W: structuredItems/graphData/status
W-->>User: UI 更新与联动高亮14.3 组件与 composables 依赖图(核心模块)
graph LR
W[DocumentParsedWorkspace.vue]
R[DocumentParsedViewerSpace.vue]
V[PDF_Viewer.vue]
IT[Preview_IndexTree.vue]
IG[Preview_IndexGraph.vue]
PM[Preview_Markdown.vue]
ST[SmartTree.vue]
WP[useWorkspacePreview.ts]
WI[useWorkspaceIngest.ts]
WL[useWorkspaceLinkage.ts]
PV[useParsedPdfViewer.ts]
KT[useKnowledgeTree.ts]
UA[useKnowledgeChat.ts]
TY[types/*.ts]
UT[utils/knowledge.ts]
AP[/api/* + docs-core/]
W --> WP
W --> WI
W --> WL
W --> R
W --> V
W --> TY
W --> UT
R --> PV
R --> IT
R --> IG
R --> PM
R --> TY
ST --> TY
AC --> UA
PV --> TY
WI --> TY
WL --> TY
UA --> AP
WP --> AP15. 第一批改造清单(逐文件可执行)
15.1 已落地(低风险去冗余)
useWorkspacePreview.ts:删除本地扩展名/预览类型重复判断,统一复用utils/knowledge.ts的getFileExtension与getPreviewFileType。Preview_IndexList.vue:列表模式已下线,组件已删除;结构导航统一由树形视图承担。useParsedPdfViewer.ts+useDocBlocksGraph.ts:抽出buildDocBlocksGraphIndex,统一构建nodeMap/childrenMap/parentMap/roots,删除重复图索引逻辑。useKnowledgeTree.ts+types/tree.ts:把知识树契约集中到types/tree.ts,统一为KnowledgeTreeNode(不再保留TreeNode别名),移除 composable 内重复类型声明。DocumentParsedWorkspace.vue+ParsedPDF_Viewer.vue+useParsedPdfViewer.ts:统一PreviewMode与图视口事件载荷类型,收敛update-graph-viewport的重复对象定义。DocumentParsedWorkspace.vue+types/knowledge.ts:提炼DocumentParsedWorkspaceEventMap,统一parse/query/rebuild/save-content/change-strategy事件契约。Preview_IndexTree.vue+Preview_IndexGraph.vue+types/knowledge.ts:提炼PreviewIndexInteractionEventMap,统一toggle/select/update-viewport事件命名与载荷结构。Preview_IndexTree.vue+Preview_IndexGraph.vue:图树事件源统一为toggle/select/update-viewport,移除命名适配分支。- 结果:预览链路、图链路与知识树链路共享统一契约入口,减少结构漂移风险。
15.2 下一批建议(按优先级)
- 暂无(第一批改造清单已完成)。
15.3 每项改造验收标准
- 单项改造后
pnpm run lint必须通过。 - 不改变现有交互行为(入库、联动高亮、页签切换)。
- 同类能力只保留一个实现位置(函数/映射/类型)。
- A 层不新增对 D 层的直接依赖。
16. PDF 高亮悬停显示原文(v0.1.2)
PDF_Viewer 内置"证据高亮框悬停显示原文"浮框:悬停 .pdf-highlight-box 时展示该
bbox 区域原文,命中段加粗。取字复用组件内部按页缓存的 pdfjs getTextContent(),
不二次加载 PDF;仅高亮锚点触发,普通文本区域 hover 无浮框。
新增 props(均向后兼容,默认开启):
| prop | 类型 | 默认 | 说明 |
| :--- | :--- | :--- | :--- |
| highlightHoverText | boolean | true | 是否启用高亮悬停原文 |
| highlightHoverFontSize | number | 13 | 浮框字号 |
| highlightHoverMaxWidth | number | 340 | 浮框最大宽度(超出滚动) |
| highlightHoverMaxHeight | number | 180 | 浮框最大高度(超出滚动) |
highlights 条目新增可选字段:
text?: bbox 原文全文,优先展示(未提供时按 bbox 内部提取);matchText?: 雷同段,浮框内加粗高亮(未提供时尝试全文定位,或不做加粗);excerpt?: 兼容别名,matchText未提供时当matchText用。
浮框行为:pointer-events: none 不拦截交互;靠近边缘自动翻转防溢出;翻页、缩放、
搜索、定位时自动隐藏;亮色/暗色主题均适配。
17. PDF 子集渲染与加载事件(v0.1.3)
pdf-page-range?: number[]:绝对页码数组,仅渲染这些页(虚拟滚动、工具栏、高亮、
悬停取字均按子集工作);undefined 或空数组 = 整篇;越界页码自动过滤,全部越界时
退化为整篇。页码输入框与 current-pdf-page 均使用绝对页码,子集外输入就近吸附
(距离相等取较小页)。
pdf-loaded 事件:文档加载完成后触发,payload 为当前源 URL,可用于加载完成后
重放定位等场景。
18. 流式加载降级与日志清理(v0.1.4)
PDF_Viewer 优先以 Range/流式方式加载 PDF;当流式加载因中断(Loading aborted)
失败时,自动降级为全量数组缓冲加载,并且同会话内记住该源,后续直接走全量加载,
不再重复失败的流式尝试(Loading aborted 属预期竞态,不再输出警告日志)。
文档切换/卸载的调试日志同步移除。
