feat: 文档模块

This commit is contained in:
wangdan-fit2cloud 2023-11-07 19:04:59 +08:00
parent 98681964d7
commit 68c6d409be
16 changed files with 220 additions and 58 deletions

View File

@ -67,14 +67,26 @@ const postDateset: (data: any) => Promise<Result<any>> = (data) => {
* @param file:file,limit:number,patterns:array,with_filter:boolean * @param file:file,limit:number,patterns:array,with_filter:boolean
*/ */
const postSplitDocument: (data: any) => Promise<Result<any>> = (data) => { const postSplitDocument: (data: any) => Promise<Result<any>> = (data) => {
console.log(data)
return post(`${prefix}/document/split`, data) return post(`${prefix}/document/split`, data)
} }
/**
*
* @param dataset_id, name
*/
const getDocument: (dataset_id: string, name?: string) => Promise<Result<any>> = (
dataset_id,
name
) => {
return get(`${prefix}/${dataset_id}/document`, name && { name })
}
export default { export default {
getDateset, getDateset,
getAllDateset, getAllDateset,
delDateset, delDateset,
postDateset, postDateset,
postSplitDocument postSplitDocument,
getDocument
} }

View File

@ -13,10 +13,11 @@ import { ref, onBeforeUpdate } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
const route = useRoute() const route = useRoute()
const cachedViews: any = ref([]) const cachedViews: any = ref([])
onBeforeUpdate(() => { onBeforeUpdate(() => {
let isCached = route.meta?.cache const { name, meta } = route
let name = route.name let isCached = meta?.cache
if (isCached && name && !cachedViews.value.includes(name)) { if (isCached && name && !cachedViews.value.includes(name)) {
cachedViews.value.push(name) cachedViews.value.push(name)
} }

View File

@ -23,7 +23,8 @@ import SidebarItem from './SidebarItem.vue'
const route = useRoute() const route = useRoute()
const subMenuList = computed(() => { const subMenuList = computed(() => {
return getChildRouteListByPathAndName(route.meta.parentPath, route.meta.parentName) const { meta } = route
return getChildRouteListByPathAndName(meta.parentPath, meta.parentName)
}) })
const activeMenu = computed(() => { const activeMenu = computed(() => {

View File

@ -15,15 +15,14 @@ import { useRouter, useRoute, type RouteRecordRaw } from 'vue-router'
import { computed } from 'vue' import { computed } from 'vue'
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const props = defineProps<{ const props = defineProps<{
menu: RouteRecordRaw menu: RouteRecordRaw
}>() }>()
const isActive = computed(() => { const isActive = computed(() => {
return ( const { name, path, meta } = route
(route.name == props.menu.name && route.path == props.menu.path) || return (name == props.menu.name && path == props.menu.path) || meta?.activeMenu == props.menu.path
route?.meta?.activeMenu == props.menu.path
)
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,7 +1,8 @@
<template> <template>
<div class="main-layout h-full flex"> <div class="main-layout h-full flex">
<div class="sidebar-container"> <div class="sidebar-container">
<Sidebar /></div> <Sidebar />
</div>
<div class="view-container"> <div class="view-container">
<AppMain /> <AppMain />
</div> </div>
@ -20,6 +21,6 @@ import { Sidebar, AppMain } from '../components'
background-color: var(--sidebar-bg-color); background-color: var(--sidebar-bg-color);
} }
.view-container { .view-container {
width: 100%; width: calc(100% - var(--sidebar-width));
} }
</style> </style>

View File

@ -18,23 +18,23 @@ const datasetRouter = {
hidden: true hidden: true
}, },
{ {
path: '/dataset/:id', path: '/dataset/:datasetId',
name: 'DatasetDetail', name: 'DatasetDetail',
meta: { title: '文档', activeMenu: '/dataset' }, meta: { title: '文档', activeMenu: '/dataset' },
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [
{ {
path: 'doc', path: 'document',
name: 'DatasetDoc', name: 'DatasetDocument',
meta: { meta: {
icon: 'Document', icon: 'Document',
title: '文档', title: '文档',
active: 'doc', active: 'document',
parentPath: '/dataset/:id', parentPath: '/dataset/:datasetId',
parentName: 'DatasetDetail' parentName: 'DatasetDetail'
}, },
component: () => import('@/views/dataset/DatasetDoc.vue') component: () => import('@/views/dataset/DatasetDocument.vue')
}, },
{ {
path: 'setting', path: 'setting',
@ -43,7 +43,7 @@ const datasetRouter = {
icon: 'Setting', icon: 'Setting',
title: '设置', title: '设置',
active: 'setting', active: 'setting',
parentPath: '/dataset/:id', parentPath: '/dataset/:datasetId',
parentName: 'DatasetDetail' parentName: 'DatasetDetail'
}, },
component: () => import('@/views/dataset/DatasetSetting.vue') component: () => import('@/views/dataset/DatasetSetting.vue')

View File

@ -100,6 +100,9 @@ h4 {
.h-full { .h-full {
height: 100%; height: 100%;
} }
.w-240 {
width: 240px;
}
.mt-8 { .mt-8 {
margin-top: 8px; margin-top: 8px;
@ -249,3 +252,24 @@ h4 {
background: var(--app-layout-bg-color); background: var(--app-layout-bg-color);
border: none; border: none;
} }
// 表格第一行插入自定义行
.table-custom-append {
.el-table__append-wrapper {
position: absolute;
top: 0;
border-bottom: var(--el-table-border);
width: 100%;
height: 49px;
box-sizing: border-box;
align-items: center;
display: flex;
padding: 0 12px;
&:hover {
background: var(--el-color-primary-light-9);
}
}
.el-table__body {
margin-top: 49px;
}
}

View File

@ -8,6 +8,14 @@
.el-button { .el-button {
padding: 5px 12px; padding: 5px 12px;
&.is-text {
padding: 4px !important;
font-size: 16px;
max-height: 24px;
&:not(.is-disabled):hover {
background: var(--app-text-color-primary-light-1);
}
}
} }
.el-avatar { .el-avatar {
--el-avatar-bg-color: var(--el-color-primary); --el-avatar-bg-color: var(--el-color-primary);
@ -92,15 +100,24 @@
} }
.el-table { .el-table {
--el-table-header-bg-color: var(--app-layout-bg-color); --el-table-header-bg-color: var(--app-layout-bg-color);
}
.el-table {
--el-table-text-color: var(--app-text-color-primary); --el-table-text-color: var(--app-text-color-primary);
font-weight: 400;
thead { thead {
color: var(--app-text-color-secondary); color: var(--app-text-color-secondary);
th {
font-weight: 500;
} }
}
th.el-table__cell { th.el-table__cell {
border-top: var(--el-table-border); border-top: var(--el-table-border);
} }
.el-table__cell {
padding: 12px 0;
}
.el-checkbox {
height: 23px;
}
} }
// el-steps // el-steps
@ -124,7 +141,6 @@
} }
} }
.el-scrollbar { .el-switch {
overflow-x: hidden; height: auto;
} }

30
ui/src/utils/time.ts Normal file
View File

@ -0,0 +1,30 @@
const getCheckDate = (timestamp: any) => {
if (!timestamp) return false
const dt = new Date(timestamp)
if (isNaN(dt.getTime())) return false
return dt
}
export const datetimeFormat = (timestamp: any) => {
const dt = getCheckDate(timestamp)
if (!dt) return timestamp
const y = dt.getFullYear()
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
const d = (dt.getDate() + '').padStart(2, '0')
const hh = (dt.getHours() + '').padStart(2, '0')
const mm = (dt.getMinutes() + '').padStart(2, '0')
const ss = (dt.getSeconds() + '').padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
export const dateFormat = (timestamp: any) => {
const dt = getCheckDate(timestamp)
if (!dt) return timestamp
const y = dt.getFullYear()
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
const d = (dt.getDate() + '').padStart(2, '0')
return `${y}-${m}-${d}`
}

View File

@ -1,4 +1,4 @@
function toThousands(num: any) { export function toThousands(num: any) {
return num.toString().replace(/\d+/, function (n: any) { return num.toString().replace(/\d+/, function (n: any) {
return n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') return n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
}) })

View File

@ -1,14 +0,0 @@
<template>
<LayoutContainer header="文档">
<div class="main-calc-height">
<div class="p-24">
1111
</div>
</div>
</LayoutContainer>
</template>
<script setup lang="ts">
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,100 @@
<template>
<LayoutContainer header="文档">
<div class="main-calc-height">
<div class="p-24" v-loading="loading">
<div class="flex-between">
<el-button type="primary">上传文档</el-button>
<el-input
v-model="filterText"
placeholder="按 文档名称 搜索"
prefix-icon="Search"
class="w-240"
/>
</div>
<el-table :data="documentData" class="table-custom-append mt-16">
<template #append>
<el-button type="primary" link>
<el-icon><Plus /></el-icon>
<span class="ml-4">快速创建空白文档</span>
</el-button>
</template>
<el-table-column prop="name" label="文件名称" />
<el-table-column prop="char_length" label="字符数" align="right">
<template #default="{ row }">
{{ toThousands(row.char_length) }}
</template>
</el-table-column>
<el-table-column prop="paragraph_count" label="分段" align="right" />
<el-table-column prop="status" label="文件状态">
<!-- <el-switch v-model="value1" /> -->
</el-table-column>
<el-table-column prop="name" label="启动状态">
<template #default="{ row }">
<el-switch v-model="row.is_active" />
</template>
</el-table-column>
<el-table-column prop="create_time" label="创建时间" width="170">
<template #default="{ row }">
{{ datetimeFormat(row.create_time) }}
</template>
</el-table-column>
<el-table-column prop="update_time" label="更新时间" width="170">
<template #default="{ row }">
{{ datetimeFormat(row.update_time) }}
</template>
</el-table-column>
<el-table-column prop="name" label="操作" align="center">
<template #default="{ row }">
<span>
<el-tooltip effect="dark" content="刷新" placement="top">
<el-button type="primary" text>
<el-icon><RefreshRight /></el-icon>
</el-button> </el-tooltip
></span>
<span class="ml-4">
<el-tooltip effect="dark" content="删除" placement="top">
<el-button type="primary" text>
<el-icon><Delete /></el-icon>
</el-button>
</el-tooltip>
</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</LayoutContainer>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import datasetApi from '@/api/dataset'
import { toThousands } from '@/utils/utils'
import { datetimeFormat } from '@/utils/time'
const router = useRouter()
const route = useRoute()
const { params } = route
const { datasetId } = params
const loading = ref(false)
const filterText = ref('')
const documentData = ref<any[]>([])
function getList() {
loading.value = true
datasetApi
.getDocument(datasetId as string, filterText.value)
.then((res) => {
documentData.value = res.data
loading.value = false
})
.catch(() => {
loading.value = false
})
}
onMounted(() => {
getList()
})
</script>
<style lang="scss" scoped></style>

View File

@ -2,12 +2,7 @@
<div class="dataset-list-container p-24"> <div class="dataset-list-container p-24">
<div class="flex-between"> <div class="flex-between">
<h3>数据集</h3> <h3>数据集</h3>
<el-input <el-input v-model="filterText" placeholder="搜索内容" prefix-icon="Search" class="w-240" />
v-model="filterText"
placeholder="搜索内容"
prefix-icon="Search"
style="width: 300px"
/>
</div> </div>
<div v-loading.fullscreen.lock="loading"> <div v-loading.fullscreen.lock="loading">
<el-row <el-row
@ -32,7 +27,7 @@
:title="item.name" :title="item.name"
:description="item.desc" :description="item.desc"
class="cursor" class="cursor"
@click="router.push({ path: `/dataset/${item.id}/doc` })" @click="router.push({ path: `/dataset/${item.id}/document` })"
> >
<template #mouseEnter> <template #mouseEnter>
<el-tooltip effect="dark" content="删除" placement="top"> <el-tooltip effect="dark" content="删除" placement="top">
@ -128,7 +123,6 @@ onMounted(() => {
position: absolute; position: absolute;
right: 12px; right: 12px;
top: 18px; top: 18px;
padding: 6px;
height: auto; height: auto;
} }
.footer-content { .footer-content {

View File

@ -5,7 +5,6 @@
<!-- 上传文档 --> <!-- 上传文档 -->
<UploadComponent ref="UploadComponentRef" /> <UploadComponent ref="UploadComponentRef" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, onMounted } from 'vue'
@ -39,6 +38,5 @@ defineExpose({
.upload-document { .upload-document {
width: 70%; width: 70%;
margin: 0 auto; margin: 0 auto;
} }
</style> </style>

View File

@ -63,6 +63,8 @@ import type { FormInstance, FormRules } from 'element-plus'
import UserApi from '@/api/user' import UserApi from '@/api/user'
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const { params } = route
const { code, email } = params
const resetPasswordForm = ref<ResetPasswordRequest>({ const resetPasswordForm = ref<ResetPasswordRequest>({
password: '', password: '',
re_password: '', re_password: '',
@ -71,8 +73,6 @@ const resetPasswordForm = ref<ResetPasswordRequest>({
}) })
onMounted(() => { onMounted(() => {
const code = route.params.code
const email = route.params.email
if (code && email) { if (code && email) {
resetPasswordForm.value.code = code as string resetPasswordForm.value.code = code as string
resetPasswordForm.value.email = email as string resetPasswordForm.value.email = email as string

View File

@ -240,7 +240,7 @@ onMounted(() => {
.permission-setting { .permission-setting {
box-sizing: border-box; box-sizing: border-box;
width: calc(100% - var(--team-manage-left-width) - 5px); width: calc(100% - var(--team-manage-left-width));
flex-direction: column; flex-direction: column;
} }