فهرست منبع

feat: 实现实体标记功能及相关API适配

- 新增 documentApi 实体标记接口 (markEntity, unmarkEntity, updateEntity, confirmEntity)
- 新增 projectApi 项目管理接口
- 新增 sourceDocumentApi 来源文件管理接口
- 新增 knowledgeGraphApi 知识图谱接口
- Editor.vue 实现右键菜单实体标记功能
- 实体编辑弹窗支持修改类型、确认/删除操作
- 优化实体列表渲染性能,支持分页加载
- 修复 documentContent 变量初始化顺序问题
- 修复 el-radio-button label 属性废弃警告
- 添加空值保护避免页面崩溃
何文松 3 هفته پیش
والد
کامیت
68e497d36f
2فایلهای تغییر یافته به همراه928 افزوده شده و 66 حذف شده
  1. 272 0
      frontend/vue-demo/src/api/index.js
  2. 656 66
      frontend/vue-demo/src/views/Editor.vue

+ 272 - 0
frontend/vue-demo/src/api/index.js

@@ -333,6 +333,11 @@ export const documentApi = {
     return api.get(`/documents/${documentId}`)
   },
 
+  // 获取文档列表
+  list(params = {}) {
+    return api.get('/documents', { params })
+  },
+
   // 获取文档纯文本内容
   getText(documentId) {
     return api.get(`/documents/${documentId}/text`)
@@ -353,9 +358,276 @@ export const documentApi = {
     return api.get(`/documents/${documentId}/toc`)
   },
 
+  // 获取文档解析状态
+  getParseStatus(documentId) {
+    return api.get(`/documents/${documentId}/parse-status`)
+  },
+
+  // 更新文档
+  update(documentId, data) {
+    return api.put(`/documents/${documentId}`, data)
+  },
+
+  // 删除文档
+  delete(documentId) {
+    return api.delete(`/documents/${documentId}`)
+  },
+
+  // 批量删除文档
+  batchDelete(documentIds) {
+    return api.post('/documents/batch-delete', { documentIds })
+  },
+
+  // 获取文档图片列表
+  getImages(documentId) {
+    return api.get(`/documents/${documentId}/images`)
+  },
+
+  // 获取文档表格列表
+  getTables(documentId) {
+    return api.get(`/documents/${documentId}/tables`)
+  },
+
   // 重新生成并保存文档块结构
   regenerateBlocks(documentId) {
     return api.post(`/ner/documents/${documentId}/regenerate-blocks`)
+  },
+
+  // ==================== 块操作 ====================
+
+  // 更新块元素
+  updateBlockElements(documentId, blockId, elements) {
+    return api.put(`/documents/${documentId}/blocks/${blockId}/elements`, { elements })
+  },
+
+  // 创建新块
+  createBlock(documentId, data) {
+    return api.post(`/documents/${documentId}/blocks`, data)
+  },
+
+  // 删除块
+  deleteBlock(documentId, blockId) {
+    return api.delete(`/documents/${documentId}/blocks/${blockId}`)
+  },
+
+  // 批量保存块
+  saveBlocksBatch(documentId, blocks) {
+    return api.post(`/documents/${documentId}/blocks/batch`, { blocks })
+  },
+
+  // ==================== 实体标记操作 ====================
+
+  /**
+   * 标记实体(将文本转为实体)
+   * @param {string} documentId - 文档ID
+   * @param {string} blockId - 块ID
+   * @param {object} data - 标记数据
+   * @param {number} data.elementIndex - 要标记的元素在 elements 数组中的索引
+   * @param {number} data.startOffset - 在该元素文本中的起始位置
+   * @param {number} data.endOffset - 在该元素文本中的结束位置
+   * @param {string} data.entityType - 实体类型
+   */
+  markEntity(documentId, blockId, data) {
+    return api.post(`/documents/${documentId}/blocks/${blockId}/mark-entity`, data)
+  },
+
+  /**
+   * 取消实体标记(将实体还原为文本)
+   * @param {string} documentId - 文档ID
+   * @param {string} blockId - 块ID
+   * @param {string} entityId - 实体ID
+   */
+  unmarkEntity(documentId, blockId, entityId) {
+    return api.delete(`/documents/${documentId}/blocks/${blockId}/entities/${entityId}`)
+  },
+
+  /**
+   * 更新实体类型
+   * @param {string} documentId - 文档ID
+   * @param {string} blockId - 块ID
+   * @param {string} entityId - 实体ID
+   * @param {string} entityType - 新的实体类型
+   */
+  updateEntity(documentId, blockId, entityId, entityType) {
+    return api.put(`/documents/${documentId}/blocks/${blockId}/entities/${entityId}`, { entityType })
+  },
+
+  /**
+   * 确认实体
+   * @param {string} documentId - 文档ID
+   * @param {string} blockId - 块ID
+   * @param {string} entityId - 实体ID
+   */
+  confirmEntity(documentId, blockId, entityId) {
+    return api.post(`/documents/${documentId}/blocks/${blockId}/entities/${entityId}/confirm`)
+  }
+}
+
+// ==================== 项目 API ====================
+
+export const projectApi = {
+  // 创建项目
+  create(data) {
+    return api.post('/extract/projects', data)
+  },
+
+  // 获取项目详情
+  getById(id, includeDocuments = true) {
+    return api.get(`/extract/projects/${id}`, { params: { includeDocuments } })
+  },
+
+  // 分页查询项目列表
+  list(params = {}) {
+    return api.get('/extract/projects', { params })
+  },
+
+  // 按状态查询项目列表
+  listByStatus(status) {
+    return api.get(`/extract/projects/by-status/${status}`)
+  },
+
+  // 更新项目
+  update(id, data) {
+    return api.put(`/extract/projects/${id}`, data)
+  },
+
+  // 删除项目
+  delete(id) {
+    return api.delete(`/extract/projects/${id}`)
+  },
+
+  // 归档项目
+  archive(id) {
+    return api.post(`/extract/projects/${id}/archive`)
+  },
+
+  // 获取用户项目统计
+  getStatistics() {
+    return api.get('/extract/projects/statistics')
+  }
+}
+
+// ==================== 来源文档 API(项目子资源) ====================
+
+export const sourceDocumentApi = {
+  /**
+   * 添加来源文档到项目
+   * @param {string} projectId - 项目ID
+   * @param {object} data - 文档数据
+   * @param {string} data.documentId - 关联的 Document ID
+   * @param {string} data.alias - 文档别名,如'可研批复'
+   * @param {string} data.docType - 文档类型: pdf/docx/xlsx
+   * @param {number} data.displayOrder - 显示顺序
+   * @param {object} data.metadata - 元数据
+   */
+  add(projectId, data) {
+    return api.post(`/extract/projects/${projectId}/documents`, data)
+  },
+
+  /**
+   * 批量添加来源文档
+   * @param {string} projectId - 项目ID
+   * @param {Array} documents - 文档数组
+   */
+  batchAdd(projectId, documents) {
+    return api.post(`/extract/projects/${projectId}/documents/batch`, { documents })
+  },
+
+  /**
+   * 获取项目的来源文档列表
+   * @param {string} projectId - 项目ID
+   */
+  list(projectId) {
+    return api.get(`/extract/projects/${projectId}/documents`)
+  },
+
+  /**
+   * 获取来源文档详情
+   * @param {string} projectId - 项目ID
+   * @param {string} id - 来源文档ID
+   */
+  getById(projectId, id) {
+    return api.get(`/extract/projects/${projectId}/documents/${id}`)
+  },
+
+  /**
+   * 更新来源文档
+   * @param {string} projectId - 项目ID
+   * @param {string} id - 来源文档ID
+   * @param {object} data - 更新数据
+   */
+  update(projectId, id, data) {
+    return api.put(`/extract/projects/${projectId}/documents/${id}`, data)
+  },
+
+  /**
+   * 移除来源文档
+   * @param {string} projectId - 项目ID
+   * @param {string} id - 来源文档ID
+   * @param {boolean} force - 是否强制删除
+   */
+  remove(projectId, id, force = false) {
+    return api.delete(`/extract/projects/${projectId}/documents/${id}`, { params: { force } })
+  },
+
+  /**
+   * 调整来源文档顺序
+   * @param {string} projectId - 项目ID
+   * @param {Array<string>} orderedIds - 排序后的文档ID数组
+   */
+  reorder(projectId, orderedIds) {
+    return api.post(`/extract/projects/${projectId}/documents/reorder`, { orderedIds })
+  }
+}
+
+// ==================== 知识图谱 API ====================
+
+export const knowledgeGraphApi = {
+  /**
+   * 获取文档图谱
+   * @param {string} documentId - 文档ID
+   */
+  getDocumentGraph(documentId) {
+    return api.get(`/graph/documents/${documentId}`)
+  },
+
+  /**
+   * 获取文档实体列表(按类型分组)
+   * @param {string} documentId - 文档ID
+   * @param {string} type - 可选,筛选实体类型
+   */
+  getDocumentEntities(documentId, type = null) {
+    const params = type ? { type } : {}
+    return api.get(`/graph/documents/${documentId}/entities`, { params })
+  },
+
+  /**
+   * 获取实体详情
+   * @param {string} entityId - 实体ID
+   */
+  getEntityDetail(entityId) {
+    return api.get(`/graph/entities/${entityId}`)
+  },
+
+  /**
+   * 获取用户的全局知识图谱
+   * @param {string} userId - 用户ID
+   * @param {number} limit - 限制返回数量
+   */
+  getUserGraph(userId, limit = 100) {
+    return api.get(`/graph/users/${userId}`, { params: { limit } })
+  },
+
+  /**
+   * 搜索实体
+   * @param {string} keyword - 关键词
+   * @param {string} documentId - 可选,限定文档
+   * @param {number} limit - 限制返回数量
+   */
+  searchEntities(keyword, documentId = null, limit = 20) {
+    const params = { keyword, limit }
+    if (documentId) params.documentId = documentId
+    return api.get('/graph/search', { params })
   }
 }
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 656 - 66
frontend/vue-demo/src/views/Editor.vue


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است