| | |
| | | :on-success="handleUploadSuccess" |
| | | :on-error="handleUploadError" |
| | | :before-upload="beforeUpload" |
| | | name="files" |
| | | multiple |
| | | :show-file-list="false" |
| | | accept=".txt,.md,.docx,.xlsx,.xls,.pdf" |
| | |
| | | getVectorStatus, |
| | | reprocessVector, |
| | | saveKnowledgeBaseFiles, |
| | | deleteKnowledgeBaseFiles, |
| | | deleteKnowledgeBaseFile, |
| | | knowledgeChat |
| | | } from "@/api/collaborativeApproval/knowledgeBase.js"; |
| | | import useUserStore from '@/store/modules/user'; |
| | |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listKnowledgeBase({...page.value, ...searchForm.value}) |
| | | |
| | | // ✅ GET请求使用params传参 |
| | | listKnowledgeBase({ |
| | | current: page.value.current, |
| | | size: page.value.size, |
| | | title: searchForm.value.title, |
| | | type: searchForm.value.type |
| | | }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | page.value.total = res.data.total; |
| | | // 如果当前页数超过总页数,重置到第1页并重新查询 |
| | | |
| | | // 如果当前页数超过总页数,重置到第1页并重新查询 |
| | | const maxPage = Math.ceil(res.data.total / page.value.size) || 1; |
| | | if (page.value.current > maxPage && maxPage > 0) { |
| | | page.value.current = 1; |
| | | // 重新查询第1页数据 |
| | | return getList(); |
| | | } |
| | | |
| | | tableData.value = res.data.records; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | console.error("查询知识库列表失败:", err); |
| | | }); |
| | | }; |
| | | |
| | | // 分页处理 |
| | |
| | | const submitForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | // ✅ POST请求使用data传参,明确参数结构 |
| | | const formData = { |
| | | title: form.value.title, |
| | | type: form.value.type, |
| | | scenario: form.value.scenario || "", |
| | | efficiency: form.value.efficiency || "", |
| | | problem: form.value.problem, |
| | | solution: form.value.solution, |
| | | keyPoints: form.value.keyPoints || "", |
| | | creator: form.value.creator || "", |
| | | usageCount: form.value.usageCount || 0 |
| | | }; |
| | | |
| | | if (dialogType.value === "add") { |
| | | // 新增知识 |
| | | addKnowledgeBase({...form.value}).then(res => { |
| | | addKnowledgeBase(formData).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("添加成功"); |
| | | closeKnowledgeDialog(); |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | console.error("添加知识库失败:", err); |
| | | ElMessage.error(err.msg || "添加失败"); |
| | | }); |
| | | } else { |
| | | updateKnowledgeBase({...form.value}).then(res => { |
| | | // 更新知识 - 添加id参数 |
| | | updateKnowledgeBase({ |
| | | id: form.value.id, |
| | | ...formData |
| | | }).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("更新成功"); |
| | | closeKnowledgeDialog(); |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | console.error("更新知识库失败:", err); |
| | | ElMessage.error(err.msg || "更新失败"); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("表单验证失败:", error); |
| | |
| | | return; |
| | | } |
| | | |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", { |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | // console.log(selectedIds.value); |
| | | // ✅ DELETE请求使用data传递ID数组 |
| | | delKnowledgeBase(selectedIds.value).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("删除成功"); |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }) |
| | | }).catch(err => { |
| | | console.error("删除知识库失败:", err); |
| | | ElMessage.error(err.msg || "删除失败"); |
| | | }); |
| | | }).catch(() => { |
| | | // 用户取消 |
| | | }); |
| | |
| | | |
| | | // 上传成功 |
| | | const handleUploadSuccess = (response, file) => { |
| | | console.log("上传响应:", response); // 调试日志 |
| | | |
| | | if (response.code === 200) { |
| | | uploadedBlobIds.value.push(response.data.id); |
| | | ElMessage.success(`文件 ${file.name} 上传成功`); |
| | | // ✅ 后端返回的是 List<StorageBlobVO>,所以data是数组 |
| | | if (Array.isArray(response.data) && response.data.length > 0) { |
| | | // 取数组第一个元素的id |
| | | const blobId = response.data[0].id; |
| | | if (blobId) { |
| | | uploadedBlobIds.value.push(blobId); |
| | | ElMessage.success(`文件 ${file.name} 上传成功`); |
| | | } else { |
| | | console.error("上传响应中未找到id:", response.data[0]); |
| | | ElMessage.error("上传失败: 未获取到文件ID"); |
| | | } |
| | | } else { |
| | | console.error("上传响应格式错误:", response); |
| | | ElMessage.error("上传失败: 响应格式错误"); |
| | | } |
| | | } else { |
| | | ElMessage.error(response.msg || "上传失败"); |
| | | } |
| | |
| | | |
| | | // 保存文件关联 |
| | | const saveFiles = async () => { |
| | | // 参数校验 |
| | | if (!currentKnowledgeBase.value?.id) { |
| | | ElMessage.error("知识库信息异常"); |
| | | return; |
| | | } |
| | | |
| | | if (uploadedBlobIds.value.length === 0) { |
| | | ElMessage.warning("请先上传文件"); |
| | | return; |
| | | } |
| | | |
| | | savingFiles.value = true; |
| | | |
| | | try { |
| | | // ✅ POST请求使用data传参,明确参数结构 |
| | | await saveKnowledgeBaseFiles({ |
| | | knowledgeBaseId: currentKnowledgeBase.value.id, |
| | | storageBlobIds: uploadedBlobIds.value |
| | | knowledgeBaseId: currentKnowledgeBase.value.id, // 知识库ID |
| | | storageBlobIds: uploadedBlobIds.value // 文件blob ID数组 |
| | | }); |
| | | |
| | | ElMessage.success("文件关联保存成功,正在后台处理向量化"); |
| | | ElMessage.success("文件关联保存成功,正在后台处理向量化"); |
| | | uploadedBlobIds.value = []; |
| | | |
| | | // 延迟刷新文件列表,给后台处理时间 |
| | | // 延迟刷新文件列表,给后台处理时间 |
| | | setTimeout(() => { |
| | | loadFileList(); |
| | | }, 1000); |
| | |
| | | const deleteFile = async (row) => { |
| | | try { |
| | | await ElMessageBox.confirm( |
| | | "确定要删除该文件吗?删除后将无法恢复向量数据", |
| | | "确定要删除该文件吗?删除后将无法恢复向量数据", |
| | | "删除确认", |
| | | { |
| | | confirmButtonText: "确定", |
| | |
| | | } |
| | | ); |
| | | |
| | | await deleteKnowledgeBaseFiles([row.id]); |
| | | // ✅ DELETE请求使用data传递ID数组 |
| | | await deleteKnowledgeBaseFile([row.id]); // 注意: row.id是向量记录ID,不是storageBlobId |
| | | ElMessage.success("删除成功"); |
| | | loadFileList(); |
| | | } catch (error) { |
| | |
| | | |
| | | // 发送消息 |
| | | const sendMessage = async () => { |
| | | // 参数校验 |
| | | if (!inputQuestion.value.trim()) { |
| | | ElMessage.warning("请输入问题"); |
| | | return; |
| | |
| | | scrollToBottom(); |
| | | |
| | | try { |
| | | // 流式请求 |
| | | const response = await fetch('/api/ai/knowledge/chat', { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Content-Type': 'application/json', |
| | | 'Authorization': 'Bearer ' + getToken() |
| | | }, |
| | | body: JSON.stringify({ |
| | | knowledgeBaseId: currentKnowledgeBase.value.id, |
| | | memoryId: memoryId.value, |
| | | question: question |
| | | }) |
| | | // ✅ 流式请求使用Fetch API |
| | | const response = await knowledgeChat({ |
| | | knowledgeBaseId: currentKnowledgeBase.value.id, // 知识库ID |
| | | memoryId: memoryId.value, // 会话ID |
| | | question: question // 用户问题 |
| | | }); |
| | | |
| | | if (!response.ok) { |
| | |
| | | throw new Error(errorText || '请求失败'); |
| | | } |
| | | |
| | | // 处理SSE流式响应 |
| | | // ✅ 后端返回 text/stream;charset=utf-8 |
| | | const reader = response.body.getReader(); |
| | | const decoder = new TextDecoder(); |
| | | let aiContent = ''; |
| | |
| | | const { done, value } = await reader.read(); |
| | | if (done) break; |
| | | |
| | | const text = decoder.decode(value); |
| | | const text = decoder.decode(value, { stream: true }); // ✅ 添加stream选项 |
| | | aiContent += text; |
| | | messages.value[messages.value.length - 1].content = aiContent; |
| | | |