4
This commit is contained in:
@@ -1,10 +1,164 @@
|
||||
<script setup lang="ts">
|
||||
// Phase 4 实现知识库详情
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import apiClient from '@/api/client'
|
||||
|
||||
const route = useRoute()
|
||||
const kbId = route.params.id as string
|
||||
|
||||
const kb = ref<any>(null)
|
||||
const docs = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const uploading = ref(false)
|
||||
const aiUrl = ref('')
|
||||
|
||||
onMounted(async () => {
|
||||
await loadKb()
|
||||
await loadDocs()
|
||||
await loadLink()
|
||||
})
|
||||
|
||||
async function loadKb() {
|
||||
try {
|
||||
const { data } = await apiClient.get(`/knowledge-bases/${kbId}`)
|
||||
kb.value = data
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
async function loadDocs() {
|
||||
loading.value = true
|
||||
try {
|
||||
const { data } = await apiClient.get(`/documents?kb_id=${kbId}`)
|
||||
docs.value = data.items
|
||||
} catch { /* ignore */ }
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
async function loadLink() {
|
||||
try {
|
||||
const { data } = await apiClient.get(`/knowledge-bases/${kbId}/link`)
|
||||
aiUrl.value = `${window.location.origin}/k/${data.token}`
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
async function handleUpload(options: any) {
|
||||
uploading.value = true
|
||||
try {
|
||||
const formData = new FormData()
|
||||
formData.append('kb_id', kbId)
|
||||
formData.append('file', options.file)
|
||||
await apiClient.post('/documents/upload', formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
})
|
||||
ElMessage.success('文档上传成功!')
|
||||
loadDocs()
|
||||
} catch { /* ignore */ }
|
||||
uploading.value = false
|
||||
}
|
||||
|
||||
async function handleDeleteDoc(doc: any) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定删除文档「${doc.original_filename}」?`, '确认删除', { type: 'warning' })
|
||||
await apiClient.delete(`/documents/${doc.id}`)
|
||||
ElMessage.success('已删除。')
|
||||
loadDocs()
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
async function handleReprocess(doc: any) {
|
||||
try {
|
||||
await apiClient.post(`/documents/${doc.id}/reprocess`)
|
||||
ElMessage.success('重新解析已提交。')
|
||||
loadDocs()
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
async function handleCopyLink() {
|
||||
try {
|
||||
await navigator.clipboard.writeText(aiUrl.value)
|
||||
ElMessage.success('AI 链接已复制!')
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
async function handleRegenerate() {
|
||||
try {
|
||||
await ElMessageBox.confirm('重新生成链接后,旧链接将立即失效。确定继续?', '确认', { type: 'warning' })
|
||||
const { data } = await apiClient.post(`/knowledge-bases/${kbId}/regenerate-token`)
|
||||
aiUrl.value = `${window.location.origin}/k/${data.token}`
|
||||
ElMessage.success('链接已重新生成。')
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
function formatSize(bytes: number) {
|
||||
if (bytes < 1024) return bytes + ' B'
|
||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
|
||||
return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
|
||||
}
|
||||
|
||||
function statusType(status: string) {
|
||||
if (status === 'READY') return 'success'
|
||||
if (status === 'FAILED') return 'danger'
|
||||
return 'warning'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>知识库详情</h1>
|
||||
<p>知识库详情(Phase 4 实现)</p>
|
||||
<div v-if="kb">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px">
|
||||
<h1 style="margin: 0">{{ kb.name }}</h1>
|
||||
<el-button type="primary" @click="handleCopyLink">复制 AI 链接</el-button>
|
||||
</div>
|
||||
|
||||
<el-card style="margin-bottom: 20px">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="描述">{{ kb.description || '无' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="kb.enabled ? 'success' : 'danger'">{{ kb.enabled ? '启用' : '禁用' }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="AI 链接">
|
||||
<div style="display: flex; align-items: center; gap: 8px">
|
||||
<el-input :model-value="aiUrl" readonly size="small" style="flex: 1" />
|
||||
<el-button size="small" @click="handleRegenerate">重新生成</el-button>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="文档数">{{ docs.length }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span>文档列表</span>
|
||||
<el-upload
|
||||
:show-file-list="false"
|
||||
:http-request="handleUpload"
|
||||
accept=".docx,.pdf"
|
||||
>
|
||||
<el-button type="primary" :loading="uploading">上传文档</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="docs" v-loading="loading" style="width: 100%">
|
||||
<el-table-column prop="original_filename" label="文件名" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="状态" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="statusType(row.status)" size="small">{{ row.status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="大小" width="100" align="center">
|
||||
<template #default="{ row }">{{ formatSize(row.file_size) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="title" label="标题" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="keywords" label="关键词" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="200" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="handleReprocess(row)">重新解析</el-button>
|
||||
<el-button size="small" type="danger" @click="handleDeleteDoc(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user