update: 数据源管理组件替换、弹窗优化

This commit is contained in:
easy 2023-03-07 14:58:42 +08:00
parent a57870a2e1
commit e2417ed44e
3 changed files with 252 additions and 282 deletions

View File

@ -1,13 +1,13 @@
<template>
<a-card class="mangement-container">
<div class="mangement-container">
<div class="left">
<a-input-search
<j-input-search
v-model:value="leftData.searchValue"
placeholder="请输入"
style="margin-bottom: 24px"
/>
<!-- 使用v-if用于解决异步加载数据后不展开的问题 -->
<a-tree
<j-tree
v-if="leftData.treeData.length > 0"
showLine
defaultExpandAll
@ -37,12 +37,12 @@
{{ dataRef.title }}
</span>
</template>
</a-tree>
</j-tree>
</div>
<div class="right">
<div class="btns">
<a-button type="primary" @click="table.clickSave"
>保存</a-button
<j-button type="primary" @click="table.clickSave"
>保存</j-button
>
</div>
<j-pro-table
@ -52,7 +52,7 @@
:dataSource="table.data"
>
<template #name="slotProps">
<a-input
<j-input
:disabled="slotProps.scale !== undefined"
v-model:value="slotProps.name"
placeholder="请输入名称"
@ -60,37 +60,37 @@
/>
</template>
<template #type="slotProps">
<a-input
<j-input
v-model:value="slotProps.type"
placeholder="请输入类型"
:maxlength="64"
/>
</template>
<template #length="slotProps">
<a-input-number
<j-input-number
v-model:value="slotProps.length"
:min="0"
:max="99999"
/>
</template>
<template #precision="slotProps">
<a-input-number
<j-input-number
v-model:value="slotProps.precision"
:min="0"
:max="99999"
/>
</template>
<template #notnull="slotProps">
<a-radio-group
<j-radio-group
v-model:value="slotProps.notnull"
button-style="solid"
>
<a-radio-button :value="true"></a-radio-button>
<a-radio-button :value="false"></a-radio-button>
</a-radio-group>
<j-radio-button :value="true"></j-radio-button>
<j-radio-button :value="false"></j-radio-button>
</j-radio-group>
</template>
<template #comment="slotProps">
<a-input
<j-input
v-model:value="slotProps.comment"
placeholder="请输入说明"
/>
@ -110,19 +110,19 @@
</PermissionButton>
</template>
</j-pro-table>
<a-botton class="add-row" @click="table.addRow">
<j-botton class="add-row" @click="table.addRow">
<AIcon type="PlusOutlined" /> 新增行
</a-botton>
</j-botton>
</div>
</a-card>
</div>
<div class="dialogs">
<a-modal
<j-modal
v-model:visible="dialog.visible"
title="新增"
@ok="dialog.handleOk"
>
<a-form :model="dialog.form" ref="addFormRef">
<a-form-item
<j-form :model="dialog.form" ref="addFormRef">
<j-form-item
label="名称"
name="name"
:rules="[
@ -148,13 +148,13 @@
},
]"
>
<a-input
<j-input
v-model:value="dialog.form.name"
placeholder="请输入名称"
/>
</a-form-item>
</a-form>
</a-modal>
</j-form-item>
</j-form>
</j-modal>
</div>
</template>
@ -311,8 +311,11 @@ const table = reactive({
name: leftData.selectedKeys[0],
columns: table.data,
};
saveTable_api(id, params).then(() => {
table.getTabelData(params.name);
saveTable_api(id, params).then((resp) => {
if (resp.status === 200) {
message.success('操作成功');
table.getTabelData(params.name);
}
});
},
clickDel: (row: any) => {},
@ -348,50 +351,48 @@ function init() {
<style lang="less" scoped>
.mangement-container {
margin: 24px;
padding: 24px;
background-color: transparent;
:deep(.ant-card-body) {
display: flex;
background-color: #fff;
background-color: #fff;
display: flex;
.left {
flex-basis: 280px;
padding-right: 24px;
box-sizing: border-box;
.left {
flex-basis: 280px;
padding-right: 24px;
box-sizing: border-box;
.ant-tree-treenode {
:deep(.ant-tree-treenode) {
width: 100%;
.ant-tree-switcher-noop {
display: none;
}
.ant-tree-node-content-wrapper {
width: 100%;
.ant-tree-switcher-noop {
display: none;
}
.ant-tree-node-content-wrapper {
.ant-tree-title {
width: 100%;
.ant-tree-title {
width: 100%;
}
}
&:first-child .ant-tree-node-selected {
background-color: transparent;
}
}
&:first-child .ant-tree-node-selected {
background-color: transparent;
}
}
.right {
width: calc(100% - 280px);
box-sizing: border-box;
border-left: 1px solid #f0f0f0;
}
.right {
width: calc(100% - 280px);
box-sizing: border-box;
border-left: 1px solid #f0f0f0;
.btns {
display: flex;
justify-content: right;
padding: 0px 24px;
}
.btns {
display: flex;
justify-content: right;
padding: 0px 24px;
}
.add-row {
display: block;
text-align: center;
width: 100%;
cursor: pointer;
}
.add-row {
display: block;
text-align: center;
width: 100%;
cursor: pointer;
}
}
}

View File

@ -1,18 +1,17 @@
<template>
<a-modal
<j-modal
class="edit-dialog-container"
:title="dialog.title"
width="1050px"
@ok="dialog.handleOk"
:confirmLoading="dialog.loading.value"
cancelText="取消"
okText="确定"
v-model:visible="dialog.visible.value"
visible
:title="dialogTitle"
:confirmLoading="loading"
@ok="confirm"
@cancel="emits('update:visible', false)"
>
<a-form ref="formRef" :model="form.data" layout="vertical">
<a-row :gutter="24">
<a-col :span="12">
<a-form-item
<j-form ref="formRef" :model="form.data" layout="vertical">
<j-row :gutter="24">
<j-col :span="12">
<j-form-item
name="name"
label="名称"
:rules="[
@ -20,72 +19,72 @@
{ max: 64, message: '最多可输入64个字符' },
]"
>
<a-input
<j-input
v-model:value="form.data.name"
placeholder="请输入名称"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item
</j-form-item>
</j-col>
<j-col :span="12">
<j-form-item
name="typeId"
label="类型"
:rules="[{ required: true, message: '请选择类型' }]"
>
<a-select
<j-select
v-model:value="form.data.typeId"
:options="form.typeOptions"
placeholder="请选择类型"
:disabled="!!form.data.id"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24" v-if="form.data.typeId === 'rdb'">
<a-col :span="24">
<a-form-item
</j-form-item>
</j-col>
</j-row>
<j-row :gutter="24" v-if="form.data.typeId === 'rdb'">
<j-col :span="24">
<j-form-item
:name="['shareConfig', 'url']"
label="URL"
:rules="[{ required: true, message: '请输入URL' }]"
>
<a-input
<j-input
v-model:value="form.data.shareConfig.url"
placeholder="请输入r2bdc或者jdbc连接地址示例r2dbc:mysql://127.0.0.1:3306/test"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24" v-if="form.data.typeId === 'rabbitmq'">
<a-col :span="24">
<a-form-item
</j-form-item>
</j-col>
</j-row>
<j-row :gutter="24" v-if="form.data.typeId === 'rabbitmq'">
<j-col :span="24">
<j-form-item
:name="['shareConfig', 'adminUrl']"
label="管理地址"
:rules="[{ required: true, message: '请输入管理地址' }]"
>
<a-input
<j-input
v-model:value="form.data.shareConfig.adminUrl"
placeholder="请输入管理地址示例http://localhost:15672"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24" v-if="form.data.typeId === 'rabbitmq'">
<a-col :span="24">
<a-form-item
</j-form-item>
</j-col>
</j-row>
<j-row :gutter="24" v-if="form.data.typeId === 'rabbitmq'">
<j-col :span="24">
<j-form-item
:name="['shareConfig', 'addresses']"
label="链接地址"
:rules="[{ required: true, message: '请输入链接地址' }]"
>
<a-input
<j-input
v-model:value="form.data.shareConfig.addresses"
placeholder="请输入链接地址示例localhost:5672"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24" v-show="form.data.typeId">
<a-col :span="12">
<a-form-item
</j-form-item>
</j-col>
</j-row>
<j-row :gutter="24" v-show="form.data.typeId">
<j-col :span="12">
<j-form-item
:name="['shareConfig', 'username']"
label="用户名"
:rules="[
@ -96,14 +95,14 @@
},
]"
>
<a-input
<j-input
v-model:value="form.data.shareConfig.username"
placeholder="请输入用户名"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item
</j-form-item>
</j-col>
<j-col :span="12">
<j-form-item
:name="['shareConfig', 'password']"
label="密码"
:rules="[
@ -114,16 +113,16 @@
},
]"
>
<a-input-password
<j-input-password
v-model:value="form.data.shareConfig.password"
placeholder="请输入密码"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24" v-if="form.data.typeId === 'rabbitmq'">
<a-col :span="24">
<a-form-item
</j-form-item>
</j-col>
</j-row>
<j-row :gutter="24" v-if="form.data.typeId === 'rabbitmq'">
<j-col :span="24">
<j-form-item
:name="['shareConfig', 'virtualHost']"
label="虚拟域"
:rules="[
@ -134,16 +133,16 @@
},
]"
>
<a-input
<j-input
v-model:value="form.data.shareConfig.virtualHost"
placeholder="请输入虚拟域"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24" v-if="form.data.typeId === 'rdb'">
<a-col :span="24">
<a-form-item
</j-form-item>
</j-col>
</j-row>
<j-row :gutter="24" v-if="form.data.typeId === 'rdb'">
<j-col :span="24">
<j-form-item
:name="['shareConfig', 'schema']"
label="schema"
:rules="[
@ -154,28 +153,28 @@
},
]"
>
<a-input
<j-input
v-model:value="form.data.shareConfig.schema"
placeholder="请输入schema"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :span="24">
<a-form-item name="description" label="说明">
<a-textarea
</j-form-item>
</j-col>
</j-row>
<j-row :gutter="24">
<j-col :span="24">
<j-form-item name="description" label="说明">
<j-textarea
v-model:value="form.data.description"
placeholder="请输入说明"
:rows="3"
showCount
:maxlength="200"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-modal>
</j-form-item>
</j-col>
</j-row>
</j-form>
</j-modal>
</template>
<script setup lang="ts">
@ -186,38 +185,35 @@ import {
import { FormInstance, message } from 'ant-design-vue';
import type { dictItemType, optionItemType, sourceItemType } from '../typing';
const emits = defineEmits(['confirm']);
const emits = defineEmits(['confirm', 'update:visible']);
const props = defineProps<{
visible: boolean;
data: sourceItemType;
}>();
//
const dialog = {
title: '',
loading: ref<boolean>(false),
visible: ref<boolean>(false),
handleOk: () => {
formRef.value?.validate().then(() => {
form.submit();
});
},
//
openDialog: (row: sourceItemType) => {
if (row.id) dialog.title = '编辑数据源';
else dialog.title = '新增数据源';
form.data = { ...row };
nextTick(() => {
formRef.value?.clearValidate();
dialog.visible.value = true;
});
},
const dialogTitle = computed(() =>
props.data.id ? '编辑数据源' : '新增数据源',
);
const loading = ref(false);
const confirm = () => {
loading.value = true;
formRef.value
?.validate()
.then(() => form.submit())
.then((resp: any) => {
if (resp.status === 200) {
message.success('操作成功');
emits('confirm');
emits('update:visible', false);
}
})
.finally(() => (loading.value = false));
};
//
defineExpose({
openDialog: dialog.openDialog,
});
const formRef = ref<FormInstance>();
const form = reactive({
data: {
shareConfig: {},
...props.data,
} as sourceItemType,
typeOptions: [] as optionItemType[],
@ -232,14 +228,7 @@ const form = reactive({
});
},
submit: () => {
dialog.loading.value = true;
saveDataSource_api(form.data)
.then(() => {
message.success('操作成功');
emits('confirm');
dialog.visible.value = false;
})
.finally(() => (dialog.loading.value = false));
return saveDataSource_api(form.data);
},
});
form.getTypeOption();

View File

@ -1,14 +1,17 @@
<template>
<page-container>
<div class="data-source-container">
<Search :columns="query.columns" @search="query.search" />
<j-advanced-search
:columns="columns"
@search="(params:any)=>queryParams = {...params}"
/>
<j-pro-table
ref="tableRef"
:columns="table.columns"
:columns="columns"
:request="getDataSourceList_api"
model="TABLE"
:params="query.params.value"
:params="queryParams"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
@ -41,7 +44,7 @@
}}
</template>
<template #action="slotProps">
<a-space :size="16">
<j-space :size="16">
<PermissionButton
:uhasPermission="`${permission}:update`"
type="link"
@ -120,13 +123,16 @@
>
<AIcon type="DeleteOutlined" />
</PermissionButton>
</a-space>
</j-space>
</template>
</j-pro-table>
<div class="dialogs">
<EditDialog ref="editDialogRef" @confirm="table.refresh" />
</div>
<EditDialog
v-if="dialog.visible"
v-model:visible="dialog.visible"
:data="dialog.selectItem"
@confirm="table.refresh"
/>
</div>
</page-container>
</template>
@ -150,113 +156,81 @@ const permission = 'system/DataSource';
const router = useRouter();
const query = {
columns: [
{
title: '名称',
dataIndex: 'name',
key: 'name',
search: {
type: 'string',
},
const columns = [
{
title: '名称',
dataIndex: 'name',
key: 'name',
search: {
type: 'string',
},
{
title: '类型',
dataIndex: 'typeId',
key: 'typeId',
search: {
type: 'select',
options: () =>
new Promise((resolve) => {
if (table.typeOptions.value.length > 0)
return resolve(table.typeOptions.value);
getDataTypeDict_api().then((resp: any) => {
const result = resp.result as dictItemType[];
resolve(
result.map((item) => ({
label: item.name,
value: item.id,
})),
);
});
}),
},
},
{
title: '说明',
dataIndex: 'description',
key: 'description',
search: {
type: 'string',
},
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
ellipsis: true,
fixed: 'left',
search: {
type: 'select',
options: [
{
label: '正常',
value: 'enabled',
},
{
label: '已禁用',
value: 'disabled',
},
],
},
},
],
params: ref({}),
search: (params: object) => {
query.params.value = params;
width: '250px',
},
};
{
title: '类型',
dataIndex: 'typeId',
key: 'typeId',
search: {
type: 'select',
options: () =>
new Promise((resolve) => {
if (table.typeOptions.value.length > 0)
return resolve(table.typeOptions.value);
getDataTypeDict_api().then((resp: any) => {
const result = resp.result as dictItemType[];
resolve(
result.map((item) => ({
label: item.name,
value: item.id,
})),
);
});
}),
},
scopedSlots: true,
},
{
title: '说明',
dataIndex: 'description',
key: 'description',
search: {
type: 'string',
},
ellipsis: true,
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
search: {
type: 'select',
options: [
{
label: '正常',
value: 'enabled',
},
{
label: '已禁用',
value: 'disabled',
},
],
},
scopedSlots: true,
width: '120px',
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
scopedSlots: true,
width: '200px',
fixed: 'right',
},
];
const queryParams = ref({});
const editDialogRef = ref(); //
const tableRef = ref<Record<string, any>>({}); //
const table = {
columns: [
{
title: '名称',
dataIndex: 'name',
key: 'name',
width: '250px',
},
{
title: '类型',
dataIndex: 'typeId',
key: 'typeId',
scopedSlots: true,
},
{
title: '说明',
dataIndex: 'description',
key: 'description',
ellipsis: true,
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
scopedSlots: true,
width: '120px',
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
scopedSlots: true,
width: '200px',
fixed: 'right',
},
],
typeOptions: ref<optionItemType[]>([]),
getTypeOption: () => {
@ -279,7 +253,8 @@ const table = {
},
//
openDialog: (row: sourceItemType | {}) => {
editDialogRef.value.openDialog({ shareConfig: {}, ...row });
dialog.selectItem = { shareConfig: {}, ...row };
dialog.visible = true;
},
//
clickDel: (row: sourceItemType) => {
@ -304,6 +279,11 @@ const table = {
},
};
table.getTypeOption();
const dialog = reactive({
visible: false,
selectItem: {} as any,
});
</script>
<style lang="less" scoped>