Commit 54997e8b authored by nick zheng's avatar nick zheng

feat: 数据库管理(未对接&&未多语言)

parent 0f8252c7
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 2</title>
<defs>
<path d="M18.4,0 L5.6,0 C2.5072,0 0,2.5072 0,5.6 L0,18.4 C0,21.4928 2.5072,24 5.6,24 L18.4,24 C21.4928,24 24,21.4928 24,18.4 L24,5.6 C24,2.5072 21.4928,0 18.4,0 Z" id="path-1"></path>
<linearGradient x1="39.6239575%" y1="70.8561794%" x2="100%" y2="36.0841055%" id="linearGradient-3">
<stop stop-color="#2633D2" offset="0%"></stop>
<stop stop-color="#B8C4FF" stop-opacity="0" offset="100%"></stop>
</linearGradient>
<linearGradient x1="66.169365%" y1="14.8194694%" x2="50%" y2="56.882504%" id="linearGradient-4">
<stop stop-color="#296C00" offset="0%"></stop>
<stop stop-color="#B9B8FF" stop-opacity="0" offset="100%"></stop>
</linearGradient>
</defs>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="个人空间-数据库-创建数据库" transform="translate(-819.000000, -426.000000)">
<g id="编组-22" transform="translate(693.000000, 322.000000)">
<g id="编组-2" transform="translate(126.000000, 104.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="路径" fill="#2633D2" fill-rule="nonzero" xlink:href="#path-1"></use>
<polygon id="路径-2" fill="url(#linearGradient-3)" mask="url(#mask-2)" points="-1.1255766 7.28306304e-14 16.2152 13.6067546 29 2.75346667 16.9377678 -5.84988091"></polygon>
<polygon id="路径-2备份" fill="url(#linearGradient-4)" mask="url(#mask-2)" points="-7.1255766 21 10.2152 34.6067546 23 23.7534667 10.9377678 15.1501191"></polygon>
<g id="编组" mask="url(#mask-2)" fill="#FFFFFF" fill-rule="nonzero">
<g transform="translate(5.874423, 4.150119)" id="形状">
<path d="M3.28800082,1.01590661 L0.30520136,1.01590661 C0.136616649,1.01590661 0,1.1453438 0,1.30487669 L0,14.7110299 C0,14.8705628 0.136616649,15 0.30520136,15 L3.28800082,15 C3.45664989,15 3.59336698,14.8706237 3.59336698,14.7110299 L3.59336698,1.30487669 C3.59336698,1.14528292 3.45664989,1.01590661 3.28800082,1.01590661 L3.28800082,1.01590661 Z M1.79660109,12.4624279 C1.48664696,12.462491 1.20717586,12.2858528 1.08851536,12.0148862 C0.969854858,11.7439196 1.03537549,11.4319923 1.25452259,11.2245673 C1.47366969,11.0171422 1.80328161,10.9550725 2.08964827,11.0673035 C2.37601493,11.1795345 2.56273589,11.4439619 2.56273589,11.7372736 C2.56291051,11.9296775 2.48227548,12.11426 2.33858317,12.2503832 C2.19489085,12.3865065 1.99992201,12.4630104 1.79660109,12.4630517 L1.79660109,12.4624279 Z M2.94028221,4.85688507 L0.652755176,4.85688507 L0.652755176,4.49274846 L2.94028221,4.49274846 L2.94028221,4.85688507 Z M2.94028221,3.22520997 L0.652755176,3.22520997 L0.652755176,2.86076147 L2.94028221,2.86076147 L2.94028221,3.22520997 Z M7.69463384,1 L4.71183438,1 C4.54318531,1 4.40646823,1.12937631 4.40646823,1.28897008 L4.40646823,14.6951233 C4.40646823,14.8547171 4.54318531,14.9840934 4.71183438,14.9840934 L7.69463384,14.9840934 C7.86328292,14.9840934 8,14.8547171 8,14.6951233 L8,1.28897008 C8,1.12937631 7.86328292,1 7.69463384,1 Z M6.20323411,12.4465213 C5.78001869,12.4465213 5.4369348,12.1218586 5.4369348,11.721367 C5.4369348,11.3208753 5.78001869,10.9962127 6.20323411,10.9962127 C6.62644954,10.9962127 6.96953371,11.3208753 6.96953371,11.721367 C6.96970835,11.9137979 6.8890507,12.098404 6.74532274,12.2345318 C6.60159478,12.3706595 6.40658359,12.4471451 6.20323411,12.4471451 L6.20323411,12.4465213 Z M7.34708003,4.84129035 L5.0593882,4.84129035 L5.0593882,4.4766859 L7.34708003,4.4766859 L7.34708003,4.84129035 Z M7.34708003,3.2097712 L5.0593882,3.2097712 L5.0593882,2.84516675 L7.34708003,2.84516675 L7.34708003,3.2097712 Z"></path>
<path d="M11.0858378,0.00537990653 L8.24117296,0.558092253 C8.16392942,0.573028922 8.09565421,0.618816362 8.05139485,0.685363258 C8.00713549,0.751910154 7.9905249,0.833754139 8.00522398,0.91285722 L10.5675498,14.7529514 C10.5980765,14.9176287 10.7530959,15.0258162 10.9138749,14.9946504 L13.7586997,14.441938 C13.835952,14.4269988 13.9042398,14.3812182 13.9485248,14.3146779 C13.9928097,14.2481377 14.0094599,14.1662949 13.9948086,14.087173 L11.4323228,0.247078902 C11.4017987,0.0823249454 11.2466724,-0.0258871701 11.0858378,0.00537990653 Z M11.8512722,12.0999976 C11.5557528,12.1574955 11.2555215,12.0269689 11.0905855,11.7692866 C10.9256495,11.5116044 10.928493,11.1775169 11.0977901,10.9228198 C11.2670871,10.6681227 11.5694946,10.5429785 11.8639904,10.6057459 C12.1584862,10.6685133 12.3870693,10.9068303 12.4431442,11.2095622 C12.5196065,11.6228445 12.2546754,12.0214173 11.8512722,12.0999976 L11.8512722,12.0999976 Z M11.4884707,4.03478892 L9.30670252,4.45870438 L9.23711757,4.08296486 L11.4193656,3.6590494 L11.4884707,4.03478892 Z M11.1765381,2.35010596 L8.99492994,2.77434914 L8.92534499,2.39926508 L11.1069532,1.97534962 L11.1765381,2.35010596 Z"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>错误</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="创建数据库" transform="translate(-36.000000, -1011.000000)" fill="#D03050">
<g id="错误" transform="translate(36.000000, 1011.000000)">
<path d="M8,14.6666667 C11.6818983,14.6666667 14.6666667,11.6818983 14.6666667,8 C14.6666667,4.31810167 11.6818983,1.33333333 8,1.33333333 C4.31810167,1.33333333 1.33333333,4.31810167 1.33333333,8 C1.33333333,11.6818983 4.31810167,14.6666667 8,14.6666667 Z M10.3570226,5.6429774 C10.6043547,5.89030945 10.6043547,6.29131393 10.3570226,6.53864599 L8.89613999,7.9995286 L10.3570226,9.46135401 C10.6043547,9.70868607 10.6043547,10.1096906 10.3570226,10.3570226 C10.1096906,10.6043547 9.70868607,10.6043547 9.46135401,10.3570226 L8,8.89472578 L6.53864599,10.3570226 C6.29131393,10.6043547 5.89030945,10.6043547 5.6429774,10.3570226 C5.39564534,10.1096906 5.39564534,9.70868607 5.6429774,9.46135401 L7.10480282,7.9995286 L5.6429774,6.53864599 C5.39564534,6.29131393 5.39564534,5.89030945 5.6429774,5.6429774 C5.89030945,5.39564534 6.29131393,5.39564534 6.53864599,5.6429774 L8.0004714,7.10386001 L9.46135401,5.6429774 C9.70868607,5.39564534 10.1096906,5.39564534 10.3570226,5.6429774 Z" id="形状结合"></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>成功</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编辑数据库" transform="translate(-37.000000, -854.000000)" fill="#18A058">
<g id="成功" transform="translate(37.000000, 854.000000)">
<path d="M8,1.33333333 C11.6818983,1.33333333 14.6666667,4.31810167 14.6666667,8 C14.6666667,11.6818983 11.6818983,14.6666667 8,14.6666667 C4.31810167,14.6666667 1.33333333,11.6818983 1.33333333,8 C1.33333333,4.31810167 4.31810167,1.33333333 8,1.33333333 Z M11.0876996,6.51172559 C10.8403676,6.26439354 10.4393631,6.26439354 10.192031,6.51172559 L10.192031,6.51172559 L7.29289322,9.41039199 L5.80796898,7.92593915 C5.56063693,7.6786071 5.15963244,7.6786071 4.91230039,7.92593915 C4.66496834,8.1732712 4.66496834,8.57427569 4.91230039,8.82160774 L4.91230039,8.82160774 L6.84505892,10.7543663 L6.91609227,10.8156883 C7.16403086,10.9996543 7.51588019,10.9792136 7.74072751,10.7543663 L7.74072751,10.7543663 L11.0876996,7.40739418 C11.3350317,7.16006213 11.3350317,6.75905764 11.0876996,6.51172559 Z" id="形状结合"></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
...@@ -45,6 +45,16 @@ export default [ ...@@ -45,6 +45,16 @@ export default [
}, },
component: () => import('@/views/personal-space/personal-knowledge/personal-knowledge.vue'), component: () => import('@/views/personal-space/personal-knowledge/personal-knowledge.vue'),
}, },
{
path: 'database',
name: 'PersonalSpaceDatabase',
meta: {
rank: 1001,
title: '数据库',
belong: 'PersonalSpace',
},
component: () => import('@/views/personal-space/personal-database/personal-database.vue'),
},
], ],
}, },
......
import i18n from '@/locales'
import { DatabaseItemInterface } from './type.d'
import { formatDateTime } from '@/utils/date-formatter'
const t = i18n.global.t
export function createDatabaseColumn(handleDatabaseTableAction: (actionType: string, databaseId: number) => void) {
return [
{
title: () => <span>数据库名称</span>,
key: 'databaseName',
align: 'left',
ellipsis: {
tooltip: true,
},
width: 210,
fixed: 'left',
render(row: DatabaseItemInterface) {
return row.databaseName || '--'
},
},
{
title: () => <span>数据库描述</span>,
key: 'databaseDesc',
align: 'left',
ellipsis: {
tooltip: true,
},
width: 380,
render(row: DatabaseItemInterface) {
return row.databaseDesc || '--'
},
},
{
title: () => <span>编辑时间</span>,
key: 'updateTime',
align: 'left',
ellipsis: {
tooltip: true,
},
width: 170,
render(row: DatabaseItemInterface) {
return row.updateTime ? formatDateTime(row.updateTime) : '--'
},
},
{
title: () => <span>{t('common_module.data_table_module.action')}</span>,
key: 'action',
align: 'left',
ellipsis: {
tooltip: true,
},
width: 190,
fixed: 'right',
render(row: DatabaseItemInterface) {
return (
<div>
<span
className='text-theme-color mr-5 cursor-pointer hover:opacity-80'
onClick={() => handleDatabaseTableAction('view', row.id)}
>
{t('common_module.data_table_module.view')}
</span>
<span
className='text-theme-color mr-5 cursor-pointer hover:opacity-80'
onClick={() => handleDatabaseTableAction('edit', row.id)}
>
{t('common_module.data_table_module.edit')}
</span>
<span
className='text-error-font-color mr-5 cursor-pointer hover:opacity-80'
onClick={() => handleDatabaseTableAction('delete', row.id)}
>
{t('common_module.data_table_module.delete')}
</span>
</div>
)
},
},
]
}
<script setup lang="ts">
import { FormInst, FormItemRule, FormRules, ScrollbarInst } from 'naive-ui'
import { nextTick, reactive, readonly, ref, shallowReadonly, useTemplateRef } from 'vue'
import CustomModal from '@/components/custom-modal/custom-modal.vue'
import DatabaseDirectIcon from '@/assets/svgs/database-direct.svg'
const showModal = defineModel<boolean>('showModal', { required: true })
const databaseFormRef = ref<FormInst | null>(null)
const scrollbarRef = useTemplateRef<ScrollbarInst | null>('scrollbarRef')
const databaseFormData = reactive({
name: '',
databaseDesc: '',
databaseSourceType: 'MySQL',
databaseHost: '',
databasePort: '',
databaseName: '',
databaseUserName: '',
databasePassword: '',
})
const databaseFormRules = shallowReadonly<FormRules>({
name: [
{
key: 'name',
required: true,
validator: (_rule: FormItemRule, value: string) => {
const pattern = /^[\u4e00-\u9fa5a-zA-Z0-9_\-\\.]+$/
if (!value) {
return new Error('请输入数据库名称')
} else if (!pattern.test(value)) {
return new Error('数据库名称仅支持中文、英文、数字、下划线(_)、中划线(-)、英文点(.)')
}
return
},
trigger: 'blur',
},
],
databaseSourceType: [{ required: true, message: '请选择数据源类型', trigger: 'blur' }],
databaseHost: [{ required: true, message: '请输入IP地址或域名', trigger: 'blur' }],
databasePort: [{ required: true, message: '请输入端口号', trigger: 'blur' }],
databaseName: [{ required: true, message: '请输入数据库名', trigger: 'blur' }],
databaseUserName: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
databasePassword: [{ required: true, message: '请输入密码', trigger: 'blur' }],
})
const databaseTypeList = readonly([
{
id: 'KJ7rCkq3HNOk',
icon: DatabaseDirectIcon,
type: 'Direct',
name: '直连数据库',
},
])
const databaseSourceTypeOptions = [
{
label: 'MySQL',
value: 'MySQL',
},
]
const isConnectDatabaseSuccess = ref(false)
const showConnectStatus = ref(false)
function handleConnectDatabase() {
databaseFormRef.value?.validate(
(errors) => {
if (!errors) {
showConnectStatus.value = true
isConnectDatabaseSuccess.value = false
nextTick(() => {
scrollbarRef.value?.scrollTo({ top: 9999, behavior: 'smooth' })
})
}
},
(rule) => {
return rule?.key !== 'name'
},
)
}
function handleCreateDatabase() {
databaseFormRef.value?.validate((errors) => {
if (!errors) {
// TODO
}
})
}
</script>
<template>
<CustomModal
v-model:is-show="showModal"
:title="'创建知识库'"
:width="534"
:confirm-btn-text="'创建'"
@confirm="handleCreateDatabase"
>
<template #content>
<n-scrollbar ref="scrollbarRef" style="max-height: 550px">
<n-form ref="databaseFormRef" :model="databaseFormData" :rules="databaseFormRules">
<n-form-item label="创建方式">
<div
v-for="databaseTypeItem in databaseTypeList"
:key="databaseTypeItem.id"
class="flex-center border-theme-color rounded-theme text-theme-color h-[66px] w-[110px] cursor-pointer flex-col gap-[2px] border"
>
<img :src="databaseTypeItem.icon" class="h-6 w-6" />
<span>{{ databaseTypeItem.name }}</span>
</div>
</n-form-item>
<n-form-item label="数据库名称" path="name" :feedback-style="{ fontSize: '13px' }">
<div class="flex w-full flex-col">
<n-input
v-model:value="databaseFormData.name"
placeholder="请输入数据库名称"
show-count
:maxlength="50"
/>
<span class="text-gray-font-color mt-1 px-2.5 text-[12px]">
仅支持中文、英文、数字、下划线(_)、中划线(-)、英文点(.)
</span>
</div>
</n-form-item>
<n-form-item label="数据库描述">
<n-input
v-model:value="databaseFormData.databaseDesc"
placeholder="请输入数据库描述,此描述仅用于区分不同数据库,不会影响数据库调用"
show-count
:maxlength="100"
type="textarea"
:autosize="{ minRows: 3, maxRows: 5 }"
/>
</n-form-item>
<h3 class="font-family-medium mb-4 text-[18px]">数据源信息</h3>
<n-form-item label="数据源类型" path="databaseSourceType" :feedback-style="{ fontSize: '13px' }">
<n-select
v-model:value="databaseFormData.databaseSourceType"
placeholder="请选择数据源类型"
:options="databaseSourceTypeOptions"
/>
</n-form-item>
<n-form-item label="数据库地址host" path="databaseHost" :feedback-style="{ fontSize: '13px' }">
<div class="flex w-full flex-col">
<n-input v-model:value="databaseFormData.databaseHost" placeholder="请输入IP地址或域名" />
<span class="mt-1 px-2.5 text-[13px] text-[#6F77FF]">
输入的数据源Host必须是公网地址,以百度云GaiaDB数据库为例,请参考文档进行配置
</span>
</div>
</n-form-item>
<n-form-item label="端口号" path="databasePort" :feedback-style="{ fontSize: '13px' }">
<n-input v-model:value="databaseFormData.databasePort" placeholder="请输入端口号" />
</n-form-item>
<n-form-item label="数据库名" path="databaseName" :feedback-style="{ fontSize: '13px' }">
<n-input v-model:value="databaseFormData.databaseName" placeholder="请输入数据库名" />
</n-form-item>
<n-form-item label="用户名" path="databaseUserName" :feedback-style="{ fontSize: '13px' }">
<n-input v-model:value="databaseFormData.databaseUserName" placeholder="请输入用户名" />
</n-form-item>
<n-form-item label="密码" path="databasePassword" :feedback-style="{ fontSize: '13px' }">
<n-input
v-model:value="databaseFormData.databasePassword"
type="password"
show-password-on="click"
placeholder="请输入密码"
class="font-sans"
/>
</n-form-item>
</n-form>
<div
v-show="showConnectStatus"
class="flex items-center gap-[8px] rounded-[10px] px-3 py-[5px]"
:class="isConnectDatabaseSuccess ? 'bg-[#ECFFE6]' : 'bg-[#FFE8E6]'"
>
<div class="h-[16px] w-[16px]" :class="isConnectDatabaseSuccess ? 'bg-svg-success' : 'bg-svg-error'" />
<span class="text-[12px] leading-[16px]">
{{ isConnectDatabaseSuccess ? '数据库连接成功' : '无法联通数据库,请检查填写内容' }}
</span>
</div>
<div class="flex-center mt-5">
<n-button
type="primary"
color="#6F77FF"
class="h-[34px]!"
:bordered="false"
:focusable="false"
@click="handleConnectDatabase"
>
连接测试
</n-button>
</div>
</n-scrollbar>
</template>
</CustomModal>
</template>
<style lang="scss" scoped>
:deep(.n-form-item-label__text) {
font-family: 'SourceHanSansCN-Medium';
}
</style>
<script setup lang="ts">
import { FormInst, FormRules, ScrollbarInst } from 'naive-ui'
import { nextTick, reactive, ref, shallowReadonly, useTemplateRef } from 'vue'
import CustomModal from '@/components/custom-modal/custom-modal.vue'
const showModal = defineModel<boolean>('showModal', { required: true })
const databaseFormRef = ref<FormInst | null>(null)
const scrollbarRef = useTemplateRef<ScrollbarInst | null>('scrollbarRef')
const databaseFormData = reactive({
databaseName: 'test',
databaseDesc: '',
databaseSourceType: 'MySQL',
databaseHost: '125.88.205.65',
databasePort: '8080',
databaseUserName: 'root',
databasePassword: '88888',
})
const databaseFormRules = shallowReadonly<FormRules>({
databaseName: [{ required: true, message: '请输入数据库名称', trigger: 'blur' }],
databasePassword: [{ required: true, message: '请输入密码', trigger: 'blur' }],
})
const isConnectDatabaseSuccess = ref(false)
const showConnectStatus = ref(false)
function handleConnectDatabase() {
databaseFormRef.value?.validate(
(errors) => {
if (!errors) {
showConnectStatus.value = true
isConnectDatabaseSuccess.value = false
nextTick(() => {
scrollbarRef.value?.scrollTo({ top: 9999, behavior: 'smooth' })
})
}
},
(rule) => {
return rule?.key !== 'name'
},
)
}
</script>
<template>
<CustomModal v-model:is-show="showModal" :title="'编辑知识库'" :width="534">
<template #content>
<n-scrollbar ref="scrollbarRef" style="max-height: 550px">
<n-form ref="databaseFormRef" :model="databaseFormData" :rules="databaseFormRules">
<n-form-item label="数据库名称" path="databaseName" :feedback-style="{ fontSize: '13px' }">
<div class="flex w-full flex-col">
<n-input
v-model:value="databaseFormData.databaseName"
placeholder="请输入数据库名称"
show-count
:maxlength="50"
/>
<span class="text-gray-font-color mt-1 px-2.5 text-[12px]">
仅支持中文、英文、数字、下划线(_)、中划线(-)、英文点(.)
</span>
</div>
</n-form-item>
<n-form-item label="数据库描述">
<n-input
v-model:value="databaseFormData.databaseDesc"
placeholder="请输入数据库描述,此描述仅用于区分不同数据库,不会影响数据库调用"
show-count
:maxlength="100"
type="textarea"
:autosize="{ minRows: 4, maxRows: 6 }"
/>
</n-form-item>
<h3 class="font-family-medium mb-4 text-[18px]">数据源信息</h3>
<n-form-item label="数据源类型" show-require-mark :feedback-style="{ fontSize: '13px' }">
<div class="rounded-theme flex h-[32px] w-full items-center bg-[#FAFAFA] px-[14px]">
{{ databaseFormData.databaseSourceType }}
</div>
</n-form-item>
<n-form-item label="数据库地址host" show-require-mark :feedback-style="{ fontSize: '13px' }">
<div class="rounded-theme flex h-[32px] w-full items-center bg-[#FAFAFA] px-[14px]">
{{ databaseFormData.databaseHost }}
</div>
</n-form-item>
<n-form-item label="端口号" show-require-mark :feedback-style="{ fontSize: '13px' }">
<div class="rounded-theme flex h-[32px] w-full items-center bg-[#FAFAFA] px-[14px]">
{{ databaseFormData.databasePort }}
</div>
</n-form-item>
<n-form-item label="数据库名称" show-require-mark :feedback-style="{ fontSize: '13px' }">
<div class="rounded-theme flex h-[32px] w-full items-center bg-[#FAFAFA] px-[14px]">
{{ databaseFormData.databaseName }}
</div>
</n-form-item>
<n-form-item label="用户名" show-require-mark :feedback-style="{ fontSize: '13px' }">
<div class="rounded-theme flex h-[32px] w-full items-center bg-[#FAFAFA] px-[14px]">
{{ databaseFormData.databaseUserName }}
</div>
</n-form-item>
<n-form-item label="密码" path="databasePassword" :feedback-style="{ fontSize: '13px' }">
<n-input
v-model:value="databaseFormData.databasePassword"
type="password"
show-password-on="click"
placeholder="请输入密码"
class="font-sans"
/>
</n-form-item>
</n-form>
<div
v-show="showConnectStatus"
class="flex items-center gap-[8px] rounded-[10px] px-3 py-[5px]"
:class="isConnectDatabaseSuccess ? 'bg-[#ECFFE6]' : 'bg-[#FFE8E6]'"
>
<div class="h-[16px] w-[16px]" :class="isConnectDatabaseSuccess ? 'bg-svg-success' : 'bg-svg-error'" />
<span class="text-[12px] leading-[16px]">
{{ isConnectDatabaseSuccess ? '数据库连接成功' : '无法联通数据库,请检查填写内容' }}
</span>
</div>
<div class="flex-center mt-5">
<n-button
type="primary"
color="#6F77FF"
class="h-[34px]!"
:bordered="false"
:focusable="false"
@click="handleConnectDatabase"
>
连接测试
</n-button>
</div>
</n-scrollbar>
</template>
</CustomModal>
</template>
<style lang="scss" scoped>
:deep(.n-form-item-label__text) {
font-family: 'SourceHanSansCN-Medium';
}
</style>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { Search } from '@icon-park/vue-next'
import useTableScrollY from '@/composables/useTableScrollY'
import { usePagination } from '@/composables/usePagination.ts'
import CustomPagination from '@/components/custom-pagination/custom-pagination.vue'
import { createDatabaseColumn } from './columns.tsx'
import { DatabaseItemInterface } from './type.d'
import EditDatabaseModal from './components/edit-database-modal.vue'
const { t } = useI18n()
const { pageContentWrapRef, tableContentY } = useTableScrollY(48 + 32 + 18 + 16 + 28)
const { paginationData, handlePageNoChange, handlePageSizeChange } = usePagination()
const searchDatabaseInputValue = ref('')
const isSearchEmptyList = ref(false)
const showEditDatabaseModal = ref(false)
const databaseList = ref<DatabaseItemInterface[]>([
{
id: 1,
databaseName: '数据库1',
databaseDesc: '描述1',
updateTime: new Date(),
},
{
id: 2,
databaseName: '数据库2',
databaseDesc: '描述2',
updateTime: new Date(),
},
])
const databaseColumns = createDatabaseColumn(handleDatabaseTableAction)
const emptyTableDataText = computed(() => {
return isSearchEmptyList.value ? t('common_module.search_empty_data') : t('common_module.empty_data')
})
const isLoadingPagination = computed(() => {
return tableContentY.value > 0
})
function handleDatabaseTableAction(actionType: string, databaseId: number) {
switch (actionType) {
case 'view':
handleToDatabaseDetail(databaseId)
break
case 'edit':
handleShowEditDatabaseModal(databaseId)
break
case 'delete':
handleDeleteDatabaseById(databaseId)
break
}
}
function handleToDatabaseDetail(_databaseId: number) {}
function handleShowEditDatabaseModal(_databaseId: number) {
showEditDatabaseModal.value = true
}
function handleDeleteDatabaseById(_databaseId: number) {
window.$message.ctWarning('', '删除后将无法恢复').then(() => {})
}
</script>
<template>
<div ref="pageContentWrapRef" class="h-full w-full">
<div class="mb-[18px] flex justify-end">
<n-input v-model:value="searchDatabaseInputValue" :placeholder="t('common_module.search')" class="w-[256px]!">
<template #suffix>
<Search theme="outline" size="16" fill="#999" class="cursor-pointer" />
</template>
</n-input>
</div>
<div class="mb-4" :style="{ height: tableContentY + 48 + 'px' }">
<n-data-table
ref="knowledgeListTableRef"
:loading="false"
:bordered="true"
:bottom-bordered="true"
:single-line="false"
:data="databaseList"
:columns="databaseColumns"
:max-height="tableContentY"
>
<template #empty>
<div :style="{ height: tableContentY + 'px' }" class="flex items-center justify-center">
<div class="flex flex-col items-center justify-center">
<div
class="mb-5 h-[68px] w-[68px]"
:class="isSearchEmptyList ? 'bg-px-search_empty_list-png' : 'bg-px-empty_list-png'"
/>
<p class="text-gray-font-color select-none">{{ emptyTableDataText }}</p>
</div>
</div>
</template>
</n-data-table>
</div>
<footer v-show="isLoadingPagination" class="flex justify-end">
<CustomPagination
:paging-info="paginationData"
@update-page-no="handlePageNoChange"
@update-page-size="handlePageSizeChange"
/>
</footer>
<EditDatabaseModal v-model:show-modal="showEditDatabaseModal" />
</div>
</template>
export interface DatabaseItemInterface {
id: number
databaseName: string
databaseDesc: string
updateTime: Date
}
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
import { h, readonly, ref, watch } from 'vue' import { h, readonly, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { Plus, ApplicationTwo, NotebookOne } from '@icon-park/vue-next' import { Plus, ApplicationTwo, NotebookOne, DatabaseSetting } from '@icon-park/vue-next'
import CreateKnowledgeModal, { import CreateKnowledgeModal, {
KnowledgeFormDataInterface, KnowledgeFormDataInterface,
} from './personal-knowledge/components/create-knowledge-modal.vue' } from './personal-knowledge/components/create-knowledge-modal.vue'
import CreateDatabaseModal from './personal-database/components/create-database-modal.vue'
import { fetchCreateKnowledge } from '@/apis/knowledge' import { fetchCreateKnowledge } from '@/apis/knowledge'
const { t } = useI18n() const { t } = useI18n()
...@@ -24,6 +25,10 @@ const personalSpaceModuleList = [ ...@@ -24,6 +25,10 @@ const personalSpaceModuleList = [
routeName: 'PersonalSpaceKnowledge', routeName: 'PersonalSpaceKnowledge',
label: 'common_module.knowledge', label: 'common_module.knowledge',
}, },
{
routeName: 'PersonalSpaceDatabase',
label: '数据库',
},
] ]
const addPersonalSpaceOptions = readonly([ const addPersonalSpaceOptions = readonly([
...@@ -38,11 +43,18 @@ const addPersonalSpaceOptions = readonly([ ...@@ -38,11 +43,18 @@ const addPersonalSpaceOptions = readonly([
key: 'addKnowledge', key: 'addKnowledge',
icon: () => h(NotebookOne, { theme: 'outline', size: 16, fill: '#333' }), icon: () => h(NotebookOne, { theme: 'outline', size: 16, fill: '#333' }),
}, },
{
label: () => h('span', {}, '数据库'),
key: 'addDatabase',
icon: () => h(DatabaseSetting, { theme: 'outline', size: 16, fill: '#333' }),
},
]) ])
const showCreateKnowledgeModal = ref(false) const showCreateKnowledgeModal = ref(false)
const createKnowledgeBtnLoading = ref(false) const createKnowledgeBtnLoading = ref(false)
const showCreateDatabaseModal = ref(false)
watch( watch(
() => currentRoute.fullPath, () => currentRoute.fullPath,
() => { () => {
...@@ -62,6 +74,9 @@ function handleSelectAddType(type: string) { ...@@ -62,6 +74,9 @@ function handleSelectAddType(type: string) {
case 'addKnowledge': case 'addKnowledge':
showCreateKnowledgeModal.value = true showCreateKnowledgeModal.value = true
break break
case 'addDatabase':
showCreateDatabaseModal.value = true
break
} }
} }
...@@ -138,6 +153,8 @@ async function handleCreateKnowledgeNextStep(createKnowledgeData: KnowledgeFormD ...@@ -138,6 +153,8 @@ async function handleCreateKnowledgeNextStep(createKnowledgeData: KnowledgeFormD
:btn-loading="createKnowledgeBtnLoading" :btn-loading="createKnowledgeBtnLoading"
@confirm="handleCreateKnowledgeNextStep" @confirm="handleCreateKnowledgeNextStep"
/> />
<CreateDatabaseModal v-model:show-modal="showCreateDatabaseModal" />
</div> </div>
</template> </template>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment