13 小时以前 3d2fd3a3f7d0571721b0f894e07c80553fd1e26c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package com.ruoyi.approve.controller;
 
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.approve.dto.KnowledgeBaseVectorVO;
import com.ruoyi.approve.pojo.KnowledgeBase;
import com.ruoyi.approve.pojo.KnowledgeBaseVector;
import com.ruoyi.approve.service.KnowledgeBaseService;
import com.ruoyi.approve.service.KnowledgeBaseVectorService;
import com.ruoyi.basic.dto.StorageAttachmentDTO;
import com.ruoyi.basic.dto.StorageBlobDTO;
import com.ruoyi.basic.pojo.StorageBlob;
import com.ruoyi.basic.service.StorageAttachmentService;
import com.ruoyi.basic.service.StorageBlobService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
 
import java.util.ArrayList;
import java.util.List;
 
@RestController
@RequestMapping("/knowledgeBase")
@AllArgsConstructor
@Tag(name = "知识库管理")
public class KnowledgeBaseController {
    private KnowledgeBaseService knowledgeBaseService;
    private KnowledgeBaseVectorService knowledgeBaseVectorService;
    private StorageAttachmentService storageAttachmentService;
    private StorageBlobService storageBlobService;
 
    /**
     * 获取列表
     */
    @GetMapping("/getList")
    public AjaxResult getList(@RequestParam(defaultValue = "1") long current,
                              @RequestParam(defaultValue = "10") long size, KnowledgeBase knowledgeBase) {
        Page page = new Page(current, size);
        return AjaxResult.success(knowledgeBaseService.listpage(page, knowledgeBase));
    }
 
    /**
     * 新增知识库
     */
    @PostMapping("/add")
    public AjaxResult add(@RequestBody KnowledgeBase knowledgeBase) {
        return AjaxResult.success(knowledgeBaseService.save(knowledgeBase));
    }
 
    /**
     * 更新知识库
     */
    @PostMapping("/update")
    public AjaxResult update(@RequestBody KnowledgeBase knowledgeBase) {
        return AjaxResult.success(knowledgeBaseService.updateById(knowledgeBase));
    }
 
    /**
     * 删除知识库
     */
    @DeleteMapping("/delete")
    public AjaxResult delete(@RequestBody List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("请传入要删除的ID");
        return AjaxResult.success(knowledgeBaseService.removeByIds(ids));
    }
 
    @Operation(summary = "知识库管理导出")
    @PostMapping("/export")
    public void export(HttpServletResponse response) {
        List<KnowledgeBase> accountExpenses = knowledgeBaseService.list();
        ExcelUtil<KnowledgeBase> util = new ExcelUtil<KnowledgeBase>(KnowledgeBase.class);
        util.exportExcel(response, accountExpenses, "知识库管理导出");
    }
 
    /**
     * 查询知识库文件向量化状态
     */
    @GetMapping("/vector/status/{knowledgeBaseId}")
    @Operation(summary = "查询知识库文件向量化状态")
    public AjaxResult getVectorStatus(@PathVariable Long knowledgeBaseId) {
        List<KnowledgeBaseVectorVO> list = knowledgeBaseVectorService.getVectorStatusByKnowledgeBaseId(knowledgeBaseId);
        return AjaxResult.success(list);
    }
 
    /**
     * 重新向量化文件
     */
    @PostMapping("/vector/reprocess/{vectorId}")
    @Operation(summary = "重新向量化文件")
    public AjaxResult reprocessVector(@PathVariable Long vectorId) {
        knowledgeBaseVectorService.reprocessVector(vectorId);
        return AjaxResult.success("已重新提交向量化任务");
    }
 
    /**
     * 保存知识库文件关联(文件上传后调用)
     * 上传流程:
     * 1. 先调用 /common/upload 上传文件,获取 storageBlobDTOs
     * 2. 再调用此接口关联文件到知识库并触发向量化
     */
    @PostMapping("/file/save")
    @Operation(summary = "保存知识库文件关联")
    public AjaxResult saveKnowledgeBaseFiles(@RequestBody KnowledgeBaseFileDTO dto) {
        if (dto.getKnowledgeBaseId() == null) {
            return AjaxResult.error("知识库ID不能为空");
        }
        if (CollectionUtils.isEmpty(dto.getStorageBlobIds())) {
            return AjaxResult.error("文件ID不能为空");
        }
 
        // 保存附件关联
        StorageAttachmentDTO attachmentDTO = new StorageAttachmentDTO();
        attachmentDTO.setRecordType("knowledge_base");
        attachmentDTO.setRecordId(dto.getKnowledgeBaseId());
        attachmentDTO.setApplication("rag_file");
        List<StorageBlobDTO> blobDTOs = new ArrayList<>();
        for (Long blobId : dto.getStorageBlobIds()) {
            StorageBlobDTO blobDTO = new StorageBlobDTO();
            blobDTO.setId(blobId);
            blobDTOs.add(blobDTO);
        }
        attachmentDTO.setStorageBlobDTOs(blobDTOs);
        storageAttachmentService.saveStorageAttachment(attachmentDTO);
 
        // 创建向量记录并触发向量化
        for (Long blobId : dto.getStorageBlobIds()) {
            StorageBlob blob = storageBlobService.getById(blobId);
            if (blob != null) {
                String fileName = blob.getOriginalFilename();
                String fileType = getFileExtension(fileName);
 
                knowledgeBaseVectorService.createVectorRecord(
                        dto.getKnowledgeBaseId(),
                        blobId,
                        fileName,
                        fileType
                );
            }
        }
 
        return AjaxResult.success();
    }
 
    private String getFileExtension(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return "unknown";
        }
        return fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
    }
 
    /**
     * 删除知识库文件
     */
    @DeleteMapping("/file/delete")
    @Operation(summary = "删除知识库文件")
    public AjaxResult deleteKnowledgeBaseFiles(@RequestBody List<Long> vectorIds) {
        if (CollectionUtils.isEmpty(vectorIds)) {
            return AjaxResult.error("请选择要删除的文件");
        }
        knowledgeBaseVectorService.deleteVectors(vectorIds);
        return AjaxResult.success();
    }
 
    /**
     * 知识库文件DTO
     */
    @lombok.Data
    public static class KnowledgeBaseFileDTO {
        private Long knowledgeBaseId;
        private List<Long> storageBlobIds;
    }
}