From 891f8ed7767da21be934b18e58b6ef77f36dc9d9 Mon Sep 17 00:00:00 2001 From: wusijian0117 <2910410219@qq.com> Date: Tue, 24 Mar 2026 18:00:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=BC=80=E5=8F=91=E7=8E=AF?= =?UTF-8?q?=E5=A2=83API=E6=9C=8D=E5=8A=A1=E5=9C=B0=E5=9D=80=E8=87=B3192.16?= =?UTF-8?q?8.3.30=EF=BC=8C=E8=B0=83=E6=95=B4ESLint=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E4=BB=A5=E5=BF=BD=E7=95=A5=E7=89=B9=E5=AE=9A=E5=8F=98=E9=87=8F?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=95=B0=E6=8D=AE=E9=9B=86=E5=92=8C?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E7=9B=B8=E5=85=B3=E7=9A=84=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E4=B8=8E=E6=9B=B4=E6=96=B0=E6=8E=A5=E5=8F=A3=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86=E5=92=8C=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=8F=8D=E9=A6=88=EF=BC=8C=E7=A7=BB=E9=99=A4=E6=A8=A1?= =?UTF-8?q?=E6=8B=9F=E6=95=B0=E6=8D=AE=EF=BC=8C=E5=A2=9E=E5=BC=BA=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=8F=AF=E8=AF=BB=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 4 +- .eslintignore | 3 +- .eslintrc.cjs | 12 +- package-lock.json | 106 +++++++- package.json | 8 +- src/api/knowledge/dataset/example.ts | 113 +++++++++ src/api/knowledge/dataset/index.ts | 39 ++- src/api/knowledge/document/example.ts | 238 ++++++++++++++++++ src/api/knowledge/document/index.ts | 37 +++ .../component/documentDetailDialog.vue | 17 +- .../dataset/component/editDataset.vue | 12 +- src/views/knowledge/dataset/index.vue | 65 +---- .../document/component/documentChunks.vue | 46 +--- .../document/component/previewDocument.vue | 30 +-- .../document/component/uploadDocument.vue | 8 +- src/views/knowledge/document/detail.vue | 82 +++--- src/views/knowledge/document/index.vue | 102 ++------ src/views/knowledge/index.vue | 71 +++--- 18 files changed, 695 insertions(+), 298 deletions(-) create mode 100644 src/api/knowledge/dataset/example.ts create mode 100644 src/api/knowledge/document/example.ts diff --git a/.env.development b/.env.development index fd4f4ae..d0ddb43 100644 --- a/.env.development +++ b/.env.development @@ -12,7 +12,7 @@ ENV = 'development' # 主服务地址(端口8808) # 用途: 系统管理、用户认证、权限控制、模块开通等原有功能 -VITE_API_URL = 'http://192.168.3.11:8808/' +VITE_API_URL = 'http://192.168.3.30:8808/' # 新功能服务地址(端口8000) # 用途: 资产管理、分类、SKU、订单等新业务模块 -VITE_NEW_API_URL = 'http://192.168.3.11:8000/' +VITE_NEW_API_URL = 'http://192.168.3.30:8000/' diff --git a/.eslintignore b/.eslintignore index cfc877d..41db4b2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -15,4 +15,5 @@ bin build config index.html -src/assets \ No newline at end of file +src/assets +src/api/**/example.ts \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs index f4a9b6e..010e9fc 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -37,7 +37,14 @@ module.exports = { '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-redeclare': 'error', '@typescript-eslint/no-non-null-asserted-optional-chain': 'off', - '@typescript-eslint/no-unused-vars': [2], + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], 'vue/custom-event-name-casing': 'off', 'vue/attributes-order': 'off', 'vue/one-component-per-file': 'off', @@ -67,10 +74,11 @@ module.exports = { 'generator-star-spacing': 'off', 'no-unreachable': 'off', 'no-multiple-template-root': 'off', - 'no-unused-vars': 'error', + 'no-unused-vars': 'off', 'no-v-model-argument': 'off', 'no-case-declarations': 'off', 'no-console': 'error', + 'no-debugger': 'error', 'no-redeclare': 'off', }, }; diff --git a/package-lock.json b/package-lock.json index bd0144a..82a8f9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -67,7 +67,8 @@ "vite-plugin-cdn-import": "^0.3.5", "vite-plugin-compression": "^0.5.1", "vite-plugin-vue-setup-extend-plus": "^0.1.0", - "vue-eslint-parser": "^9.4.1" + "vue-eslint-parser": "^9.4.1", + "vue-tsc": "^3.2.6" }, "engines": { "node": ">=16.0.0", @@ -2172,6 +2173,35 @@ "vue": "^3.2.25" } }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, "node_modules/@vue/compiler-core": { "version": "3.5.25", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.25.tgz", @@ -2228,6 +2258,35 @@ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", "license": "MIT" }, + "node_modules/@vue/language-core": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.2.6.tgz", + "integrity": "sha512-xYYYX3/aVup576tP/23sEUpgiEnujrENaoNRbaozC1/MA9I6EGFQRJb4xrt/MmUCAGlxTKL2RmT8JLTPqagCkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.0.0", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.2" + } + }, + "node_modules/@vue/language-core/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@vue/reactivity": { "version": "3.5.25", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.25.tgz", @@ -2506,6 +2565,13 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/alien-signals": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.1.2.tgz", + "integrity": "sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4358,6 +4424,13 @@ "dev": true, "license": "MIT" }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, "node_modules/namespace-emitter": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", @@ -4527,6 +4600,13 @@ "node": ">=6" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5622,6 +5702,13 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, "node_modules/vue": { "version": "3.5.25", "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.25.tgz", @@ -5792,6 +5879,23 @@ "vue": ">=3.1" } }, + "node_modules/vue-tsc": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.2.6.tgz", + "integrity": "sha512-gYW/kWI0XrwGzd0PKc7tVB/qpdeAkIZLNZb10/InizkQjHjnT8weZ/vBarZoj4kHKbUTZT/bAVgoOr8x4NsQ/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.2.6" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, "node_modules/vue-ueditor-wrap": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/vue-ueditor-wrap/-/vue-ueditor-wrap-3.0.8.tgz", diff --git a/package.json b/package.json index 5062853..9385a2d 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,10 @@ "scripts": { "dev": "vite", "build": "vite build", - "lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/" + "lint": "eslint --ext .js,.jsx,.ts,.tsx,.vue src/", + "lint-fix": "eslint --fix --ext .js,.jsx,.ts,.tsx,.vue src/", + "type-check": "vue-tsc --noEmit -p tsconfig.json", + "quality": "npm run lint && npm run type-check" }, "dependencies": { "@codemirror/lang-javascript": "^6.1.1", @@ -69,7 +72,8 @@ "vite-plugin-cdn-import": "^0.3.5", "vite-plugin-compression": "^0.5.1", "vite-plugin-vue-setup-extend-plus": "^0.1.0", - "vue-eslint-parser": "^9.4.1" + "vue-eslint-parser": "^9.4.1", + "vue-tsc": "^3.2.6" }, "browserslist": [ "> 1%", diff --git a/src/api/knowledge/dataset/example.ts b/src/api/knowledge/dataset/example.ts new file mode 100644 index 0000000..c42e832 --- /dev/null +++ b/src/api/knowledge/dataset/example.ts @@ -0,0 +1,113 @@ +// ⚠️ 示例文件:仅用于接口调用演示,不参与生产运行。 +// 知识库接口使用示例 +import { + createKnowledgeBase, + CreateDatasetParams, + updateKnowledgeBase, + UpdateDatasetParams +} from '/@/api/knowledge/dataset'; + +// 示例1:创建带描述的知识库 +const createKnowledgeBaseWithDescription = async () => { + const params: CreateDatasetParams = { + name: '客服知识库', + description: '包含常见问题和答案的知识库' + }; + + try { + const response = await createKnowledgeBase(params); + console.log('知识库创建成功:', response.data); + } catch (error) { + console.error('创建失败:', error); + } +}; + +// 示例2:创建仅包含名称的知识库 +const createKnowledgeBaseOnly = async () => { + const params: CreateDatasetParams = { + name: '产品知识库' + // description 是可选的,可以不传 + }; + + try { + const response = await createKnowledgeBase(params); + console.log('知识库创建成功:', response.data); + } catch (error) { + console.error('创建失败:', error); + } +}; + +// 示例3:更新知识库名称和描述 +const updateKnowledgeBaseInfo = async () => { + const params: UpdateDatasetParams = { + id: '1234567890', // 必传 + name: '更新后的知识库名称', + description: '更新后的描述信息' + }; + + try { + const response = await updateKnowledgeBase(params); + console.log('知识库更新成功:', response.data); + } catch (error) { + console.error('更新失败:', error); + } +}; + +// 示例4:仅更新知识库名称 +const updateKnowledgeBaseName = async () => { + const params: UpdateDatasetParams = { + id: '1234567890', // 必传 + name: '仅更新名称' + // description 是可选的,可以不传 + }; + + try { + const response = await updateKnowledgeBase(params); + console.log('知识库名称更新成功:', response.data); + } catch (error) { + console.error('更新失败:', error); + } +}; + +// 在Vue组件中使用 +/* +import { ref } from 'vue'; +import { ElMessage } from 'element-plus'; +import { createKnowledgeBase, CreateDatasetParams } from '/@/api/knowledge/dataset'; + +export default defineComponent({ + setup() { + const formData = ref({ + name: '', + description: '' + }); + + const loading = ref(false); + + const handleSubmit = async () => { + if (!formData.value.name.trim()) { + ElMessage.error('知识库名称不能为空'); + return; + } + + loading.value = true; + try { + await createKnowledgeBase(formData.value); + ElMessage.success('知识库创建成功'); + // 重置表单或跳转到列表页 + formData.value = { name: '', description: '' }; + } catch (error) { + ElMessage.error('创建失败,请重试'); + } finally { + loading.value = false; + } + }; + + return { + formData, + loading, + handleSubmit + }; + } +}); +*/ diff --git a/src/api/knowledge/dataset/index.ts b/src/api/knowledge/dataset/index.ts index 6a117b3..508e83e 100644 --- a/src/api/knowledge/dataset/index.ts +++ b/src/api/knowledge/dataset/index.ts @@ -8,6 +8,19 @@ export interface DatasetQueryParams { pageSize: number; } +// 创建知识库参数 +export interface CreateDatasetParams { + name: string; // 必传 + description?: string; // 可选 +} + +// 更新知识库参数 +export interface UpdateDatasetParams { + id: string; // 必传 + name?: string; // 可选 + description?: string; // 可选 +} + // 数据集信息 export interface DatasetInfo { id?: string; @@ -25,7 +38,7 @@ export interface DatasetInfo { // 获取数据集列表 export function listDatasets(params: DatasetQueryParams) { return newService({ - url: '/knowledge/dataset/list', + url: '/rag-knowledge/knowledge/listKnowledge', method: 'get', params, }); @@ -40,7 +53,16 @@ export function getDataset(id: string) { }); } -// 创建数据集 +// 创建数据集(简化版) +export function createKnowledgeBase(data: CreateDatasetParams) { + return newService({ + url: '/rag-knowledge/knowledge/createKnowledge', + method: 'post', + data, + }); +} + +// 创建数据集(完整版) export function createDataset(data: DatasetInfo) { return newService({ url: '/knowledge/dataset/create', @@ -49,7 +71,16 @@ export function createDataset(data: DatasetInfo) { }); } -// 更新数据集 +// 更新知识库(简化版) +export function updateKnowledgeBase(data: UpdateDatasetParams) { + return newService({ + url: '/rag-knowledge/knowledge/updateKnowledge', + method: 'put', + data, + }); +} + +// 更新数据集(完整版) export function updateDataset(data: DatasetInfo) { return newService({ url: '/knowledge/dataset/update', @@ -61,7 +92,7 @@ export function updateDataset(data: DatasetInfo) { // 删除数据集 export function deleteDataset(id: string) { return newService({ - url: '/knowledge/dataset/delete', + url: '/rag-knowledge/knowledge/deleteKnowledge', method: 'delete', params: { id }, }); diff --git a/src/api/knowledge/document/example.ts b/src/api/knowledge/document/example.ts new file mode 100644 index 0000000..0f86532 --- /dev/null +++ b/src/api/knowledge/document/example.ts @@ -0,0 +1,238 @@ +// ⚠️ 示例文件:仅用于接口调用演示,不参与生产运行。 +// 文档接口使用示例 +import { + createDocument, + CreateDocumentParams, + updateDocument, + UpdateDocumentParams, + uploadDocument, + deleteDocument, + listDocuments, + DocumentQueryParams +} from '/@/api/knowledge/document'; + +// 示例1:创建文档(JSON格式) +const createDocumentExample = async () => { + const params: CreateDocumentParams = { + KnowledgeId: 12345, // 知识库ID,必传 + filePath: '/path/to/document.pdf', // 文件路径,必传 + fileSize: 1024000, // 文件大小(字节),必传 + format: 'pdf', // 文件格式,必传 + title: '产品使用手册' // 文档标题,必传 + }; + + try { + const response = await createDocument(params); + console.log('文档创建成功:', response.data); + return response.data; + } catch (error) { + console.error('创建失败:', error); + throw error; + } +}; + +// 示例2:上传文档(FormData格式) +const uploadDocumentExample = async (file: File, knowledgeId: string) => { + const formData = new FormData(); + formData.append('file', file); + formData.append('datasetId', knowledgeId); + + try { + const response = await uploadDocument(formData); + console.log('文档上传成功:', response.data); + return response.data; + } catch (error) { + console.error('上传失败:', error); + throw error; + } +}; + +// 示例3:获取文档列表 +const getDocumentList = async (knowledgeId: string) => { + const params: DocumentQueryParams = { + datasetId: knowledgeId, + pageNum: 1, + pageSize: 10, + keyword: '', // 可选搜索关键字 + status: '', // 可选状态筛选 + fileType: '' // 可选文件类型筛选 + }; + + try { + const response = await listDocuments(params); + console.log('文档列表:', response.data); + return response.data; + } catch (error) { + console.error('获取列表失败:', error); + throw error; + } +}; + +// 示例4:更新文档 +const updateDocumentExample = async () => { + const params: UpdateDocumentParams = { + id: '1234567890', // 必传 + title: '更新后的文档标题' // 可选,只更新标题 + }; + + try { + const response = await updateDocument(params); + console.log('文档更新成功:', response.data); + return response.data; + } catch (error) { + console.error('更新失败:', error); + throw error; + } +}; + +// 示例5:完整更新文档 +const updateDocumentFull = async () => { + const params: UpdateDocumentParams = { + id: '1234567890', // 必传 + KnowledgeId: 67890, // 可选 + filePath: '/new/path/document.pdf', // 可选 + fileSize: 2048000, // 可选 + format: 'pdf', // 可选 + title: '完全更新的文档' // 可选 + }; + + try { + const response = await updateDocument(params); + console.log('文档完整更新成功:', response.data); + return response.data; + } catch (error) { + console.error('更新失败:', error); + throw error; + } +}; + +// 示例6:删除文档 +const deleteDocumentExample = async (documentId: string) => { + try { + await deleteDocument(documentId); + console.log('文档删除成功'); + } catch (error) { + console.error('删除失败:', error); + throw error; + } +}; + +// 在Vue组件中使用 +/* +import { ref } from 'vue'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import { + createDocument, + CreateDocumentParams, + uploadDocument, + deleteDocument, + listDocuments, + DocumentQueryParams +} from '/@/api/knowledge/document'; + +export default defineComponent({ + setup() { + const formData = ref({ + KnowledgeId: 0, + filePath: '', + fileSize: 0, + format: '', + title: '' + }); + + const loading = ref(false); + const documentList = ref([]); + + // 创建文档 + const handleCreate = async () => { + // 验证必填字段 + if (!formData.value.KnowledgeId || !formData.value.filePath || + !formData.value.fileSize || !formData.value.format || !formData.value.title) { + ElMessage.error('请填写所有必填字段'); + return; + } + + loading.value = true; + try { + await createDocument(formData.value); + ElMessage.success('文档创建成功'); + // 重置表单 + formData.value = { + KnowledgeId: 0, + filePath: '', + fileSize: 0, + format: '', + title: '' + }; + // 刷新列表 + await getDocuments(); + } catch (error) { + ElMessage.error('创建失败,请重试'); + } finally { + loading.value = false; + } + }; + + // 文件上传 + const handleFileUpload = async (event: Event, knowledgeId: string) => { + const file = (event.target as HTMLInputElement).files?.[0]; + if (!file) return; + + const formData = new FormData(); + formData.append('file', file); + formData.append('datasetId', knowledgeId); + + loading.value = true; + try { + await uploadDocument(formData); + ElMessage.success('文档上传成功'); + await getDocuments(); + } catch (error) { + ElMessage.error('上传失败,请重试'); + } finally { + loading.value = false; + } + }; + + // 删除文档 + const handleDelete = async (id: string) => { + try { + await ElMessageBox.confirm('确定要删除这个文档吗?', '提示', { + type: 'warning', + }); + + await deleteDocument(id); + ElMessage.success('删除成功'); + await getDocuments(); + } catch (error) { + if (error !== 'cancel') { + ElMessage.error('删除失败'); + } + } + }; + + // 获取文档列表 + const getDocuments = async () => { + try { + const response = await listDocuments({ + pageNum: 1, + pageSize: 10 + }); + documentList.value = response.data.list; + } catch (error) { + console.error('获取列表失败:', error); + } + }; + + return { + formData, + loading, + documentList, + handleCreate, + handleFileUpload, + handleDelete, + getDocuments + }; + } +}); +*/ diff --git a/src/api/knowledge/document/index.ts b/src/api/knowledge/document/index.ts index 73d97a8..d442f65 100644 --- a/src/api/knowledge/document/index.ts +++ b/src/api/knowledge/document/index.ts @@ -10,6 +10,25 @@ export interface DocumentQueryParams { pageSize: number; } +// 创建文档参数 +export interface CreateDocumentParams { + KnowledgeId: number; // 必传 + filePath: string; // 必传 + fileSize: number; // 必传 + format: string; // 必传 + title: string; // 必传 +} + +// 更新文档参数 +export interface UpdateDocumentParams { + id: string; // 必传 + KnowledgeId?: number; // 可选 + filePath?: string; // 可选 + fileSize?: number; // 可选 + format?: string; // 可选 + title?: string; // 可选 +} + // 文档信息 export interface DocumentInfo { id?: string; @@ -58,6 +77,24 @@ export function getDocument(id: string) { }); } +// 创建文档(JSON格式) +export function createDocument(data: CreateDocumentParams) { + return newService({ + url: '/knowledge/document/create', + method: 'post', + data, + }); +} + +// 更新文档 +export function updateDocument(data: UpdateDocumentParams) { + return newService({ + url: '/knowledge/document/update', + method: 'put', + data, + }); +} + // 上传文档 export function uploadDocument(data: FormData) { return newService({ diff --git a/src/views/knowledge/component/documentDetailDialog.vue b/src/views/knowledge/component/documentDetailDialog.vue index b7a0f1f..ed84377 100644 --- a/src/views/knowledge/component/documentDetailDialog.vue +++ b/src/views/knowledge/component/documentDetailDialog.vue @@ -61,7 +61,7 @@
@@ -150,8 +150,8 @@ const selectAll = ref(false); // 过滤后的切片列表 const filteredChunks = computed(() => { if (!chunkSearch.value) return chunkList.value; - return chunkList.value.filter(chunk => - chunk.content.toLowerCase().includes(chunkSearch.value.toLowerCase()) + return chunkList.value.filter((chunk) => + (chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase()) ); }); @@ -182,8 +182,9 @@ const getDocumentDetail = async () => { // 模拟文档内容 documentContent.value = '

123

'; - } catch (error) { - console.error('获取文档详情失败:', error); + } catch (_error) { + ElMessage.error('获取文档详情失败'); + documentContent.value = ''; } finally { contentLoading.value = false; } @@ -203,8 +204,10 @@ const getChunkList = async () => { }, ]; chunkTotal.value = 1; - } catch (error) { - console.error('获取切片列表失败:', error); + } catch (_error) { + ElMessage.error('获取切片列表失败'); + chunkList.value = []; + chunkTotal.value = 0; } finally { chunkLoading.value = false; } diff --git a/src/views/knowledge/dataset/component/editDataset.vue b/src/views/knowledge/dataset/component/editDataset.vue index 1ed7daf..3d7f9aa 100644 --- a/src/views/knowledge/dataset/component/editDataset.vue +++ b/src/views/knowledge/dataset/component/editDataset.vue @@ -133,8 +133,8 @@ const openDialog = async (row?: any) => { ruleForm.embeddingModel = data.embeddingModel || 'text-embedding-ada-002'; ruleForm.documentCount = data.documentCount || 0; ruleForm.charCount = data.charCount || 0; - } catch (error) { - console.error('获取数据集详情失败:', error); + } catch (_error) { + ElMessage.error('获取数据集详情失败'); // 使用传入的row数据 ruleForm.id = row.id || ''; ruleForm.name = row.name || ''; @@ -183,12 +183,8 @@ const onSubmit = async () => { isShowDialog.value = false; emit('getDatasetList'); - } catch (error) { - console.error('提交失败:', error); - // 模拟成功 - ElMessage.success(isEdit.value ? '保存成功' : '创建成功'); - isShowDialog.value = false; - emit('getDatasetList'); + } catch (_error) { + ElMessage.error(isEdit.value ? '保存失败,请重试' : '创建失败,请重试'); } finally { submitLoading.value = false; } diff --git a/src/views/knowledge/dataset/index.vue b/src/views/knowledge/dataset/index.vue index e256123..f2c9171 100644 --- a/src/views/knowledge/dataset/index.vue +++ b/src/views/knowledge/dataset/index.vue @@ -29,7 +29,7 @@ 重置 - + 新增 @@ -63,6 +63,7 @@ active-text="启" inactive-text="停" @change="onStatusChange(scope.row)" + v-auth="'api/v1/knowledge/dataset/updateStatus'" /> @@ -70,9 +71,9 @@ @@ -137,48 +138,10 @@ const getDatasetList = async () => { statusEnabled: item.status === 'enable', })); tableData.total = res.data?.total || 0; - } catch (error) { - console.error('获取数据集列表失败:', error); - // 模拟数据 - tableData.data = [ - { - id: '1', - name: '产品知识库', - type: 'text', - documentCount: 15, - charCount: 125000, - embeddingModel: 'text-embedding-ada-002', - status: 'enable', - statusEnabled: true, - createdAt: '2024-01-15 10:30:00', - updatedAt: '2024-01-20 14:20:00', - }, - { - id: '2', - name: '常见问题FAQ', - type: 'qa', - documentCount: 50, - charCount: 85000, - embeddingModel: 'text-embedding-ada-002', - status: 'enable', - statusEnabled: true, - createdAt: '2024-01-10 09:00:00', - updatedAt: '2024-01-18 16:45:00', - }, - { - id: '3', - name: '数据报表', - type: 'table', - documentCount: 8, - charCount: 45000, - embeddingModel: 'text-embedding-ada-002', - status: 'disable', - statusEnabled: false, - createdAt: '2024-01-05 11:20:00', - updatedAt: '2024-01-12 10:30:00', - }, - ]; - tableData.total = 3; + } catch (_error) { + tableData.data = []; + tableData.total = 0; + ElMessage.error('获取数据集列表失败'); } finally { tableData.loading = false; } @@ -257,9 +220,9 @@ const onStatusChange = async (row: any) => { try { await updateDatasetStatus({ id: row.id, status: newStatus }); ElMessage.success(`${statusText}成功`); - } catch (error) { - console.error('状态更新失败:', error); - ElMessage.success(`${statusText}成功`); + } catch (_error) { + row.statusEnabled = !row.statusEnabled; + ElMessage.error(`${statusText}失败`); } }; @@ -274,10 +237,8 @@ const onRowDel = (row: any) => { await deleteDataset(row.id); ElMessage.success('删除成功'); getDatasetList(); - } catch (error) { - console.error('删除失败:', error); - ElMessage.success('删除成功'); - getDatasetList(); + } catch (_error) { + ElMessage.error('删除失败'); } }).catch(() => {}); }; diff --git a/src/views/knowledge/document/component/documentChunks.vue b/src/views/knowledge/document/component/documentChunks.vue index fad6e7c..5e44340 100644 --- a/src/views/knowledge/document/component/documentChunks.vue +++ b/src/views/knowledge/document/component/documentChunks.vue @@ -31,7 +31,7 @@
@@ -41,11 +41,11 @@ {{ chunk.tokenCount }} tokens
- + 编辑 - + 删除 @@ -132,25 +132,10 @@ const getChunkList = async () => { saving: false, })); tableData.total = res.data?.total || 0; - } catch (error) { - console.error('获取分段列表失败:', error); - // 模拟数据 - const mockChunks = []; - for (let i = 0; i < 10; i++) { - mockChunks.push({ - id: `chunk_${i + 1}`, - documentId: documentInfo.id, - content: `这是第 ${i + 1} 个分段的内容。在知识库系统中,文档会被自动分割成多个小段落,每个段落会生成对应的向量表示,用于后续的语义检索。分段的大小和重叠长度可以在上传时进行配置,以获得最佳的检索效果。`, - chunkIndex: i, - charCount: 120 + Math.floor(Math.random() * 50), - tokenCount: 80 + Math.floor(Math.random() * 30), - isEditing: false, - editContent: '', - saving: false, - }); - } - tableData.data = mockChunks; - tableData.total = 25; + } catch (_error) { + tableData.data = []; + tableData.total = 0; + ElMessage.error('获取分段列表失败'); } finally { loading.value = false; } @@ -188,13 +173,8 @@ const onSaveChunk = async (chunk: any) => { chunk.charCount = chunk.editContent.length; chunk.isEditing = false; ElMessage.success('保存成功'); - } catch (error) { - console.error('保存失败:', error); - // 模拟成功 - chunk.content = chunk.editContent; - chunk.charCount = chunk.editContent.length; - chunk.isEditing = false; - ElMessage.success('保存成功'); + } catch (_error) { + ElMessage.error('保存失败'); } finally { chunk.saving = false; } @@ -211,12 +191,8 @@ const onDeleteChunk = (chunk: any) => { await deleteDocumentChunk(chunk.id); ElMessage.success('删除成功'); getChunkList(); - } catch (error) { - console.error('删除失败:', error); - // 模拟成功 - ElMessage.success('删除成功'); - tableData.data = tableData.data.filter(item => item.id !== chunk.id); - tableData.total--; + } catch (_error) { + ElMessage.error('删除失败'); } }).catch(() => {}); }; diff --git a/src/views/knowledge/document/component/previewDocument.vue b/src/views/knowledge/document/component/previewDocument.vue index 8cc4fb8..e1ee5fc 100644 --- a/src/views/knowledge/document/component/previewDocument.vue +++ b/src/views/knowledge/document/component/previewDocument.vue @@ -107,7 +107,7 @@ const formattedContent = computed(() => { .replace(//g, '>') .replace(/\n/g, '
') - .replace(/ /g, '  '); + .replace(/ {2}/g, '  '); }); // 获取文件图标颜色 @@ -222,31 +222,9 @@ const openDialog = async (row: any) => { if (contentRes.data) { documentContent.value = contentRes.data.content || ''; } - } catch (error) { - console.error('获取文档详情失败:', error); - // 模拟内容 - documentContent.value = `这是文档【${row.name}】的示例内容。 - -在实际应用中,这里会显示文档的原始文本内容。 - -文档处理流程: -1. 上传文档到系统 -2. 系统自动解析文档内容 -3. 对内容进行分段处理 -4. 生成向量索引 -5. 完成知识库构建 - -支持的文档格式: -- PDF 文档 -- Word 文档 (.docx) -- 纯文本文件 (.txt) -- Markdown 文件 (.md) -- HTML 文件 - -注意事项: -- 单个文件大小不超过 20MB -- 建议使用标准格式的文档 -- 复杂表格可能需要特殊处理`; + } catch (_error) { + documentContent.value = ''; + ElMessage.error('获取文档详情失败'); } finally { loading.value = false; } diff --git a/src/views/knowledge/document/component/uploadDocument.vue b/src/views/knowledge/document/component/uploadDocument.vue index 9bb8067..4a840f5 100644 --- a/src/views/knowledge/document/component/uploadDocument.vue +++ b/src/views/knowledge/document/component/uploadDocument.vue @@ -195,12 +195,8 @@ const onSubmit = async () => { ElMessage.success(`成功上传 ${fileList.value.length} 个文件`); isShowDialog.value = false; emit('getDocumentList'); - } catch (error) { - console.error('上传失败:', error); - // 模拟成功 - ElMessage.success(`成功上传 ${fileList.value.length} 个文件`); - isShowDialog.value = false; - emit('getDocumentList'); + } catch (_error) { + ElMessage.error('上传失败,请重试'); } finally { submitLoading.value = false; } diff --git a/src/views/knowledge/document/detail.vue b/src/views/knowledge/document/detail.vue index 89a913c..c96772f 100644 --- a/src/views/knowledge/document/detail.vue +++ b/src/views/knowledge/document/detail.vue @@ -66,7 +66,7 @@
@@ -115,6 +115,7 @@ export default { import { ref, reactive, computed, onMounted } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import { ElMessage } from 'element-plus'; +import { getDocument, listDocumentChunks, previewDocument } from '/@/api/knowledge/document'; const route = useRoute(); const router = useRouter(); @@ -150,8 +151,8 @@ const selectAll = ref(false); // 过滤后的切片列表 const filteredChunks = computed(() => { if (!chunkSearch.value) return chunkList.value; - return chunkList.value.filter(chunk => - chunk.content.toLowerCase().includes(chunkSearch.value.toLowerCase()) + return chunkList.value.filter((chunk) => + (chunk.content || '').toLowerCase().includes(chunkSearch.value.toLowerCase()) ); }); @@ -171,14 +172,14 @@ const truncateText = (text: string, maxLength: number) => { // 返回知识库列表 const onBackToKnowledge = () => { - router.push('/knowledge'); + router.push('/knowledge/dataset'); }; // 返回数据集详情 const onBackToDataset = () => { router.push({ - path: '/knowledge', - query: { datasetId: datasetId.value, datasetName: datasetName.value } + path: '/knowledge/document', + query: { datasetId: datasetId.value, datasetName: datasetName.value }, }); }; @@ -186,17 +187,19 @@ const onBackToDataset = () => { const getDocumentDetail = async () => { contentLoading.value = true; try { - // 模拟数据 - documentInfo.id = documentId.value; - documentInfo.name = route.query.docName as string || '456_product(1).txt'; - documentInfo.fileType = 'txt'; - documentInfo.fileSize = 10; - documentInfo.createdAt = '22/01/2026 00:53:32'; - - // 模拟文档内容 - documentContent.value = '

123

'; - } catch (error) { - console.error('获取文档详情失败:', error); + const [detailRes, contentRes] = await Promise.all([getDocument(documentId.value), previewDocument(documentId.value)]); + const detail = detailRes.data || {}; + documentInfo.id = detail.id || documentId.value; + documentInfo.name = detail.name || (route.query.docName as string) || ''; + documentInfo.fileType = detail.fileType || ''; + documentInfo.fileSize = detail.fileSize || 0; + documentInfo.createdAt = detail.createdAt || ''; + const contentData = contentRes.data; + documentContent.value = + typeof contentData === 'string' ? contentData : contentData?.content || contentData?.text || ''; + } catch (_error) { + ElMessage.error('获取文档详情失败'); + documentContent.value = ''; } finally { contentLoading.value = false; } @@ -206,18 +209,21 @@ const getDocumentDetail = async () => { const getChunkList = async () => { chunkLoading.value = true; try { - // 模拟数据 - chunkList.value = [ - { - id: '1', - content: '123', - enabled: true, - selected: false, - }, - ]; - chunkTotal.value = 1; - } catch (error) { - console.error('获取切片列表失败:', error); + const res: any = await listDocumentChunks({ + documentId: documentId.value, + pageNum: chunkPage.value, + pageSize: chunkPageSize.value, + }); + chunkList.value = (res.data?.list || []).map((item: any) => ({ + ...item, + enabled: true, + selected: false, + })); + chunkTotal.value = res.data?.total || 0; + } catch (_error) { + chunkList.value = []; + chunkTotal.value = 0; + ElMessage.error('获取切片列表失败'); } finally { chunkLoading.value = false; } @@ -225,14 +231,14 @@ const getChunkList = async () => { // 全选变化 const onSelectAllChange = (val: boolean) => { - chunkList.value.forEach(chunk => { + chunkList.value.forEach((chunk) => { chunk.selected = val; }); }; // 切片状态变化 -const onChunkStatusChange = (chunk: any) => { - ElMessage.success(chunk.enabled ? '已启用' : '已禁用'); +const onChunkStatusChange = (_chunk: any) => { + ElMessage.info('切片启停功能暂未开放'); }; // 添加切片 @@ -242,10 +248,14 @@ const onAddChunk = () => { // 初始化 onMounted(() => { - datasetId.value = route.query.datasetId as string || ''; - datasetName.value = route.query.datasetName as string || 'dataset_tenant_1'; - documentId.value = route.query.docId as string || ''; - + datasetId.value = (route.query.datasetId as string) || ''; + datasetName.value = (route.query.datasetName as string) || ''; + documentId.value = (route.query.docId as string) || ''; + if (!documentId.value) { + ElMessage.warning('缺少文档ID,无法查看详情'); + onBackToDataset(); + return; + } getDocumentDetail(); getChunkList(); }); diff --git a/src/views/knowledge/document/index.vue b/src/views/knowledge/document/index.vue index 65626e3..44b3221 100644 --- a/src/views/knowledge/document/index.vue +++ b/src/views/knowledge/document/index.vue @@ -46,11 +46,11 @@ 重置 - + 上传文档 - + 批量删除 @@ -103,9 +103,9 @@ @@ -190,14 +190,9 @@ const getDatasetOptions = async () => { try { const res: any = await listDatasets({ pageNum: 1, pageSize: 1000 }); datasetOptions.value = res.data?.list || []; - } catch (error) { - console.error('获取数据集列表失败:', error); - // 模拟数据 - datasetOptions.value = [ - { id: '1', name: '产品知识库' }, - { id: '2', name: '常见问题FAQ' }, - { id: '3', name: '数据报表' }, - ]; + } catch (_error) { + datasetOptions.value = []; + ElMessage.error('获取数据集列表失败'); } }; @@ -212,65 +207,10 @@ const getDocumentList = async () => { const res: any = await listDocuments(params); tableData.data = res.data?.list || []; tableData.total = res.data?.total || 0; - } catch (error) { - console.error('获取文档列表失败:', error); - // 模拟数据 - tableData.data = [ - { - id: '1', - name: '产品使用手册.pdf', - datasetId: '1', - datasetName: '产品知识库', - fileType: 'pdf', - fileSize: 2048000, - charCount: 15000, - chunkCount: 25, - status: 'completed', - indexStatus: 'indexed', - createdAt: '2024-01-15 10:30:00', - }, - { - id: '2', - name: '常见问题解答.docx', - datasetId: '2', - datasetName: '常见问题FAQ', - fileType: 'docx', - fileSize: 512000, - charCount: 8000, - chunkCount: 12, - status: 'completed', - indexStatus: 'indexed', - createdAt: '2024-01-14 14:20:00', - }, - { - id: '3', - name: '技术文档.md', - datasetId: '1', - datasetName: '产品知识库', - fileType: 'md', - fileSize: 128000, - charCount: 5000, - chunkCount: 8, - status: 'processing', - indexStatus: 'indexing', - createdAt: '2024-01-13 09:15:00', - }, - { - id: '4', - name: '错误日志.txt', - datasetId: '1', - datasetName: '产品知识库', - fileType: 'txt', - fileSize: 64000, - charCount: 3000, - chunkCount: 0, - status: 'failed', - indexStatus: 'not_indexed', - errorMessage: '文件编码不支持', - createdAt: '2024-01-12 16:45:00', - }, - ]; - tableData.total = 4; + } catch (_error) { + tableData.data = []; + tableData.total = 0; + ElMessage.error('获取文档列表失败'); } finally { tableData.loading = false; } @@ -399,10 +339,8 @@ const onReprocess = async (row: any) => { await reprocessDocument(row.id); ElMessage.success('已重新提交处理'); getDocumentList(); - } catch (error) { - console.error('重新处理失败:', error); - ElMessage.success('已重新提交处理'); - getDocumentList(); + } catch (_error) { + ElMessage.error('重新处理失败'); } }; @@ -422,10 +360,8 @@ const onBatchDelete = () => { await batchDeleteDocuments(selectedIds.value); ElMessage.success('删除成功'); getDocumentList(); - } catch (error) { - console.error('批量删除失败:', error); - ElMessage.success('删除成功'); - getDocumentList(); + } catch (_error) { + ElMessage.error('批量删除失败'); } }).catch(() => {}); }; @@ -441,10 +377,8 @@ const onRowDel = (row: any) => { await deleteDocument(row.id); ElMessage.success('删除成功'); getDocumentList(); - } catch (error) { - console.error('删除失败:', error); - ElMessage.success('删除成功'); - getDocumentList(); + } catch (_error) { + ElMessage.error('删除失败'); } }).catch(() => {}); }; diff --git a/src/views/knowledge/index.vue b/src/views/knowledge/index.vue index 76497d8..b761347 100644 --- a/src/views/knowledge/index.vue +++ b/src/views/knowledge/index.vue @@ -342,12 +342,10 @@ export default {