|
|
@@ -46,7 +46,8 @@
|
|
|
|
|
|
<el-table-column label="知识库表名" min-width="150">
|
|
|
<template #default="{ row }">
|
|
|
- <div style="white-space: pre-wrap; line-height: 1.5;">{{ row.collection_name }}</div>
|
|
|
+ <div>{{ row.collection_name1 }}</div>
|
|
|
+ <div v-if="row.collection_name2" class="sub-collection">{{ row.collection_name2 }}</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
|
|
|
@@ -86,9 +87,9 @@
|
|
|
<el-icon><Edit /></el-icon>
|
|
|
</el-button>
|
|
|
</el-tooltip>
|
|
|
- <el-tooltip :content="row.is_synced ? '已同步' : '同步到Milvus'" placement="top">
|
|
|
- <el-button link type="warning" @click="handleSync(row)" :disabled="row.is_synced">
|
|
|
- <el-icon><Refresh /></el-icon>
|
|
|
+ <el-tooltip :content="syncingStates[row.id] ? '转换中' : (row.is_synced ? '已同步' : '同步到Milvus')" placement="top">
|
|
|
+ <el-button link type="warning" @click="handleSync(row)" :disabled="row.is_synced || syncingStates[row.id]">
|
|
|
+ <el-icon :class="{'is-loading': syncingStates[row.id]}"><Refresh /></el-icon>
|
|
|
</el-button>
|
|
|
</el-tooltip>
|
|
|
<el-tooltip content="删除" placement="top">
|
|
|
@@ -149,18 +150,21 @@
|
|
|
</el-col>
|
|
|
<el-col :span="12">
|
|
|
<template v-if="dialogType === 'create'">
|
|
|
- <el-form-item label="父集合名称" prop="parent_collection_name">
|
|
|
- <el-input v-model="formData.parent_collection_name" placeholder="父集合名(英文)" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="子集合名称" prop="child_collection_name">
|
|
|
- <el-input v-model="formData.child_collection_name" placeholder="子集合名(英文)" />
|
|
|
- </el-form-item>
|
|
|
- </template>
|
|
|
- <template v-else>
|
|
|
- <el-form-item label="集合名称">
|
|
|
- <el-input v-model="formData.collection_name" disabled />
|
|
|
- </el-form-item>
|
|
|
- </template>
|
|
|
+ <el-form-item label="父集合名称" prop="collection_name1">
|
|
|
+ <el-input v-model="formData.collection_name1" placeholder="父集合名(英文)" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="子集合名称" prop="collection_name2">
|
|
|
+ <el-input v-model="formData.collection_name2" placeholder="子集合名(英文)" />
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-form-item label="父集合名称">
|
|
|
+ <el-input v-model="formData.collection_name1" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="子集合名称" v-if="formData.collection_name2">
|
|
|
+ <el-input v-model="formData.collection_name2" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
|
|
|
@@ -273,7 +277,8 @@
|
|
|
>
|
|
|
<el-descriptions :column="2" border class="detail-descriptions">
|
|
|
<el-descriptions-item label="知识库名称" label-class-name="desc-label">{{ viewData.name }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="集合名称" label-class-name="desc-label">{{ viewData.collection_name }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="父集合名称" label-class-name="desc-label">{{ viewData.collection_name1 }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="子集合名称" label-class-name="desc-label">{{ viewData.collection_name2 || '-' }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="状态" label-class-name="desc-label">
|
|
|
<el-tag :type="getStatusType(viewData.status)" effect="plain">
|
|
|
{{ getStatusText(viewData.status) }}
|
|
|
@@ -343,6 +348,7 @@ const queryParams = reactive({
|
|
|
|
|
|
// Table Data
|
|
|
const loading = ref(false)
|
|
|
+const syncingStates = ref<Record<string, boolean>>({})
|
|
|
const tableData = ref<KnowledgeBase[]>([])
|
|
|
const pagination = reactive({
|
|
|
page: 1,
|
|
|
@@ -358,9 +364,8 @@ const formRef = ref<FormInstance>()
|
|
|
const formData = reactive({
|
|
|
id: '',
|
|
|
name: '',
|
|
|
- collection_name: '',
|
|
|
- parent_collection_name: '',
|
|
|
- child_collection_name: '',
|
|
|
+ collection_name1: '',
|
|
|
+ collection_name2: '',
|
|
|
description: '',
|
|
|
dimension: 768,
|
|
|
status: 'normal',
|
|
|
@@ -398,15 +403,12 @@ const getDisabledOptions = (currentIndex: number) => {
|
|
|
|
|
|
const rules: FormRules = {
|
|
|
name: [{ required: true, message: '请输入知识库名称', trigger: 'blur' }],
|
|
|
- collection_name: [
|
|
|
- { required: false, message: '请输入集合名称', trigger: 'blur' }
|
|
|
- ],
|
|
|
- parent_collection_name: [
|
|
|
+ collection_name1: [
|
|
|
{ required: true, message: '请输入父集合名称', trigger: 'blur' },
|
|
|
{ pattern: /^[a-zA-Z_][a-zA-Z0-9_]*$/, message: '必须以字母或下划线开头,只能包含字母、数字和下划线', trigger: 'blur' }
|
|
|
],
|
|
|
- child_collection_name: [
|
|
|
- { required: true, message: '请输入子集合名称', trigger: 'blur' },
|
|
|
+ collection_name2: [
|
|
|
+ { required: false, message: '请输入子集合名称', trigger: 'blur' },
|
|
|
{ pattern: /^[a-zA-Z_][a-zA-Z0-9_]*$/, message: '必须以字母或下划线开头,只能包含字母、数字和下划线', trigger: 'blur' }
|
|
|
],
|
|
|
dimension: [{ required: true, message: '请输入维度', trigger: 'blur' }]
|
|
|
@@ -474,9 +476,8 @@ const handleAdd = () => {
|
|
|
dialogType.value = 'create'
|
|
|
formData.id = ''
|
|
|
formData.name = ''
|
|
|
- formData.collection_name = ''
|
|
|
- formData.parent_collection_name = ''
|
|
|
- formData.child_collection_name = ''
|
|
|
+ formData.collection_name1 = ''
|
|
|
+ formData.collection_name2 = ''
|
|
|
formData.description = ''
|
|
|
formData.dimension = 768
|
|
|
formData.status = 'normal'
|
|
|
@@ -487,8 +488,8 @@ const handleEdit = async (row: KnowledgeBase) => {
|
|
|
dialogType.value = 'edit'
|
|
|
formData.id = row.id
|
|
|
formData.name = row.name
|
|
|
- formData.collection_name = row.collection_name
|
|
|
- // 暂时不需要回显 parent/child,因为编辑是对单个进行的
|
|
|
+ formData.collection_name1 = row.collection_name1
|
|
|
+ formData.collection_name2 = row.collection_name2 || ''
|
|
|
formData.description = row.description || ''
|
|
|
formData.status = row.status
|
|
|
|
|
|
@@ -512,12 +513,17 @@ const handleEdit = async (row: KnowledgeBase) => {
|
|
|
}
|
|
|
|
|
|
const handleSync = async (row: KnowledgeBase) => {
|
|
|
+ if (syncingStates.value[row.id]) return
|
|
|
+
|
|
|
try {
|
|
|
+ syncingStates.value[row.id] = true
|
|
|
await syncKnowledgeBase(row.id)
|
|
|
ElMessage.success('同步成功,Milvus集合已创建')
|
|
|
loadData()
|
|
|
} catch (error) {
|
|
|
// error handled by request interceptor
|
|
|
+ } finally {
|
|
|
+ syncingStates.value[row.id] = false
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -613,24 +619,14 @@ const handleSubmit = async () => {
|
|
|
submitLoading.value = true
|
|
|
try {
|
|
|
if (dialogType.value === 'create') {
|
|
|
- // 1. 创建父集合 KB
|
|
|
- await createKnowledgeBase({
|
|
|
- name: formData.name + ' (父)',
|
|
|
- collection_name: formData.parent_collection_name,
|
|
|
- description: formData.description,
|
|
|
- dimension: formData.dimension,
|
|
|
- metadata_fields: formData.metadata_fields.filter(f => f.field_zh_name && f.field_en_name)
|
|
|
- })
|
|
|
-
|
|
|
- // 2. 创建子集合 KB
|
|
|
await createKnowledgeBase({
|
|
|
- name: formData.name + ' (子)',
|
|
|
- collection_name: formData.child_collection_name,
|
|
|
+ name: formData.name,
|
|
|
+ collection_name1: formData.collection_name1,
|
|
|
+ collection_name2: formData.collection_name2,
|
|
|
description: formData.description,
|
|
|
dimension: formData.dimension,
|
|
|
metadata_fields: formData.metadata_fields.filter(f => f.field_zh_name && f.field_en_name)
|
|
|
})
|
|
|
-
|
|
|
ElMessage.success('创建成功')
|
|
|
} else {
|
|
|
await updateKnowledgeBase(formData.id, {
|
|
|
@@ -645,8 +641,6 @@ const handleSubmit = async () => {
|
|
|
loadData()
|
|
|
} catch (error) {
|
|
|
console.error(error)
|
|
|
- // 注意:如果是第二个失败,第一个可能已经创建成功。
|
|
|
- // 这里简单提示错误,用户可以刷新列表看到已创建的,然后手动处理。
|
|
|
} finally {
|
|
|
submitLoading.value = false
|
|
|
}
|
|
|
@@ -761,6 +755,12 @@ onMounted(() => {
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
+.sub-collection {
|
|
|
+ color: #909399;
|
|
|
+ font-size: 12px;
|
|
|
+ margin-top: 4px;
|
|
|
+}
|
|
|
+
|
|
|
.pagination-container {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|