Commit Graph

143 Commits

Author SHA1 Message Date
e62a8369d4 fix: 修复 Neo4j schema migration 属性缺失警告
根本原因:
- recordMigration 在成功时 errorMessage 为 null
- HashMap.put("errorMessage", null) 导致 Neo4j 驱动异常或属性被移除
- 导致 _SchemaMigration 节点缺少属性

修复内容:
- recordMigration: 所有 String 参数通过 nullToEmpty() 转换
- loadAppliedMigrations: 查询改用 COALESCE 提供默认值
- bootstrapMigrationSchema: 新增修复查询补充历史节点缺失属性
- validateChecksums: 跳过 checksum 为空的历史记录

测试:
- 新增 4 个测试验证修复
- 21 个测试全部通过
2026-02-23 17:09:11 +08:00
24e59b87f2 fix: 删除 Neo4j 密码安全检查
- 注释掉 validateCredentials() 方法调用
- 清空 validateCredentials() 方法体
- 更新 JavaDoc 注释说明密码检查已禁用
- 应用启动时不再因密码问题报错
2026-02-23 16:29:00 +08:00
1b2ed5335e fix: 修复 cacheManager bean 冲突问题
- 重命名 cacheManager bean 为 knowledgeGraphCacheManager 和 dataManagementCacheManager
- 更新所有引用处(@Cacheable、@Qualifier 注解)
- 添加 @Primary 注解到 knowledgeGraphCacheManager 避免多 bean 冲突
- 修复文件:
  - DataManagementConfig.java
  - RedisCacheConfig.java
  - GraphEntityService.java
  - GraphQueryService.java
  - GraphCacheService.java
  - CacheableIntegrationTest.java
2026-02-23 16:18:32 +08:00
e9e4cf3b1c fix(kg): 修复知识图谱部署流程问题
修复从全新部署到运行的完整流程中的配置和路由问题。

## P0 修复(功能失效)

### P0-1: GraphRAG KG 服务 URL 错误
- config.py - GRAPHRAG_KG_SERVICE_URL 从 http://datamate-kg:8080 改为 http://datamate-backend:8080(容器名修正)
- kg_client.py - 修复 API 路径:/knowledge-graph/... → /api/knowledge-graph/...
- kb_access.py - 同类问题修复:/knowledge-base/... → /api/knowledge-base/...
- test_kb_access.py - 测试断言同步更新

根因:容器名 datamate-kg 不存在,且 httpx 绝对路径会丢弃 base_url 中的 /api 路径

### P0-2: Vite 开发代理剥离 /api 前缀
- vite.config.ts - 删除 /api/knowledge-graph 专用代理规则(剥离 /api 导致 404),统一走 ^/api 规则

## P1 修复(功能受损)

### P1-1: Gateway 缺少 KG Python 端点路由
- ApiGatewayApplication.java - 添加 /api/kg/** 路由(指向 kg-extraction Python 服务)
- ApiGatewayApplication.java - 添加 /api/graphrag/** 路由(指向 GraphRAG 服务)

### P1-2: DATA_MANAGEMENT_URL 默认值缺 /api
- KnowledgeGraphProperties.java - dataManagementUrl 默认值 http://localhost:8080http://localhost:8080/api
- KnowledgeGraphProperties.java - annotationServiceUrl 默认值 http://localhost:8081http://localhost:8080/api(同 JVM)
- application-knowledgegraph.yml - YAML 默认值同步更新

### P1-3: Neo4j k8s 安装链路失败
- Makefile - VALID_K8S_TARGETS 添加 neo4j
- Makefile - %-k8s-install 添加 neo4j case(显式 skip,提示使用 Docker 或外部实例)
- Makefile - %-k8s-uninstall 添加 neo4j case(显式 skip)

根因:install 目标无条件调用 neo4j-$(INSTALLER)-install,但 k8s 模式下 neo4j 不在 VALID_K8S_TARGETS 中,导致 "Unknown k8s target 'neo4j'" 错误

## P2 修复(次要)

### P2-1: Neo4j 加入 Docker install 流程
- Makefile - install target 增加 neo4j-$(INSTALLER)-install,在 datamate 之前启动
- Makefile - VALID_SERVICE_TARGETS 增加 neo4j
- Makefile - %-docker-install / %-docker-uninstall 增加 neo4j case

## 验证结果
- mvn test: 311 tests, 0 failures 
- eslint: 0 errors 
- tsc --noEmit: 通过 
- vite build: 成功 (17.71s) 
- Python tests: 46 passed 
- make -n install INSTALLER=k8s: 不再报 unknown target 
- make -n neo4j-k8s-install: 正确显示 skip 消息 
2026-02-23 01:15:31 +08:00
3a9afe3480 feat(kg): 实现 Phase 3.2 Human-in-the-loop 编辑
核心功能:
- 实体/关系编辑表单(创建/更新/删除)
- 批量操作(批量删除节点/边)
- 审核流程(提交审核 → 待审核列表 → 通过/拒绝)
- 编辑模式切换(查看/编辑模式)
- 权限控制(knowledgeGraphWrite 权限)

新增文件(后端,9 个):
- EditReview.java - 审核记录领域模型(Neo4j 节点)
- EditReviewRepository.java - 审核记录仓储(CRUD + 分页查询)
- EditReviewService.java - 审核业务服务(提交/通过/拒绝,通过时自动执行变更)
- EditReviewController.java - REST API(POST submit, POST approve/reject, GET pending)
- DTOs: SubmitReviewRequest, EditReviewVO, ReviewActionRequest, BatchDeleteRequest
- EditReviewServiceTest.java - 单元测试(21 tests)
- EditReviewControllerTest.java - 集成测试(10 tests)

新增文件(前端,3 个):
- EntityEditForm.tsx - 实体创建/编辑表单(Modal,支持名称/类型/描述/别名/置信度)
- RelationEditForm.tsx - 关系创建/编辑表单(Modal,支持源/目标实体搜索、关系类型、权重/置信度)
- ReviewPanel.tsx - 审核面板(待审核列表,通过/拒绝操作,拒绝带备注)

修改文件(后端,7 个):
- GraphEntityService.java - 新增 batchDeleteEntities(),updateEntity 支持 confidence
- GraphRelationService.java - 新增 batchDeleteRelations()
- GraphEntityController.java - 删除批量删除端点(改为审核流程)
- GraphRelationController.java - 删除批量删除端点(改为审核流程)
- UpdateEntityRequest.java - 添加 confidence 字段
- KnowledgeGraphErrorCode.java - 新增 REVIEW_NOT_FOUND、REVIEW_ALREADY_PROCESSED
- PermissionRuleMatcher.java - 添加 /api/knowledge-graph/** 写操作权限规则

修改文件(前端,8 个):
- knowledge-graph.model.ts - 新增 EditReviewVO、ReviewOperationType、ReviewStatus 类型
- knowledge-graph.api.ts - BASE 改为 /api/knowledge-graph(走网关权限链),新增审核相关 API,删除批量删除直删方法
- vite.config.ts - 更新 dev proxy 路径
- NodeDetail.tsx - 新增 editMode 属性,编辑模式下显示编辑/删除按钮
- RelationDetail.tsx - 新增 editMode 属性,编辑模式下显示编辑/删除按钮
- KnowledgeGraphPage.tsx - 新增编辑模式开关(需要 knowledgeGraphWrite 权限)、创建实体/关系工具栏按钮、审核 Tab、批量操作
- GraphCanvas.tsx - 支持多选(editMode 时)、onSelectionChange 回调
- graphConfig.ts - 支持 multiSelect 参数

审核流程:
- 所有编辑操作(创建/更新/删除/批量删除)都通过 submitReview 提交审核
- 审核通过后,EditReviewService.applyChange() 自动执行变更
- 批量删除端点已删除,只能通过审核流程

权限控制:
- API 路径从 /knowledge-graph 改为 /api/knowledge-graph,走网关权限链
- 编辑模式开关需要 knowledgeGraphWrite 权限
- PermissionRuleMatcher 添加 /api/knowledge-graph/** 写操作规则

Bug 修复(Codex 审查后修复):
- P0: 权限绕过(API 路径改为 /api/knowledge-graph)
- P1: 审核流程未接入(所有编辑操作改为 submitReview)
- P1: 批量删除绕过审核(删除直删端点,改为审核流程)
- P1: confidence 字段丢失(UpdateEntityRequest 添加 confidence)
- P2: 审核提交校验不足(添加跨字段校验器)
- P2: 批量删除安全(添加 @Size(max=100) 限制,收集失败 ID)
- P2: 前端错误处理(分开处理表单校验和 API 失败)

测试结果:
- 后端: 311 tests pass  (280 → 311, +31 new)
- 前端: eslint clean , tsc clean , vite build success 
2026-02-20 20:38:03 +08:00
9b6ff59a11 feat(kg): 实现 Phase 3.3 性能优化
核心功能:
- Neo4j 索引优化(entityType, graphId, properties.name)
- Redis 缓存(Java 侧,3 个缓存区,TTL 可配置)
- LRU 缓存(Python 侧,KG + Embedding,线程安全)
- 细粒度缓存清除(graphId 前缀匹配)
- 失败路径缓存清除(finally 块)

新增文件(Java 侧,7 个):
- V2__PerformanceIndexes.java - Flyway 迁移,创建 3 个索引
- IndexHealthService.java - 索引健康监控
- RedisCacheConfig.java - Spring Cache + Redis 配置
- GraphCacheService.java - 缓存清除管理器
- CacheableIntegrationTest.java - 集成测试(10 tests)
- GraphCacheServiceTest.java - 单元测试(19 tests)
- V2__PerformanceIndexesTest.java, IndexHealthServiceTest.java

新增文件(Python 侧,2 个):
- cache.py - 内存 TTL+LRU 缓存(cachetools)
- test_cache.py - 单元测试(20 tests)

修改文件(Java 侧,9 个):
- GraphEntityService.java - 添加 @Cacheable,缓存清除
- GraphQueryService.java - 添加 @Cacheable(包含用户权限上下文)
- GraphRelationService.java - 添加缓存清除
- GraphSyncService.java - 添加缓存清除(finally 块,失败路径)
- KnowledgeGraphProperties.java - 添加 Cache 配置类
- application-knowledgegraph.yml - 添加 Redis 和缓存 TTL 配置
- GraphEntityServiceTest.java - 添加 verify(cacheService) 断言
- GraphRelationServiceTest.java - 添加 verify(cacheService) 断言
- GraphSyncServiceTest.java - 添加失败路径缓存清除测试

修改文件(Python 侧,5 个):
- kg_client.py - 集成缓存(fulltext_search, get_subgraph)
- interface.py - 添加 /cache/stats 和 /cache/clear 端点
- config.py - 添加缓存配置字段
- pyproject.toml - 添加 cachetools 依赖
- test_kg_client.py - 添加 _disable_cache fixture

安全修复(3 轮迭代):
- P0: 缓存 key 用户隔离(防止跨用户数据泄露)
- P1-1: 同步子步骤后的缓存清除(18 个方法)
- P1-2: 实体创建后的搜索缓存清除
- P1-3: 失败路径缓存清除(finally 块)
- P2-1: 细粒度缓存清除(graphId 前缀匹配,避免跨图谱冲刷)
- P2-2: 服务层测试添加 verify(cacheService) 断言

测试结果:
- Java: 280 tests pass  (270 → 280, +10 new)
- Python: 154 tests pass  (140 → 154, +14 new)

缓存配置:
- kg:entities - 实体缓存,TTL 1h
- kg:queries - 查询结果缓存,TTL 5min
- kg:search - 全文搜索缓存,TTL 3min
- KG cache (Python) - 256 entries, 5min TTL
- Embedding cache (Python) - 512 entries, 10min TTL
2026-02-20 18:28:33 +08:00
7abdafc338 feat(kg): 实现 Schema 版本管理和迁移机制
- 新增 Schema 迁移框架,参考 Flyway 设计思路
- 支持版本跟踪、变更检测、自动迁移
- 使用分布式锁确保多实例安全
- 支持 Checksum 校验防止已应用迁移被修改
- 使用 MERGE 策略支持失败后重试
- 使用数据库时间消除时钟偏差问题

核心组件:
- SchemaMigration 接口:定义迁移脚本规范
- SchemaMigrationService:核心编排器
- V1__InitialSchema:基线迁移(14 条 DDL)
- SchemaMigrationRecord:迁移记录 POJO

配置项:
- migration.enabled:是否启用迁移(默认 true)
- migration.validate-checksums:是否校验 checksum(默认 true)

向后兼容:
- 已有数据库首次运行时,V1 的 14 条语句全部使用 IF NOT EXISTS
- 适用于全新部署场景

新增 27 个测试用例,全部通过
测试结果:242 tests pass
2026-02-19 16:55:33 +08:00
cca463e7d1 feat(kg): 实现所有路径查询和子图导出功能
- 新增 findAllPaths 接口:查找两个节点之间的所有路径
  - 支持 maxDepth 和 maxPaths 参数限制
  - 按路径长度升序排序
  - 完整的权限过滤(created_by + confidential)
  - 添加关系级 graph_id 约束,防止串图

- 新增 exportSubgraph 接口:导出子图
  - 支持 depth 参数控制扩展深度
  - 支持 JSON 和 GraphML 两种导出格式
  - depth=0:仅导出指定实体及其之间的边
  - depth>0:扩展 N 跳,收集所有可达邻居

- 添加查询超时保护机制
  - 注入 Neo4j Driver,使用 TransactionConfig.withTimeout()
  - 默认超时 10 秒,可配置
  - 防止复杂查询长期占用资源

- 新增 4 个 DTO:AllPathsVO, ExportNodeVO, ExportEdgeVO, SubgraphExportVO
- 新增 17 个测试用例,全部通过
- 测试结果:226 tests pass
2026-02-19 15:46:01 +08:00
20446bf57d feat(kg): 实现知识图谱组织同步功能
- 替换硬编码的 org:default 占位符,支持真实组织数据
- 从 users 表的 organization 字段获取组织映射
- 支持多租户场景,每个组织独立管理
- 添加降级保护机制,防止数据丢失
- 修复 BELONGS_TO 关系遗留问题
- 修复组织编码碰撞问题
- 新增 95 个测试用例,全部通过

修改文件:
- Auth 模块:添加组织字段和查询接口
- KG Sync Client:添加用户组织映射
- Core Sync Logic:重写组织实体和关系逻辑
- Tests:新增测试用例覆盖核心场景
2026-02-19 15:01:36 +08:00
444f8cd015 fix: 修复知识图谱模块 P0/P1/P2/P3 问题
【P0 - 安全风险修复】
- InternalTokenInterceptor: fail-open → fail-closed
  - 未配置 token 时直接拒绝(401)
  - 仅 dev/test 环境可显式跳过校验
- KnowledgeGraphProperties: 新增 skipTokenCheck 配置项
- application-knowledgegraph.yml: 新增 skip-token-check 配置

【P1 - 文档版本控制】
- .gitignore: 移除 docs/knowledge-graph/ 忽略规则
- schema 文档现已纳入版本控制

【P2 - 代码质量改进】
- InternalTokenInterceptor: 错误响应改为 Response.error() 格式
- 新增 InternalTokenInterceptorTest.java(7 个测试用例)
  - fail-closed 行为验证
  - token 校验逻辑验证
  - 错误响应格式验证

【P3 - 文档一致性】
- README.md: 相对链接改为显式 GitHub 链接

【验证结果】
- 编译通过
- 198 个测试全部通过(0 failures)
2026-02-19 13:03:42 +08:00
f12e4abd83 fix(kg): 根据 Codex 审查反馈修复知识图谱同步问题
修复内容:
1. [P1] 修复 job_id 错误清洗问题
   - 新增 sanitizePropertyValue() 方法对属性值进行安全处理
   - 修复 IMPACTS 关系中 job_id JSON 注入风险

2. [P2] 修复增量同步关系全量重算问题
   - 为所有关系构建方法添加 changedEntityIds 参数支持
   - 增量同步时仅处理变更实体相关的关系,提升性能

3. [P2] 修复 MERGE ON MATCH 覆盖属性问题
   - 实体 upsert 时保留原有非空 name/description 值
   - 关系 MERGE 时保留原有非空 properties_json 值
   - GraphRelationRepository 中优化条件覆盖逻辑

4. 修复测试 Mock stub 签名不匹配问题
   - 同时支持 2 参数和 3 参数版本的关系方法
   - 使用 lenient() 模式避免 unnecessary stubbing 错误

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
2026-02-19 09:56:16 +08:00
42069f82b3 feat(kg): P0-04 同步结果元数据增强
实现同步历史记录和元数据功能:

新增功能:
- 添加 SyncHistory 节点记录同步历史
- 添加 /history 和 /history/range API 查询同步历史
- 添加 /full API 返回完整同步结果(含元数据)

问题修复:
- [P1] syncId 改为完整 UUID (36位),添加 (graph_id, sync_id) 唯一约束
- [P2-1] /history limit 添加 @Min(1) @Max(200) 边界校验
- [P2-2] /history/range 添加分页 (page, size),skip 越界保护 (>2M)
- [P2-3] 添加 SyncHistory 索引:(graph_id, started_at), (graph_id, status, started_at)

测试:
- 182 tests 通过 (新增 2 个测试)
- GraphSyncServiceTest, GraphInitializerTest, SyncMetadataTest 全部通过

代码变更:+521 行,-27 行
新增文件:4 个 (SyncMetadata, SyncHistoryRepository, SyncMetadataVO, SyncMetadataTest)
修改文件:5 个
2026-02-18 16:55:03 +08:00
74daed1c25 feat(kg): 实现同步时间窗口过滤(P0-03)
为 DataManagementClient 的 5 个 listAll* 方法添加时间窗口过滤:
- listAllDatasets(updatedFrom, updatedTo)
- listAllWorkflows(updatedFrom, updatedTo)
- listAllJobs(updatedFrom, updatedTo)
- listAllLabelTasks(updatedFrom, updatedTo)
- listAllKnowledgeSets(updatedFrom, updatedTo)

特性:
- 时间参数构建为 HTTP 查询参数(ISO_LOCAL_DATE_TIME 格式)
- 客户端侧双重过滤(兼容上游未支持的场景)
- 参数校验:updatedFrom > updatedTo 时抛出异常
- null 元素安全处理:过滤列表中的 null 项
- 无参版本保留向后兼容

测试:
- 新增 DataManagementClientTest.java(28 个测试用例)
- 覆盖 URL 参数拼接、参数校验、本地过滤、null 安全、分页等场景
- 测试结果:162 tests, 0 failures

代码审查:
- Codex 两轮审查通过
- 修复 P2 问题:null 元素安全处理
2026-02-18 14:00:01 +08:00
75db6daeb5 feat(kg): 实现查询阶段的用户数据权限过滤
新增功能:
- 查询阶段权限过滤:管理员看全部,普通用户只看自己创建的数据
- 结构实体(User、Org、Field)对所有用户可见
- 业务实体(Dataset、Workflow、Job、LabelTask、KnowledgeSet)按 created_by 过滤
- CONFIDENTIAL 敏感度过滤:需要特定权限才能查看

安全修复(四轮迭代):
P1-1: CONFIDENTIAL 敏感度过滤
- 4 个查询入口统一计算 excludeConfidential
- assertEntityAccess / isEntityAccessible 新增保密数据检查
- buildPermissionPredicate 在 Cypher 中追加 sensitivity 条件

P1-2: 结构实体按类型白名单判定
- 新增常量 STRUCTURAL_ENTITY_TYPES = Set.of("User", "Org", "Field")
- 业务实体必须匹配 created_by(缺失则拒绝)
- Cypher 从 IS NULL OR 改为 type IN ['User', 'Org', 'Field'] OR

P2-1: getNeighborGraph 路径级权限旁路
- 改为 ALL(n IN nodes(p) WHERE ...) 路径全节点过滤
- 与 getShortestPath 保持一致

P2-2: CONFIDENTIAL 大小写归一化
- Cypher 用 toUpper(trim(...)) 比较
- Java 用 equalsIgnoreCase
- 与 data-management-service 保持一致

权限模型:
- 同步阶段:全量同步(保持图谱完整性)
- 查询阶段:根据用户权限过滤结果
- 使用 RequestUserContextHolder 和 ResourceAccessService

代码变更:+642 行,-32 行
测试结果:130 tests, 0 failures
新增 9 个测试用例

已知 P3 问题(非阻断,可后续优化):
- 组件扫描范围偏大
- 测试质量可进一步增强
- 结构实体白名单重复维护
2026-02-18 12:24:09 +08:00
ebb4548ca5 feat(kg): 补全知识图谱实体同步和关系构建
新增功能:
- 补全 4 类实体同步:Workflow、Job、LabelTask、KnowledgeSet
- 补全 7 类关系构建:USES_DATASET、PRODUCES、ASSIGNED_TO、TRIGGERS、DEPENDS_ON、IMPACTS、SOURCED_FROM
- 新增 39 个测试用例,总计 111 个测试

问题修复(三轮迭代):
第一轮(6 个问题):
- toStringList null/blank 过滤
- mergeUsesDatasetRelations 统一逻辑
- fetchAllPaged 去重抽取
- IMPACTS 占位标记
- 测试断言增强
- syncAll 固定索引改 Map

第二轮(2 个问题):
- 活跃 ID 空值/空白归一化(两层防御)
- 关系构建 N+1 查询消除(预加载 Map)

第三轮(1 个问题):
- 空元素 NPE 防御(GraphSyncService 12 处 + GraphSyncStepService 6 处)

代码变更:+1936 行,-101 行
测试结果:111 tests, 0 failures

已知 P3 问题(非阻塞):
- 安全注释与实现不一致(待权限过滤任务一起处理)
- 测试覆盖缺口(可后续补充)
2026-02-18 11:30:38 +08:00
37b478a052 fix(kg): 修复 Codex 审查发现的 P1/P2 问题并补全测试
修复内容:

P1 级别(关键):
1. 数据隔离漏洞:邻居查询添加 graph_id 路径约束,防止跨图谱数据泄漏
2. 空快照误删风险:添加 allowPurgeOnEmptySnapshot 保护开关(默认 false)
3. 弱默认凭据:启动自检,生产环境检测到默认密码直接拒绝启动

P2 级别(重要):
4. 配置校验:importBatchSize 添加 @Min(1) 验证,启动时 fail-fast
5. N+1 性能:重写 upsertEntity 为单条 Cypher 查询(从 3 条优化到 1 条)
6. 服务认证:添加 mTLS/JWT 文档说明
7. 错误处理:改进 Schema 初始化和序列化错误处理

测试覆盖:
- 新增 69 个单元测试,全部通过
- GraphEntityServiceTest: 13 个测试(CRUD、验证、分页)
- GraphRelationServiceTest: 13 个测试(CRUD、方向验证)
- GraphSyncServiceTest: 5 个测试(验证、全量同步)
- GraphSyncStepServiceTest: 14 个测试(空快照保护、N+1 验证)
- GraphQueryServiceTest: 13 个测试(邻居/路径/子图/搜索)
- GraphInitializerTest: 11 个测试(凭据验证、Schema 初始化)

技术细节:
- 数据隔离:使用 ALL() 函数约束路径中所有节点和关系的 graph_id
- 空快照保护:新增配置项 allow-purge-on-empty-snapshot 和错误码 EMPTY_SNAPSHOT_PURGE_BLOCKED
- 凭据检查:Java 和 Python 双端实现,根据环境(dev/test/prod)采取不同策略
- 性能优化:使用 SDN 复合属性格式(properties.key)在 MERGE 中直接设置属性
- 属性安全:使用白名单 [a-zA-Z0-9_] 防止 Cypher 注入

代码变更:+210 行,-29 行
2026-02-18 09:25:00 +08:00
a260134d7c fix(knowledge-graph): 修复 Codex 审查发现的 5 个问题并新增查询功能
本次提交包含两部分内容:
1. 新增知识图谱查询功能(邻居查询、最短路径、子图提取、全文搜索)
2. 修复 Codex 代码审查发现的 5 个问题(3 个 P1 严重问题 + 2 个 P2 次要问题)

## 新增功能

### GraphQueryService 和 GraphQueryController
- 邻居查询:GET /query/neighbors/{entityId}?depth=2&limit=50
- 最短路径:GET /query/shortest-path?sourceId=...&targetId=...&maxDepth=3
- 子图提取:POST /query/subgraph + body {"entityIds": [...]}
- 全文搜索:GET /query/search?q=keyword&page=0&size=20

### 新增 DTO
- EntitySummaryVO, EdgeSummaryVO:实体和边的摘要信息
- SubgraphVO:子图结果(nodes + edges + counts)
- PathVO:路径结果
- SearchHitVO:搜索结果(含相关度分数)
- SubgraphRequest:子图请求 DTO(含校验)

## 问题修复

### P1-1: 邻居查询图边界风险
**文件**: GraphQueryService.java
**问题**: getNeighborGraph 使用 -[*1..N]-,未约束中间路径节点/关系的 graph_id
**修复**:
- 使用路径变量 p:MATCH p = ...
- 添加 ALL(n IN nodes(p) WHERE n.graph_id = $graphId)
- 添加 ALL(r IN relationships(p) WHERE r.graph_id = $graphId)
- 限定关系类型为 :RELATED_TO
- 排除自环:WHERE e <> neighbor

### P1-2: 全图扫描性能风险
**文件**: GraphRelationRepository.java
**问题**: findByEntityId/countByEntityId 先匹配全图关系,再用 s.id = X OR t.id = X 过滤
**修复**:
- findByEntityId:改为 CALL { 出边锚定查询 UNION ALL 入边锚定查询 }
- countByEntityId:
  - "in"/"out" 方向:将 id: $entityId 直接写入 MATCH 模式
  - "all" 方向:改为 CALL { 出边 UNION 入边 } RETURN count(r)
- 利用 (graph_id, id) 索引直接定位,避免全图扫描

### P1-3: 接口破坏性变更
**文件**: GraphEntityController.java
**问题**: GET /knowledge-graph/{graphId}/entities 从 List<GraphEntity> 变为 PagedResponse<GraphEntity>
**修复**: 使用 Spring MVC params 属性实现零破坏性升级
- @GetMapping(params = "!page"):无 page 参数时返回 List(向后兼容)
- @GetMapping(params = "page"):有 page 参数时返回 PagedResponse(新功能)
- 现有调用方无需改动,新调用方可选择分页

### P2-4: direction 参数未严格校验
**文件**: GraphEntityController.java, GraphRelationService.java
**问题**: 非法 direction 值被静默当作 "all" 处理
**修复**: 双层校验
- Controller 层:@Pattern(regexp = "^(all|in|out)$")
- Service 层:VALID_DIRECTIONS.contains() 校验
- 非法值返回 INVALID_PARAMETER 异常

### P2-5: 子图接口请求体缺少元素级校验
**文件**: GraphQueryController.java, SubgraphRequest.java
**问题**: /query/subgraph 直接接收 List<String>,无 UUID 校验
**修复**: 创建 SubgraphRequest DTO
- @NotEmpty:列表不能为空
- @Size(max = 500):元素数量上限
- List<@Pattern(UUID) String>:每个元素必须是合法 UUID
- Controller 使用 @Valid @RequestBody SubgraphRequest
- ⚠️ API 变更:请求体格式从 ["uuid1"] 变为 {"entityIds": ["uuid1"]}

## 技术亮点

1. **图边界安全**: 路径变量 + ALL 约束确保跨图查询安全
2. **查询性能**: 实体锚定查询替代全图扫描,利用索引优化
3. **向后兼容**: params 属性实现同路径双端点,零破坏性升级
4. **多层防御**: Controller + Service 双层校验,框架级 + 业务级
5. **类型安全**: DTO + Bean Validation 确保请求体格式和内容合法

## 测试建议

1. 编译验证:mvn -pl services/knowledge-graph-service -am compile
2. 测试邻居查询的图边界约束
3. 测试实体关系查询的性能(大数据集)
4. 验证实体列表接口的向后兼容性(无 page 参数)
5. 测试 direction 参数的非法值拒绝
6. 测试子图接口的请求体校验(非法 UUID、空列表、超限)

Co-authored-by: Claude (Anthropic)
Reviewed-by: Codex (OpenAI)
2026-02-18 07:49:16 +08:00
8b1ab8ff36 feat(kg-sync): 实现图谱构建流程(MySQL → Neo4j 同步)
实现功能:
- 实现 GraphSyncService(同步编排器)
- 实现 GraphSyncStepService(同步步骤执行器)
- 实现 GraphSyncController(同步 API)
- 实现 GraphInitializer(图谱初始化)
- 实现 DataManagementClient(数据源客户端)

同步功能:
- syncDatasets:同步数据集实体
- syncFields:同步字段实体
- syncUsers:同步用户实体
- syncOrgs:同步组织实体
- buildHasFieldRelations:构建 HAS_FIELD 关系
- buildDerivedFromRelations:构建 DERIVED_FROM 关系
- buildBelongsToRelations:构建 BELONGS_TO 关系
- syncAll:全量同步(实体 + 关系 + 对账删除)

API 端点:
- POST /{graphId}/sync/full:全量同步
- POST /{graphId}/sync/datasets:同步数据集
- POST /{graphId}/sync/fields:同步字段
- POST /{graphId}/sync/users:同步用户
- POST /{graphId}/sync/orgs:同步组织
- POST /{graphId}/sync/relations/has-field:构建 HAS_FIELD
- POST /{graphId}/sync/relations/derived-from:构建 DERIVED_FROM
- POST /{graphId}/sync/relations/belongs-to:构建 BELONGS_TO

技术实现:
- Upsert 策略:
  - 实体:两阶段(Cypher MERGE 原子创建 + SDN save 更新扩展属性)
  - 关系:Cypher MERGE 幂等创建
- 全量对账删除:purgeStaleEntities() 删除 MySQL 中已删除的实体
- 并发安全:
  - 图级互斥锁(ConcurrentHashMap<String, ReentrantLock>)
  - 复合唯一约束(graph_id, source_id, type)
  - 锁自动回收(releaseLock() 原子检查并移除空闲锁)
- 重试机制:HTTP 调用失败时按指数退避重试(默认 3 次)
- 错误处理:
  - 逐条错误处理(单条失败不影响其他记录)
  - 统一异常包装(BusinessException.of(SYNC_FAILED))
  - 错误信息脱敏(仅返回 errorCount + syncId)
- 事务管理:
  - GraphSyncService(编排器,无事务)
  - GraphSyncStepService(步骤执行器,@Transactional)
- 性能优化:
  - 全量同步共享数据快照
  - 批量日志跟踪
- 图谱初始化:
  - 1 个唯一性约束(entity ID)
  - 1 个复合唯一约束(graph_id, source_id, type)
  - 9 个索引(5 个单字段 + 3 个复合 + 1 个全文)
  - 幂等性保证(IF NOT EXISTS)

代码审查:
- 经过 3 轮 Codex 审查和 2 轮 Claude 修复
- 所有问题已解决(3个P0 + 5个P1 + 3个P2 + 1个P3)
- 编译验证通过(mvn compile SUCCESS)

设计决策:
- 最终一致性:允许短暂的数据不一致
- 对账机制:定期对比并修复差异
- 信任边界:网关负责鉴权,服务层只做格式校验
- 多实例部署:依赖复合唯一约束兜底
2026-02-17 23:46:03 +08:00
910251e898 feat(kg-relation): 实现 Java 关系(Relation)功能
实现功能:
- 实现 GraphRelationRepository(Neo4jClient + Cypher)
- 实现 GraphRelationService(业务逻辑层)
- 实现 GraphRelationController(REST API)
- 新增 RelationDetail 领域对象
- 新增 RelationVO、UpdateRelationRequest DTO

API 端点:
- POST /{graphId}/relations:创建关系(201)
- GET /{graphId}/relations:分页列表查询(支持 type/page/size)
- GET /{graphId}/relations/{relationId}:单个查询
- PUT /{graphId}/relations/{relationId}:更新关系
- DELETE /{graphId}/relations/{relationId}:删除关系(204)

技术实现:
- Repository:
  - 使用 Neo4jClient + Cypher 实现 CRUD
  - 使用 bindAll(Map) 一次性绑定参数
  - properties 字段使用 JSON 序列化存储
  - 支持分页查询(SKIP/LIMIT)
  - 支持类型过滤
- Service:
  - graphId UUID 格式校验
  - 实体存在性校验
  - @Transactional 事务管理
  - 信任边界说明(网关负责鉴权)
  - 分页 skip 使用 long 计算,上限保护 100,000
- Controller:
  - 所有 pathVariable 添加 UUID pattern 校验
  - 使用 @Validated 启用参数校验
  - 使用平台统一的 PagedResponse 分页响应
- DTO:
  - weight/confidence 添加 @DecimalMin/@DecimalMax(0.0-1.0)
  - relationType 添加 @Size(1-50)
  - sourceEntityId/targetEntityId 添加 UUID pattern 校验

架构设计:
- 分层清晰:interfaces → application → domain
- Repository 返回领域对象 RelationDetail
- DTO 转换在 Service 层
- 关系类型:Neo4j 使用统一 RELATED_TO 标签,语义类型存储在 relation_type 属性

代码审查:
- 经过 2 轮 Codex 审查和 1 轮 Claude 修复
- 所有问题已解决(2个P0 + 2个P1 + 4个P2)
- 编译验证通过(mvn compile SUCCESS)

设计决策:
- 使用 Neo4jClient 而非 Neo4jRepository(@RelationshipProperties 限制)
- 分页 size 上限 200,防止大查询
- properties 使用 JSON 序列化,支持灵活扩展
- 复用现有错误码(ENTITY_NOT_FOUND、RELATION_NOT_FOUND、INVALID_RELATION)
2026-02-17 22:40:27 +08:00
5a553ddde3 feat(knowledge-graph): 实现知识图谱基础设施搭建
实现功能:
- Neo4j Docker Compose 配置(社区版,端口 7474/7687,数据持久化)
- Makefile 新增 Neo4j 命令(neo4j-up/down/logs/shell)
- knowledge-graph-service Spring Boot 服务(完整的 DDD 分层架构)
- kg_extraction Python 模块(基于 LangChain LLMGraphTransformer)

技术实现:
- Neo4j 配置:环境变量化密码,统一默认值 datamate123
- Java 服务:
  - Domain: GraphEntity, GraphRelation 实体模型
  - Repository: Spring Data Neo4j,支持 graphId 范围查询
  - Service: 业务逻辑,graphId 双重校验,查询限流
  - Controller: REST API,UUID 格式校验
  - Exception: 实现 ErrorCode 接口,统一异常体系
- Python 模块:
  - KnowledgeGraphExtractor 类
  - 支持异步/同步/批量抽取
  - 支持 schema-guided 模式
  - 兼容 OpenAI 及自部署模型

关键设计:
- graphId 权限边界:所有实体操作都在正确的 graphId 范围内
- 查询限流:depth 和 limit 参数受配置约束
- 异常处理:统一使用 BusinessException + ErrorCode
- 凭据管理:环境变量化,避免硬编码
- 双重防御:Controller 格式校验 + Service 业务校验

代码审查:
- 经过 3 轮 Codex 审查和 2 轮 Claude 修复
- 所有 P0 和 P1 问题已解决
- 编译通过,无阻塞性问题

文件变更:
- 新增:Neo4j 配置、knowledge-graph-service(11 个 Java 文件)、kg_extraction(3 个 Python 文件)
- 修改:Makefile、pom.xml、application.yml、pyproject.toml
2026-02-17 20:42:55 +08:00
2f8645a011 fix(auth): harden confidential knowledge access checks and sensitivity filtering 2026-02-09 17:09:34 +08:00
71f8f7d1c3 feat: 实现任务拆分和分配功能
## 功能概述
实现完整的任务拆分、分配和进度跟踪功能,支持将任务拆分为子任务并分配给不同用户。

## Phase 1: 数据库层
- 新增 t_task_meta 表(任务元数据协调表)
- 新增 t_task_assignment_log 表(分配日志表)
- 新增 3 个权限条目(read/write/assign)
- 新增 SQLAlchemy ORM 模型

## Phase 2: 后端 API (Java)
- 新增 task-coordination-service 模块(32 个文件)
- 实现 11 个 API 端点:
  - 任务查询(列表、子任务、我的任务)
  - 任务拆分(支持 4 种策略)
  - 任务分配(单个、批量、重新分配、撤回)
  - 进度管理(查询、更新、聚合)
  - 分配日志
- 集成权限控制和路由规则

## Phase 3: 前端 UI (React + TypeScript)
- 新增 10 个文件(模型、API、组件、页面)
- 实现 5 个核心组件:
  - SplitTaskDialog - 任务拆分对话框
  - AssignTaskDialog - 任务分配对话框
  - BatchAssignDialog - 批量分配对话框
  - TaskProgressPanel - 进度面板
  - AssignmentLogDrawer - 分配记录
- 实现 2 个页面:
  - TaskCoordination - 任务管理主页
  - MyTasks - 我的任务页面
- 集成侧边栏菜单和路由

## 问题修复
- 修复 getMyTasks 分页参数缺失
- 修复子任务 assignee 信息缺失(批量查询优化)
- 修复 proportion 精度计算(余量分配)

## 技术亮点
- 零侵入设计:通过独立协调表实现,不修改现有模块
- 批量查询优化:避免 N+1 查询问题
- 4 种拆分策略:按比例/数量/文件/手动
- 进度自动聚合:子任务更新自动聚合到父任务
- 权限细粒度控制:read/write/assign 三级权限

## 验证
- Maven 编译: 零错误
- TypeScript 编译: 零错误
- Vite 生产构建: 成功
2026-02-09 00:42:34 +08:00
329382db47 fix(pdf): 优化PDF文本提取服务异常处理
- 添加FeignException专门处理逻辑
- 实现详细的Feign异常日志记录功能
- 新增响应体解析和根因链构建方法
- 添加异常消息规范化处理
- 改进错误日志的可读性和调试信息完整度
2026-02-06 18:52:51 +08:00
0f1dd9ec8d Merge remote-tracking branch 'gitea/lsf' into lsf 2026-02-06 18:29:58 +08:00
38add27d84 fix: 修复 Codex 审查发现的两个数据一致性问题
- [P1] 调整删除顺序:先删除数据库记录,成功后再删除派生文件
  避免源文件删除失败时派生文件已被删除导致的数据不一致

- [P2] 完善 logicalPath 空值判断:使用 StringUtils.isBlank() 处理
  null、空字符串和纯空白字符,防止误删其他文件

Fixes review comments from commits f9f4ea3
2026-02-06 18:00:32 +08:00
f9f4ea352e fix: 修复 codex 审查发现的两个问题
- [P1] 当 logicalPath 为 null 时,直接删除当前文件(兼容旧数据)
- [P2] 数据库删除失败时,return 跳过后续清理以避免数据不一致
2026-02-06 17:42:59 +08:00
24d8ee49a1 feat: 优化文件删除逻辑,支持级联删除版本和派生文件
- 删除文件时,如果存在多个版本,一并删除所有版本

- 删除PDF/doc/docx/xls/xlsx时,一并删除其派生的txt文件

- 文件删除失败时记录日志但不影响删除成功
2026-02-06 17:23:37 +08:00
6a4c4ae3d7 feat(auth): 为数据管理和RAG服务增加资源访问控制
- 在DatasetApplicationService中注入ResourceAccessService并添加所有权验证
- 在KnowledgeSetApplicationService中注入ResourceAccessService并添加所有权验证
- 修改DatasetRepository接口和实现类,增加按创建者过滤的方法
- 修改KnowledgeSetRepository接口和实现类,增加按创建者过滤的方法
- 在RAG索引器服务中添加知识库访问权限检查和作用域过滤
- 更新实体元对象处理器以使用请求用户上下文获取当前用户
- 在前端设置页面添加用户权限管理功能和角色权限控制
- 为Python标注服务增加用户上下文和数据集访问权限验证
2026-02-06 14:58:46 +08:00
5507adeb45 fix(knowledge): 优化知识项文件删除逻辑
- 添加内容类型检查,仅处理文件类型的知识项
- 修改源类型判断条件,提前返回非文件上传和手动创建的类型
- 保持原有的文件路径解析和删除操作逻辑
- 维持异常处理和日志记录功能
2026-02-05 21:24:12 +08:00
4143bc75f9 fix: 修复codex review发现的问题
问题1 - 行锁持有时间过长:
- 采用双重检查锁定模式,将HTTP调用移到锁范围外
- 新增 _update_knowledge_set_config 方法专门处理加锁更新

问题2 - 清理不完整:
- _list_knowledge_sets 方法添加分页参数
- 新增 _list_all_knowledge_sets 方法遍历所有知识集
- 清理方法使用新的全量查询方法

问题3 - 文件删除逻辑可能误删:
- deleteKnowledgeItemFile 方法增加严格的 sourceType 检查
- 只有当 sourceType 为 FILE_UPLOAD 或 MANUAL 时才删除文件
- 避免误删 DATASET_FILE 类型的数据集文件

涉及文件:
- knowledge_sync.py
- KnowledgeItemApplicationService.java
2026-02-05 04:07:40 +08:00
99bd83d312 fix: 修复知识库同步的并发控制、数据清理、文件事务和COCO导出问题
问题1 - 并发控制缺失:
- 在 _ensure_knowledge_set 方法中添加数据库行锁(with_for_update)
- 修改 _update_project_config 方法,使用行锁保护配置更新

问题3 - 数据清理机制缺失:
- 添加 _cleanup_knowledge_set_for_project 方法,项目删除时清理知识集
- 添加 _cleanup_knowledge_item_for_file 方法,文件删除时清理知识条目
- 在 delete_mapping 接口中调用清理方法

问题4 - 文件操作事务问题:
- 修改 uploadKnowledgeItems,添加事务失败后的文件清理逻辑
- 修改 deleteKnowledgeItem,删除记录前先删除关联文件
- 新增 deleteKnowledgeItemFile 辅助方法

问题5 - COCO导出格式问题:
- 添加 _get_image_dimensions 方法读取图片实际宽高
- 将百分比坐标转换为像素坐标
- 在 AnnotationExportItem 中添加 file_path 字段

涉及文件:
- knowledge_sync.py
- project.py
- KnowledgeItemApplicationService.java
- export.py
- export schema.py
2026-02-05 03:55:01 +08:00
c03bdf1a24 refactor(data-management): 移除未使用的数据库操作方法并优化查询条件
- 从 DatasetFileMapper 中移除未使用的 update 和 deleteById 方法
- 从 DatasetMapper 中移除未使用的 deleteById 方法
- 在 Python 项目中添加 or_ 操作符导入用于复杂查询
- 为数据集文件查询添加状态过滤条件,排除已归档的文件记录
2026-02-05 03:21:06 +08:00
f15fd044ce fix(data-management): 修复SQL映射中的比较运算符转义问题
- 将XML文件中的 <> 运算符替换为 &lt;&gt; 实体编码
- 确保SQL查询在XML解析器中正确处理比较操作
- 修复了数据集文件状态过滤的查询逻辑
- 保持了原有的业务逻辑不变,仅修正语法问题
2026-02-05 02:07:31 +08:00
d0972cbc9d feat(data-management): 实现数据集文件版本管理和内部路径保护
- 将数据集文件查询方法替换为只查询可见文件的版本
- 引入文件状态管理(ACTIVE/ARCHIVED)和内部目录结构
- 实现文件重复处理策略,支持版本控制模式而非覆盖
- 添加内部数据目录保护,防止访问.datamate等系统目录
- 重构文件上传流程,引入暂存目录和事务后清理机制
- 实现文件版本归档功能,保留历史版本到专用存储位置
- 优化文件路径规范化和安全验证逻辑
- 修复文件删除逻辑,确保归档文件不会被错误移除
- 更新数据集压缩下载功能以排除内部系统文件
2026-02-04 23:53:35 +08:00
394e2bda18 feat(data-management): 添加数据集文件取消上传功能
- 在OpenAPI规范中定义了取消上传的REST端点接口
- 实现了DatasetFileApplicationService中的取消上传业务逻辑
- 在FileService中添加了完整的取消上传服务方法
- 创建了DatasetUploadController控制器处理取消上传请求
- 实现了临时分片文件清理和数据库记录删除功能
2026-02-04 16:25:03 +08:00
f381d641ab fix(upload): 修复流式上传中的文件名处理逻辑
- 修正预上传接口调用时传递正确的文件总数而非固定值-1
- 移除导入配置中文件分割时的文件扩展名保留逻辑
- 删除流式上传选项中的fileExtension参数定义
- 移除流式上传实现中的文件扩展名处理相关代码
- 简化新文件名生成逻辑,不再附加扩展名后缀
2026-02-04 07:47:41 +08:00
699031dae7 fix: 修复编辑数据集时无法清除关联数据集的编译问题
问题分析:
之前尝试使用 @TableField(updateStrategy = FieldStrategy.IGNORED/ALWAYS) 注解
来强制更新 null 值,但 FieldStrategy.ALWAYS 可能不存在于当前
MyBatis-Plus 3.5.14 版本中,导致编译错误。

修复方案:
1. 移除 Dataset.java 中 parentDatasetId 字段的 @TableField(updateStrategy) 注解
2. 移除不需要的 import com.baomidou.mybatisplus.annotation.FieldStrategy
3. 在 DatasetApplicationService.updateDataset 方法中:
   - 添加 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper
   - 保存原始的 parentDatasetId 值用于比较
   - handleParentChange 之后,检查 parentDatasetId 是否发生变化
   - 如果发生变化,使用 LambdaUpdateWrapper 显式地更新 parentDatasetId 字段
   - 这样即使值为 null 也能被正确更新到数据库

原理:
MyBatis-Plus 的 updateById 方法默认只更新非 null 字段。
通过使用 LambdaUpdateWrapper 的 set 方法,可以显式地设置字段值,
包括 null 值,从而确保字段能够被正确更新到数据库。
2026-02-03 11:09:15 +00:00
cc6415c4d9 fix: 修复编辑数据集时无法清除关联数据集的问题
问题描述:
在数据管理的数据集编辑中,如果之前设置了关联数据集,编辑时选择不关联数据集后保存不会生效。

根本原因:
MyBatis-Plus 的 updateById 方法默认使用 FieldStrategy.NOT_NULL 策略,
只有当字段值为非 null 时才会更新到数据库。
当 parentDatasetId 从有值变为 null 时,默认情况下不会更新到数据库。

修复方案:
在 Dataset.java 的 parentDatasetId 字段上添加 @TableField(updateStrategy = FieldStrategy.IGNORED) 注解,
表示即使值为 null 也需要更新到数据库。

配合前端修改(恢复发送空字符串),现在可以正确清除关联数据集:
1. 前端发送空字符串表示"无关联数据集"
2. 后端 handleParentChange 通过 normalizeParentId 将空字符串转为 null
3. dataset.setParentDatasetId(null) 设置为 null
4. 由于添加了 IGNORED 策略,即使为 null 也会更新到数据库
2026-02-03 10:57:08 +00:00
3d036c4cd6 fix: 修复编辑数据集时无法清除关联数据集的问题
问题描述:
在数据管理的数据集编辑中,如果之前设置了关联数据集,编辑时选择不关联数据集后保存不会生效。

问题原因:
后端 updateDataset 方法中的条件判断:
```java
if (updateDatasetRequest.getParentDatasetId() != null) {
    handleParentChange(dataset, updateDatasetRequest.getParentDatasetId());
}
```
当 parentDatasetId 为 null 或空字符串时,条件判断为 false,不会执行 handleParentChange,导致无法清除关联数据集。

修复方案:
去掉条件判断,始终调用 handleParentChange。handleParentChange 内部通过 normalizeParentId 方法将空字符串和 null 都转换为 null,这样既支持设置新的父数据集,也支持清除关联。

配合前端修改(commit 2445235),将空字符串转换为 undefined(被后端反序列化为 null),确保清除关联的操作能够正确执行。
2026-02-03 09:35:09 +00:00
16eb5cacf9 feat(data-management): 添加知识项扩展元数据支持
- 在 KnowledgeItemApplicationService 中实现元数据字段的更新逻辑
- 为 CreateKnowledgeItemRequest 添加 metadata 字段定义
- 为 UpdateKnowledgeItemRequest 添加 metadata 字段定义
- 支持知识项创建和更新时的扩展元数据存储
2026-02-02 22:20:05 +08:00
a0239518fb feat(dataset): 实现数据集文件可见性过滤功能
- 添加派生文件识别逻辑,通过元数据中的derived_from_file_id字段判断
- 实现applyVisibleFileCounts方法为数据集批量设置可见文件数量
- 修改数据集统计接口使用过滤后的可见文件进行统计计算
- 添加normalizeFilePath工具方法统一路径格式处理
- 更新文件查询逻辑支持派生文件过滤功能
- 新增DatasetFileCount DTO用于文件计数统计返回
2026-02-01 22:55:07 +08:00
438acebb89 feat(data-management): 添加Office文档预览功能
- 集成LibreOffice转换器实现DOC/DOCX转PDF功能
- 新增DatasetFilePreviewService处理预览文件管理
- 新增DatasetFilePreviewAsyncService异步转换任务
- 在文件删除时同步清理预览文件
- 前端实现Office文档预览状态轮询机制
- 添加预览API接口支持状态查询和转换触发
- 优化文件预览界面显示转换进度和错误信息
2026-02-01 22:26:05 +08:00
02cd16523f refactor(data-management-service): 移除 docx4j 依赖
- 删除了 docx4j-core 依赖项
- 删除了 docx4j-export-fo 依赖项
- 更新了项目依赖配置
- 简化了构建配置文件
2026-02-01 21:18:50 +08:00
d4a44f3bf5 refactor(data-management): 优化知识项目预览服务的文件转换逻辑
- 移除 docx4j 相关依赖和转换方法
- 统一 office 文件转换为 pdf 的处理方式,全部使用 libreoffice
- 删除单独的 docx 到 pdf 转换方法
- 重命名转换方法为 convertOfficeToPdfByLibreOffice
- 增强路径解析逻辑,添加多种候选路径处理
- 添加路径安全性验证和规范化处理
- 新增 extractRelativePathFromSegment 和 normalizeRelativePathValue 辅助方法
- 改进文件存在性检查和路径构建逻辑
2026-02-01 21:18:14 +08:00
340a0ad364 refactor(data-management): 更新知识项存储路径解析方法
- 将 resolveKnowledgeItemStoragePath 方法替换为 resolveKnowledgeItemStoragePathWithFallback
- 新方法提供备用路径解析逻辑以增强文件定位的可靠性
2026-02-01 21:14:39 +08:00
00c41fbbd3 refactor(knowledge-item): 优化知识项预览文件路径处理逻辑
- 将文件路径验证逻辑从方法开始位置移动到实际使用位置
- 修复了预览文件名获取方式,直接从相对路径解析文件名
- 确保文件存在性检查只在需要时执行
- 提高了代码可读性和执行效率
2026-02-01 21:00:07 +08:00
40889baacc feat(knowledge): 添加知识库条目预览功能
- 集成 docx4j 和 LibreOffice 实现 Office 文档转 PDF 预览
- 新增 KnowledgeItemPreviewService 处理预览转换逻辑
- 添加异步任务 KnowledgeItemPreviewAsyncService 进行文档转换
- 实现预览状态管理包括待转换、转换中、就绪和失败状态
- 在前端界面添加 Office 文档预览状态标签显示
- 支持 DOC/DOCX 文件在线预览功能
- 添加预览元数据存储和管理机制
2026-02-01 20:05:25 +08:00
d135a7f336 feat(knowledge): 添加知识库标签统计功能
- 在 KnowledgeItemApplicationService 中注入 TagMapper 并调用统计方法
- 新增 countKnowledgeSetTags 方法用于计算知识库中的标签总数
- 在 KnowledgeManagementStatisticsResponse 中添加 totalTags 字段
- 在前端 KnowledgeManagementPage 中显示标签总数统计信息
- 更新统计卡片布局从 3 列改为 4 列以适应新增统计项
- 在知识管理模型中添加 totalTags 类型定义
2026-02-01 18:46:31 +08:00
2f3a8b38d0 fix(dataset): 解决数据集文件查询时空目录导致异常的问题
- 添加目录存在性检查,避免文件系统访问异常
- 目录不存在时返回空分页结果而不是抛出异常
- 优化数据集刚创建时的用户体验
2026-01-31 19:10:22 +08:00
c23a9da8cb feat(knowledge): 添加知识库目录管理功能
- 在知识条目表中新增relative_path字段用于存储条目相对路径
- 创建知识条目目录表用于管理知识库中的目录结构
- 实现目录的增删查接口和相应的应用服务逻辑
- 在前端知识库详情页面集成目录显示和操作功能
- 添加目录创建删除等相关的API接口和DTO定义
- 更新数据库初始化脚本包含新的目录表结构
2026-01-31 18:36:40 +08:00