ForcePilot/web/src/views/DataBaseView.vue

261 lines
6.6 KiB
Vue
Raw Normal View History

2024-07-16 18:14:27 +08:00
<template>
<div class="database-container">
<h2>文档知识库</h2>
<p>知识型数据库主要是非结构化的文本组成使用向量检索使用</p>
<a-modal :open="newDatabase.open" title="新建数据库" @ok="createDatabase">
<h3>数据库名称<span style="color: red">*</span></h3>
<a-input v-model:value="newDatabase.name" placeholder="新建数据库名称" />
<h3 style="margin-top: 20px;">数据库描述</h3>
<a-textarea
v-model:value="newDatabase.description"
placeholder="新建数据库描述"
:auto-size="{ minRows: 2, maxRows: 5 }"
/>
<template #footer>
<a-button key="back" @click="newDatabase.open=false">取消</a-button>
<a-button key="submit" type="primary" :loading="newDatabase.loading" @click="createDatabase">创建</a-button>
</template>
</a-modal>
<div class="databases">
<div class="new-database dbcard" @click="newDatabase.open=true">
<div class="top">
<div class="icon"><PlusOutlined /></div>
<div class="info">
<h3>新建数据库</h3>
</div>
</div>
<p>导入您自己的文本数据或通过Webhook实时写入数据以增强 LLM 的上下文</p>
</div>
<div
v-for="database in databases"
:key="database.db_id"
class="database dbcard"
@click="navigateToDatabase(database.db_id)">
<div class="top">
<div class="icon"><ReadFilled /></div>
<div class="info">
<h3>{{ database.name }}</h3>
<p><span>{{ database.metaname }}</span> · <span>{{ database.metadata.row_count }}</span></p>
2024-07-16 18:14:27 +08:00
</div>
</div>
<p class="description">{{ database.description }}</p>
<div class="tags">
<a-tag color="blue" v-if="database.embed_model">Embed: {{ database.embed_model }}</a-tag>
</div>
2024-07-16 18:14:27 +08:00
<!-- <button @click="deleteDatabase(database.collection_name)">删除</button> -->
</div>
</div>
<h2>图数据库 &nbsp; <a-spin v-if="graphloading" :indicator="indicator" /></h2>
2024-07-16 18:14:27 +08:00
<p>基于 neo4j 构建的图数据库</p>
2024-07-24 18:32:14 +08:00
<div :class="{'graphloading': graphloading}" v-if="graph">
2024-07-17 18:52:20 +08:00
<div class="dbcard graphbase" @click="navigateToGraph">
2024-07-16 18:14:27 +08:00
<div class="top">
<div class="icon"><AppstoreFilled /></div>
<div class="info">
<h3>{{ graph?.database_name }}</h3>
<p>
<span>{{ graph?.status }}</span> ·
<span>{{ graph?.entity_count }}实体</span>
</p>
</div>
</div>
<p class="description">基于 neo4j 构建的图数据库基于 neo4j 构建的图数据库基于 neo4j 构建的图数据库</p>
<!-- <button @click="deleteDatabase(database.collection_name)">删除</button> -->
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, reactive, watch, h } from 'vue'
2024-07-17 18:52:20 +08:00
import { useRouter, useRoute } from 'vue-router';
2024-07-16 18:14:27 +08:00
import { message, Button } from 'ant-design-vue'
import { ReadFilled, PlusOutlined, AppstoreFilled, LoadingOutlined } from '@ant-design/icons-vue'
2024-07-16 18:14:27 +08:00
2024-07-17 18:52:20 +08:00
const route = useRoute()
2024-07-16 18:14:27 +08:00
const router = useRouter()
const databases = ref([])
const graph = ref(null)
const graphloading = ref(false)
const indicator = h(LoadingOutlined, {spin: true});
2024-07-16 18:14:27 +08:00
const newDatabase = reactive({
name: '',
description: '',
loading: false,
})
2024-07-17 18:52:20 +08:00
const loadDatabases = () => {
2024-07-16 18:14:27 +08:00
loadGraph()
fetch('/api/database/', {
method: "GET",
})
.then(response => response.json())
.then(data => {
console.log(data)
databases.value = data.databases
}
)
}
const createDatabase = () => {
newDatabase.loading = true
console.log(newDatabase)
if (!newDatabase.name) {
message.error('数据库名称不能为空')
newDatabase.loading = false
return
}
fetch('/api/database/', {
method: "POST",
body: JSON.stringify({
database_name: newDatabase.name,
description: newDatabase.description,
db_type: "knowledge"
})
})
.then(response => response.json())
.then(data => {
console.log(data)
2024-07-17 18:52:20 +08:00
loadDatabases()
2024-07-16 18:14:27 +08:00
newDatabase.open = false
newDatabase.name = ''
newDatabase.description = ''
})
.finally(() => {
newDatabase.loading = false
})
}
const navigateToDatabase = (databaseId) => {
router.push({ path: `/database/${databaseId}` });
};
2024-07-17 18:52:20 +08:00
const navigateToGraph = () => {
router.push({ path: `/database/graph` });
};
2024-07-16 18:14:27 +08:00
const loadGraph = () => {
graphloading.value = true
fetch('/api/database/graph', {
method: "GET",
})
.then(response => response.json())
.then(data => {
console.log(data)
graph.value = data.graph
graphloading.value = false
})
.catch(error => {
console.error(error)
message.error(error.message)
graphloading.value = false
})
}
2024-07-17 18:52:20 +08:00
watch(() => route.path, (newPath, oldPath) => {
if (newPath === '/database') {
loadDatabases();
}
});
2024-07-16 18:14:27 +08:00
onMounted(() => {
2024-07-17 18:52:20 +08:00
loadDatabases()
2024-07-16 18:14:27 +08:00
})
</script>
<style lang="less" scoped>
.database-container {
padding: 10px 30px;
background-color: #FCFEFF;
h2 {
margin: 20px 0 10px 0;
}
}
.database-actions, .document-actions {
margin-bottom: 20px;
}
.databases {
display: flex;
flex-wrap: wrap;
gap: 16px;
.new-database {
background-color: #F0F3F4;
}
}
.database, .graphbase {
background-color: white;
box-shadow: 0px 1px 2px 0px rgba(16,24,40,.06),0px 1px 3px 0px rgba(16,24,40,.1);
border: 2px solid white;
transition: box-shadow 0.2s ease-in-out;
2024-07-16 18:14:27 +08:00
&:hover {
box-shadow: 0px 4px 6px -2px rgba(16,24,40,.03),0px 12px 16px -4px rgba(16,24,40,.08);
2024-07-16 18:14:27 +08:00
}
}
2024-07-16 18:14:27 +08:00
.dbcard, .database {
padding: 10px;
border-radius: 12px;
width: 340px;
height: 160px;
2024-07-16 18:14:27 +08:00
padding: 20px;
cursor: pointer;
flex: 1 1 380px;
max-width: 450px;
2024-07-16 18:14:27 +08:00
.top {
display: flex;
align-items: center;
height: 50px;
margin-bottom: 10px;
.icon {
width: 50px;
height: 50px;
font-size: 28px;
margin-right: 10px;
display: flex;
justify-content: center;
align-items: center;
background-color: #F5F8FF;
border-radius: 8px;
border: 1px solid #E0EAFF;
}
.info {
h3, p {
margin: 0;
color: black;
2024-07-16 18:14:27 +08:00
}
p {
color: var(--c-text-light-1);
font-size: small;
}
}
}
.description {
color: var(--c-text-light-1);
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 1;
2024-07-16 18:14:27 +08:00
-webkit-box-orient: vertical;
text-overflow: ellipsis;
margin-bottom: 10px;
2024-07-16 18:14:27 +08:00
}
}
// 整个卡片是模糊的
.graphloading {
filter: blur(2px);
}
</style>