@@ -0,0 +1,8 @@ | |||||
export interface DataSourceConfigVO { | |||||
id: number | |||||
name: string | |||||
url: string | |||||
username: string | |||||
password: string | |||||
createTime: Date | |||||
} |
@@ -10,6 +10,7 @@ export * from './notice.data.ts' | |||||
export * from './logs.data.ts' | export * from './logs.data.ts' | ||||
export * from './system-dict.data.ts' | export * from './system-dict.data.ts' | ||||
export * from './error-code.data.ts' | export * from './error-code.data.ts' | ||||
export * from './data-source.data.ts' | |||||
export interface ResponseDTO<T>{ | export interface ResponseDTO<T>{ | ||||
code: number; | code: number; | ||||
@@ -0,0 +1,121 @@ | |||||
import React, { useEffect, useState } from 'react' | |||||
import { Form, Input, Modal } from 'antd'; | |||||
import { useRequest } from '@/hooks/use-request'; | |||||
import dataSourceService from '@/request/service/data-source'; | |||||
import { DataSourceConfigVO } from '@/models'; | |||||
import { antdUtils } from '@/utils/antd'; | |||||
const layout = { | |||||
labelCol: { span: 4, }, | |||||
wrapperCol: { span: 16 } | |||||
}; | |||||
interface DataTypeEditorProps { | |||||
visible: boolean; | |||||
onCancel: (flag?: boolean) => void; | |||||
onSave: (value: DataSourceConfigVO) => void; | |||||
data?: DataSourceConfigVO | null; | |||||
} | |||||
export default (props: DataTypeEditorProps) => { | |||||
const { visible, onCancel, onSave, data } = props; | |||||
const { runAsync: update } = useRequest(dataSourceService.updateDataSourceConfigApi, { manual: true }); | |||||
const { runAsync: create } = useRequest(dataSourceService.createDataSourceConfigApi, { manual: true }); | |||||
const isEdit = !!data; | |||||
const [saveLoading, setSaveLoading] = useState(false); | |||||
const [form] = Form.useForm(); | |||||
useEffect(() => { | |||||
if (visible) { | |||||
if (data) { | |||||
form.setFieldsValue(data); | |||||
} | |||||
} else { | |||||
form.resetFields(); | |||||
} | |||||
}, [visible]); | |||||
const save = async () => { | |||||
setSaveLoading(true); | |||||
const fieldValues = form.getFieldsValue(); | |||||
const newValue = isEdit ? { ...data, ...fieldValues } : fieldValues; | |||||
const [error, { msg, code }] = isEdit ? await update(newValue) : await create(newValue); | |||||
if (!error && code === 0) { | |||||
onSave(newValue); | |||||
} else { | |||||
antdUtils.message?.open({ | |||||
type: 'error', | |||||
content: msg ?? '操作失败', | |||||
}); | |||||
} | |||||
setSaveLoading(false); | |||||
} | |||||
return ( | |||||
<> | |||||
<Modal | |||||
open={visible} | |||||
title={isEdit ? "编辑" : "新建"} | |||||
width={640} | |||||
onOk={save} | |||||
onCancel={() => onCancel()} | |||||
confirmLoading={saveLoading} | |||||
destroyOnClose | |||||
> | |||||
<Form | |||||
form={form} | |||||
{...layout} | |||||
onFinish={save} | |||||
labelCol={{ flex: '0 0 100px' }} | |||||
wrapperCol={{ span: 16 }} | |||||
> | |||||
<Form.Item name="name" label="数据源名称" | |||||
rules={[ | |||||
{ | |||||
required: true, | |||||
message: '请输入数据源名称', | |||||
}, | |||||
]} | |||||
> | |||||
<Input allowClear/> | |||||
</Form.Item> | |||||
<Form.Item name="url" label="数据源连接" | |||||
rules={[ | |||||
{ | |||||
required: true, | |||||
message: '请输入数据源连接', | |||||
}, | |||||
]} | |||||
> | |||||
<Input.TextArea className='h-[150px]' showCount maxLength={200} /> | |||||
</Form.Item> | |||||
<Form.Item name="username" label="用户名" rules={[ | |||||
{ | |||||
required: true, | |||||
message: '请输入用户名', | |||||
}, | |||||
]}> | |||||
<Input allowClear/> | |||||
</Form.Item> | |||||
<Form.Item name="password" label="密码" rules={[ | |||||
{ | |||||
required: true, | |||||
message: '请输入密码', | |||||
}, | |||||
]}> | |||||
<Input allowClear /> | |||||
</Form.Item> | |||||
</Form> | |||||
</Modal> | |||||
</> | |||||
) | |||||
}; |
@@ -0,0 +1,166 @@ | |||||
import React, { useState, useEffect } from 'react'; | |||||
import { Space, Table, Button, Divider, Card } from 'antd'; | |||||
import type { TableColumnsType } from 'antd'; | |||||
import { t } from '@/utils/i18n'; | |||||
import { PlusOutlined, ExclamationCircleFilled } from '@ant-design/icons'; | |||||
import { antdUtils } from '@/utils/antd'; | |||||
import { useRequest } from '@/hooks/use-request'; | |||||
import { formatDate } from '@/utils/formatTime' | |||||
import dataSourceService from '@/request/service/data-source'; | |||||
import { DataSourceConfigVO } from '@/models'; | |||||
import DataSourceConfigEditor from './data-source-config-editor'; | |||||
export default () => { | |||||
const [editorVisable, seEditorVisable] = useState<boolean>(false); | |||||
const [editNotice, setEditNotice] = useState<DataSourceConfigVO>(); | |||||
const [dataSource, setDataSource] = useState<DataSourceConfigVO[]>([]); | |||||
const { runAsync: getListData } = useRequest(dataSourceService.getDataSourceConfigListApi, { manual: true }); | |||||
const { runAsync: deleteItem } = useRequest(dataSourceService.deleteDataSourceConfigApi, { manual: true }); | |||||
const load = async () => { | |||||
const [error, { code, msg, data }] = await getListData(); | |||||
if (error || code !== 0) { | |||||
antdUtils.message?.open({ type: 'error', content: msg ?? '操作失败' }); | |||||
return | |||||
} | |||||
setDataSource(data); | |||||
}; | |||||
const showDeleteConfirm = (role: DataSourceConfigVO) => { | |||||
antdUtils.modal?.confirm({ | |||||
title: '确认要将该通知删除吗?', | |||||
icon: <ExclamationCircleFilled />, | |||||
content: '请注意删除以后不可恢复!', | |||||
okText: '删除', | |||||
okType: 'danger', | |||||
cancelText: '取消', | |||||
onOk() { | |||||
return new Promise(async (resolve) => { | |||||
const [error, { code, msg }] = await deleteItem(role.id); | |||||
if (error || code !== 0) { | |||||
antdUtils.message?.open({ type: 'error', content: msg ?? '操作失败' }) | |||||
} else { | |||||
antdUtils.message?.open({ type: 'success', content: '删除成功' }) | |||||
} | |||||
await load(); | |||||
resolve('') | |||||
}).catch(() => antdUtils.message?.open({ | |||||
type: 'error', | |||||
content: '操作失败', | |||||
})); | |||||
}, | |||||
onCancel() { | |||||
}, | |||||
}); | |||||
}; | |||||
const columns: TableColumnsType<DataSourceConfigVO> = [ | |||||
{ | |||||
title: '序号', | |||||
dataIndex: 'id', | |||||
key: 'id', | |||||
align: 'center', | |||||
width: 100, | |||||
}, | |||||
{ | |||||
title: '数据源名称', | |||||
dataIndex: 'name', | |||||
key: 'name', | |||||
filterSearch: true, | |||||
align: 'center', | |||||
width: 200, | |||||
}, | |||||
{ | |||||
title: '数据源连接', | |||||
dataIndex: 'url', | |||||
key: 'url', | |||||
align: 'center', | |||||
}, | |||||
{ | |||||
title: '用户名', | |||||
key: 'username', | |||||
dataIndex: 'username', | |||||
width: 150, | |||||
align: 'center' | |||||
}, | |||||
{ | |||||
title: '创建时间', | |||||
key: 'createTime', | |||||
dataIndex: 'createTime', | |||||
width: 200, | |||||
align: 'center', | |||||
render: (value: number) => { | |||||
return formatDate(new Date(value), "YYYY-mm-dd HH:MM:SS") | |||||
} | |||||
}, | |||||
{ | |||||
title: t("QkOmYwne" /* 操作 */), | |||||
key: 'action', | |||||
fixed: 'right', | |||||
align: 'center', | |||||
width: 200, | |||||
render: (value: DataSourceConfigVO, record) => ( | |||||
<Space size="small" split={(<Divider type='vertical' />)}> | |||||
<a onClick={() => { | |||||
setEditNotice(value); | |||||
seEditorVisable(true); | |||||
}}> | |||||
编辑 | |||||
</a> | |||||
<a onClick={() => { | |||||
}}> | |||||
详情 | |||||
</a> | |||||
<a onClick={() => { | |||||
showDeleteConfirm(value); | |||||
}}> | |||||
删除 | |||||
</a> | |||||
</Space> | |||||
), | |||||
}, | |||||
]; | |||||
useEffect(() => { | |||||
load(); | |||||
}, []); | |||||
return ( | |||||
<> | |||||
<div> | |||||
<Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]' | |||||
bodyStyle={{ | |||||
paddingTop: 0, | |||||
paddingBottom: 0 | |||||
}}> | |||||
<div className='flex justify-end content-center'> | |||||
<div className="py-[4px] flex justify-normal items-center"> | |||||
<Button className="ml-5" type='primary' size='large' icon={<PlusOutlined />} onClick={() => { | |||||
setEditNotice(undefined); | |||||
seEditorVisable(true); | |||||
}}> 新增 </Button> | |||||
</div> | |||||
</div> | |||||
<Table rowKey="id" | |||||
scroll={{ x: true }} | |||||
columns={columns} | |||||
dataSource={dataSource} | |||||
className='bg-transparent' | |||||
pagination={false}/> | |||||
</Card> | |||||
</div> | |||||
<DataSourceConfigEditor | |||||
onSave={() => { | |||||
load(); | |||||
seEditorVisable(false); | |||||
}} | |||||
onCancel={() => { seEditorVisable(false) }} | |||||
visible={editorVisable} | |||||
data={editNotice} /> | |||||
</> | |||||
); | |||||
}; |
@@ -0,0 +1,34 @@ | |||||
import request from '@/request'; | |||||
import { DataSourceConfigVO } from '@/models'; | |||||
const BASE_URL = '/admin-api/infra/data-source-config'; | |||||
export default { | |||||
// 查询数据源配置列表 | |||||
getDataSourceConfigListApi: () => { | |||||
return request.get<DataSourceConfigVO[]>(`${BASE_URL}/list`) | |||||
}, | |||||
// 查询数据源配置详情 | |||||
getDataSourceConfigApi: (id: number) => { | |||||
return request.get(`${BASE_URL}/get?id=${id}`) | |||||
}, | |||||
// 新增数据源配置 | |||||
createDataSourceConfigApi: (data: DataSourceConfigVO) => { | |||||
return request.post(`${BASE_URL}/create`, data) | |||||
}, | |||||
// 修改数据源配置 | |||||
updateDataSourceConfigApi: (data: DataSourceConfigVO) => { | |||||
return request.put(`${BASE_URL}/update`, data) | |||||
}, | |||||
// 删除数据源配置 | |||||
deleteDataSourceConfigApi: (id: number) => { | |||||
return request.delete(`${BASE_URL}/delete?id=${id}`) | |||||
}, | |||||
}; | |||||