fetch: 页面移植

知识库列表,知识库数据页面
This commit is contained in:
杨谢雨 2025-02-19 15:25:35 +08:00
parent cbc3f3296a
commit a92e21767b
9 changed files with 340 additions and 326 deletions

View File

@ -22,13 +22,13 @@
>
<el-button type="primary">
<Icon icon="ep:upload-filled" />
选取文件
{{ props.drag ? '拖拽或' : ''}}选取文件
</el-button>
<template v-if="isShowTip" #tip>
<div style="font-size: 8px">
<div >
大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
</div>
<div style="font-size: 8px">
<div >
格式为 <b style="color: #f56c6c">{{ fileType.join('/') }}</b> 的文件
</div>
</template>

View File

@ -0,0 +1,78 @@
<script setup lang="ts">
import {useTable} from "@/hooks/web/useTable";
import {FormSchema} from "@/types/form";
const tableRef = ref()
const elTableRef = ref()
const columns = [
{
label: '文档名称',
field: 'text',
key: 'text',
width: 200,
},
{
label: '字符数',
field: 'text',
key: 'text',
width: 200,
},
{
label: '切片内容',
field: 'text',
key: 'text',
width: 200,
},
{
label: '切片状态',
field: 'text',
key: 'text',
width: 200,
},
{
label: '切片时间',
field: 'text',
},
{
label: '操作',
field: 'text',
key: 'text',
width: 200,
}
]
const {tableObject, register, tableMethods} = useTable()
const schema = ref<FormSchema[]>([
{
label: '所属文档',
field: 'text',
component: 'Select',
componentProps: {
style: {
width: '150px'
}
}
}
])
const pagination = computed(() => {
return {
pageSize: tableObject.pageSize,
currentPage: tableObject.currentPage,
total: tableObject.total,
}
})
onMounted(() => {
register(tableRef.value, elTableRef.value)
})
</script>
<template>
<content-wrap>
<Search :schema="schema"/>
</content-wrap>
<content-wrap>
<Table ref="tableRef" :pagination="pagination" :columns="columns"/>
</content-wrap>
</template>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,84 @@
<script setup lang="ts">
import {useTable} from "@/hooks/web/useTable";
import {FormSchema} from "@/types/form";
const tableRef = ref()
const elTableRef = ref()
const columns = [
{
label: '文档名称',
field: 'text',
key: 'text',
width: 200,
},
{
label: '文档链接',
field: 'text',
key: 'text',
width: 200,
},
{
label: '文档来源',
field: 'text',
key: 'text',
width: 200,
},
{
label: '切片数量',
field: 'text',
key: 'text',
width: 200,
},
{
label: '切片状态',
field: 'text',
key: 'text',
width: 200,
},
{
label: '文件大小',
field: 'text',
},
{
label: '操作',
field: 'text',
key: 'text',
width: 200,
}
]
const {tableObject, register, tableMethods} = useTable()
const schema = ref<FormSchema[]>([
{
label: '文档名称',
field: 'text',
component: 'Select',
componentProps: {
style: {
width: '150px'
}
}
}
])
const pagination = computed(() => {
return {
pageSize: tableObject.pageSize,
currentPage: tableObject.currentPage,
total: tableObject.total,
}
})
onMounted(() => {
register(tableRef.value, elTableRef.value)
})
</script>
<template>
<content-wrap>
<Search :schema="schema"/>
</content-wrap>
<content-wrap>
<Table ref="tableRef" :pagination="pagination" :columns="columns"/>
</content-wrap>
</template>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,48 @@
<script setup lang="ts">
import { Management } from '@element-plus/icons-vue'
</script>
<template>
<div class="flex flex-wrap wrap">
<el-card class="mb-20px ">
<template #header>
<el-button class="w-full">向量搜索</el-button>
</template>
<el-input rows="10" type="textarea" />
</el-card>
<el-card v-for="index in 5" :key="index" class="mb-20px ">
<template #header>
<div class="flex items-center">
<el-icon class="mr-10px ">
<Management class="text-18px color-[var(--el-color-primary)]"/>
</el-icon>
<span class="">首席信息</span>
</div>
</template>
<div class="inner"></div>
</el-card>
</div>
</template>
<style scoped lang="scss">
.wrap {
&>div {
width: calc((100% - 40px) / 3);
margin-right: 20px;
&:nth-child(3n) {
margin-right: 0px;
}
}
}
.inner {
height: 220px;
}
.el-card:not(:first-child) {
background-color: mix(grey, #fff, 10%);
}
//div {
// display: grid;
// grid-template-columns: repeat(3, 1fr);
// gap: 20px;
//}
</style>

View File

@ -0,0 +1,11 @@
<script setup lang="ts">
import {UploadFile} from '@/components/UploadFile'
</script>
<template>
<UploadFile drag />
</template>
<style scoped lang="scss">
</style>

View File

@ -1,151 +0,0 @@
<template>
<div class="upload-container">
<!-- 标题 -->
<div class="title">
<div>选择数据源</div>
</div>
<!-- 数据源选择 -->
<div class="resource-btn" >导入已有文本</div>
<!-- 上传文件区域 -->
<el-form>
<div class="upload-section">
<div class="upload-label">上传文本文件</div>
<el-upload
class="upload-area"
action="#"
:file-list="fileList"
:on-remove="handleRemove"
:before-upload="beforeUpload"
list-type="text"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">拖拽文件至此或者 <em>选择文件</em></div>
<div class="el-upload__tip">
已支持 TXTMARKDOWNPDFHTMLXLSXXLSDOCXCSVEMLMSGPPTXPPTXMLEPUB每个文件不超过 15MB
</div>
</el-upload>
</div>
<!-- 下一步按钮 -->
<div class="next-button">
<el-button type="primary" :disabled="!fileList.length">下一步</el-button>
</div>
</el-form>
<!-- 知识库创建 -->
<div class="create-knowledge">
<el-link type="primary" underline>创建一个空知识库</el-link>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const fileList = ref([])
const handleRemove = (file, fileList) => {
console.log(file, fileList)
}
const beforeUpload = (file) => {
fileList.value.push(file)
return false
}
</script>
<style scoped lang="scss">
.upload-container {
width: 600px;
margin: 0 auto;
padding: 20px;
background-color: #fff;
border-radius: 8px;
border: 1px solid #ebebeb;
}
.title {
font-size: 22px;
font-weight: bold;
}
.resource-btn {
margin-top: 20px;
border-radius: 10px;
cursor: pointer;
width: 150px;
border: 1.5px solid #528bff;
padding: 10px;
text-align: center;
font-weight: 500;
font-size: 14px;
line-height: 30px;
color: #101828;
}
.upload-section {
margin: 20px 0;
padding-top: 10px;
}
.upload-label {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
color: #303133;
}
.upload-area {
margin-top: 10px;
border: 1px dashed #d9d9d9;
padding: 40px;
text-align: center;
background-color: #f5f7fa;
border-radius: 8px;
}
.el-upload__text em {
color: #409eff;
cursor: pointer;
}
.el-upload__tip {
margin-top: 10px;
font-size: 12px;
color: #909399;
}
.next-button {
text-align: left;
margin-top: 20px;
}
.create-knowledge {
text-align: left;
margin-top: 20px;
}
.el-form-item {
margin-bottom: 0;
}
.source-radio-group {
display: flex;
justify-content: space-between;
}
.el-radio-button {
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
padding: 10px 20px;
}
.el-radio-button .el-icon {
margin-right: 8px;
}
</style>

View File

@ -1,168 +0,0 @@
<template>
<el-row>
<!-- Left Section -->
<el-col :span="12">
<el-card>
<!-- 分段设置 -->
<el-form>
<el-form-item label="分段设置">
<el-radio-group v-model="segmentSetting">
<el-radio label="自动分段与清洗">自动分段与清洗</el-radio>
<el-radio label="自定义">自定义</el-radio>
</el-radio-group>
</el-form-item>
<!-- 索引方式 -->
<el-form-item label="索引方式">
<el-radio-group v-model="indexingMethod">
<el-radio label="高质量">高质量</el-radio>
<el-radio label="经济">经济</el-radio>
</el-radio-group>
</el-form-item>
<!-- Embedding 模型 -->
<el-form-item label="Embedding 模型">
<el-select v-model="embeddingModel" placeholder="Select Embedding Model">
<el-option label="text-embedding-3-large" value="text-embedding-3-large"/>
</el-select>
</el-form-item>
<!-- 检索设置 -->
<el-form-item label="检索设置">
<el-card style="width: 400px;">
<div class="card-header">
<span>向量检索</span>
</div>
<el-slider v-model="topK" :min="1" :max="10" label="Top K"/>
<el-slider v-model="scoreThreshold" :min="0" :max="1" step="0.1" label="Score 阈值"/>
</el-card>
<el-card style="width: 400px;">
<div class="card-header">
<span>全文检索</span>
</div>
<el-slider v-model="topK" :min="1" :max="10" label="Top K"/>
<el-slider v-model="scoreThreshold" :min="0" :max="1" step="0.1" label="Score 阈值"/>
</el-card>
<el-card style="width: 400px;">
<div class="card-header">
<span>混合检索</span>
</div>
<el-slider v-model="topK" :min="1" :max="10" label="Top K"/>
<el-slider v-model="scoreThreshold" :min="0" :max="1" step="0.1" label="Score 阈值"/>
</el-card>
</el-form-item>
</el-form>
</el-card>
</el-col>
<!-- Right Section: 分段预览 -->
<el-col :span="9">
<el-card shadow="never">
<div class="previews-title">分段预览</div>
<template v-for="(segment, index) in segmentPreviews" :key="index">
<div class="segment-preview">
<div class="title">
<div class="left">
<svg width="12" height="12" viewBox="0 0 12 12" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M4.74999 1.5L3.24999 10.5M8.74998 1.5L7.24998 10.5M10.25 4H1.75M9.75 8H1.25"
stroke="#98A2B3" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span class="id">{{ segment.number }}</span>
</div>
<div class="right">
<svg width="12" height="12" viewBox="0 0 12 12" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M4 3.5H8M6 3.5V8.5M3.9 10.5H8.1C8.94008 10.5 9.36012 10.5 9.68099 10.3365C9.96323 10.1927 10.1927 9.96323 10.3365 9.68099C10.5 9.36012 10.5 8.94008 10.5 8.1V3.9C10.5 3.05992 10.5 2.63988 10.3365 2.31901C10.1927 2.03677 9.96323 1.8073 9.68099 1.66349C9.36012 1.5 8.94008 1.5 8.1 1.5H3.9C3.05992 1.5 2.63988 1.5 2.31901 1.66349C2.03677 1.8073 1.8073 2.03677 1.66349 2.31901C1.5 2.63988 1.5 3.05992 1.5 3.9V8.1C1.5 8.94008 1.5 9.36012 1.66349 9.68099C1.8073 9.96323 2.03677 10.1927 2.31901 10.3365C2.63988 10.5 3.05992 10.5 3.9 10.5Z"
stroke="#667085" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span class="char-size">7777 字符</span>
</div>
</div>
<div class="content">{{ segment.text }}</div>
</div>
</template>
</el-card>
</el-col>
</el-row>
</template>
<script setup>
import {ref} from 'vue';
// Reactive variables for form control
const segmentSetting = ref('自动分段与清洗');
const indexingMethod = ref('高质量');
const embeddingModel = ref('text-embedding-3-large');
const directionalSearch = ref(true);
const topK = ref(3);
const scoreThreshold = ref(0.5);
// Mock data for segment previews
const segmentPreviews = ref([
{number: '001', text: "同步obs模型...'UAE-large-V1'"},
{number: '002', text: "同步obs模型...'plip'"},
{number: '003', text: "同步obs模型...'phoBERT-base-v2'"},
{number: '004', text: "同步obs模型...'lama3-bb-bnb-4bit'"},
{number: '005', text: "同步obs模型...'t5-base-split-and-rephrase'"}
]);
</script>
<style scoped lang="scss">
/* Add any custom styles here */
.previews-title {
font-size: 18px;
font-weight: 500;
}
.segment-preview {
background-color: rgba(228, 228, 228, 0.38);
border-radius: 10px;
padding: 15px;
margin-top: 15px;
.title {
display: flex;
justify-content: space-between;
.left {
border-right: 5px;
font-size: 13px;
font-style: italic;
font-weight: 500;
color: #676767;
box-sizing: border-box;
align-items: center;
.id {
margin-left: 5px;
}
}
.right {
display: flex;
flex-direction: row;
align-items: center;
.char-size {
margin-left: 5px;
font-size: 13px;
color: rgba(57, 57, 57, 0.66);
}
}
}
.content {
margin-top: 10px;
font-size: 15px;
font-weight: 500;
}
}
</style>

View File

@ -0,0 +1,104 @@
<script lang="ts" setup>
import {useRoute, useRouter} from 'vue-router'
import {CopyDocument, UploadFilled, Files, Document, Search} from '@element-plus/icons-vue'
import DataCut from "@/views/knowledge/dataset-form/components/data-cut.vue";
import DataImport from "@/views/knowledge/dataset-form/components/data-import.vue";
import DataDocument from "@/views/knowledge/dataset-form/components/data-document.vue";
import DataEmbedding from "@/views/knowledge/dataset-form/components/data-embedding.vue";
const Route = useRoute()
const Router = useRouter()
const active = ref('1')
const tabs = ref([
{
label: '数据导入',
name: '1',
icon: UploadFilled,
component: DataImport
},
{
label: '文档管理',
name: '2',
icon: CopyDocument,
component: DataDocument
},
{
label: '切片管理',
name: '3',
icon: Files,
component: DataCut
},
{
label: '向量搜索',
name: '4',
icon: Search,
component: DataEmbedding
}
])
</script>
<template>
<div class="children flex">
<div class="flex flex-col mr-30px w-350px">
<el-button
class="w-full mb-10px" plain type="primary"
@click="Router.push({ path: '/ai/console/knowledge' })">知识库列表
</el-button>
<el-scrollbar class="flex-1">
<div class="py-20px flex items-center border-b-solid border-gray border-1 mb-10px">
<div
class="icon-bg bg-[var(--el-color-primary-light-7)] w-40px lh-40px text-center mr-10px">
<el-icon class="font-bold">
<Document/>
</el-icon>
</div>
<h3>本地测试</h3>
</div>
<el-form label-position="top">
<el-form-item label="知识库ID">
<el-input />
</el-form-item>
<el-form-item label="关联向量数据库">
<el-input />
</el-form-item>
<el-form-item label="关联向量化模型">
<el-input />
</el-form-item>
</el-form>
</el-scrollbar>
</div>
<div class="flex-1">
<el-tabs v-model="active" class="h-full">
<el-tab-pane class="h-full" v-for="(item, index) in tabs" :key="index" :label="item.label" :name="item.name">
<template #label>
<div class="flex items-center">
<el-icon class=" mr-5px">
<component :is="item.icon" />
</el-icon>
<span>{{item.label}}</span>
</div>
</template>
<el-scrollbar class="inner h-full overflow-y-auto">
<component :is="item.component" />
</el-scrollbar>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<style lang="scss" scoped>
.children {
height: calc(100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - (var(--app-content-padding) * 3)) !important;
box-sizing: border-box;
& > div {
height: 100%;
background-color: #ffffff;
padding: 20px;
box-sizing: border-box;
}
}
:deep(.el-scrollbar__view) {
height: 100%;
}
</style>

View File

@ -11,9 +11,12 @@
</div>
</el-card>
<el-card class="document-card" shadow="hover" v-for="index in 4" :key="index">
<el-card v-for="index in 4" :key="index" class="document-card" shadow="hover"
@click="toDataset(index)">
<div class="document-header">
<el-icon><Folder /></el-icon>
<el-icon>
<Folder/>
</el-icon>
<span>接口鉴权示例代码.md</span>
</div>
<div class="document-info">
@ -45,9 +48,11 @@
</template>
<script setup>
import { ref } from 'vue'
import { Folder, Plus } from '@element-plus/icons-vue'
import {ref} from 'vue'
import {Folder, Plus} from '@element-plus/icons-vue'
import {useRouter} from "vue-router";
const router = useRouter()
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(100) // 100
@ -59,6 +64,9 @@ const handleSizeChange = (val) => {
const handleCurrentChange = (val) => {
console.log(`当前页: ${val}`)
}
const toDataset = (index) => {
router.push({path: '/ai/console/knowledge/' + index})
}
</script>
<style scoped>