diff --git a/schoolNewsServ/admin/src/main/resources/log4j2-spring.xml b/schoolNewsServ/admin/src/main/resources/log4j2-spring.xml index 1870b58..fa73629 100644 --- a/schoolNewsServ/admin/src/main/resources/log4j2-spring.xml +++ b/schoolNewsServ/admin/src/main/resources/log4j2-spring.xml @@ -102,6 +102,9 @@ + + + diff --git a/schoolNewsServ/ai/src/main/java/org/xyzh/ai/mapper/AiKnowledgeMapper.java b/schoolNewsServ/ai/src/main/java/org/xyzh/ai/mapper/AiKnowledgeMapper.java index 9ea1f86..c2a2f2c 100644 --- a/schoolNewsServ/ai/src/main/java/org/xyzh/ai/mapper/AiKnowledgeMapper.java +++ b/schoolNewsServ/ai/src/main/java/org/xyzh/ai/mapper/AiKnowledgeMapper.java @@ -3,6 +3,7 @@ package org.xyzh.ai.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import org.xyzh.common.core.page.PageParam; import org.xyzh.common.dto.ai.TbAiKnowledge; import org.xyzh.common.vo.UserDeptRoleVO; @@ -48,7 +49,7 @@ public interface AiKnowledgeMapper extends BaseMapper { */ List selectKnowledgesPage( @Param("filter") TbAiKnowledge filter, - @Param("pageParam") org.xyzh.common.core.page.PageParam pageParam, + @Param("pageParam") PageParam pageParam, @Param("userDeptRoles") List userDeptRoles ); diff --git a/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/AiKnowledgeRedisService.java b/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/AiKnowledgeRedisService.java index 903ac87..e769a14 100644 --- a/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/AiKnowledgeRedisService.java +++ b/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/AiKnowledgeRedisService.java @@ -1,7 +1,5 @@ package org.xyzh.ai.service; -import java.util.List; - /** * @description AI知识库Redis管理服务接口 * @filename AiKnowledgeRedisService.java @@ -21,5 +19,19 @@ public interface AiKnowledgeRedisService { * 清除所有知识库配置 */ void clearAllKnowledgeConfig(); + + /** + * 添加知识库到部门缓存 + * @param deptId 部门ID + * @param difyDatasetId Dify知识库ID + */ + void addKnowledgeToDeptCache(String deptId, String difyDatasetId); + + /** + * 从部门缓存移除知识库 + * @param deptId 部门ID + * @param difyDatasetId Dify知识库ID + */ + void removeKnowledgeFromDeptCache(String deptId, String difyDatasetId); } diff --git a/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/impl/AiKnowledgeRedisServiceImpl.java b/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/impl/AiKnowledgeRedisServiceImpl.java index 5514f63..53a81c5 100644 --- a/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/impl/AiKnowledgeRedisServiceImpl.java +++ b/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/impl/AiKnowledgeRedisServiceImpl.java @@ -122,13 +122,9 @@ public class AiKnowledgeRedisServiceImpl implements AiKnowledgeRedisService, Com } // 解析部门路径,例如:/1/3/5/ -> [1, 3, 5] - String[] deptIds = deptPath.split("/"); - List deptIdList = new ArrayList<>(); - for (String deptId : deptIds) { - if (deptId != null && !deptId.isEmpty()) { - deptIdList.add(deptId); - } - } + Set deptIdList = new HashSet<>(Arrays.asList(deptPath.split("/"))); + deptIdList.add("root_department"); + if (deptIdList.isEmpty()) { log.warn("解析部门路径失败: {}", deptPath); @@ -146,6 +142,7 @@ public class AiKnowledgeRedisServiceImpl implements AiKnowledgeRedisService, Com } } + List resultList = new ArrayList<>(knowledgeIdSet); log.info("根据部门路径 {} 获取到 {} 个知识库(已去重)", deptPath, resultList.size()); return resultList; @@ -166,5 +163,81 @@ public class AiKnowledgeRedisServiceImpl implements AiKnowledgeRedisService, Com log.error("清除所有知识库配置失败", e); } } + + @Override + @SuppressWarnings("unchecked") + public void addKnowledgeToDeptCache(String deptId, String difyDatasetId) { + try { + if (deptId == null || deptId.isEmpty()) { + log.warn("部门ID为空,无法添加知识库到缓存"); + return; + } + if (difyDatasetId == null || difyDatasetId.isEmpty()) { + log.warn("Dify知识库ID为空,无法添加到缓存"); + return; + } + + String key = REDIS_KEY_DEPT_KNOWLEDGE + deptId; + + // 获取现有的知识库列表 + List knowledgeIds = (List) redisTemplate.opsForValue().get(key); + if (knowledgeIds == null) { + knowledgeIds = new ArrayList<>(); + } + + // 避免重复添加 + if (!knowledgeIds.contains(difyDatasetId)) { + knowledgeIds.add(difyDatasetId); + // 更新到Redis + redisTemplate.opsForValue().set(key, knowledgeIds, REDIS_EXPIRE_DAYS, TimeUnit.DAYS); + log.info("已添加知识库到部门缓存: deptId={}, difyDatasetId={}", deptId, difyDatasetId); + } else { + log.debug("知识库已存在于部门缓存中: deptId={}, difyDatasetId={}", deptId, difyDatasetId); + } + } catch (Exception e) { + log.error("添加知识库到部门缓存失败: deptId={}, difyDatasetId={}", deptId, difyDatasetId, e); + } + } + + @Override + @SuppressWarnings("unchecked") + public void removeKnowledgeFromDeptCache(String deptId, String difyDatasetId) { + try { + if (deptId == null || deptId.isEmpty()) { + log.warn("部门ID为空,无法从缓存移除知识库"); + return; + } + if (difyDatasetId == null || difyDatasetId.isEmpty()) { + log.warn("Dify知识库ID为空,无法从缓存移除"); + return; + } + + String key = REDIS_KEY_DEPT_KNOWLEDGE + deptId; + + // 获取现有的知识库列表 + List knowledgeIds = (List) redisTemplate.opsForValue().get(key); + if (knowledgeIds == null || knowledgeIds.isEmpty()) { + log.debug("部门缓存为空,无需移除: deptId={}", deptId); + return; + } + + // 移除知识库 + if (knowledgeIds.remove(difyDatasetId)) { + // 更新到Redis + if (knowledgeIds.isEmpty()) { + // 如果列表为空,删除整个key + redisTemplate.delete(key); + log.info("部门缓存已空,已删除key: deptId={}", deptId); + } else { + redisTemplate.opsForValue().set(key, knowledgeIds, REDIS_EXPIRE_DAYS, TimeUnit.DAYS); + } + log.info("已从部门缓存移除知识库: deptId={}, difyDatasetId={}", deptId, difyDatasetId); + } else { + log.debug("知识库不存在于部门缓存中: deptId={}, difyDatasetId={}", deptId, difyDatasetId); + } + } catch (Exception e) { + log.error("从部门缓存移除知识库失败: deptId={}, difyDatasetId={}", deptId, difyDatasetId, e); + } + } } diff --git a/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/impl/AiKnowledgeServiceImpl.java b/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/impl/AiKnowledgeServiceImpl.java index 42544cd..99d48e9 100644 --- a/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/impl/AiKnowledgeServiceImpl.java +++ b/schoolNewsServ/ai/src/main/java/org/xyzh/ai/service/impl/AiKnowledgeServiceImpl.java @@ -62,6 +62,9 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService { @Autowired private ResourcePermissionService resourcePermissionService; + @Autowired + private org.xyzh.ai.service.AiKnowledgeRedisService knowledgeRedisService; + @Override @Transactional(rollbackFor = Exception.class) public ResultDomain createKnowledge( @@ -232,12 +235,21 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService { deptIds, roleIds, userDeptRoles.get(0) - ); + ); } catch (Exception e) { log.error("创建知识库权限失败", e); // 权限创建失败不影响知识库创建,记录日志即可 } + // 6. 更新Redis缓存 + try { + knowledgeRedisService.addKnowledgeToDeptCache(deptId, difyDatasetId); + log.info("已添加知识库到Redis缓存: deptId={}, difyDatasetId={}", deptId, difyDatasetId); + } catch (Exception e) { + log.error("更新Redis缓存失败", e); + // 缓存更新失败不影响知识库创建,记录日志即可 + } + log.info("知识库创建成功: {} - {}", knowledge.getID(), knowledge.getTitle()); resultDomain.success("知识库创建成功", knowledge); return resultDomain; @@ -484,6 +496,17 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService { int rows = knowledgeMapper.deleteKnowledge(deleteEntity); if (rows > 0) { + // 6. 更新Redis缓存 + try { + if (StringUtils.hasText(existing.getCreatorDept()) && StringUtils.hasText(existing.getDifyDatasetId())) { + knowledgeRedisService.removeKnowledgeFromDeptCache(existing.getCreatorDept(), existing.getDifyDatasetId()); + log.info("已从Redis缓存移除知识库: deptId={}, difyDatasetId={}", existing.getCreatorDept(), existing.getDifyDatasetId()); + } + } catch (Exception e) { + log.error("更新Redis缓存失败", e); + // 缓存更新失败不影响知识库删除,记录日志即可 + } + log.info("知识库删除成功: {} - {}", knowledgeId, existing.getTitle()); resultDomain.success("知识库删除成功", true); return resultDomain; @@ -564,8 +587,8 @@ public class AiKnowledgeServiceImpl implements AiKnowledgeService { PageParam resultPageParam = new PageParam(pageParam.getPageNumber(), pageParam.getPageSize()); resultPageParam.setTotalElements(total); resultPageParam.setTotalPages((int) Math.ceil((double) total / pageParam.getPageSize())); - - resultDomain.success("查询成功", knowledges); + PageDomain pageDomain = new PageDomain<>(resultPageParam, knowledges); + resultDomain.success("查询成功", pageDomain); return resultDomain; } catch (Exception e) { diff --git a/schoolNewsServ/ai/src/main/resources/mapper/AiKnowledgeMapper.xml b/schoolNewsServ/ai/src/main/resources/mapper/AiKnowledgeMapper.xml index a203c49..659b7a9 100644 --- a/schoolNewsServ/ai/src/main/resources/mapper/AiKnowledgeMapper.xml +++ b/schoolNewsServ/ai/src/main/resources/mapper/AiKnowledgeMapper.xml @@ -35,6 +35,11 @@ + + + + + @@ -106,10 +111,27 @@ @@ -255,10 +277,27 @@ diff --git a/schoolNewsServ/common/common-dto/src/main/java/org/xyzh/common/dto/ai/TbAiKnowledge.java b/schoolNewsServ/common/common-dto/src/main/java/org/xyzh/common/dto/ai/TbAiKnowledge.java index b231bd3..6cb8686 100644 --- a/schoolNewsServ/common/common-dto/src/main/java/org/xyzh/common/dto/ai/TbAiKnowledge.java +++ b/schoolNewsServ/common/common-dto/src/main/java/org/xyzh/common/dto/ai/TbAiKnowledge.java @@ -143,6 +143,28 @@ public class TbAiKnowledge extends BaseDTO { */ private String updater; + // ========== 权限相关字段(不映射到数据库) ========== + + /** + * @description 权限类型(all/dept/role/custom) + */ + private transient String permissionType; + + /** + * @description 是否可读 + */ + private transient Boolean canRead; + + /** + * @description 是否可写 + */ + private transient Boolean canWrite; + + /** + * @description 是否可删除 + */ + private transient Boolean canDelete; + public String getTitle() { return title; } @@ -351,6 +373,38 @@ public class TbAiKnowledge extends BaseDTO { this.retrievalScoreThreshold = retrievalScoreThreshold; } + public String getPermissionType() { + return permissionType; + } + + public void setPermissionType(String permissionType) { + this.permissionType = permissionType; + } + + public Boolean getCanRead() { + return canRead; + } + + public void setCanRead(Boolean canRead) { + this.canRead = canRead; + } + + public Boolean getCanWrite() { + return canWrite; + } + + public void setCanWrite(Boolean canWrite) { + this.canWrite = canWrite; + } + + public Boolean getCanDelete() { + return canDelete; + } + + public void setCanDelete(Boolean canDelete) { + this.canDelete = canDelete; + } + @Override public String toString() { return "TbAiKnowledge{" + diff --git a/schoolNewsServ/system/src/main/resources/mapper/DeptRoleMapper.xml b/schoolNewsServ/system/src/main/resources/mapper/DeptRoleMapper.xml index 7f666b0..ad739a6 100644 --- a/schoolNewsServ/system/src/main/resources/mapper/DeptRoleMapper.xml +++ b/schoolNewsServ/system/src/main/resources/mapper/DeptRoleMapper.xml @@ -74,7 +74,8 @@ d.description AS dept_description, dr.role_id, r.name AS role_name, - r.description AS role_description + r.description AS role_description, + d.parent_id FROM tb_sys_dept_role dr LEFT JOIN tb_sys_dept d ON dr.dept_id = d.dept_id AND d.deleted = 0 LEFT JOIN tb_sys_role r ON dr.role_id = r.role_id AND r.deleted = 0 diff --git a/schoolNewsWeb/index.html b/schoolNewsWeb/index.html index 1691f44..086b7da 100644 --- a/schoolNewsWeb/index.html +++ b/schoolNewsWeb/index.html @@ -6,6 +6,11 @@ 校园新闻管理系统 +