package com.gxwebsoft.ai.service.impl; import com.aliyun.bailian20231229.Client; import com.aliyun.bailian20231229.models.AddFileResponse; import com.gxwebsoft.ai.config.KnowledgeBaseConfig; import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory; import com.gxwebsoft.ai.util.AiCloudDataCenterUtil; import com.gxwebsoft.ai.util.AiCloudKnowledgeBaseUtil; import com.gxwebsoft.common.system.controller.FileController; import com.gxwebsoft.common.system.entity.FileRecord; import com.gxwebsoft.common.system.entity.User; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gxwebsoft.ai.mapper.AiCloudFileMapper; import com.gxwebsoft.ai.service.AiCloudFileService; import com.gxwebsoft.ai.entity.AiCloudFile; import com.gxwebsoft.ai.entity.AiCloudDoc; import com.gxwebsoft.ai.service.AiCloudDocService; import com.gxwebsoft.ai.service.KnowledgeBaseService; import com.gxwebsoft.ai.param.AiCloudFileParam; import com.gxwebsoft.common.core.web.PageParam; import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.oa.entity.OaCompany; import com.gxwebsoft.oa.service.OaCompanyService; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.concurrent.CompletableFuture; /** * AI云文件表Service实现 * * @author yc */ @Slf4j @Service public class AiCloudFileServiceImpl extends ServiceImpl implements AiCloudFileService { @Resource private KnowledgeBaseConfig config; @Resource private KnowledgeBaseClientFactory clientFactory; @Resource private AiCloudDocService aiCloudDocService; @Resource private OaCompanyService oaCompanyService; @Resource private KnowledgeBaseService knowledgeBaseService; @Resource private FileController fileController; @Override public PageResult pageRel(AiCloudFileParam param) { PageParam page = new PageParam<>(param); page.setDefaultOrder("sort_number asc, upload_time desc"); List list = baseMapper.selectPageRel(page, param); return new PageResult<>(list, page.getTotal()); } @Override public List listRel(AiCloudFileParam param) { List list = baseMapper.selectListRel(param); //文件名排序 list.sort(Comparator.comparing(AiCloudFile::getFileName)); // 排序 PageParam page = new PageParam<>(); page.setDefaultOrder("sort_number asc, upload_time desc"); return page.sortRecords(list); } @Override public AiCloudFile getByIdRel(Integer id) { AiCloudFileParam param = new AiCloudFileParam(); param.setId(id); return param.getOne(baseMapper.selectListRel(param)); } @Async @Override public CompletableFuture processFileAsync(String categoryId, Integer docId, MultipartFile file, User loginUser) { return CompletableFuture.supplyAsync(() -> { try { String workspaceId = config.getWorkspaceId(); Client client = clientFactory.createClient(); AddFileResponse addFileResponse = AiCloudDataCenterUtil.uploadFile(client, workspaceId, categoryId, file); String fileId = addFileResponse.getBody().getData().getFileId(); FileRecord fileRecord = fileController.upload(file, loginUser.getTenantId()); // 保存文件信息到数据库 AiCloudFile aiCloudFile = new AiCloudFile(); aiCloudFile.setDocId(docId); aiCloudFile.setFileName(file.getOriginalFilename()); aiCloudFile.setFileSize(file.getSize()); aiCloudFile.setFileType(getFileExtension(file.getOriginalFilename())); aiCloudFile.setFileExt(getFileExtension(file.getOriginalFilename())); aiCloudFile.setFileId(fileId); aiCloudFile.setFileUrl(fileRecord.getDownloadUrl()); aiCloudFile.setUploadTime(LocalDateTime.now()); aiCloudFile.setWorkspaceId(workspaceId); if (loginUser != null) { aiCloudFile.setUserId(loginUser.getUserId()); aiCloudFile.setTenantId(loginUser.getTenantId()); } this.save(aiCloudFile); log.info("文件上传成功: {}", file.getOriginalFilename()); return fileId; } catch (Exception e) { log.error("异步处理文件上传失败: {}", e.getMessage(), e); throw new RuntimeException("文件上传失败: " + file.getOriginalFilename(), e); } }); } @Override public boolean removeFileWithCloud(Integer id) { AiCloudFile aiCloudFile = this.getById(id); if (aiCloudFile == null) { return false; } try { String workspaceId = config.getWorkspaceId(); Client client = clientFactory.createClient(); AiCloudDataCenterUtil.deleteFile(client, workspaceId, aiCloudFile.getFileId()); } catch (Exception e) { log.error("删除云文件失败: {}", e.getMessage(), e); return false; } return this.removeById(id); } @Override public boolean removeFilesWithCloud(List ids) { boolean allSuccess = true; for (Integer id : ids) { if (!removeFileWithCloud(id)) { allSuccess = false; } } return allSuccess; } @Override public String getFileExtension(String filename) { if (filename == null || filename.lastIndexOf(".") == -1) { return ""; } return filename.substring(filename.lastIndexOf(".") + 1); } @Override public String getCompanyKbId(Integer docId) { if (docId == null) { return ""; } AiCloudDoc aiCloudDoc = aiCloudDocService.getById(docId); if (aiCloudDoc == null || aiCloudDoc.getCompanyId() == null) { return ""; } OaCompany oaCompany = oaCompanyService.getById(aiCloudDoc.getCompanyId()); return oaCompany != null && oaCompany.getKbId() != null ? oaCompany.getKbId() : ""; } @Override public void submitDocuments(Integer docId, List fileIds) { if (docId == null || fileIds == null || fileIds.isEmpty()) { return; } String kbId = getCompanyKbId(docId); if (kbId == null || kbId.isEmpty()) { return; } // 异步添加文件 for(String fileId : fileIds) { if (fileId != null && !fileId.isEmpty()) { knowledgeBaseService.submitDocuments(kbId, fileId); } } } @Override public boolean removeFileWithCloudAndIndex(Integer id) { AiCloudFile aiCloudFile = this.getById(id); if (aiCloudFile == null) { return false; } // 删除云文件 if (!removeFileWithCloud(id)) { return false; } // 同时删除默认知识库文件 String kbId = getCompanyKbId(aiCloudFile.getDocId()); if (!kbId.isEmpty()) { try { String workspaceId = config.getWorkspaceId(); Client client = clientFactory.createClient(); AiCloudKnowledgeBaseUtil.deleteIndexDocument(client, workspaceId, kbId, Arrays.asList(aiCloudFile.getFileId())); } catch (Exception e) { log.error("删除知识库索引失败: {}", e.getMessage(), e); // 这里可以根据业务需求决定是否抛出异常 } } return true; } @Override public boolean removeFilesWithCloudAndIndex(List ids) { boolean allSuccess = true; for (Integer id : ids) { if (!removeFileWithCloudAndIndex(id)) { allSuccess = false; } } return allSuccess; } }