提交 e331c308 作者: 方治民

feat: 完成数据源管理模块静态界面开发

上级 ab45b098
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
const itemLabelWidthProp = useItemLabelWidth(schema, formProps) const itemLabelWidthProp = useItemLabelWidth(schema, formProps)
const getValues = computed(() => { const getValues = computed(() => {
const { allDefaultValues, formModel, schema } = props const { allDefaultValues, formModel, schema } = props
// @ts-ignore
const { mergeDynamicData } = props.formProps const { mergeDynamicData } = props.formProps
return { return {
field: schema.field, field: schema.field,
...@@ -83,6 +84,7 @@ ...@@ -83,6 +84,7 @@
return componentProps as Recordable return componentProps as Recordable
}) })
const getDisable = computed(() => { const getDisable = computed(() => {
// @ts-ignore
const { disabled: globDisabled } = props.formProps const { disabled: globDisabled } = props.formProps
const { dynamicDisabled } = props.schema const { dynamicDisabled } = props.schema
const { disabled: itemDisabled = false } = unref(getComponentsProps) const { disabled: itemDisabled = false } = unref(getComponentsProps)
...@@ -97,6 +99,7 @@ ...@@ -97,6 +99,7 @@
}) })
function getShow(): { isShow: boolean; isIfShow: boolean } { function getShow(): { isShow: boolean; isIfShow: boolean } {
const { show, ifShow } = props.schema const { show, ifShow } = props.schema
// @ts-ignore
const { showAdvancedButton } = props.formProps const { showAdvancedButton } = props.formProps
const itemIsAdvanced = showAdvancedButton const itemIsAdvanced = showAdvancedButton
? isBoolean(props.isAdvanced) ? isBoolean(props.isAdvanced)
...@@ -133,6 +136,7 @@ ...@@ -133,6 +136,7 @@
return dynamicRules(unref(getValues)) as ValidationRule[] return dynamicRules(unref(getValues)) as ValidationRule[]
} }
let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[] let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[]
// @ts-ignore
const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps
const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel') const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel')
? rulesMessageJoinLabel ? rulesMessageJoinLabel
...@@ -210,7 +214,14 @@ ...@@ -210,7 +214,14 @@
return rules return rules
} }
function renderComponent() { function renderComponent() {
const { renderComponentContent, component, field, changeEvent = 'change', valueField } = props.schema const {
renderComponentContent,
component,
field,
changeEvent = 'change',
valueField,
label,
} = props.schema
const isCheck = component && ['Switch', 'Checkbox'].includes(component) const isCheck = component && ['Switch', 'Checkbox'].includes(component)
const eventKey = `on${upperFirst(changeEvent)}` const eventKey = `on${upperFirst(changeEvent)}`
const on = { const on = {
...@@ -225,6 +236,7 @@ ...@@ -225,6 +236,7 @@
}, },
} }
const Comp = componentMap.get(component) as ReturnType<typeof defineComponent> const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>
// @ts-ignore
const { autoSetPlaceHolder, size } = props.formProps const { autoSetPlaceHolder, size } = props.formProps
const propsData: Recordable = { const propsData: Recordable = {
allowClear: true, allowClear: true,
...@@ -237,7 +249,7 @@ ...@@ -237,7 +249,7 @@
// RangePicker place is an array // RangePicker place is an array
if (isCreatePlaceholder && component !== 'RangePicker' && component) { if (isCreatePlaceholder && component !== 'RangePicker' && component) {
propsData.placeholder = propsData.placeholder =
unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component) unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component) + label
} }
propsData.codeField = field propsData.codeField = field
propsData.formValues = unref(getValues) propsData.formValues = unref(getValues)
...@@ -282,6 +294,7 @@ ...@@ -282,6 +294,7 @@
function renderItem() { function renderItem() {
const { itemProps, slot, render, field, suffix, component } = props.schema const { itemProps, slot, render, field, suffix, component } = props.schema
const { labelCol, wrapperCol } = unref(itemLabelWidthProp) const { labelCol, wrapperCol } = unref(itemLabelWidthProp)
// @ts-ignore
const { colon } = props.formProps const { colon } = props.formProps
if (component === 'Divider') { if (component === 'Divider') {
return ( return (
...@@ -323,6 +336,7 @@ ...@@ -323,6 +336,7 @@
if (!componentMap.has(component)) { if (!componentMap.has(component)) {
return null return null
} }
// @ts-ignore
const { baseColProps = {} } = props.formProps const { baseColProps = {} } = props.formProps
const realColProps = { ...baseColProps, ...colProps } const realColProps = { ...baseColProps, ...colProps }
const { isIfShow, isShow } = getShow() const { isIfShow, isShow } = getShow()
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
left: 0 !important; left: 0 !important;
width: 100% !important; width: 100% !important;
height: 100%; height: 100%;
max-width: 100vw !important;
&-content { &-content {
height: 100%; height: 100%;
......
...@@ -324,11 +324,16 @@ ...@@ -324,11 +324,16 @@
.ant-form { .ant-form {
width: 100%; width: 100%;
padding: 12px 10px 6px; padding: 12px 12px 6px;
margin-bottom: 16px; margin-bottom: 16px;
background-color: @component-background; background-color: @component-background;
border-radius: 2px; border-radius: 2px;
} }
.ant-form-inline .ant-form-item-control-input-content {
display: flex;
flex-direction: row;
}
} }
.ant-tag { .ant-tag {
...@@ -336,7 +341,7 @@ ...@@ -336,7 +341,7 @@
} }
.ant-table-wrapper { .ant-table-wrapper {
padding: 6px; padding: 12px;
background-color: @component-background; background-color: @component-background;
border-radius: 2px; border-radius: 2px;
......
...@@ -97,7 +97,7 @@ export function useTableScroll( ...@@ -97,7 +97,7 @@ export function useTableScroll(
if (!headEl) return if (!headEl) return
// Table height from bottom height-custom offset // Table height from bottom height-custom offset
let paddingHeight = 32 let paddingHeight = 38
// Pager height // Pager height
let paginationHeight = 2 let paginationHeight = 2
if (!isBoolean(pagination)) { if (!isBoolean(pagination)) {
...@@ -130,7 +130,7 @@ export function useTableScroll( ...@@ -130,7 +130,7 @@ export function useTableScroll(
let bottomIncludeBody = 0 let bottomIncludeBody = 0
if (unref(wrapRef) && isCanResizeParent) { if (unref(wrapRef) && isCanResizeParent) {
const tablePadding = 12 const tablePadding = 24
const formMargin = 16 const formMargin = 16
let paginationMargin = 10 let paginationMargin = 10
const wrapHeight = unref(wrapRef)?.offsetHeight ?? 0 const wrapHeight = unref(wrapRef)?.offsetHeight ?? 0
......
<script lang="ts" setup>
import { Button } from 'ant-design-vue'
import { Icon } from '/@/components/Icon'
import { BasicForm, useForm } from '/@/components/Form'
import { BasicModal, useModalInner } from '/@/components/Modal'
import { options } from './data'
const [registerModal] = useModalInner((data) => {
console.log(data)
})
const [registerEditForm] = useForm({
colon: true,
labelWidth: 120,
showActionButtonGroup: false,
schemas: [
{
field: 'name',
label: '数据源名称',
required: true,
component: 'Input',
colProps: { span: 24 },
},
{
field: 'type',
label: '数据库类型',
required: true,
component: 'Select',
componentProps: {
options,
},
colProps: { span: 24 },
},
{
field: 'driver',
label: '驱动类',
required: true,
component: 'Input',
colProps: { span: 24 },
},
{
field: 'url',
label: '数据源地址',
required: true,
component: 'Input',
colProps: { span: 24 },
},
{
field: 'username',
label: '用户名',
required: true,
component: 'Input',
colProps: { span: 24 },
},
{
field: 'password',
label: '密码',
required: true,
component: 'InputPassword',
colProps: { span: 24 },
},
{
field: 'remark',
label: '备注',
component: 'InputTextArea',
colProps: { span: 24 },
},
],
})
const testing = ref<boolean>(false)
const test = () => {}
</script>
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :maskClosable="false">
<div class="pr-20px">
<BasicForm @register="registerEditForm" />
</div>
<template #insertFooter>
<Button type="dashed" danger @click="test" :disabled="testing">
<Icon icon="fluent-emoji-high-contrast:test-tube" />
测试连接
</Button>
</template>
</BasicModal>
</template>
<style lang="less" scoped>
/** ... */
</style>
import { BasicColumn, FormProps } from '@/components/Table'
interface Option {
label: string
value: string
property?: {
driver?: string
url?: string
}
disabled?: boolean
}
/**
* 支持的数据源类型
*/
export const options: Option[] = [
{
label: 'PostgreSQL',
value: 'PostgreSQL',
property: {
driver: 'org.postgresql.Driver',
url: 'jdbc:postgresql://127.0.0.1:5432/basic-boot',
},
},
{
label: 'H2',
value: 'H2',
property: {
driver: 'org.h2.Driver',
url: 'jdbc:h2:file:~/h2_basic;DB_CLOSE_ON_EXIT=FALSE',
},
},
{
label: 'MySQL 8.x',
value: 'MySQL',
property: {
driver: 'com.mysql.cj.jdbc.Driver',
url: 'jdbc:mysql://127.0.0.1:3306/basic-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai',
},
disabled: true,
},
{
label: '其他数据库',
value: 'custom',
property: {
driver: '',
url: '',
},
},
]
// ================================
export function getColumns(): BasicColumn[] {
return [
{
title: '数据源名称',
dataIndex: 'name',
width: 180,
},
{
title: '数据库类型',
dataIndex: 'type',
width: 150,
},
{
title: '驱动类',
dataIndex: 'driver',
},
{
title: '数据源地址',
dataIndex: 'url',
},
{
title: '用户名',
dataIndex: 'username',
width: 150,
},
{
title: '创建时间',
dataIndex: 'createTime',
defaultHidden: true,
width: 180,
},
]
}
export function getDataSource() {
return (() => {
const data = []
data.push({
id: '1',
name: 'PostgreSQL 14',
type: 'PostgreSQL',
driver: 'org.postgresql.Driver',
url: 'jdbc:postgresql://127.0.0.1:5432/basic-boot',
username: 'postgres',
password: 'postgres',
createTime: '2023-02-26 15:36:01',
})
return data
})()
}
export function getFormConfig(): Partial<FormProps> {
return {
layout: 'inline',
colon: true,
compact: true,
schemas: [
{
field: `name`,
label: `数据源名称`,
component: 'Input',
},
{
field: `type`,
label: `数据库类型`,
component: 'Select',
componentProps: {
options,
style: {
width: '180px',
},
},
},
],
showAdvancedButton: false,
submitButtonOptions: {
preIcon: 'material-symbols:search',
},
}
}
<script lang="ts" setup> <script lang="ts" setup>
import { PageComing } from '/@/components/Page' import { Button, Space } from 'ant-design-vue'
import { Icon } from '/@/components/Icon'
import { useModal } from '/@/components/Modal'
import { ActionItem, BasicColumn, BasicTable, EditRecordRow, useTable, TableAction } from '/@/components/Table'
import Modal from './Modal.vue'
import { getColumns, getDataSource, getFormConfig } from './data'
const [registerTable] = useTable({
size: 'small',
bordered: true,
canResize: true,
columns: getColumns(),
dataSource: getDataSource(),
rowKey: (record) => record.id,
useSearchForm: true,
formConfig: getFormConfig(),
showTableSetting: true,
tableSetting: { fullScreen: true },
actionColumn: {
width: 160,
title: '操作',
dataIndex: 'action',
},
})
function createActions(record: EditRecordRow, column: BasicColumn): ActionItem[] {
return [
{
label: '编辑',
onClick: () => editHandler('编辑', record),
},
{
label: '删除',
popConfirm: {
title: '是否删除',
confirm: () => console.log(record, column),
},
},
]
}
const [registerModal, { openModal, setModalProps }] = useModal()
// 新增/编辑打开窗口
const editHandler = (type: '新增' | '编辑', data?: Recordable) => {
setModalProps({ title: type + '数据源' })
openModal(true, data)
}
// 导入
const importHandler = () => {}
// 下载导入模板
const importTemplateHandler = () => {}
// 导出
const exportHandler = () => {}
</script> </script>
<template> <template>
<PageComing /> <!-- 数据表格 -->
<BasicTable @register="registerTable">
<template #form-custom> custom-slot </template>
<template #tableTitle>
<Space>
<Button type="primary" @click="editHandler('新增')">
<template #icon>
<Icon icon="ant-design:plus-outlined" />
</template>
新增
</Button>
<Button type="dashed" danger @click="exportHandler">
<template #icon>
<Icon icon="ant-design:export-outlined" />
</template>
导出
</Button>
<Button type="dashed" @click="importHandler">
<template #icon>
<Icon icon="ant-design:import-outlined" />
</template>
导入
</Button>
<Button type="default" @click="importTemplateHandler">
<template #icon>
<Icon icon="material-symbols:cloud-download" />
</template>
导入模板下载
</Button>
</Space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="createActions(record, column)" />
</template>
</template>
</BasicTable>
<!-- 新增/编辑弹窗 -->
<Modal @register="registerModal" />
</template> </template>
<style lang="less" scoped> <style lang="less" scoped>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论