作者 dong

修复bug

@@ -33,12 +33,12 @@ @@ -33,12 +33,12 @@
33 <a-col :xxl="4" :xl="6" :lg="6" :md="6" :sm="12" :xs="24"> 33 <a-col :xxl="4" :xl="6" :lg="6" :md="6" :sm="12" :xs="24">
34 <a-card class="add-knowledge-card" @click="handleAddKnowled"> 34 <a-card class="add-knowledge-card" @click="handleAddKnowled">
35 <div class="flex"> 35 <div class="flex">
36 - <Icon icon="ant-design:plus-outlined" class="add-knowledge-card-icon" size="20"></Icon> 36 + <Icon icon="ant-design:plus-outlined" class="add-knowledge-card-icon" size="20" />
37 <span class="add-knowledge-card-title">创建知识库</span> 37 <span class="add-knowledge-card-title">创建知识库</span>
38 </div> 38 </div>
39 </a-card> 39 </a-card>
40 </a-col> 40 </a-col>
41 - <a-col v-if="knowledgeList && knowledgeList.length>0" :xxl="4" :xl="6" :lg="6" :md="6" :sm="12" :xs="24" v-for="item in knowledgeList"> 41 + <a-col v-if="knowledgeList && knowledgeList.length > 0" :xxl="4" :xl="6" :lg="6" :md="6" :sm="12" :xs="24" v-for="item in knowledgeList">
42 <a-card class="knowledge-card pointer" @click="handleDocClick(item.id)"> 42 <a-card class="knowledge-card pointer" @click="handleDocClick(item.id)">
43 <div class="knowledge-header"> 43 <div class="knowledge-header">
44 <div class="flex"> 44 <div class="flex">
@@ -53,26 +53,26 @@ @@ -53,26 +53,26 @@
53 <span>{{ item.descr || '暂无描述' }}</span> 53 <span>{{ item.descr || '暂无描述' }}</span>
54 </div> 54 </div>
55 <div class="knowledge-footer"> 55 <div class="knowledge-footer">
56 - <Icon class="knowledge-footer-icon" icon="ant-design:deployment-unit-outlined" size="14"></Icon> 56 + <Icon class="knowledge-footer-icon" icon="ant-design:deployment-unit-outlined" size="14" />
57 <span>{{ item.embedId_dictText }}</span> 57 <span>{{ item.embedId_dictText }}</span>
58 </div> 58 </div>
59 <div class="knowledge-btn"> 59 <div class="knowledge-btn">
60 <a-dropdown placement="bottomRight" :trigger="['click']" :getPopupContainer="(node) => node.parentNode"> 60 <a-dropdown placement="bottomRight" :trigger="['click']" :getPopupContainer="(node) => node.parentNode">
61 <div class="ant-dropdown-link pointer model-icon" @click.prevent.stop> 61 <div class="ant-dropdown-link pointer model-icon" @click.prevent.stop>
62 - <Icon icon="ant-design:ellipsis-outlined" size="16"></Icon> 62 + <Icon icon="ant-design:ellipsis-outlined" size="16" />
63 </div> 63 </div>
64 <template #overlay> 64 <template #overlay>
65 <a-menu> 65 <a-menu>
66 <a-menu-item key="vectorization" @click.prevent.stop="handleVectorization(item.id)"> 66 <a-menu-item key="vectorization" @click.prevent.stop="handleVectorization(item.id)">
67 - <Icon icon="ant-design:retweet-outlined" size="16"></Icon> 67 + <Icon icon="ant-design:retweet-outlined" size="16" />
68 向量化 68 向量化
69 </a-menu-item> 69 </a-menu-item>
70 <a-menu-item key="text" @click.prevent.stop="handleEditClick(item)"> 70 <a-menu-item key="text" @click.prevent.stop="handleEditClick(item)">
71 - <Icon class="pointer" icon="ant-design:edit-outlined" size="16"></Icon> 71 + <Icon class="pointer" icon="ant-design:edit-outlined" size="16" />
72 编辑 72 编辑
73 </a-menu-item> 73 </a-menu-item>
74 <a-menu-item key="file" @click.prevent.stop="handleDelete(item)"> 74 <a-menu-item key="file" @click.prevent.stop="handleDelete(item)">
75 - <Icon class="pointer" icon="ant-design:delete-outlined" size="16"></Icon> 75 + <Icon class="pointer" icon="ant-design:delete-outlined" size="16" />
76 删除 76 删除
77 </a-menu-item> 77 </a-menu-item>
78 </a-menu> 78 </a-menu>
@@ -95,9 +95,9 @@ @@ -95,9 +95,9 @@
95 size="small" 95 size="small"
96 /> 96 />
97 <!--添加知识库弹窗--> 97 <!--添加知识库弹窗-->
98 - <KnowledgeBaseModal @register="registerModal" @success="reload"></KnowledgeBaseModal> 98 + <KnowledgeBaseModal @register="registerModal" @success="reload" />
99 <!-- 知识库文档弹窗 --> 99 <!-- 知识库文档弹窗 -->
100 - <AiragKnowledgeDocListModal @register="docListRegister"></AiragKnowledgeDocListModal> 100 + <AiragKnowledgeDocListModal @register="docListRegister" />
101 </div> 101 </div>
102 </template> 102 </template>
103 103
@@ -112,7 +112,7 @@ @@ -112,7 +112,7 @@
112 import JDictSelectTag from '@/components/Form/src/jeecg/components/JDictSelectTag.vue'; 112 import JDictSelectTag from '@/components/Form/src/jeecg/components/JDictSelectTag.vue';
113 import AiragKnowledgeDocListModal from './components/AiragKnowledgeDocListModal.vue'; 113 import AiragKnowledgeDocListModal from './components/AiragKnowledgeDocListModal.vue';
114 import Icon from '@/components/Icon'; 114 import Icon from '@/components/Icon';
115 - import { useMessage } from "@/hooks/web/useMessage"; 115 + import { useMessage } from '@/hooks/web/useMessage';
116 116
117 export default { 117 export default {
118 name: 'KnowledgeBaseList', 118 name: 'KnowledgeBaseList',
@@ -190,10 +190,10 @@ @@ -190,10 +190,10 @@
190 pageNo: pageNo.value, 190 pageNo: pageNo.value,
191 pageSize: pageSize.value, 191 pageSize: pageSize.value,
192 column: 'createTime', 192 column: 'createTime',
193 - order: 'desc' 193 + order: 'desc',
194 }; 194 };
195 Object.assign(params, queryParam); 195 Object.assign(params, queryParam);
196 - 196 +
197 list(params).then((res) => { 197 list(params).then((res) => {
198 if (res.success) { 198 if (res.success) {
199 knowledgeList.value = res.result.records; 199 knowledgeList.value = res.result.records;
@@ -255,16 +255,18 @@ @@ -255,16 +255,18 @@
255 * @param id 255 * @param id
256 */ 256 */
257 async function handleVectorization(id) { 257 async function handleVectorization(id) {
258 - rebuild({ knowIds: id }).then((res) =>{  
259 - if(res.success){  
260 - createMessage.success("向量化成功!");  
261 - reload();  
262 - }else{  
263 - createMessage.warning("向量化失败!");  
264 - }  
265 - }).catch(err=>{  
266 - createMessage.warning("向量化失败!");  
267 - }); 258 + rebuild({ knowIds: id })
  259 + .then((res) => {
  260 + if (res.success) {
  261 + createMessage.success('向量化成功!');
  262 + reload();
  263 + } else {
  264 + createMessage.warning('向量化失败!');
  265 + }
  266 + })
  267 + .catch((err) => {
  268 + createMessage.warning('向量化失败!');
  269 + });
268 } 270 }
269 271
270 return { 272 return {
@@ -345,18 +347,18 @@ @@ -345,18 +347,18 @@
345 font-size: 12px; 347 font-size: 12px;
346 color: #676f83; 348 color: #676f83;
347 } 349 }
348 -  
349 - .knowledge-footer{ 350 +
  351 + .knowledge-footer {
350 font-size: 12px; 352 font-size: 12px;
351 overflow: hidden; 353 overflow: hidden;
352 text-overflow: ellipsis; 354 text-overflow: ellipsis;
353 white-space: nowrap; 355 white-space: nowrap;
354 margin-top: 16px; 356 margin-top: 16px;
355 - .knowledge-footer-icon{ 357 + .knowledge-footer-icon {
356 position: relative; 358 position: relative;
357 - top: 2px 359 + top: 2px;
358 } 360 }
359 - span{ 361 + span {
360 margin-left: 2px; 362 margin-left: 2px;
361 } 363 }
362 } 364 }
@@ -389,7 +391,7 @@ @@ -389,7 +391,7 @@
389 margin-bottom: 20px; 391 margin-bottom: 20px;
390 background: #fcfcfd; 392 background: #fcfcfd;
391 border: 1px solid #f0f0f0; 393 border: 1px solid #f0f0f0;
392 - box-shadow: 0 2px 4px rgba(0,0,0,0.1); 394 + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
393 transition: all 0.3s ease; 395 transition: all 0.3s ease;
394 border-radius: 10px; 396 border-radius: 10px;
395 display: inline-flex; 397 display: inline-flex;
@@ -407,14 +409,14 @@ @@ -407,14 +409,14 @@
407 } 409 }
408 .add-knowledge-card-title { 410 .add-knowledge-card-title {
409 font-size: 16px; 411 font-size: 16px;
410 - color:#1f2329; 412 + color: #1f2329;
411 font-weight: 400; 413 font-weight: 400;
412 align-self: center; 414 align-self: center;
413 } 415 }
414 } 416 }
415 417
416 .add-knowledge-card:hover { 418 .add-knowledge-card:hover {
417 - box-shadow: 0 6px 12px rgba(0,0,0,0.15); 419 + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
418 } 420 }
419 421
420 .knowledge-card { 422 .knowledge-card {
@@ -424,11 +426,11 @@ @@ -424,11 +426,11 @@
424 border-radius: 10px; 426 border-radius: 10px;
425 background: #fcfcfd; 427 background: #fcfcfd;
426 border: 1px solid #f0f0f0; 428 border: 1px solid #f0f0f0;
427 - box-shadow: 0 2px 4px rgba(0,0,0,0.1); 429 + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
428 transition: all 0.3s ease; 430 transition: all 0.3s ease;
429 } 431 }
430 .knowledge-card:hover { 432 .knowledge-card:hover {
431 - box-shadow: 0 6px 12px rgba(0,0,0,0.15); 433 + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
432 .knowledge-btn { 434 .knowledge-btn {
433 display: block; 435 display: block;
434 } 436 }
@@ -451,18 +453,18 @@ @@ -451,18 +453,18 @@
451 white-space: nowrap; 453 white-space: nowrap;
452 } 454 }
453 } 455 }
454 -  
455 - .model-icon{ 456 +
  457 + .model-icon {
456 background-color: unset; 458 background-color: unset;
457 border: none; 459 border: none;
458 margin-right: 2px; 460 margin-right: 2px;
459 } 461 }
460 - .model-icon:hover{ 462 + .model-icon:hover {
461 color: #000000; 463 color: #000000;
462 - background-color: rgba(0,0,0,0.05); 464 + background-color: rgba(0, 0, 0, 0.05);
463 border: none; 465 border: none;
464 } 466 }
465 - .ant-dropdown-link{ 467 + .ant-dropdown-link {
466 font-size: 14px; 468 font-size: 14px;
467 height: 24px; 469 height: 24px;
468 padding: 0 7px; 470 padding: 0 7px;
@@ -470,8 +472,8 @@ @@ -470,8 +472,8 @@
470 align-content: center; 472 align-content: center;
471 text-align: center; 473 text-align: center;
472 } 474 }
473 -  
474 - .ellipsis{ 475 +
  476 + .ellipsis {
475 overflow: hidden; 477 overflow: hidden;
476 text-overflow: ellipsis; 478 text-overflow: ellipsis;
477 white-space: nowrap; 479 white-space: nowrap;
@@ -24,7 +24,7 @@ export const searchFormSchema: FormSchema[] = [ @@ -24,7 +24,7 @@ export const searchFormSchema: FormSchema[] = [
24 { 24 {
25 label: '问题', 25 label: '问题',
26 field: 'question', 26 field: 'question',
27 - component: 'JInput', 27 + component: 'Input',
28 }, 28 },
29 // 新增知识库选择字段 29 // 新增知识库选择字段
30 { 30 {
@@ -23,40 +23,40 @@ export const listKnowledge = async () => { @@ -23,40 +23,40 @@ export const listKnowledge = async () => {
23 const res = await defHttp.get({ url: Api.listKnowledge }); 23 const res = await defHttp.get({ url: Api.listKnowledge });
24 return res; 24 return res;
25 } catch (error) { 25 } catch (error) {
26 - console.error("Error fetching knowledge list:", error); 26 + console.error('Error fetching knowledge list:', error);
27 return []; 27 return [];
28 } 28 }
29 -} 29 +};
30 30
31 export const list = async (params) => { 31 export const list = async (params) => {
32 try { 32 try {
33 const res = await defHttp.get({ 33 const res = await defHttp.get({
34 url: Api.list, 34 url: Api.list,
35 - params: { ...params, size: 1000 } 35 + params: { ...params, size: 1000 },
36 }); 36 });
37 37
38 if (res?.records && Array.isArray(res.records)) { 38 if (res?.records && Array.isArray(res.records)) {
39 - res.records = res.records.map(item => ({ 39 + res.records = res.records.map((item) => ({
40 ...item, 40 ...item,
41 ...item.metadata, 41 ...item.metadata,
42 question: item.question || '', 42 question: item.question || '',
43 answer: item.answer || '', 43 answer: item.answer || '',
44 knowledgeName: item.knowledgeName || '', 44 knowledgeName: item.knowledgeName || '',
45 - knowledgeId: item.knowledgeId || '' 45 + knowledgeId: item.knowledgeId || '',
46 })); 46 }));
47 } 47 }
48 return res; 48 return res;
49 } catch (error) { 49 } catch (error) {
50 - console.error("Error fetching question embeddings:", error); 50 + console.error('Error fetching question embeddings:', error);
51 return { 51 return {
52 records: [], 52 records: [],
53 total: 0, 53 total: 0,
54 size: 10, 54 size: 10,
55 current: 1, 55 current: 1,
56 - pages: 0 56 + pages: 0,
57 }; 57 };
58 } 58 }
59 -} 59 +};
60 60
61 export const deleteOne = (params, handleSuccess) => { 61 export const deleteOne = (params, handleSuccess) => {
62 return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => { 62 return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
@@ -13,19 +13,19 @@ export const columns: BasicColumn[] = [ @@ -13,19 +13,19 @@ export const columns: BasicColumn[] = [
13 title: '知识库', 13 title: '知识库',
14 align: 'center', 14 align: 'center',
15 dataIndex: 'knowledgeName', 15 dataIndex: 'knowledgeName',
16 - width: 150 16 + width: 150,
17 }, 17 },
18 { 18 {
19 title: '问题', 19 title: '问题',
20 align: 'center', 20 align: 'center',
21 dataIndex: 'question', 21 dataIndex: 'question',
22 - width: 250 22 + width: 250,
23 }, 23 },
24 { 24 {
25 title: '回答', 25 title: '回答',
26 align: 'center', 26 align: 'center',
27 dataIndex: 'answer', 27 dataIndex: 'answer',
28 - width: 300 28 + width: 300,
29 }, 29 },
30 ]; 30 ];
31 31
@@ -39,20 +39,20 @@ export const searchFormSchema: FormSchema[] = [ @@ -39,20 +39,20 @@ export const searchFormSchema: FormSchema[] = [
39 labelField: 'name', 39 labelField: 'name',
40 valueField: 'id', 40 valueField: 'id',
41 }, 41 },
42 - colProps: { span: 8 } 42 + colProps: { span: 8 },
43 }, 43 },
44 { 44 {
45 field: 'question', 45 field: 'question',
46 label: '问题', 46 label: '问题',
47 component: 'Input', 47 component: 'Input',
48 - colProps: { span: 8 } 48 + colProps: { span: 8 },
49 }, 49 },
50 { 50 {
51 field: 'answer', 51 field: 'answer',
52 label: '回答', 52 label: '回答',
53 component: 'Input', 53 component: 'Input',
54 colProps: { span: 8 }, 54 colProps: { span: 8 },
55 - } 55 + },
56 ]; 56 ];
57 57
58 export const formSchema: FormSchema[] = [ 58 export const formSchema: FormSchema[] = [
@@ -71,14 +71,15 @@ export const formSchema: FormSchema[] = [ @@ -71,14 +71,15 @@ export const formSchema: FormSchema[] = [
71 api: listKnowledge, 71 api: listKnowledge,
72 labelField: 'name', 72 labelField: 'name',
73 valueField: 'id', 73 valueField: 'id',
74 - } 74 + showSearch: true,
  75 + },
75 }, 76 },
76 { 77 {
77 field: 'question', 78 field: 'question',
78 label: '问题', 79 label: '问题',
79 component: 'Input', 80 component: 'Input',
80 required: true, 81 required: true,
81 - colProps: { span: 24 } 82 + colProps: { span: 24 },
82 }, 83 },
83 { 84 {
84 field: 'answer', 85 field: 'answer',
@@ -90,16 +91,16 @@ export const formSchema: FormSchema[] = [ @@ -90,16 +91,16 @@ export const formSchema: FormSchema[] = [
90 showCount: true, 91 showCount: true,
91 autoSize: { 92 autoSize: {
92 minRows: 5, 93 minRows: 5,
93 - maxRows: 10  
94 - }  
95 - }  
96 - } 94 + maxRows: 10,
  95 + },
  96 + },
  97 + },
97 ]; 98 ];
98 99
99 export const superQuerySchema = { 100 export const superQuerySchema = {
100 knowledgeId: { title: '知识库', order: 0, view: 'text', type: 'string' }, 101 knowledgeId: { title: '知识库', order: 0, view: 'text', type: 'string' },
101 question: { title: '问题', order: 1, view: 'text', type: 'string' }, 102 question: { title: '问题', order: 1, view: 'text', type: 'string' },
102 - answer: { title: '回答', order: 2, view: 'text', type: 'string' } 103 + answer: { title: '回答', order: 2, view: 'text', type: 'string' },
103 }; 104 };
104 105
105 export function getBpmFormSchema(_formData): FormSchema[] { 106 export function getBpmFormSchema(_formData): FormSchema[] {
@@ -4,17 +4,11 @@ @@ -4,17 +4,11 @@
4 <template #tableTitle> 4 <template #tableTitle>
5 <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined">新增</a-button> 5 <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined">新增</a-button>
6 <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls">导出</a-button> 6 <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls">导出</a-button>
7 - <a-button  
8 - type="primary"  
9 - preIcon="ant-design:import-outlined"  
10 - @click="handleOpenImportModal"  
11 - >导入ZIP</a-button> 7 + <a-button type="primary" preIcon="ant-design:import-outlined" @click="handleOpenImportModal">导入ZIP</a-button>
12 <a-dropdown v-if="selectedRowKeys.length > 0"> 8 <a-dropdown v-if="selectedRowKeys.length > 0">
13 <template #overlay> 9 <template #overlay>
14 <a-menu> 10 <a-menu>
15 - <a-menu-item key="1" @click="batchHandleDelete">  
16 - <Icon icon="ant-design:delete-outlined" />删除  
17 - </a-menu-item> 11 + <a-menu-item key="1" @click="batchHandleDelete"> <Icon icon="ant-design:delete-outlined" />删除 </a-menu-item>
18 </a-menu> 12 </a-menu>
19 </template> 13 </template>
20 <a-button>批量操作<Icon icon="mdi:chevron-down" /></a-button> 14 <a-button>批量操作<Icon icon="mdi:chevron-down" /></a-button>
@@ -36,30 +30,13 @@ @@ -36,30 +30,13 @@
36 :okButtonProps="{ disabled: !selectedKnowledgeId || !currentFile }" 30 :okButtonProps="{ disabled: !selectedKnowledgeId || !currentFile }"
37 > 31 >
38 <BasicForm @register="registerImportForm" :showActionButtonGroup="false" /> 32 <BasicForm @register="registerImportForm" :showActionButtonGroup="false" />
39 - <div style="margin-top: 20px;margin-left: 5%">  
40 - <input  
41 - type="file"  
42 - ref="fileInput"  
43 - accept=".zip"  
44 - @change="handleFileChange"  
45 - style="display: none"  
46 - >  
47 - <a-button  
48 - type="primary"  
49 - @click="triggerFileInput"  
50 - >  
51 - <UploadOutlined /> 选择ZIP文件  
52 - </a-button>  
53 - <div v-if="currentFile" style="margin-top: 8px;">  
54 - 已选择文件: {{ currentFile.name }} ({{ formatFileSize(currentFile.size) }})  
55 - </div>  
56 - <div v-if="uploadProgress > 0" style="margin-top: 8px;"> 33 + <div style="margin-top: 20px; margin-left: 5%">
  34 + <input type="file" ref="fileInput" accept=".zip" @change="handleFileChange" style="display: none" />
  35 + <a-button type="primary" @click="triggerFileInput"> <UploadOutlined /> 选择ZIP文件 </a-button>
  36 + <div v-if="currentFile" style="margin-top: 8px"> 已选择文件: {{ currentFile.name }} ({{ formatFileSize(currentFile.size) }}) </div>
  37 + <div v-if="uploadProgress > 0" style="margin-top: 8px">
57 上传进度: {{ uploadProgress }}% 38 上传进度: {{ uploadProgress }}%
58 - <a-progress  
59 - :percent="uploadProgress"  
60 - :stroke-color="progressColor"  
61 - :status="uploadStatus"  
62 - /> 39 + <a-progress :percent="uploadProgress" :stroke-color="progressColor" :status="uploadStatus" />
63 </div> 40 </div>
64 </div> 41 </div>
65 </BasicModal> 42 </BasicModal>
@@ -67,239 +44,237 @@ @@ -67,239 +44,237 @@
67 </template> 44 </template>
68 45
69 <script lang="ts" setup> 46 <script lang="ts" setup>
70 -import { ref, reactive } from 'vue';  
71 -import { UploadOutlined } from '@ant-design/icons-vue';  
72 -import { BasicTable, useTable, TableAction } from '/@/components/Table';  
73 -import { BasicModal } from '/@/components/Modal';  
74 -import { BasicForm, useForm } from '/@/components/Form';  
75 -import { useModal } from '/@/components/Modal';  
76 -import { useListPage } from '/@/hooks/system/useListPage';  
77 -import { message } from 'ant-design-vue';  
78 -import QuestionEmbeddingModal from './components/QuestionEmbeddingModal.vue';  
79 -import { columns, searchFormSchema } from './QuestionEmbedding.data';  
80 -import { list, deleteOne, batchDelete, getImportZipUrl, getExportUrl, listKnowledge } from './QuestionEmbedding.api';  
81 -import { useUserStore } from '/@/store/modules/user';  
82 -import { getToken } from '/@/utils/auth'; 47 + import { ref, reactive } from 'vue';
  48 + import { UploadOutlined } from '@ant-design/icons-vue';
  49 + import { BasicTable, TableAction } from '/@/components/Table';
  50 + import { BasicModal } from '/@/components/Modal';
  51 + import { BasicForm, useForm } from '/@/components/Form';
  52 + import { useModal } from '/@/components/Modal';
  53 + import { useListPage } from '/@/hooks/system/useListPage';
  54 + import { message } from 'ant-design-vue';
  55 + import QuestionEmbeddingModal from './components/QuestionEmbeddingModal.vue';
  56 + import { columns, searchFormSchema } from './QuestionEmbedding.data';
  57 + import { list, deleteOne, batchDelete, getImportZipUrl, getExportUrl, listKnowledge } from './QuestionEmbedding.api';
  58 + import { useUserStore } from '/@/store/modules/user';
  59 + import { getToken } from '/@/utils/auth';
83 60
84 -const queryParam = reactive<any>({});  
85 -const [registerModal, { openModal }] = useModal();  
86 -const importModalVisible = ref(false);  
87 -const selectedKnowledgeId = ref('');  
88 -const fileInput = ref<HTMLInputElement | null>(null);  
89 -const currentFile = ref<File | null>(null);  
90 -const uploadProgress = ref(0);  
91 -const progressColor = ref('#1890ff');  
92 -const uploadStatus = ref<'normal' | 'exception' | 'active' | 'success'>('normal'); 61 + const queryParam = reactive<any>({});
  62 + const [registerModal, { openModal }] = useModal();
  63 + const importModalVisible = ref(false);
  64 + const selectedKnowledgeId = ref('');
  65 + const fileInput = ref<HTMLInputElement | null>(null);
  66 + const currentFile = ref<File | null>(null);
  67 + const uploadProgress = ref(0);
  68 + const progressColor = ref('#1890ff');
  69 + const uploadStatus = ref<'normal' | 'exception' | 'active' | 'success'>('normal');
93 70
94 -// 知识库选择表单  
95 -const [registerImportForm] = useForm({  
96 - labelWidth: 100,  
97 - showActionButtonGroup: false,  
98 - schemas: [  
99 - {  
100 - field: 'knowledgeId',  
101 - label: '知识库',  
102 - component: 'ApiSelect',  
103 - required: true,  
104 - componentProps: {  
105 - placeholder: '请选择知识库',  
106 - api: listKnowledge,  
107 - labelField: 'name',  
108 - valueField: 'id',  
109 - onChange: (value: string) => {  
110 - selectedKnowledgeId.value = value;  
111 - } 71 + // 知识库选择表单
  72 + const [registerImportForm] = useForm({
  73 + labelWidth: 100,
  74 + showActionButtonGroup: false,
  75 + schemas: [
  76 + {
  77 + field: 'knowledgeId',
  78 + label: '知识库',
  79 + component: 'ApiSelect',
  80 + required: true,
  81 + componentProps: {
  82 + placeholder: '请选择知识库',
  83 + api: listKnowledge,
  84 + labelField: 'name',
  85 + valueField: 'id',
  86 + onChange: (value: string) => {
  87 + selectedKnowledgeId.value = value;
  88 + },
  89 + },
112 }, 90 },
113 - },  
114 - ],  
115 -}); 91 + ],
  92 + });
116 93
117 -const { tableContext, onExportXls } = useListPage({  
118 - tableProps: {  
119 - title: '问答向量库',  
120 - api: list,  
121 - columns,  
122 - formConfig: {  
123 - schemas: searchFormSchema,  
124 - autoSubmitOnEnter: true,  
125 - showAdvancedButton: true 94 + const { tableContext, onExportXls } = useListPage({
  95 + tableProps: {
  96 + title: '问答向量库',
  97 + api: list,
  98 + columns,
  99 + formConfig: {
  100 + schemas: searchFormSchema,
  101 + autoSubmitOnEnter: true,
  102 + showAdvancedButton: true,
  103 + },
  104 + actionColumn: {
  105 + width: 120,
  106 + fixed: 'right',
  107 + },
  108 + beforeFetch: (params) => Object.assign(params, queryParam),
126 }, 109 },
127 - actionColumn: {  
128 - width: 120,  
129 - fixed: 'right' 110 + exportConfig: {
  111 + name: '问答向量库',
  112 + url: getExportUrl,
130 }, 113 },
131 - beforeFetch: (params) => Object.assign(params, queryParam)  
132 - },  
133 - exportConfig: {  
134 - name: '问答向量库',  
135 - url: getExportUrl  
136 - }  
137 -}); 114 + });
138 115
139 -const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext; 116 + const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
140 117
141 -function handleOpenImportModal() {  
142 - importModalVisible.value = true;  
143 - selectedKnowledgeId.value = '';  
144 - resetFileInput();  
145 -} 118 + function handleOpenImportModal() {
  119 + importModalVisible.value = true;
  120 + selectedKnowledgeId.value = '';
  121 + resetFileInput();
  122 + }
146 123
147 -function handleImportCancel() {  
148 - importModalVisible.value = false;  
149 - resetFileInput();  
150 -} 124 + function handleImportCancel() {
  125 + importModalVisible.value = false;
  126 + resetFileInput();
  127 + }
151 128
152 -function triggerFileInput() {  
153 - fileInput.value?.click();  
154 -} 129 + function triggerFileInput() {
  130 + fileInput.value?.click();
  131 + }
155 132
156 -function handleFileChange(e: Event) {  
157 - const input = e.target as HTMLInputElement;  
158 - if (input.files && input.files.length > 0) {  
159 - currentFile.value = input.files[0]; 133 + function handleFileChange(e: Event) {
  134 + const input = e.target as HTMLInputElement;
  135 + if (input.files && input.files.length > 0) {
  136 + currentFile.value = input.files[0];
  137 + uploadProgress.value = 0;
  138 + uploadStatus.value = 'normal';
  139 + console.log('文件选择成功:', {
  140 + name: currentFile.value.name,
  141 + size: currentFile.value.size,
  142 + type: currentFile.value.type,
  143 + });
  144 + } else {
  145 + currentFile.value = null;
  146 + }
  147 + }
  148 +
  149 + function resetFileInput() {
  150 + if (fileInput.value) {
  151 + fileInput.value.value = '';
  152 + }
  153 + currentFile.value = null;
160 uploadProgress.value = 0; 154 uploadProgress.value = 0;
161 uploadStatus.value = 'normal'; 155 uploadStatus.value = 'normal';
162 - console.log('文件选择成功:', {  
163 - name: currentFile.value.name,  
164 - size: currentFile.value.size,  
165 - type: currentFile.value.type  
166 - });  
167 - } else {  
168 - currentFile.value = null;  
169 } 156 }
170 -}  
171 157
172 -function resetFileInput() {  
173 - if (fileInput.value) {  
174 - fileInput.value.value = ''; 158 + function formatFileSize(bytes: number): string {
  159 + if (bytes === 0) return '0 Bytes';
  160 + const k = 1024;
  161 + const sizes = ['Bytes', 'KB', 'MB', 'GB'];
  162 + const i = Math.floor(Math.log(bytes) / Math.log(k));
  163 + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
175 } 164 }
176 - currentFile.value = null;  
177 - uploadProgress.value = 0;  
178 - uploadStatus.value = 'normal';  
179 -}  
180 -  
181 -function formatFileSize(bytes: number): string {  
182 - if (bytes === 0) return '0 Bytes';  
183 - const k = 1024;  
184 - const sizes = ['Bytes', 'KB', 'MB', 'GB'];  
185 - const i = Math.floor(Math.log(bytes) / Math.log(k));  
186 - return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];  
187 -}  
188 165
189 -// 获取用户token  
190 -const userStore = useUserStore();  
191 -const token = getToken(); 166 + // 获取用户token
  167 + const userStore = useUserStore();
  168 + const token = getToken();
192 169
193 -async function handleImportSubmit() {  
194 - if (!selectedKnowledgeId.value || !currentFile.value) {  
195 - message.warning('请完整填写上传信息');  
196 - return;  
197 - } 170 + async function handleImportSubmit() {
  171 + if (!selectedKnowledgeId.value || !currentFile.value) {
  172 + message.warning('请完整填写上传信息');
  173 + return;
  174 + }
198 175
199 - const formData = new FormData();  
200 - formData.append('file', currentFile.value, currentFile.value.name);  
201 - formData.append('knowledgeId', selectedKnowledgeId.value); 176 + const formData = new FormData();
  177 + formData.append('file', currentFile.value, currentFile.value.name);
  178 + formData.append('knowledgeId', selectedKnowledgeId.value);
202 179
203 - try {  
204 - uploadProgress.value = 0;  
205 - uploadStatus.value = 'active'; 180 + try {
  181 + uploadProgress.value = 0;
  182 + uploadStatus.value = 'active';
206 183
207 - // 使用fetch API并添加认证头  
208 - const response = await fetch("/jeecgboot" + getImportZipUrl, {  
209 - method: 'POST',  
210 - body: formData,  
211 - headers: {  
212 - 'X-Access-Token': token, // JEECG标准认证头  
213 - 'Authorization': `Bearer ${token}` // 备用认证头  
214 - },  
215 - credentials: 'include' // 携带cookie  
216 - }); 184 + // 使用fetch API并添加认证头
  185 + const response = await fetch('/jeecgboot' + getImportZipUrl, {
  186 + method: 'POST',
  187 + body: formData,
  188 + headers: {
  189 + 'X-Access-Token': token, // JEECG标准认证头
  190 + Authorization: `Bearer ${token}`, // 备用认证头
  191 + },
  192 + credentials: 'include', // 携带cookie
  193 + });
217 194
218 - if (response.status === 401) {  
219 - message.error('登录已过期,请重新登录');  
220 - userStore.logout(true);  
221 - return;  
222 - } 195 + if (response.status === 401) {
  196 + message.error('登录已过期,请重新登录');
  197 + userStore.logout(true);
  198 + return;
  199 + }
223 200
224 - if (!response.ok) {  
225 - throw new Error(`上传失败: ${response.statusText}`);  
226 - } 201 + if (!response.ok) {
  202 + throw new Error(`上传失败: ${response.statusText}`);
  203 + }
227 204
228 - const result = await response.json();  
229 - if (result.success) {  
230 - message.success('上传成功');  
231 - importModalVisible.value = false;  
232 - handleSuccess();  
233 - } else {  
234 - throw new Error(result.message || '上传处理失败'); 205 + const result = await response.json();
  206 + if (result.success) {
  207 + message.success('上传成功');
  208 + importModalVisible.value = false;
  209 + handleSuccess();
  210 + } else {
  211 + throw new Error(result.message || '上传处理失败');
  212 + }
  213 + } catch (error) {
  214 + uploadStatus.value = 'exception';
  215 + message.error(error.message || '上传失败');
  216 + console.error('上传错误:', error);
235 } 217 }
236 - } catch (error) {  
237 - uploadStatus.value = 'exception';  
238 - message.error(error.message || '上传失败');  
239 - console.error('上传错误:', error);  
240 } 218 }
241 -}  
242 219
243 -function handleSuperQuery(params: any) {  
244 - Object.assign(queryParam, params);  
245 - reload();  
246 -} 220 + function handleSuperQuery(params: any) {
  221 + Object.assign(queryParam, params);
  222 + reload();
  223 + }
247 224
248 -function handleAdd() {  
249 - openModal(true, { isUpdate: false, showFooter: true });  
250 -} 225 + function handleAdd() {
  226 + openModal(true, { isUpdate: false, showFooter: true });
  227 + }
251 228
252 -function handleEdit(record: any) {  
253 - openModal(true, { record, isUpdate: true, showFooter: true });  
254 -} 229 + function handleEdit(record: any) {
  230 + openModal(true, { record, isUpdate: true, showFooter: true });
  231 + }
255 232
256 -function handleDetail(record: any) {  
257 - openModal(true, { record, isUpdate: true, showFooter: false });  
258 -} 233 + function handleDetail(record: any) {
  234 + openModal(true, { record, isUpdate: true, showFooter: false });
  235 + }
259 236
260 -async function handleDelete(record: any) {  
261 - await deleteOne({ id: record.id }, handleSuccess);  
262 -} 237 + async function handleDelete(record: any) {
  238 + await deleteOne({ id: record.id }, handleSuccess);
  239 + }
263 240
264 -async function batchHandleDelete() {  
265 - await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);  
266 -} 241 + async function batchHandleDelete() {
  242 + await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
  243 + }
267 244
268 -function handleSuccess() {  
269 - selectedRowKeys.value = [];  
270 - reload();  
271 -} 245 + function handleSuccess() {
  246 + selectedRowKeys.value = [];
  247 + reload();
  248 + }
272 249
273 -function getTableAction(record: any) {  
274 - return [  
275 - { label: '编辑', onClick: handleEdit.bind(null, record) }  
276 - ];  
277 -} 250 + function getTableAction(record: any) {
  251 + return [{ label: '编辑', onClick: handleEdit.bind(null, record) }];
  252 + }
278 253
279 -function getDropDownAction(record: any) {  
280 - return [  
281 - { label: '详情', onClick: handleDetail.bind(null, record) },  
282 - {  
283 - label: '删除',  
284 - popConfirm: {  
285 - title: '确认删除此问答?',  
286 - confirm: handleDelete.bind(null, record)  
287 - }  
288 - }  
289 - ];  
290 -} 254 + function getDropDownAction(record: any) {
  255 + return [
  256 + { label: '详情', onClick: handleDetail.bind(null, record) },
  257 + {
  258 + label: '删除',
  259 + popConfirm: {
  260 + title: '确认删除此问答?',
  261 + confirm: handleDelete.bind(null, record),
  262 + },
  263 + },
  264 + ];
  265 + }
291 </script> 266 </script>
292 267
293 <style scoped> 268 <style scoped>
294 -.upload-area {  
295 - margin-top: 20px;  
296 - padding: 20px;  
297 - border: 1px dashed #d9d9d9;  
298 - border-radius: 4px;  
299 - text-align: center;  
300 - cursor: pointer;  
301 -}  
302 -.upload-area:hover {  
303 - border-color: #1890ff;  
304 -} 269 + .upload-area {
  270 + margin-top: 20px;
  271 + padding: 20px;
  272 + border: 1px dashed #d9d9d9;
  273 + border-radius: 4px;
  274 + text-align: center;
  275 + cursor: pointer;
  276 + }
  277 + .upload-area:hover {
  278 + border-color: #1890ff;
  279 + }
305 </style> 280 </style>
@@ -39,6 +39,7 @@ @@ -39,6 +39,7 @@
39 async function handleSubmit() { 39 async function handleSubmit() {
40 try { 40 try {
41 const values = await validate(); 41 const values = await validate();
  42 + console.log(values);
42 setModalProps({ confirmLoading: true }); 43 setModalProps({ confirmLoading: true });
43 await saveOrUpdate(values, isUpdate.value); 44 await saveOrUpdate(values, isUpdate.value);
44 closeModal(); 45 closeModal();
@@ -182,6 +182,7 @@ @@ -182,6 +182,7 @@
182 * 编辑事件 182 * 编辑事件
183 */ 183 */
184 function handleEdit(record: Recordable) { 184 function handleEdit(record: Recordable) {
  185 + console.log('当前行数据:', record);
185 openModal(true, { 186 openModal(true, {
186 record, 187 record,
187 isUpdate: true, 188 isUpdate: true,
@@ -220,6 +221,7 @@ @@ -220,6 +221,7 @@
220 * 操作栏 221 * 操作栏
221 */ 222 */
222 function getTableAction(record) { 223 function getTableAction(record) {
  224 + console.log('record', record);
223 return [ 225 return [
224 { 226 {
225 label: '编辑', 227 label: '编辑',
@@ -199,6 +199,12 @@ export const formSchema: FormSchema[] = [ @@ -199,6 +199,12 @@ export const formSchema: FormSchema[] = [
199 }, 199 },
200 }, 200 },
201 }, 201 },
  202 + {
  203 + label: '',
  204 + field: 'docId',
  205 + component: 'Input',
  206 + show: false,
  207 + },
202 // TODO 主键隐藏字段,目前写死为ID 208 // TODO 主键隐藏字段,目前写死为ID
203 { 209 {
204 label: '', 210 label: '',
@@ -36,6 +36,7 @@ @@ -36,6 +36,7 @@
36 try { 36 try {
37 const metadata = typeof formData.metadata === 'string' ? JSON.parse(formData.metadata) : formData.metadata; 37 const metadata = typeof formData.metadata === 'string' ? JSON.parse(formData.metadata) : formData.metadata;
38 formData.docName = metadata.docName || '未命名'; 38 formData.docName = metadata.docName || '未命名';
  39 + formData.docId = metadata.docId || 'null';
39 40
40 // 关键修复:设置知识库ID 41 // 关键修复:设置知识库ID
41 formData.knowledgeId = metadata.knowledgeId; 42 formData.knowledgeId = metadata.knowledgeId;
@@ -53,19 +54,25 @@ @@ -53,19 +54,25 @@
53 //设置标题 54 //设置标题
54 const title = computed(() => (!unref(isUpdate) ? '新增' : !unref(isDetail) ? '详情' : '编辑')); 55 const title = computed(() => (!unref(isUpdate) ? '新增' : !unref(isDetail) ? '详情' : '编辑'));
55 //表单提交事件 56 //表单提交事件
56 - async function handleSubmit() { 57 + async function handleSubmit(record) {
  58 + console.log('22222222222222', record);
57 try { 59 try {
58 let values = await validate(); 60 let values = await validate();
  61 + console.log('表单数据:', values);
59 62
60 const metadata = { 63 const metadata = {
61 knowledgeId: values.knowledgeId, 64 knowledgeId: values.knowledgeId,
  65 + docId: values.docId,
62 }; 66 };
  67 + console.log('values', values);
63 // 仅保留需要的字段,其他由后端自动生成 68 // 仅保留需要的字段,其他由后端自动生成
64 const payload = { 69 const payload = {
65 id: values.id, 70 id: values.id,
66 docName: values.docName, // 文件名称 71 docName: values.docName, // 文件名称
67 text: values.text, // 文件内容 72 text: values.text, // 文件内容
68 metadata: metadata, 73 metadata: metadata,
  74 + knowledgeId: values.knowledgeId,
  75 + docId: values.docId,
69 }; 76 };
70 setModalProps({ confirmLoading: true }); 77 setModalProps({ confirmLoading: true });
71 //提交表单 78 //提交表单