mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 10:12:51 +00:00
feat: knowledge
This commit is contained in:
parent
0cb33dad5a
commit
d33bc56db1
|
|
@ -75,7 +75,7 @@ const putSyncWebKnowledge: (
|
|||
* 向量化知识库
|
||||
* @param 参数 knowledge_id
|
||||
*/
|
||||
const putReEmbeddingDataset: (
|
||||
const putReEmbeddingKnowledge: (
|
||||
wordspace_id: string,
|
||||
knowledge_id: string,
|
||||
loading?: Ref<boolean>,
|
||||
|
|
@ -110,7 +110,7 @@ const getKnowledgeDetail: (
|
|||
"embedding": "string"
|
||||
}
|
||||
*/
|
||||
const postDataset: (
|
||||
const postKnowledge: (
|
||||
wordspace_id: string,
|
||||
data: knowledgeData,
|
||||
loading?: Ref<boolean>,
|
||||
|
|
@ -130,7 +130,7 @@ const postDataset: (
|
|||
"selector": "string"
|
||||
}
|
||||
*/
|
||||
const postWebDataset: (
|
||||
const postWebKnowledge: (
|
||||
wordspace_id: string,
|
||||
data: any,
|
||||
loading?: Ref<boolean>,
|
||||
|
|
@ -138,29 +138,30 @@ const postWebDataset: (
|
|||
return post(`${prefix}/${wordspace_id}/knowledge/web`, data, undefined, loading)
|
||||
}
|
||||
/**
|
||||
* 创建Lark知识库
|
||||
* 修改知识库信息
|
||||
* @param 参数
|
||||
* knowledge_id
|
||||
* {
|
||||
"name": "string",
|
||||
"desc": "string",
|
||||
"app_id": "string",
|
||||
"app_secret": "string",
|
||||
"folder_token": "string",
|
||||
"desc": true
|
||||
}
|
||||
*/
|
||||
const postLarkDataset: (data: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
data,
|
||||
loading,
|
||||
) => {
|
||||
return post(`${prefix}/lark/save`, data, undefined, loading)
|
||||
const putKnowledge: (
|
||||
wordspace_id: string,
|
||||
knowledge_id: string,
|
||||
data: any,
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<any>> = (wordspace_id, knowledge_id, data, loading) => {
|
||||
return put(`${prefix}/${wordspace_id}/knowledge/${knowledge_id}`, data, undefined, loading)
|
||||
}
|
||||
|
||||
export default {
|
||||
getKnowledgeByFolder,
|
||||
getKnowledgeList,
|
||||
putReEmbeddingDataset,
|
||||
putReEmbeddingKnowledge,
|
||||
putSyncWebKnowledge,
|
||||
getKnowledgeDetail,
|
||||
postDataset,
|
||||
postWebDataset
|
||||
postKnowledge,
|
||||
postWebKnowledge,
|
||||
putKnowledge,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import { get, post, del, put } from '@/request/index'
|
|||
import type { Ref } from 'vue'
|
||||
import type { KeyValue } from '@/api/type/common'
|
||||
import type { pageRequest } from '@/api/type/common'
|
||||
const prefix = '/dataset'
|
||||
const prefix = '/workspace'
|
||||
|
||||
/**
|
||||
* 文档分页列表
|
||||
* @param 参数 dataset_id,
|
||||
* 问题分页列表
|
||||
* @param 参数 dataset_id,
|
||||
* page {
|
||||
"current_page": "string",
|
||||
"page_size": "string",
|
||||
|
|
@ -18,15 +18,16 @@ const prefix = '/dataset'
|
|||
*/
|
||||
|
||||
const getProblems: (
|
||||
workspace_id: string,
|
||||
dataset_id: string,
|
||||
page: pageRequest,
|
||||
param: any,
|
||||
loading?: Ref<boolean>
|
||||
) => Promise<Result<any>> = (dataset_id, page, param, loading) => {
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<any>> = (wordspace_id, dataset_id, page, param, loading) => {
|
||||
return get(
|
||||
`${prefix}/${dataset_id}/problem/${page.current_page}/${page.page_size}`,
|
||||
`${prefix}/${wordspace_id}/knowledge/${dataset_id}/problem/${page.current_page}/${page.page_size}`,
|
||||
param,
|
||||
loading
|
||||
loading,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +39,7 @@ const getProblems: (
|
|||
const postProblems: (
|
||||
dataset_id: string,
|
||||
data: any,
|
||||
loading?: Ref<boolean>
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<any>> = (dataset_id, data, loading) => {
|
||||
return post(`${prefix}/${dataset_id}/problem`, data, undefined, loading)
|
||||
}
|
||||
|
|
@ -50,7 +51,7 @@ const postProblems: (
|
|||
const delProblems: (
|
||||
dataset_id: string,
|
||||
problem_id: string,
|
||||
loading?: Ref<boolean>
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<boolean>> = (dataset_id, problem_id, loading) => {
|
||||
return del(`${prefix}/${dataset_id}/problem/${problem_id}`, loading)
|
||||
}
|
||||
|
|
@ -62,15 +63,15 @@ const delProblems: (
|
|||
const delMulProblem: (
|
||||
dataset_id: string,
|
||||
data: any,
|
||||
loading?: Ref<boolean>
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<boolean>> = (dataset_id, data, loading) => {
|
||||
return del(`${prefix}/${dataset_id}/problem/_batch`, undefined, data, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改问题
|
||||
* @param 参数
|
||||
* dataset_id, problem_id,
|
||||
* @param 参数
|
||||
* dataset_id, problem_id,
|
||||
* {
|
||||
"content": "string",
|
||||
}
|
||||
|
|
@ -79,7 +80,7 @@ const putProblems: (
|
|||
dataset_id: string,
|
||||
problem_id: string,
|
||||
data: any,
|
||||
loading?: Ref<boolean>
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<any>> = (dataset_id, problem_id, data: any, loading) => {
|
||||
return put(`${prefix}/${dataset_id}/problem/${problem_id}`, data, undefined, loading)
|
||||
}
|
||||
|
|
@ -92,7 +93,7 @@ const putProblems: (
|
|||
const getDetailProblems: (
|
||||
dataset_id: string,
|
||||
problem_id: string,
|
||||
loading?: Ref<boolean>
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<any>> = (dataset_id, problem_id, loading) => {
|
||||
return get(`${prefix}/${dataset_id}/problem/${problem_id}/paragraph`, undefined, loading)
|
||||
}
|
||||
|
|
@ -108,7 +109,7 @@ const getDetailProblems: (
|
|||
const postMulAssociationProblem: (
|
||||
dataset_id: string,
|
||||
data: any,
|
||||
loading?: Ref<boolean>
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<boolean>> = (dataset_id, data, loading) => {
|
||||
return post(`${prefix}/${dataset_id}/problem/_batch`, data, undefined, loading)
|
||||
}
|
||||
|
|
@ -120,5 +121,5 @@ export default {
|
|||
putProblems,
|
||||
getDetailProblems,
|
||||
delMulProblem,
|
||||
postMulAssociationProblem
|
||||
postMulAssociationProblem,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,4 +25,44 @@ export default {
|
|||
])
|
||||
},
|
||||
},
|
||||
'app-setting': {
|
||||
iconReader: () => {
|
||||
return h('i', [
|
||||
h(
|
||||
'svg',
|
||||
{
|
||||
viewBox: '0 0 20 20',
|
||||
version: '1.1',
|
||||
xmlns: 'http://www.w3.org/2000/svg',
|
||||
},
|
||||
[
|
||||
h('path', {
|
||||
d: 'M3.60734 16.4448L3.34807 16.1624C2.44036 15.1737 1.75935 13.9944 1.36011 12.7066L1.24756 12.3435L2.95427 10.0001L1.24756 7.65668L1.36011 7.29361C1.75935 6.00574 2.44036 4.82649 3.34807 3.83779L3.60734 3.55539L6.47552 3.86889L7.64049 1.21319L8.01405 1.12909C8.66134 0.983366 9.32633 0.90918 10.0004 0.90918C10.6744 0.90918 11.3394 0.983366 11.9867 1.12909L12.3603 1.21319L13.5252 3.86889L16.3934 3.55539L16.6527 3.83779C17.5604 4.82649 18.2414 6.00574 18.6406 7.29361L18.7532 7.65668L17.0465 10.0001L18.7532 12.3435L18.6406 12.7066C18.2414 13.9944 17.5604 15.1737 16.6527 16.1624L16.3934 16.4448L13.5252 16.1313L12.3603 18.787L11.9867 18.8711C11.3394 19.0168 10.6744 19.091 10.0004 19.091C9.32633 19.091 8.66134 19.0168 8.01405 18.8711L7.64049 18.787L6.47552 16.1313L3.60734 16.4448ZM6.51159 14.6031C7.05002 14.5443 7.56436 14.8417 7.78194 15.3377L8.71565 17.4662C9.13677 17.5389 9.56603 17.5758 10.0004 17.5758C10.4347 17.5758 10.864 17.5389 11.2851 17.4662L12.2188 15.3377C12.4364 14.8417 12.9507 14.5443 13.4892 14.6031L15.7844 14.854C16.3387 14.1868 16.7757 13.4286 17.0741 12.6116L15.7038 10.7301C15.3869 10.295 15.3869 9.70511 15.7038 9.26999L17.0741 7.38847C16.7757 6.57146 16.3387 5.81331 15.7844 5.14609L13.4892 5.39696C12.9507 5.45581 12.4364 5.1584 12.2188 4.66238L11.2851 2.53389C10.864 2.46117 10.4347 2.42429 10.0004 2.42429C9.56603 2.42429 9.13677 2.46117 8.71565 2.53389L7.78194 4.66238C7.56436 5.1584 7.05002 5.45581 6.51159 5.39696L4.21641 5.14609C3.66208 5.81331 3.22502 6.57146 2.92666 7.38847L4.29697 9.26999C4.61387 9.70511 4.61387 10.295 4.29697 10.7301L2.92666 12.6116C3.22502 13.4286 3.66208 14.1868 4.21641 14.854L6.51159 14.6031ZM10.0004 13.788C7.91555 13.788 6.22693 12.0913 6.22693 10.0001C6.22693 7.9089 7.91555 6.2122 10.0004 6.2122C12.0852 6.2122 13.7738 7.9089 13.7738 10.0001C13.7738 12.0913 12.0852 13.788 10.0004 13.788ZM10.0004 12.2729C11.2468 12.2729 12.2587 11.2561 12.2587 10.0001C12.2587 8.74413 11.2468 7.72741 10.0004 7.72741C8.75397 7.72741 7.74208 8.74413 7.74208 10.0001C7.74208 11.2561 8.75397 12.2729 10.0004 12.2729Z',
|
||||
fill: 'currentColor',
|
||||
}),
|
||||
],
|
||||
),
|
||||
])
|
||||
},
|
||||
},
|
||||
'app-setting-active': {
|
||||
iconReader: () => {
|
||||
return h('i', [
|
||||
h(
|
||||
'svg',
|
||||
{
|
||||
viewBox: '0 0 20 20',
|
||||
version: '1.1',
|
||||
xmlns: 'http://www.w3.org/2000/svg',
|
||||
},
|
||||
[
|
||||
h('path', {
|
||||
d: 'M3.26425 16.2151C2.35478 15.2292 1.65887 14.0432 1.25 12.7305L2.70785 10.7384C3.02952 10.2988 3.02952 9.70154 2.70785 9.26197L1.25 7.26979C1.65887 5.95714 2.35478 4.77112 3.26425 3.78522L5.71416 4.05172C6.25589 4.11065 6.77338 3.81185 6.99316 3.31321L7.98848 1.05505C8.63579 0.910018 9.30896 0.833496 10 0.833496C10.691 0.833496 11.3642 0.910018 12.0115 1.05505L13.0068 3.31321C13.2266 3.81185 13.7441 4.11065 14.2858 4.05172L16.7357 3.78522C17.6452 4.77112 18.3411 5.95714 18.75 7.26979L17.2921 9.26197C16.9705 9.70154 16.9705 10.2988 17.2921 10.7384L18.75 12.7305C18.3411 14.0432 17.6452 15.2292 16.7357 16.2151L14.2858 15.9486C13.7441 15.8897 13.2266 16.1885 13.0068 16.6871L12.0115 18.9453C11.3642 19.0903 10.691 19.1668 10 19.1668C9.30896 19.1668 8.63579 19.0903 7.98848 18.9453L6.99316 16.6871C6.77338 16.1885 6.25589 15.8897 5.71416 15.9486L3.26425 16.2151ZM10 13.3335C11.8409 13.3335 13.3333 11.8411 13.3333 10.0002C13.3333 8.15921 11.8409 6.66683 10 6.66683C8.15905 6.66683 6.66667 8.15921 6.66667 10.0002C6.66667 11.8411 8.15905 13.3335 10 13.3335Z',
|
||||
fill: 'currentColor',
|
||||
}),
|
||||
],
|
||||
),
|
||||
])
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,4 +79,5 @@ export default {
|
|||
fileSizeExceeded: 'File size exceeds 10 MB',
|
||||
uploadImagePrompt: 'Please upload an image',
|
||||
},
|
||||
info: 'Base Information',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ export default {
|
|||
title: 'User',
|
||||
createUser: 'Create User',
|
||||
editUser: 'Edit User',
|
||||
info: 'Base Information',
|
||||
roleSetting: 'Role Setting',
|
||||
setting: {
|
||||
updatePwd: 'Change Password',
|
||||
|
|
|
|||
|
|
@ -83,4 +83,5 @@ export default {
|
|||
fileSizeExceeded: '文件大小超过 10 MB',
|
||||
uploadImagePrompt: '请上传一张图片',
|
||||
},
|
||||
info: '基本信息',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ export default {
|
|||
title: '用户管理',
|
||||
createUser: '创建用户',
|
||||
editUser: '编辑用户',
|
||||
info: '基本信息',
|
||||
roleSetting: '角色设置',
|
||||
setting: {
|
||||
updatePwd: '修改用户密码',
|
||||
|
|
|
|||
|
|
@ -79,4 +79,5 @@ export default {
|
|||
fileSizeExceeded: '檔案大小超過 10 MB',
|
||||
uploadImagePrompt: '請上傳一張圖片',
|
||||
},
|
||||
info: '使用者資訊',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,23 +2,22 @@ export default {
|
|||
title: '使用者管理',
|
||||
createUser: '建立使用者',
|
||||
editUser: '編輯使用者',
|
||||
info: '使用者資訊',
|
||||
roleSetting: '角色設定',
|
||||
setting: {
|
||||
updatePwd: '修改使用者密碼'
|
||||
updatePwd: '修改使用者密碼',
|
||||
},
|
||||
tip: {
|
||||
professionalMessage: '社群版最多支援 2 個使用者,如需擁有更多使用者,請升級為專業版。',
|
||||
updatePwdSuccess: '使用者密碼修改成功'
|
||||
updatePwdSuccess: '使用者密碼修改成功',
|
||||
},
|
||||
delete: {
|
||||
confirmTitle: '是否刪除該使用者?',
|
||||
confirmMessage:
|
||||
'刪除該使用者後,該使用者建立的所有資源(應用、知識庫、模型)都會被刪除,請謹慎操作。'
|
||||
'刪除該使用者後,該使用者建立的所有資源(應用、知識庫、模型)都會被刪除,請謹慎操作。',
|
||||
},
|
||||
disabled: {
|
||||
confirmTitle: '是否停用函數?',
|
||||
confirmMessage: '停用後,引用該函數的應用在查詢時會報錯,請謹慎操作。'
|
||||
confirmMessage: '停用後,引用該函數的應用在查詢時會報錯,請謹慎操作。',
|
||||
},
|
||||
userForm: {
|
||||
form: {
|
||||
|
|
@ -26,45 +25,45 @@ export default {
|
|||
label: '使用者名稱',
|
||||
placeholder: '請輸入使用者名稱',
|
||||
requiredMessage: '請輸入使用者名稱',
|
||||
lengthMessage: '長度須介於 6 到 20 個字元之間'
|
||||
lengthMessage: '長度須介於 6 到 20 個字元之間',
|
||||
},
|
||||
nick_name: {
|
||||
label: '姓名',
|
||||
placeholder: '請輸入姓名'
|
||||
placeholder: '請輸入姓名',
|
||||
},
|
||||
email: {
|
||||
label: '電子信箱',
|
||||
placeholder: '請輸入電子信箱',
|
||||
requiredMessage: '請輸入電子信箱'
|
||||
requiredMessage: '請輸入電子信箱',
|
||||
},
|
||||
phone: {
|
||||
label: '手機號碼',
|
||||
placeholder: '請輸入手機號碼'
|
||||
placeholder: '請輸入手機號碼',
|
||||
},
|
||||
password: {
|
||||
label: '登入密碼',
|
||||
placeholder: '請輸入密碼',
|
||||
requiredMessage: '請輸入密碼',
|
||||
lengthMessage: '長度須介於 6 到 20 個字元之間'
|
||||
lengthMessage: '長度須介於 6 到 20 個字元之間',
|
||||
},
|
||||
new_password: {
|
||||
label: '新密碼',
|
||||
placeholder: '請輸入新密碼',
|
||||
requiredMessage: '請輸入新密碼'
|
||||
requiredMessage: '請輸入新密碼',
|
||||
},
|
||||
re_password: {
|
||||
label: '確認密碼',
|
||||
placeholder: '請輸入確認密碼',
|
||||
requiredMessage: '請輸入確認密碼',
|
||||
validatorMessage: '密碼不一致'
|
||||
}
|
||||
}
|
||||
validatorMessage: '密碼不一致',
|
||||
},
|
||||
},
|
||||
},
|
||||
source: {
|
||||
label: '使用者來源',
|
||||
local: '系統使用者',
|
||||
wecom: '企業微信',
|
||||
lark: '飛書',
|
||||
dingtalk: '釘釘'
|
||||
}
|
||||
dingtalk: '釘釘',
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,19 +43,19 @@ const DocumentRouter = {
|
|||
},
|
||||
component: () => import('@/views/hit-test/index.vue')
|
||||
},
|
||||
// {
|
||||
// path: 'setting',
|
||||
// name: 'DatasetSetting',
|
||||
// meta: {
|
||||
// icon: 'app-setting',
|
||||
// iconActive: 'app-setting-active',
|
||||
// title: 'common.setting',
|
||||
// active: 'setting',
|
||||
// parentPath: '/knowledge/:id/:folderId',
|
||||
// parentName: 'KnowledgeDetail'
|
||||
// },
|
||||
// component: () => import('@/views/dataset/DatasetSetting.vue')
|
||||
// }
|
||||
{
|
||||
path: 'setting',
|
||||
name: 'KnowledgeSetting',
|
||||
meta: {
|
||||
icon: 'app-setting',
|
||||
iconActive: 'app-setting-active',
|
||||
title: 'common.setting',
|
||||
active: 'setting',
|
||||
parentPath: '/knowledge/:id/:folderId',
|
||||
parentName: 'KnowledgeDetail'
|
||||
},
|
||||
component: () => import('@/views/knowledge/KnowledgeSetting.vue')
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import useThemeStore from './modules/theme'
|
|||
import useKnowledgeStore from './modules/knowledge'
|
||||
import useModelStore from './modules/model'
|
||||
import usePromptStore from './modules/prompt'
|
||||
import useProblemStore from './modules/problem'
|
||||
|
||||
const useStore = () => ({
|
||||
common: useCommonStore(),
|
||||
|
|
@ -16,6 +17,7 @@ const useStore = () => ({
|
|||
knowledge: useKnowledgeStore(),
|
||||
model: useModelStore(),
|
||||
prompt: usePromptStore(),
|
||||
problem: useProblemStore(),
|
||||
})
|
||||
|
||||
export default useStore
|
||||
|
|
|
|||
|
|
@ -59,10 +59,15 @@ const useKnowledgeStore = defineStore('knowledge', {
|
|||
})
|
||||
})
|
||||
},
|
||||
async asyncSyncDataset(id: string, sync_type: string, loading?: Ref<boolean>) {
|
||||
async asyncSyncDataset(
|
||||
workspace_id: string,
|
||||
id: string,
|
||||
sync_type: string,
|
||||
loading?: Ref<boolean>,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
knowledgeApi
|
||||
.putSyncWebKnowledge(id, sync_type, loading)
|
||||
.putSyncWebKnowledge(workspace_id, id, sync_type, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { type Ref } from 'vue'
|
||||
import problemApi from '@/api/knowledge/problem'
|
||||
import paragraphApi from '@/api/knowledge/paragraph'
|
||||
import type { pageRequest } from '@/api/type/common'
|
||||
|
||||
const useProblemStore = defineStore('problem', {
|
||||
state: () => ({}),
|
||||
actions: {
|
||||
async asyncPostProblem(datasetId: string, data: any, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
problemApi
|
||||
.postProblems(datasetId, data, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
async asyncGetProblem(
|
||||
workspace_id: string,
|
||||
datasetId: string,
|
||||
page: pageRequest,
|
||||
param: any,
|
||||
loading?: Ref<boolean>,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
problemApi
|
||||
.getProblems(workspace_id, datasetId, page, param, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
async asyncDisassociationProblem(
|
||||
datasetId: string,
|
||||
documentId: string,
|
||||
paragraphId: string,
|
||||
problemId: string,
|
||||
loading?: Ref<boolean>,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
paragraphApi
|
||||
.disassociationProblem(datasetId, documentId, paragraphId, problemId, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
async asyncAssociationProblem(
|
||||
datasetId: string,
|
||||
documentId: string,
|
||||
paragraphId: string,
|
||||
problemId: string,
|
||||
loading?: Ref<boolean>,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
paragraphApi
|
||||
.associationProblem(datasetId, documentId, paragraphId, problemId, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default useProblemStore
|
||||
|
|
@ -1,94 +1,88 @@
|
|||
<template>
|
||||
<div class="hit-test">
|
||||
<LayoutContainer>
|
||||
<template #header>
|
||||
<h4>
|
||||
{{ $t('views.application.hitTest.title') }}
|
||||
<el-text type="info" class="ml-4"> {{ $t('views.application.hitTest.text') }}</el-text>
|
||||
</h4>
|
||||
</template>
|
||||
<div class="hit-test__main p-16" v-loading="loading">
|
||||
<div class="question-title" :style="{ visibility: questionTitle ? 'visible' : 'hidden' }">
|
||||
<div class="avatar">
|
||||
<el-avatar>
|
||||
<img src="@/assets/user-icon.svg" style="width: 54%" alt="" />
|
||||
</el-avatar>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h4 class="text break-all">{{ questionTitle }}</h4>
|
||||
</div>
|
||||
<div class="hit-test p-16-24">
|
||||
<h4>
|
||||
{{ $t('views.application.hitTest.title') }}
|
||||
<el-text type="info" class="ml-4"> {{ $t('views.application.hitTest.text') }}</el-text>
|
||||
</h4>
|
||||
<el-card style="--el-card-padding: 0" class="hit-test__main p-16 mt-16 mb-16" v-loading="loading">
|
||||
<div class="question-title" :style="{ visibility: questionTitle ? 'visible' : 'hidden' }">
|
||||
<div class="avatar">
|
||||
<el-avatar>
|
||||
<img src="@/assets/user-icon.svg" style="width: 54%" alt="" />
|
||||
</el-avatar>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h4 class="text break-all">{{ questionTitle }}</h4>
|
||||
</div>
|
||||
<el-scrollbar>
|
||||
<div class="hit-test-height">
|
||||
<el-empty
|
||||
v-if="first"
|
||||
:image="emptyImg"
|
||||
:description="$t('views.application.hitTest.emptyMessage1')"
|
||||
style="padding-top: 160px"
|
||||
:image-size="125"
|
||||
/>
|
||||
<el-empty
|
||||
v-else-if="paragraphDetail.length == 0"
|
||||
:description="$t('views.application.hitTest.emptyMessage2')"
|
||||
style="padding-top: 160px"
|
||||
:image-size="125"
|
||||
/>
|
||||
<el-row v-else>
|
||||
<el-col
|
||||
:xs="24"
|
||||
:sm="12"
|
||||
:md="12"
|
||||
:lg="8"
|
||||
:xl="6"
|
||||
v-for="(item, index) in paragraphDetail"
|
||||
:key="index"
|
||||
class="p-8"
|
||||
>
|
||||
<CardBox
|
||||
shadow="hover"
|
||||
:title="item.title || '-'"
|
||||
:description="item.content"
|
||||
class="document-card layout-bg layout-bg cursor"
|
||||
:class="item.is_active ? '' : 'disabled'"
|
||||
:showIcon="false"
|
||||
@click="editParagraph(item)"
|
||||
>
|
||||
<template #icon>
|
||||
<el-avatar class="mr-12 avatar-light" :size="22">
|
||||
{{ index + 1 + '' }}</el-avatar
|
||||
>
|
||||
</template>
|
||||
<div class="active-button primary">{{ item.similarity?.toFixed(3) }}</div>
|
||||
<template #footer>
|
||||
<div class="footer-content flex-between">
|
||||
<el-text>
|
||||
<el-icon>
|
||||
<Document />
|
||||
</el-icon>
|
||||
{{ item?.document_name }}
|
||||
</el-text>
|
||||
<div v-if="item.trample_num || item.star_num">
|
||||
<span v-if="item.star_num">
|
||||
<AppIcon iconName="app-like-color"></AppIcon>
|
||||
{{ item.star_num }}
|
||||
</span>
|
||||
<span v-if="item.trample_num" class="ml-4">
|
||||
<AppIcon iconName="app-oppose-color"></AppIcon>
|
||||
{{ item.trample_num }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</CardBox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<el-scrollbar>
|
||||
<div class="hit-test-height">
|
||||
<el-empty
|
||||
v-if="first"
|
||||
:image="emptyImg"
|
||||
:description="$t('views.application.hitTest.emptyMessage1')"
|
||||
style="padding-top: 160px"
|
||||
:image-size="125"
|
||||
/>
|
||||
<el-empty
|
||||
v-else-if="paragraphDetail.length == 0"
|
||||
:description="$t('views.application.hitTest.emptyMessage2')"
|
||||
style="padding-top: 160px"
|
||||
:image-size="125"
|
||||
/>
|
||||
<el-row v-else>
|
||||
<el-col
|
||||
:xs="24"
|
||||
:sm="12"
|
||||
:md="12"
|
||||
:lg="8"
|
||||
:xl="6"
|
||||
v-for="(item, index) in paragraphDetail"
|
||||
:key="index"
|
||||
class="p-8"
|
||||
>
|
||||
<CardBox
|
||||
shadow="hover"
|
||||
:title="item.title || '-'"
|
||||
:description="item.content"
|
||||
class="document-card layout-bg layout-bg cursor"
|
||||
:class="item.is_active ? '' : 'disabled'"
|
||||
:showIcon="false"
|
||||
@click="editParagraph(item)"
|
||||
>
|
||||
<template #icon>
|
||||
<el-avatar class="mr-12 avatar-light" :size="22"> {{ index + 1 + '' }}</el-avatar>
|
||||
</template>
|
||||
<div class="active-button primary">{{ item.similarity?.toFixed(3) }}</div>
|
||||
<template #footer>
|
||||
<div class="footer-content flex-between">
|
||||
<el-text>
|
||||
<el-icon>
|
||||
<Document />
|
||||
</el-icon>
|
||||
{{ item?.document_name }}
|
||||
</el-text>
|
||||
<div v-if="item.trample_num || item.star_num">
|
||||
<span v-if="item.star_num">
|
||||
<AppIcon iconName="app-like-color"></AppIcon>
|
||||
{{ item.star_num }}
|
||||
</span>
|
||||
<span v-if="item.trample_num" class="ml-4">
|
||||
<AppIcon iconName="app-oppose-color"></AppIcon>
|
||||
{{ item.trample_num }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</CardBox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</el-card>
|
||||
<ParagraphDialog ref="ParagraphDialogRef" :title="title" @refresh="refresh" />
|
||||
|
||||
<ParagraphDialog ref="ParagraphDialogRef" :title="title" @refresh="refresh" />
|
||||
</LayoutContainer>
|
||||
<div class="hit-test__operate p-24 pt-0">
|
||||
<div class="hit-test__operate">
|
||||
<el-popover :visible="popoverVisible" placement="right-end" :width="500" trigger="click">
|
||||
<template #reference>
|
||||
<el-button icon="Setting" class="mb-8" @click="settingChange('open')">{{
|
||||
|
|
@ -230,7 +224,7 @@ import { t } from '@/locales'
|
|||
const route = useRoute()
|
||||
const {
|
||||
meta: { activeMenu },
|
||||
params: { id }
|
||||
params: { id },
|
||||
} = route as any
|
||||
|
||||
const quickInputRef = ref()
|
||||
|
|
@ -242,7 +236,7 @@ const inputValue = ref('')
|
|||
const formInline = ref({
|
||||
similarity: 0.6,
|
||||
top_number: 5,
|
||||
search_mode: 'embedding'
|
||||
search_mode: 'embedding',
|
||||
})
|
||||
|
||||
// 第一次加载
|
||||
|
|
@ -299,7 +293,7 @@ function sendChatHandle(event: any) {
|
|||
}
|
||||
const insertNewlineAtCursor = (event?: any) => {
|
||||
const textarea = quickInputRef.value.$el.querySelector(
|
||||
'.el-textarea__inner'
|
||||
'.el-textarea__inner',
|
||||
) as HTMLTextAreaElement
|
||||
const startPos = textarea.selectionStart
|
||||
const endPos = textarea.selectionEnd
|
||||
|
|
@ -315,7 +309,7 @@ const insertNewlineAtCursor = (event?: any) => {
|
|||
function getHitTestList() {
|
||||
const obj = {
|
||||
query_text: inputValue.value,
|
||||
...formInline.value
|
||||
...formInline.value,
|
||||
}
|
||||
if (isDataset.value) {
|
||||
datasetApi.getDatasetHitTest(id, obj, loading).then((res) => {
|
||||
|
|
@ -407,7 +401,7 @@ onMounted(() => {})
|
|||
}
|
||||
|
||||
.hit-test-height {
|
||||
height: calc(var(--app-main-height) - 170px);
|
||||
height: calc(100vh - 300px);
|
||||
}
|
||||
.document-card {
|
||||
height: 210px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,290 @@
|
|||
<template>
|
||||
<LayoutContainer :header="$t('views.document.importDocument')" class="create-dataset">
|
||||
<template #backButton>
|
||||
<back-button @click="back"></back-button>
|
||||
</template>
|
||||
<div class="create-dataset__main flex" v-loading="loading">
|
||||
<div class="create-dataset__component main-calc-height">
|
||||
<div class="upload-document p-24" style="min-width: 850px">
|
||||
<h4 class="title-decoration-1 mb-8">
|
||||
{{ $t('views.document.feishu.selectDocument') }}
|
||||
</h4>
|
||||
<el-form
|
||||
ref="FormRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
>
|
||||
<div class="mt-16 mb-16">
|
||||
<el-radio-group v-model="form.fileType" class="app-radio-button-group">
|
||||
<el-radio-button value="txt"
|
||||
>{{ $t('views.document.fileType.txt.label') }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="update-info flex p-8-12 border-r-4 mb-16">
|
||||
<div class="mt-4">
|
||||
<AppIcon iconName="app-warning-colorful" style="font-size: 16px"></AppIcon>
|
||||
</div>
|
||||
<div class="ml-16 lighter">
|
||||
<p>{{ $t('views.document.feishu.tip1') }}</p>
|
||||
<p>{{ $t('views.document.feishu.tip2') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-4 mb-16">
|
||||
<el-checkbox
|
||||
v-model="allCheck"
|
||||
:label="$t('views.document.feishu.allCheck')"
|
||||
size="large"
|
||||
class="ml-24"
|
||||
@change="handleAllCheckChange"
|
||||
/>
|
||||
</div>
|
||||
<div style="height: calc(100vh - 450px)">
|
||||
<el-scrollbar>
|
||||
<el-tree
|
||||
:props="props"
|
||||
:load="loadNode"
|
||||
lazy
|
||||
show-checkbox
|
||||
node-key="token"
|
||||
ref="treeRef"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="custom-tree-node flex align-center lighter">
|
||||
<img
|
||||
src="@/assets/fileType/file-icon.svg"
|
||||
alt=""
|
||||
height="20"
|
||||
v-if="data.type === 'folder'"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/docx-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.type === 'docx' || data.name.endsWith('.docx')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/xlsx-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.type === 'sheet' || data.name.endsWith('.xlsx')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/xls-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('xls')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/csv-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('csv')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/pdf-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.pdf')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/html-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.html')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/txt-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.txt')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/zip-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.zip')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/md-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.md')"
|
||||
/>
|
||||
|
||||
<span class="ml-4">{{ node.label }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="create-dataset__footer text-right border-t">
|
||||
<el-button @click="router.go(-1)">{{ $t('common.cancel') }}</el-button>
|
||||
|
||||
<el-button @click="submit" type="primary" :disabled="disabled">
|
||||
{{ $t('views.document.buttons.import') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</LayoutContainer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onUnmounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { MsgConfirm, MsgSuccess, MsgWarning } from '@/utils/message'
|
||||
import { getImgUrl } from '@/utils/utils'
|
||||
import { t } from '@/locales'
|
||||
import type Node from 'element-plus/es/components/tree/src/model/node'
|
||||
import dataset from '@/api/dataset'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const {
|
||||
query: { id, folder_token } // id为datasetID,有id的是上传文档 folder_token为飞书文件夹token
|
||||
} = route
|
||||
const datasetId = id as string
|
||||
const folderToken = folder_token as string
|
||||
|
||||
const loading = ref(false)
|
||||
const disabled = ref(false)
|
||||
const allCheck = ref(false)
|
||||
const treeRef = ref<any>(null)
|
||||
|
||||
interface Tree {
|
||||
name: string
|
||||
leaf?: boolean
|
||||
type: string
|
||||
token: string
|
||||
is_exist: boolean
|
||||
}
|
||||
|
||||
const form = ref({
|
||||
fileType: 'txt',
|
||||
fileList: [] as any
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
fileList: [
|
||||
{ required: true, message: t('views.document.upload.requiredMessage'), trigger: 'change' }
|
||||
]
|
||||
})
|
||||
|
||||
const props = {
|
||||
label: 'name',
|
||||
children: 'zones',
|
||||
isLeaf: (data: any) => data.type !== 'folder',
|
||||
disabled: (data: any) => data.is_exist
|
||||
}
|
||||
|
||||
const loadNode = (node: Node, resolve: (nodeData: Tree[]) => void) => {
|
||||
const token = node.level === 0 ? folderToken : node.data.token // 根节点使用 folder_token,其他节点使用 node.data.token
|
||||
dataset
|
||||
.getLarkDocumentList(datasetId, token, {}, loading)
|
||||
.then((res: any) => {
|
||||
const nodes = res.data.files as Tree[]
|
||||
resolve(nodes)
|
||||
nodes.forEach((childNode) => {
|
||||
if (childNode.is_exist) {
|
||||
treeRef.value?.setChecked(childNode.token, true, false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
.catch((err) => {
|
||||
console.error('Failed to load tree nodes:', err)
|
||||
})
|
||||
}
|
||||
|
||||
const handleAllCheckChange = (checked: boolean) => {
|
||||
if (checked) {
|
||||
// 获取所有已加载的节点
|
||||
const nodes = Object.values(treeRef.value?.store.nodesMap || {}) as any[]
|
||||
nodes.forEach((node) => {
|
||||
// 只选择未禁用且是文件的节点
|
||||
if (!node.disabled) {
|
||||
treeRef.value?.setChecked(node.data, true, false)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
treeRef.value?.setCheckedKeys([])
|
||||
}
|
||||
}
|
||||
|
||||
function submit() {
|
||||
loading.value = true
|
||||
disabled.value = true
|
||||
// 选中的节点的token
|
||||
const checkedNodes = treeRef.value?.getCheckedNodes() || []
|
||||
const filteredNodes = checkedNodes.filter((node: any) => !node.is_exist)
|
||||
const newList = filteredNodes.map((node: any) => {
|
||||
return {
|
||||
name: node.name,
|
||||
token: node.token,
|
||||
type: node.type
|
||||
}
|
||||
})
|
||||
if (newList.length === 0) {
|
||||
disabled.value = false
|
||||
MsgWarning(t('views.document.feishu.errorMessage1'))
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
dataset
|
||||
.importLarkDocument(datasetId, newList, loading)
|
||||
.then((res) => {
|
||||
MsgSuccess(t('views.document.tip.importMessage'))
|
||||
disabled.value = false
|
||||
router.go(-1)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to load tree nodes:', err)
|
||||
})
|
||||
.finally(() => {
|
||||
disabled.value = false
|
||||
})
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
function back() {
|
||||
router.go(-1)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.create-dataset {
|
||||
&__component {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
padding: 16px 24px;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: #ffffff;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.upload-document {
|
||||
width: 70%;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.xlsx-icon {
|
||||
svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: #000000 !important;
|
||||
fill: #ffffff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
<template>
|
||||
<div class="p-16-24">
|
||||
<h2 class="mb-16">{{ $t('common.setting') }}</h2>
|
||||
<el-card style="--el-card-padding: 0">
|
||||
<div class="knowledge-setting main-calc-height">
|
||||
<el-scrollbar>
|
||||
<div class="p-24" v-loading="loading">
|
||||
<h4 class="title-decoration-1 mb-16">
|
||||
{{ $t('common.info') }}
|
||||
</h4>
|
||||
<BaseForm ref="BaseFormRef" :data="detail" />
|
||||
|
||||
<el-form
|
||||
ref="webFormRef"
|
||||
:rules="rules"
|
||||
:model="form"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
>
|
||||
<el-form-item :label="$t('views.knowledge.knowledgeType.label')" required>
|
||||
<el-card shadow="never" class="mb-8" style="width: 50%" v-if="detail.type === 0">
|
||||
<div class="flex align-center">
|
||||
<el-avatar class="mr-8 avatar-blue" shape="square" :size="32">
|
||||
<img src="@/assets/knowledge/icon_document.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<div>
|
||||
<div>{{ $t('views.knowledge.knowledgeType.generalKnowledge') }}</div>
|
||||
<el-text type="info"
|
||||
>{{ $t('views.knowledge.knowledgeType.generalInfo') }}
|
||||
</el-text>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="mb-8" style="width: 50%" v-if="detail?.type === 1">
|
||||
<div class="flex align-center">
|
||||
<el-avatar class="mr-8 avatar-purple" shape="square" :size="32">
|
||||
<img src="@/assets/knowledge/icon_web.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<div>
|
||||
<div>{{ $t('views.knowledge.knowledgeType.webKnowledge') }}</div>
|
||||
<el-text type="info">
|
||||
{{ $t('views.knowledge.knowledgeType.webInfo') }}
|
||||
</el-text>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="never" class="mb-8" style="width: 50%" v-if="detail?.type === 2">
|
||||
<div class="flex align-center">
|
||||
<el-avatar shape="square" :size="32" style="background: none">
|
||||
<img src="@/assets/knowledge/logo_lark.svg" style="width: 100%" alt="" />
|
||||
</el-avatar>
|
||||
<div>
|
||||
<p>
|
||||
<el-text>{{ $t('views.knowledge.knowledgeType.larkKnowledge') }}</el-text>
|
||||
</p>
|
||||
<el-text type="info"
|
||||
>{{ $t('views.knowledge.knowledgeType.larkInfo') }}
|
||||
</el-text>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('views.knowledge.form.source_url.label')"
|
||||
prop="source_url"
|
||||
v-if="detail.type === 1"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.source_url"
|
||||
:placeholder="$t('views.knowledge.form.source_url.placeholder')"
|
||||
@blur="form.source_url = form.source_url.trim()"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('views.knowledge.form.selector.label')"
|
||||
v-if="detail.type === 1"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.selector"
|
||||
:placeholder="$t('views.knowledge.form.selector.placeholder')"
|
||||
@blur="form.selector = form.selector.trim()"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="App ID" prop="app_id" v-if="detail.type === 2">
|
||||
<el-input
|
||||
v-model="form.app_id"
|
||||
:placeholder="
|
||||
$t('views.application.applicationAccess.larkSetting.appIdPlaceholder')
|
||||
"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="App Secret" prop="app_id" v-if="detail.type === 2">
|
||||
<el-input
|
||||
v-model="form.app_secret"
|
||||
type="password"
|
||||
show-password
|
||||
:placeholder="
|
||||
$t('views.application.applicationAccess.larkSetting.appSecretPlaceholder')
|
||||
"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Folder Token" prop="folder_token" v-if="detail.type === 2">
|
||||
<el-input
|
||||
v-model="form.folder_token"
|
||||
:placeholder="
|
||||
$t('views.application.applicationAccess.larkSetting.folderTokenPlaceholder')
|
||||
"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div v-if="application_id_list.length > 0">
|
||||
<h4 class="title-decoration-1 mb-16">
|
||||
{{ $t('views.dataset.relatedApplications') }}
|
||||
</h4>
|
||||
<el-row :gutter="12">
|
||||
<el-col
|
||||
:span="12"
|
||||
v-for="(item, index) in application_list.filter((obj: any) =>
|
||||
application_id_list.some((v: any) => v === obj?.id),
|
||||
)"
|
||||
:key="index"
|
||||
class="mb-16"
|
||||
>
|
||||
<el-card shadow="never">
|
||||
<div class="flex-between">
|
||||
<div class="flex align-center">
|
||||
<el-avatar
|
||||
v-if="isAppIcon(item?.icon)"
|
||||
shape="square"
|
||||
:size="32"
|
||||
style="background: none"
|
||||
class="mr-12"
|
||||
>
|
||||
<img :src="item?.icon" alt="" />
|
||||
</el-avatar>
|
||||
<el-avatar
|
||||
v-else-if="item?.name"
|
||||
:name="item?.name"
|
||||
pinyinColor
|
||||
shape="square"
|
||||
:size="32"
|
||||
class="mr-12"
|
||||
/>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<div class="text-right">
|
||||
<el-button @click="submit" type="primary"> {{ $t('common.save') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import BaseForm from '@/views/knowledge/component/BaseForm.vue'
|
||||
import KnowledgeApi from '@/api/knowledge/knowledge'
|
||||
import type { ApplicationFormType } from '@/api/type/application'
|
||||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||
import { isAppIcon } from '@/utils/common'
|
||||
import useStore from '@/stores'
|
||||
import { t } from '@/locales'
|
||||
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: { id },
|
||||
} = route as any
|
||||
|
||||
const { knowledge } = useStore()
|
||||
const webFormRef = ref()
|
||||
const BaseFormRef = ref()
|
||||
const loading = ref(false)
|
||||
const detail = ref<any>({})
|
||||
const application_list = ref<Array<ApplicationFormType>>([])
|
||||
const application_id_list = ref([])
|
||||
const cloneModelId = ref('')
|
||||
|
||||
const form = ref<any>({
|
||||
source_url: '',
|
||||
selector: '',
|
||||
app_id: '',
|
||||
app_secret: '',
|
||||
folder_token: '',
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
source_url: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.knowledge.form.source_url.requiredMessage'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
app_id: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.application.applicationAccess.larkSetting.appIdPlaceholder'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
app_secret: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.application.applicationAccess.larkSetting.appSecretPlaceholder'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
folder_token: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.application.applicationAccess.larkSetting.folderTokenPlaceholder'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
async function submit() {
|
||||
if (await BaseFormRef.value?.validate()) {
|
||||
await webFormRef.value.validate((valid: any) => {
|
||||
if (valid) {
|
||||
const obj =
|
||||
detail.value.type === '1' || detail.value.type === '2'
|
||||
? {
|
||||
application_id_list: application_id_list.value,
|
||||
meta: form.value,
|
||||
...BaseFormRef.value.form,
|
||||
}
|
||||
: {
|
||||
application_id_list: application_id_list.value,
|
||||
...BaseFormRef.value.form,
|
||||
}
|
||||
|
||||
if (cloneModelId.value !== BaseFormRef.value.form.embedding_mode_id) {
|
||||
MsgConfirm(t('common.tip'), t('views.knowledge.tip.updateModeMessage'), {
|
||||
confirmButtonText: t('views.knowledge.setting.vectorization'),
|
||||
})
|
||||
.then(() => {
|
||||
if (detail.value.type === 2) {
|
||||
KnowledgeApi.putLarkDataset(id, obj, loading).then((res) => {
|
||||
KnowledgeApi.putReEmbeddingDataset(id).then(() => {
|
||||
MsgSuccess(t('common.saveSuccess'))
|
||||
})
|
||||
})
|
||||
} else {
|
||||
KnowledgeApi.putKnowledge('default', id, obj, loading).then((res) => {
|
||||
KnowledgeApi.putReEmbeddingDataset(id).then(() => {
|
||||
MsgSuccess(t('common.saveSuccess'))
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
} else {
|
||||
if (detail.value.type === 2) {
|
||||
KnowledgeApi.putLarkDataset(id, obj, loading).then((res) => {
|
||||
KnowledgeApi.putReEmbeddingDataset(id).then(() => {
|
||||
MsgSuccess(t('common.saveSuccess'))
|
||||
})
|
||||
})
|
||||
} else {
|
||||
KnowledgeApi.putKnowledge('default', id, obj, loading).then((res) => {
|
||||
MsgSuccess(t('common.saveSuccess'))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getDetail() {
|
||||
knowledge.asyncGetDatasetDetail(id, loading).then((res: any) => {
|
||||
detail.value = res.data
|
||||
cloneModelId.value = res.data?.embedding_mode_id
|
||||
if (detail.value.type === '1' || detail.value.type === '2') {
|
||||
form.value = res.data.meta
|
||||
}
|
||||
application_id_list.value = res.data?.application_id_list
|
||||
KnowledgeApi.listUsableApplication(id, loading).then((ok) => {
|
||||
application_list.value = ok.data
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDetail()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.knowledge-setting {
|
||||
width: 70%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
<template>
|
||||
<LayoutContainer :header="$t('views.document.uploadDocument')" class="create-dataset">
|
||||
<template #backButton>
|
||||
<back-button @click="back"></back-button>
|
||||
</template>
|
||||
<div class="create-dataset__main flex" v-loading="loading">
|
||||
<div class="create-dataset__component main-calc-height">
|
||||
<el-scrollbar>
|
||||
<template v-if="active === 0">
|
||||
<div class="upload-document p-24">
|
||||
<!-- 上传文档 -->
|
||||
<UploadComponent ref="UploadComponentRef" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="active === 1">
|
||||
<SetRules ref="SetRulesRef" />
|
||||
</template>
|
||||
<template v-else-if="active === 2">
|
||||
<ResultSuccess :data="successInfo" />
|
||||
</template>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="create-dataset__footer text-right border-t" v-if="active !== 2">
|
||||
<el-button @click="router.go(-1)" :disabled="SetRulesRef?.loading || loading">{{
|
||||
$t('common.cancel')
|
||||
}}</el-button>
|
||||
<el-button @click="prev" v-if="active === 1" :disabled="SetRulesRef?.loading || loading">{{
|
||||
$t('views.document.buttons.prev')
|
||||
}}</el-button>
|
||||
<el-button
|
||||
@click="next"
|
||||
type="primary"
|
||||
v-if="active === 0"
|
||||
:disabled="SetRulesRef?.loading || loading"
|
||||
>
|
||||
{{
|
||||
documentsType === 'txt'
|
||||
? $t('views.document.buttons.next')
|
||||
: $t('views.document.buttons.import')
|
||||
}}
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="submit"
|
||||
type="primary"
|
||||
v-if="active === 1"
|
||||
:disabled="SetRulesRef?.loading || loading"
|
||||
>
|
||||
{{ $t('views.document.buttons.import') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</LayoutContainer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onUnmounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import SetRules from './component/SetRules.vue'
|
||||
import ResultSuccess from './component/ResultSuccess.vue'
|
||||
import UploadComponent from './component/UploadComponent.vue'
|
||||
import documentApi from '@/api/document'
|
||||
import { MsgConfirm, MsgSuccess } from '@/utils/message'
|
||||
import { t } from '@/locales'
|
||||
import useStore from '@/stores'
|
||||
const { dataset, document } = useStore()
|
||||
const documentsFiles = computed(() => dataset.documentsFiles)
|
||||
const documentsType = computed(() => dataset.documentsType)
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const {
|
||||
query: { id } // id为datasetID,有id的是上传文档
|
||||
} = route
|
||||
|
||||
const SetRulesRef = ref()
|
||||
const UploadComponentRef = ref()
|
||||
|
||||
const loading = ref(false)
|
||||
const disabled = ref(false)
|
||||
const active = ref(0)
|
||||
const successInfo = ref<any>(null)
|
||||
async function next() {
|
||||
disabled.value = true
|
||||
if (await UploadComponentRef.value.validate()) {
|
||||
if (documentsType.value === 'QA') {
|
||||
let fd = new FormData()
|
||||
documentsFiles.value.forEach((item: any) => {
|
||||
if (item?.raw) {
|
||||
fd.append('file', item?.raw)
|
||||
}
|
||||
})
|
||||
if (id) {
|
||||
// QA文档上传
|
||||
documentApi.postQADocument(id as string, fd, loading).then((res) => {
|
||||
MsgSuccess(t('common.submitSuccess'))
|
||||
clearStore()
|
||||
router.push({ path: `/dataset/${id}/document` })
|
||||
})
|
||||
}
|
||||
} else if (documentsType.value === 'table') {
|
||||
let fd = new FormData()
|
||||
documentsFiles.value.forEach((item: any) => {
|
||||
if (item?.raw) {
|
||||
fd.append('file', item?.raw)
|
||||
}
|
||||
})
|
||||
if (id) {
|
||||
// table文档上传
|
||||
documentApi.postTableDocument(id as string, fd, loading).then((res) => {
|
||||
MsgSuccess(t('common.submitSuccess'))
|
||||
clearStore()
|
||||
router.push({ path: `/dataset/${id}/document` })
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (active.value++ > 2) active.value = 0
|
||||
}
|
||||
} else {
|
||||
disabled.value = false
|
||||
}
|
||||
}
|
||||
const prev = () => {
|
||||
active.value = 0
|
||||
}
|
||||
|
||||
function clearStore() {
|
||||
dataset.saveDocumentsFile([])
|
||||
dataset.saveDocumentsType('')
|
||||
}
|
||||
function submit() {
|
||||
loading.value = true
|
||||
const documents = [] as any
|
||||
SetRulesRef.value?.paragraphList.map((item: any) => {
|
||||
if (!SetRulesRef.value?.checkedConnect) {
|
||||
item.content.map((v: any) => {
|
||||
delete v['problem_list']
|
||||
})
|
||||
}
|
||||
documents.push({
|
||||
name: item.name,
|
||||
paragraphs: item.content
|
||||
})
|
||||
})
|
||||
|
||||
if (id) {
|
||||
// 上传文档
|
||||
document
|
||||
.asyncPostDocument(id as string, documents)
|
||||
.then(() => {
|
||||
MsgSuccess(t('common.submitSuccess'))
|
||||
clearStore()
|
||||
router.push({ path: `/dataset/${id}/document` })
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
function back() {
|
||||
if (documentsFiles.value?.length > 0) {
|
||||
MsgConfirm(t('common.tip'), t('views.document.tip.saveMessage'), {
|
||||
confirmButtonText: t('common.confirm'),
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
router.go(-1)
|
||||
clearStore()
|
||||
})
|
||||
.catch(() => {})
|
||||
} else {
|
||||
router.go(-1)
|
||||
}
|
||||
}
|
||||
onUnmounted(() => {
|
||||
clearStore()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.create-dataset {
|
||||
&__steps {
|
||||
min-width: 450px;
|
||||
max-width: 800px;
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
padding-right: 60px;
|
||||
|
||||
:deep(.el-step__line) {
|
||||
left: 64% !important;
|
||||
right: -33% !important;
|
||||
}
|
||||
}
|
||||
|
||||
&__component {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
&__footer {
|
||||
padding: 16px 24px;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: #ffffff;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.upload-document {
|
||||
width: 70%;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -174,6 +174,7 @@ const remoteMethod = (query: string) => {
|
|||
function getProblemOption(filterText?: string) {
|
||||
return problem
|
||||
.asyncGetProblem(
|
||||
'default',
|
||||
props.datasetId || (id as string),
|
||||
{ current_page: 1, page_size: 100 },
|
||||
filterText && { content: filterText },
|
||||
|
|
|
|||
|
|
@ -1,101 +1,123 @@
|
|||
<template>
|
||||
<LayoutContainer :header="$t('views.problem.title')">
|
||||
<div class="main-calc-height">
|
||||
<div class="p-24">
|
||||
<div class="flex-between">
|
||||
<div>
|
||||
<el-button type="primary" @click="createProblem">{{$t('views.problem.createProblem')}}</el-button>
|
||||
<el-button @click="relateProblem()" :disabled="multipleSelection.length === 0"
|
||||
>{{$t('views.problem.relateParagraph.title')}}</el-button
|
||||
>
|
||||
<el-button @click="deleteMulDocument" :disabled="multipleSelection.length === 0"
|
||||
>{{$t('views.problem.setting.batchDelete')}}</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="document p-16-24">
|
||||
<h2 class="mb-16">{{ $t('views.problem.title') }}</h2>
|
||||
<el-card style="--el-card-padding: 0">
|
||||
<div class="main-calc-height">
|
||||
<div class="p-24">
|
||||
<div class="flex-between">
|
||||
<div>
|
||||
<el-button type="primary" @click="createProblem">{{
|
||||
$t('views.problem.createProblem')
|
||||
}}</el-button>
|
||||
<el-button @click="relateProblem()" :disabled="multipleSelection.length === 0">{{
|
||||
$t('views.problem.relateParagraph.title')
|
||||
}}</el-button>
|
||||
<el-button @click="deleteMulDocument" :disabled="multipleSelection.length === 0">{{
|
||||
$t('views.problem.setting.batchDelete')
|
||||
}}</el-button>
|
||||
</div>
|
||||
|
||||
<el-input
|
||||
v-model="filterText"
|
||||
:placeholder="$t('views.problem.searchBar.placeholder')"
|
||||
prefix-icon="Search"
|
||||
class="w-240"
|
||||
@change="getList"
|
||||
clearable
|
||||
/>
|
||||
<el-input
|
||||
v-model="filterText"
|
||||
:placeholder="$t('views.problem.searchBar.placeholder')"
|
||||
prefix-icon="Search"
|
||||
class="w-240"
|
||||
@change="getList"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
<app-table
|
||||
ref="multipleTableRef"
|
||||
class="mt-16"
|
||||
:data="problemData"
|
||||
:pagination-config="paginationConfig"
|
||||
quick-create
|
||||
:quickCreateName="$t('views.problem.quickCreateName')"
|
||||
:quickCreatePlaceholder="$t('views.problem.quickCreateProblem')"
|
||||
:quickCreateMaxlength="256"
|
||||
@sizeChange="handleSizeChange"
|
||||
@changePage="getList"
|
||||
@cell-mouse-enter="cellMouseEnter"
|
||||
@cell-mouse-leave="cellMouseLeave"
|
||||
@creatQuick="creatQuickHandle"
|
||||
@row-click="rowClickHandle"
|
||||
@selection-change="handleSelectionChange"
|
||||
:row-class-name="setRowClass"
|
||||
v-loading="loading"
|
||||
:row-key="(row: any) => row.id"
|
||||
>
|
||||
<el-table-column type="selection" width="55" :reserve-selection="true" />
|
||||
<el-table-column prop="content" :label="$t('views.problem.title')" min-width="280">
|
||||
<template #default="{ row }">
|
||||
<ReadWrite
|
||||
@change="editName($event, row.id)"
|
||||
:data="row.content"
|
||||
:showEditIcon="row.id === currentMouseId"
|
||||
:maxlength="256"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="paragraph_count"
|
||||
:label="$t('views.problem.table.paragraph_count')"
|
||||
align="right"
|
||||
min-width="100"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link
|
||||
type="primary"
|
||||
@click.stop="rowClickHandle(row)"
|
||||
v-if="row.paragraph_count"
|
||||
>
|
||||
{{ row.paragraph_count }}
|
||||
</el-link>
|
||||
<span v-else>
|
||||
{{ row.paragraph_count }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" :label="$t('common.createTime')" width="170">
|
||||
<template #default="{ row }">
|
||||
{{ datetimeFormat(row.create_time) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="update_time"
|
||||
:label="$t('views.problem.table.updateTime')"
|
||||
width="170"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ datetimeFormat(row.update_time) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common.operation')" align="left" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div>
|
||||
<span class="mr-4">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('views.problem.relateParagraph.title')"
|
||||
placement="top"
|
||||
>
|
||||
<el-button type="primary" text @click.stop="relateProblem(row)">
|
||||
<el-icon><Connection /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<span>
|
||||
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
|
||||
<el-button type="primary" text @click.stop="deleteProblem(row)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</app-table>
|
||||
</div>
|
||||
<app-table
|
||||
ref="multipleTableRef"
|
||||
class="mt-16"
|
||||
:data="problemData"
|
||||
:pagination-config="paginationConfig"
|
||||
quick-create
|
||||
:quickCreateName="$t('views.problem.quickCreateName')"
|
||||
:quickCreatePlaceholder="$t('views.problem.quickCreateProblem')"
|
||||
:quickCreateMaxlength="256"
|
||||
@sizeChange="handleSizeChange"
|
||||
@changePage="getList"
|
||||
@cell-mouse-enter="cellMouseEnter"
|
||||
@cell-mouse-leave="cellMouseLeave"
|
||||
@creatQuick="creatQuickHandle"
|
||||
@row-click="rowClickHandle"
|
||||
@selection-change="handleSelectionChange"
|
||||
:row-class-name="setRowClass"
|
||||
v-loading="loading"
|
||||
:row-key="(row: any) => row.id"
|
||||
>
|
||||
<el-table-column type="selection" width="55" :reserve-selection="true" />
|
||||
<el-table-column prop="content" :label="$t('views.problem.title')" min-width="280">
|
||||
<template #default="{ row }">
|
||||
<ReadWrite
|
||||
@change="editName($event, row.id)"
|
||||
:data="row.content"
|
||||
:showEditIcon="row.id === currentMouseId"
|
||||
:maxlength="256"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="paragraph_count" :label="$t('views.problem.table.paragraph_count')" align="right" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" @click.stop="rowClickHandle(row)" v-if="row.paragraph_count">
|
||||
{{ row.paragraph_count }}
|
||||
</el-link>
|
||||
<span v-else>
|
||||
{{ row.paragraph_count }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" :label="$t('common.createTime')" width="170">
|
||||
<template #default="{ row }">
|
||||
{{ datetimeFormat(row.create_time) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="update_time" :label="$t('views.problem.table.updateTime')" width="170">
|
||||
<template #default="{ row }">
|
||||
{{ datetimeFormat(row.update_time) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common.operation')" align="left" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div>
|
||||
<span class="mr-4">
|
||||
<el-tooltip effect="dark" :content="$t('views.problem.relateParagraph.title')" placement="top">
|
||||
<el-button type="primary" text @click.stop="relateProblem(row)">
|
||||
<el-icon><Connection /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<span>
|
||||
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
|
||||
<el-button type="primary" text @click.stop="deleteProblem(row)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</app-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<CreateProblemDialog ref="CreateProblemDialogRef" @refresh="refresh" />
|
||||
<DetailProblemDrawer
|
||||
:next="nextChatRecord"
|
||||
|
|
@ -108,7 +130,7 @@
|
|||
@refresh="refreshRelate"
|
||||
/>
|
||||
<RelateProblemDialog ref="RelateProblemDialogRef" @refresh="refreshRelate" />
|
||||
</LayoutContainer>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, reactive, onBeforeUnmount, computed } from 'vue'
|
||||
|
|
@ -125,7 +147,7 @@ import useStore from '@/stores'
|
|||
import { t } from '@/locales'
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: { id } // 知识库id
|
||||
params: { id }, // 知识库id
|
||||
} = route as any
|
||||
|
||||
const { problem } = useStore()
|
||||
|
|
@ -144,7 +166,7 @@ const currentContent = ref('')
|
|||
const paginationConfig = reactive({
|
||||
current_page: 1,
|
||||
page_size: 10,
|
||||
total: 0
|
||||
total: 0,
|
||||
})
|
||||
|
||||
const filterText = ref('')
|
||||
|
|
@ -152,7 +174,7 @@ const problemData = ref<any[]>([])
|
|||
const problemIndexMap = computed<Dict<number>>(() => {
|
||||
return problemData.value
|
||||
.map((row, index) => ({
|
||||
[row.id]: index
|
||||
[row.id]: index,
|
||||
}))
|
||||
.reduce((pre, next) => ({ ...pre, ...next }), {})
|
||||
})
|
||||
|
|
@ -220,8 +242,8 @@ function deleteProblem(row: any) {
|
|||
`${t('views.problem.delete.confirmMessage1')} ${row.paragraph_count} ${t('views.problem.delete.confirmMessage2')}`,
|
||||
{
|
||||
confirmButtonText: t('common.confirm'),
|
||||
confirmButtonClass: 'danger'
|
||||
}
|
||||
confirmButtonClass: 'danger',
|
||||
},
|
||||
)
|
||||
.then(() => {
|
||||
problemApi.delProblems(id, row.id, loading).then(() => {
|
||||
|
|
@ -235,7 +257,7 @@ function deleteProblem(row: any) {
|
|||
function editName(val: string, problemId: string) {
|
||||
if (val) {
|
||||
const obj = {
|
||||
content: val
|
||||
content: val,
|
||||
}
|
||||
problemApi.putProblems(id, problemId, obj, loading).then(() => {
|
||||
getList()
|
||||
|
|
@ -334,10 +356,11 @@ function handleSizeChange() {
|
|||
function getList() {
|
||||
return problem
|
||||
.asyncGetProblem(
|
||||
'default',
|
||||
id as string,
|
||||
paginationConfig,
|
||||
filterText.value && { content: filterText.value },
|
||||
loading
|
||||
loading,
|
||||
)
|
||||
.then((res: any) => {
|
||||
problemData.value = res.data.records
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<template #header>
|
||||
<h4>{{ title }}</h4>
|
||||
</template>
|
||||
<h4 class="title-decoration-1 mb-16 mt-8">{{ $t('views.userManage.info') }}</h4>
|
||||
<h4 class="title-decoration-1 mb-16 mt-8">{{ $t('common.info') }}</h4>
|
||||
<el-form
|
||||
ref="userFormRef"
|
||||
:model="userForm"
|
||||
|
|
|
|||
Loading…
Reference in New Issue