mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
feat: web知识库
This commit is contained in:
parent
cf1dac76cd
commit
5e407c86ff
|
|
@ -88,15 +88,17 @@ const postDocument: (dataset_id: string, data: any) => Promise<Result<any>> = (
|
|||
* dataset_id, document_id,
|
||||
* {
|
||||
"name": "string",
|
||||
"is_active": true
|
||||
"is_active": true,
|
||||
"meta": {}
|
||||
}
|
||||
*/
|
||||
const putDocument: (dataset_id: string, document_id: string, data: any) => Promise<Result<any>> = (
|
||||
dataset_id,
|
||||
document_id,
|
||||
data: any
|
||||
) => {
|
||||
return put(`${prefix}/${dataset_id}/document/${document_id}`, data)
|
||||
const putDocument: (
|
||||
dataset_id: string,
|
||||
document_id: string,
|
||||
data: any,
|
||||
loading?: Ref<boolean>
|
||||
) => Promise<Result<any>> = (dataset_id, document_id, data: any, loading) => {
|
||||
return put(`${prefix}/${dataset_id}/document/${document_id}`, data, undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 464 B After Width: | Height: | Size: 464 B |
|
|
@ -85,6 +85,7 @@
|
|||
plain
|
||||
size="small"
|
||||
@click="openParagraph(item)"
|
||||
:disabled="item.paragraph_list?.length === 0"
|
||||
>引用分段:{{ item.paragraph_list?.length }}</el-button
|
||||
>
|
||||
<el-tag type="info" effect="plain">
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@
|
|||
<div class="flex-between">
|
||||
<div class="flex align-center">
|
||||
<slot name="icon">
|
||||
<AppAvatar class="mr-12" shape="square" :size="32">
|
||||
<AppAvatar v-if="data.type === '1'" class="mr-8 avatar-purple" shape="square" :size="32">
|
||||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
|
||||
<AppAvatar v-else class="mr-12" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
</slot>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,37 @@
|
|||
<template>
|
||||
<div class="ml-8 mt-8 mb-16 flex">
|
||||
<back-button :to="activeMenu"></back-button>
|
||||
<el-dropdown placement="top" trigger="click" @command="changeMenu" class="w-full" style="display: block;">
|
||||
<el-dropdown
|
||||
placement="top"
|
||||
trigger="click"
|
||||
@command="changeMenu"
|
||||
class="w-full"
|
||||
style="display: block"
|
||||
>
|
||||
<div class="flex-between">
|
||||
<div class="ellipsis">{{ currentName }}</div>
|
||||
<div class="flex align-center">
|
||||
<AppAvatar
|
||||
v-if="isApplication"
|
||||
:name="currentName"
|
||||
pinyinColor
|
||||
shape="square"
|
||||
class="mr-8"
|
||||
:size="24"
|
||||
/>
|
||||
<AppAvatar
|
||||
v-else-if="isDataset && currentType === '1'"
|
||||
class="mr-8 avatar-purple"
|
||||
shape="square"
|
||||
:size="24"
|
||||
>
|
||||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<AppAvatar v-else class="mr-8" shape="square" :size="24">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<div class="ellipsis">{{ currentName }}</div>
|
||||
</div>
|
||||
|
||||
<el-button text>
|
||||
<el-icon><CaretBottom /></el-icon>
|
||||
</el-button>
|
||||
|
|
@ -22,10 +50,17 @@
|
|||
shape="square"
|
||||
:size="24"
|
||||
/>
|
||||
<AppAvatar v-else-if="isDataset" class="mr-12" shape="square" :size="24">
|
||||
<AppAvatar
|
||||
v-else-if="isDataset && item.type === '1'"
|
||||
class="mr-12 avatar-purple"
|
||||
shape="square"
|
||||
:size="24"
|
||||
>
|
||||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<AppAvatar v-else class="mr-12" shape="square" :size="24">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
|
||||
<span class="ellipsis"> {{ item?.name }}</span>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
|
|
@ -76,6 +111,12 @@ const currentName = computed(() => {
|
|||
} = route
|
||||
return list.value?.filter((v) => v.id === id)?.[0]?.name
|
||||
})
|
||||
const currentType = computed(() => {
|
||||
const {
|
||||
params: { id }
|
||||
} = route
|
||||
return list.value?.filter((v) => v.id === id)?.[0]?.type
|
||||
})
|
||||
|
||||
const isApplication = computed(() => {
|
||||
const { meta } = route as any
|
||||
|
|
|
|||
|
|
@ -324,6 +324,12 @@ h4 {
|
|||
border: none;
|
||||
}
|
||||
|
||||
.purple-tag {
|
||||
background: #f2ebfe;
|
||||
color: #7f3bf5;
|
||||
border-color: #e0d7f0;
|
||||
}
|
||||
|
||||
/*
|
||||
card 无边框无阴影 灰色背景
|
||||
*/
|
||||
|
|
@ -386,6 +392,10 @@ h4 {
|
|||
background: var(--el-color-primary-light-4);
|
||||
}
|
||||
|
||||
.avatar-purple {
|
||||
background: #7f3bf5;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: var(--el-color-success);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,16 @@
|
|||
<el-card class="relate-dataset-card" shadow="never">
|
||||
<div class="flex-between">
|
||||
<div class="flex align-center">
|
||||
<AppAvatar class="mr-12" shape="square" :size="32">
|
||||
<AppAvatar
|
||||
v-if="realatedObject(datasetList, item, 'id')?.type === '1'"
|
||||
class="mr-8 avatar-purple"
|
||||
shape="square"
|
||||
:size="32"
|
||||
>
|
||||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
|
||||
<AppAvatar v-else class="mr-12" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<div class="ellipsis">
|
||||
|
|
|
|||
|
|
@ -31,9 +31,22 @@
|
|||
class="cursor"
|
||||
@click="router.push({ path: `/dataset/${item.id}/document` })"
|
||||
>
|
||||
<template #icon>
|
||||
<AppAvatar
|
||||
v-if="item.type === '1'"
|
||||
class="mr-8 avatar-purple"
|
||||
shape="square"
|
||||
:size="32"
|
||||
>
|
||||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<AppAvatar v-else class="mr-8" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
</template>
|
||||
<div class="delete-button">
|
||||
<el-tag v-if="item.type === '0'">通用型</el-tag>
|
||||
<el-tag v-else-if="item.type === '1'" type="warning">Web 站点</el-tag>
|
||||
<el-tag class="purple-tag" v-else-if="item.type === '1'" type="warning">Web 站点</el-tag>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ const form = ref<any>({
|
|||
source_url: '',
|
||||
selector: ''
|
||||
})
|
||||
const documentId = ref('')
|
||||
|
||||
const rules = reactive({
|
||||
source_url: [{ required: true, message: '请输入 Web 根地址', trigger: 'blur' }]
|
||||
|
|
@ -76,6 +77,8 @@ watch(dialogVisible, (bool) => {
|
|||
|
||||
const open = (row: any) => {
|
||||
if (row) {
|
||||
documentId.value = row.id
|
||||
form.value = row.meta
|
||||
isImport.value = false
|
||||
} else {
|
||||
isImport.value = true
|
||||
|
|
@ -84,15 +87,26 @@ const open = (row: any) => {
|
|||
}
|
||||
|
||||
const submit = () => {
|
||||
const obj = {
|
||||
source_url_list: form.value.source_url.split('\n'),
|
||||
selector: form.value.selector
|
||||
if (isImport.value) {
|
||||
const obj = {
|
||||
source_url_list: form.value.source_url.split('\n'),
|
||||
selector: form.value.selector
|
||||
}
|
||||
documentApi.postWebDocument(id, obj, loading).then((res: any) => {
|
||||
MsgSuccess('导入成功')
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
})
|
||||
} else {
|
||||
const obj = {
|
||||
meta: form.value
|
||||
}
|
||||
documentApi.putDocument(id, documentId.value, obj, loading).then((res) => {
|
||||
MsgSuccess('设置成功')
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
})
|
||||
}
|
||||
documentApi.postWebDocument(id, obj, loading).then((res: any) => {
|
||||
MsgSuccess('导入成功')
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
|
|
|
|||
|
|
@ -310,18 +310,11 @@ function deleteDocument(row: any) {
|
|||
更新名称或状态
|
||||
*/
|
||||
function updateData(documentId: string, data: any, msg: string) {
|
||||
loading.value = true
|
||||
documentApi
|
||||
.putDocument(id, documentId, data)
|
||||
.then((res) => {
|
||||
const index = documentData.value.findIndex((v) => v.id === documentId)
|
||||
documentData.value.splice(index, 1, res.data)
|
||||
MsgSuccess(msg)
|
||||
loading.value = false
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
documentApi.putDocument(id, documentId, data, loading).then((res) => {
|
||||
const index = documentData.value.findIndex((v) => v.id === documentId)
|
||||
documentData.value.splice(index, 1, res.data)
|
||||
MsgSuccess(msg)
|
||||
})
|
||||
}
|
||||
|
||||
function changeState(bool: Boolean, row: any) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,20 @@
|
|||
>
|
||||
<template #default="{ node, data }">
|
||||
<span class="flex align-center">
|
||||
<AppAvatar v-if="!node.isLeaf" class="mr-12" shape="square" :size="24">
|
||||
<AppAvatar
|
||||
v-if="!node.isLeaf && data.type === '1'"
|
||||
class="mr-12 avatar-purple"
|
||||
shape="square"
|
||||
:size="24"
|
||||
>
|
||||
<img src="@/assets/icon_web.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<AppAvatar
|
||||
v-else-if="!node.isLeaf && data.type === '0'"
|
||||
class="mr-12"
|
||||
shape="square"
|
||||
:size="24"
|
||||
>
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<span class="ellipsis"> {{ data.name }}</span>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<LayoutContainer :header="documentDetail?.name" back-to="-1" class="document-detail">
|
||||
<template #header>
|
||||
<el-text type="info" v-if="documentDetail?.type==='1'">(文档地址:{{ documentDetail?.meta?.source_url }})</el-text>
|
||||
<div class="document-detail__header">
|
||||
<el-button @click="addParagraph" type="primary" :disabled="loading"> 添加分段 </el-button>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue