From b21afc26b596a5a7cb77b36cd96f6e0df91637eb Mon Sep 17 00:00:00 2001
From: yuan <123@>
Date: 星期三, 26 八月 2026 14:21:41 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_天津_建诚恒商贸' into dev_天津_建诚恒商贸
---
src/views/collaborativeApproval/knowledgeBase/index.vue | 251 ++++++++++++++++++++++++++++++++------------------
1 files changed, 161 insertions(+), 90 deletions(-)
diff --git a/src/views/collaborativeApproval/knowledgeBase/index.vue b/src/views/collaborativeApproval/knowledgeBase/index.vue
index 907e51f..71d7a4e 100644
--- a/src/views/collaborativeApproval/knowledgeBase/index.vue
+++ b/src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -127,11 +127,11 @@
</el-select>
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="浣跨敤娆℃暟" prop="usageCount">
- <el-input-number v-model="form.usageCount" :min="0" style="width: 100%" />
- </el-form-item>
- </el-col>
+<!-- <el-col :span="12">-->
+<!-- <el-form-item label="浣跨敤娆℃暟" prop="usageCount">-->
+<!-- <el-input-number v-model="form.usageCount" :min="0" style="width: 100%" />-->
+<!-- </el-form-item>-->
+<!-- </el-col>-->
</el-row>
</el-form>
</FormDialog>
@@ -163,14 +163,14 @@
{{ getEfficiencyLabel(currentKnowledge.efficiency) }}
</el-tag>
</el-descriptions-item>
- <el-descriptions-item label="浣跨敤娆℃暟">
- <el-tag type="info">{{ currentKnowledge.usageCount }} 娆�</el-tag>
- </el-descriptions-item>
+<!-- <el-descriptions-item label="浣跨敤娆℃暟">-->
+<!-- <el-tag type="info">{{ currentKnowledge.usageCount }} 娆�</el-tag>-->
+<!-- </el-descriptions-item>-->
<el-descriptions-item label="鍒涘缓浜�">
{{ currentKnowledge.creator }}
</el-descriptions-item>
<el-descriptions-item label="鍒涘缓鏃堕棿">
- {{ currentKnowledge.createTime }}
+ {{dayjs(currentKnowledge.createTime).format("YYYY-MM-DD")}}
</el-descriptions-item>
</el-descriptions>
@@ -202,19 +202,19 @@
<h4>浣跨敤缁熻</h4>
<div class="usage-stats">
<el-row :gutter="20">
- <el-col :span="8">
- <div class="stat-item">
- <div class="stat-number">{{ currentKnowledge.usageCount }}</div>
- <div class="stat-label">浣跨敤娆℃暟</div>
- </div>
- </el-col>
- <el-col :span="8">
+<!-- <el-col :span="8">-->
+<!-- <div class="stat-item">-->
+<!-- <div class="stat-number">{{ currentKnowledge.usageCount }}</div>-->
+<!-- <div class="stat-label">浣跨敤娆℃暟</div>-->
+<!-- </div>-->
+<!-- </el-col>-->
+ <el-col :span="12">
<div class="stat-item">
<div class="stat-number">{{ getEfficiencyScore(currentKnowledge.efficiency) }}%</div>
<div class="stat-label">鏁堢巼鎻愬崌</div>
</div>
</el-col>
- <el-col :span="8">
+ <el-col :span="12">
<div class="stat-item">
<div class="stat-number">{{ getTimeSaved(currentKnowledge.efficiency) }}</div>
<div class="stat-label">骞冲潎鑺傜渷鏃堕棿</div>
@@ -244,6 +244,7 @@
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
:before-upload="beforeUpload"
+ name="files"
multiple
:show-file-list="false"
accept=".txt,.md,.docx,.xlsx,.xls,.pdf"
@@ -281,21 +282,21 @@
<el-table :data="fileList" style="margin-top: 20px" border>
<el-table-column prop="fileName" label="鏂囦欢鍚�" show-overflow-tooltip />
<el-table-column prop="fileType" label="鏂囦欢绫诲瀷" width="100" />
- <el-table-column label="鍚戦噺鍖栫姸鎬�" width="120">
- <template #default="{ row }">
- <el-tag :type="getStatusType(row.vectorStatus)">
- {{ getStatusText(row.vectorStatus) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="chunkCount" label="鍒囩墖鏁�" width="100" align="center" />
+<!-- <el-table-column label="鍚戦噺鍖栫姸鎬�" width="120">-->
+<!-- <template #default="{ row }">-->
+<!-- <el-tag :type="getStatusType(row.vectorStatus)">-->
+<!-- {{ getStatusText(row.vectorStatus) }}-->
+<!-- </el-tag>-->
+<!-- </template>-->
+<!-- </el-table-column>-->
+<!-- <el-table-column prop="chunkCount" label="鍒囩墖鏁�" width="100" align="center" />-->
<el-table-column label="閿欒淇℃伅" width="200" show-overflow-tooltip>
<template #default="{ row }">
<span v-if="row.vectorError" style="color: #f56c6c">{{ row.vectorError }}</span>
<span v-else style="color: #909399">-</span>
</template>
</el-table-column>
- <el-table-column prop="createTime" label="涓婁紶鏃堕棿" width="180" />
+ <el-table-column prop="createTime" label="涓婁紶鏃堕棿" width="120" :formatter="formatDate" />
<el-table-column label="鎿嶄綔" width="150" align="center">
<template #default="{ row }">
<el-button
@@ -379,12 +380,17 @@
getVectorStatus,
reprocessVector,
saveKnowledgeBaseFiles,
- deleteKnowledgeBaseFiles,
+ deleteKnowledgeBaseFile,
knowledgeChat
} from "@/api/collaborativeApproval/knowledgeBase.js";
import useUserStore from '@/store/modules/user';
import { userListNoPageByTenantId } from '@/api/system/user.js';
import { getToken } from "@/utils/auth";
+import dayjs from "dayjs";
+import { parseDate } from "@/utils/ruoyi";
+
+// 鏃ユ湡鍥炴樉鏍煎紡鍖栵紙YYYY-MM-DD锛�
+const formatDate = (row, column, cellValue) => parseDate(cellValue) || '-';
// 琛ㄥ崟楠岃瘉瑙勫垯
const rules = {
@@ -527,24 +533,24 @@
return typeMap[params] || "info";
}
},
- {
- label: "鏂囦欢鏁伴噺",
- prop: "fileCount",
- width: 100,
- align: "center"
- },
- {
- label: "鍒囩墖鏁伴噺",
- prop: "totalChunkCount",
- width: 100,
- align: "center"
- },
- {
- label: "浣跨敤娆℃暟",
- prop: "usageCount",
- width: 100,
- align: "center"
- },
+ // {
+ // label: "鏂囦欢鏁伴噺",
+ // prop: "fileCount",
+ // width: 100,
+ // align: "center"
+ // },
+ // {
+ // label: "鍒囩墖鏁伴噺",
+ // prop: "totalChunkCount",
+ // width: 100,
+ // align: "center"
+ // },
+ // {
+ // label: "浣跨敤娆℃暟",
+ // prop: "usageCount",
+ // width: 100,
+ // align: "center"
+ // },
{
label: "鍒涘缓浜�",
prop: "creator",
@@ -554,6 +560,7 @@
label: "鍒涘缓鏃堕棿",
prop: "createTime",
width: 180,
+ dataType:"date"
},
{
dataType: "action",
@@ -576,13 +583,13 @@
openFilesDialog(row);
}
},
- {
- name: "闂瓟",
- type: "text",
- clickFun: (row) => {
- openChatDialog(row);
- }
- },
+ // {
+ // name: "闂瓟",
+ // type: "text",
+ // clickFun: (row) => {
+ // openChatDialog(row);
+ // }
+ // },
{
name: "璇︽儏",
type: "text",
@@ -624,21 +631,31 @@
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);
+ });
};
// 鍒嗛〉澶勭悊
@@ -813,27 +830,47 @@
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);
@@ -847,19 +884,22 @@
return;
}
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄�,鏄惁纭鍒犻櫎?", "鍒犻櫎", {
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
type: "warning",
}).then(() => {
- // console.log(selectedIds.value);
+ // 鉁� DELETE璇锋眰浣跨敤data浼犻�扞D鏁扮粍
delKnowledgeBase(selectedIds.value).then(res => {
if(res.code == 200){
ElMessage.success("鍒犻櫎鎴愬姛");
selectedIds.value = [];
getList();
}
- })
+ }).catch(err => {
+ console.error("鍒犻櫎鐭ヨ瘑搴撳け璐�:", err);
+ ElMessage.error(err.msg || "鍒犻櫎澶辫触");
+ });
}).catch(() => {
// 鐢ㄦ埛鍙栨秷
});
@@ -963,9 +1003,24 @@
// 涓婁紶鎴愬姛
const handleUploadSuccess = (response, file) => {
+ console.log("涓婁紶鍝嶅簲:", response); // 璋冭瘯鏃ュ織
+
if (response.code === 200) {
- uploadedBlobIds.value.push(response.data.id);
- ElMessage.success(`鏂囦欢 ${file.name} 涓婁紶鎴愬姛`);
+ // 鉁� 鍚庣杩斿洖鐨勬槸 List<StorageBlobVO>,鎵�浠ata鏄暟缁�
+ 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 || "涓婁紶澶辫触");
}
@@ -978,22 +1033,30 @@
// 淇濆瓨鏂囦欢鍏宠仈
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, // 鐭ヨ瘑搴揑D
+ storageBlobIds: uploadedBlobIds.value // 鏂囦欢blob ID鏁扮粍
});
- ElMessage.success("鏂囦欢鍏宠仈淇濆瓨鎴愬姛锛屾鍦ㄥ悗鍙板鐞嗗悜閲忓寲");
+ ElMessage.success("鏂囦欢鍏宠仈淇濆瓨鎴愬姛,姝e湪鍚庡彴澶勭悊鍚戦噺鍖�");
uploadedBlobIds.value = [];
- // 寤惰繜鍒锋柊鏂囦欢鍒楄〃锛岀粰鍚庡彴澶勭悊鏃堕棿
+ // 寤惰繜鍒锋柊鏂囦欢鍒楄〃,缁欏悗鍙板鐞嗘椂闂�
setTimeout(() => {
loadFileList();
}, 1000);
@@ -1030,7 +1093,7 @@
const deleteFile = async (row) => {
try {
await ElMessageBox.confirm(
- "纭畾瑕佸垹闄よ鏂囦欢鍚楋紵鍒犻櫎鍚庡皢鏃犳硶鎭㈠鍚戦噺鏁版嵁",
+ "纭畾瑕佸垹闄よ鏂囦欢鍚�?鍒犻櫎鍚庡皢鏃犳硶鎭㈠鍚戦噺鏁版嵁",
"鍒犻櫎纭",
{
confirmButtonText: "纭畾",
@@ -1039,7 +1102,8 @@
}
);
- await deleteKnowledgeBaseFiles([row.id]);
+ // 鉁� DELETE璇锋眰浣跨敤data浼犻�扞D鏁扮粍
+ await deleteKnowledgeBaseFile([row.id]); // 娉ㄦ剰: row.id鏄悜閲忚褰旾D,涓嶆槸storageBlobId
ElMessage.success("鍒犻櫎鎴愬姛");
loadFileList();
} catch (error) {
@@ -1084,17 +1148,31 @@
// ============ 鐭ヨ瘑搴撻棶绛旂浉鍏� ============
+// 鐢熸垚UUID鐨刦allback鏂规
+const generateUUID = () => {
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
+ return crypto.randomUUID();
+ }
+ // fallback: 鍏煎涓嶆敮鎸� crypto.randomUUID 鐨勭幆澧�
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ const r = Math.random() * 16 | 0;
+ const v = c === 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+};
+
// 鎵撳紑闂瓟寮圭獥
const openChatDialog = (row) => {
currentKnowledgeBase.value = row;
chatDialogVisible.value = true;
- memoryId.value = crypto.randomUUID();
+ memoryId.value = generateUUID();
messages.value = [];
inputQuestion.value = "";
};
// 鍙戦�佹秷鎭�
const sendMessage = async () => {
+ // 鍙傛暟鏍¢獙
if (!inputQuestion.value.trim()) {
ElMessage.warning("璇疯緭鍏ラ棶棰�");
return;
@@ -1121,18 +1199,11 @@
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, // 鐭ヨ瘑搴揑D
+ memoryId: memoryId.value, // 浼氳瘽ID
+ question: question // 鐢ㄦ埛闂
});
if (!response.ok) {
@@ -1140,7 +1211,7 @@
throw new Error(errorText || '璇锋眰澶辫触');
}
- // 澶勭悊SSE娴佸紡鍝嶅簲
+ // 鉁� 鍚庣杩斿洖 text/stream;charset=utf-8
const reader = response.body.getReader();
const decoder = new TextDecoder();
let aiContent = '';
@@ -1151,7 +1222,7 @@
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;
@@ -1188,7 +1259,7 @@
}
).then(() => {
messages.value = [];
- memoryId.value = crypto.randomUUID(); // 閲嶆柊鐢熸垚浼氳瘽ID
+ memoryId.value = generateUUID(); // 閲嶆柊鐢熸垚浼氳瘽ID
ElMessage.success("瀵硅瘽宸叉竻绌�");
}).catch(() => {
// 鐢ㄦ埛鍙栨秷
--
Gitblit v1.9.3