peng.peng 2 years ago
parent
commit
55965fe9f6
  1. 11
      web/client/src/sections/metadataManagement/actions/metadata.js
  2. 7
      web/client/src/sections/metadataManagement/components/metadataDatabModal.js
  3. 5
      web/client/src/sections/metadataManagement/constants/index.js
  4. 8
      web/client/src/sections/metadataManagement/containers/databasesTable.js
  5. 7
      web/client/src/sections/metadataManagement/containers/latestMetadata.js
  6. 189
      web/client/src/sections/metadataManagement/containers/metadataDetails.js
  7. 7
      web/client/src/sections/metadataManagement/containers/metadataTab.js
  8. 1
      web/client/src/utils/webapi.js

11
web/client/src/sections/metadataManagement/actions/metadata.js

@ -136,3 +136,14 @@ export function delMeatadataDatabases(id) {
} }
}); });
} }
export function getMetadataDatabasesById(id) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_METADATA_DATABASES_Info',
url: ApiTable.getMetadataDatabasesById.replace('{id}', id),
msg: { error: '获取库表元数据基本信息失败' },
reducer: { name: 'metadataDatabasesInfo' }
});
}

7
web/client/src/sections/metadataManagement/components/metadataDatabModal.js

@ -4,6 +4,7 @@ const { TextArea } = Input;
const MetadataDatabaseModal = (props) => { const MetadataDatabaseModal = (props) => {
const { onConfirm, onCancel, editData, metadataModels, modelTypes } = props; const { onConfirm, onCancel, editData, metadataModels, modelTypes } = props;
const [form] = Form.useForm(); const [form] = Form.useForm();
const [type, setType] = useState(editData.record.type);
useEffect(() => { useEffect(() => {
}, []); }, []);
const handleOk = () => { const handleOk = () => {
@ -26,7 +27,7 @@ const MetadataDatabaseModal = (props) => {
return Promise.resolve(); return Promise.resolve();
} }
const renderModelItems = () => { const renderModelItems = () => {
const items = metadataModels.map(m => { const items = metadataModels.filter(mm => mm.modelType === type).map(m => {
if (m.control === '文本框') { if (m.control === '文本框') {
const rules = [{ required: !m.nullable, message: '' }] const rules = [{ required: !m.nullable, message: '' }]
if (!m.nullable) { if (!m.nullable) {
@ -114,6 +115,8 @@ const MetadataDatabaseModal = (props) => {
getPopupContainer={triggerNode => triggerNode.parentNode} getPopupContainer={triggerNode => triggerNode.parentNode}
filterOption={(input, option) => option.props.children filterOption={(input, option) => option.props.children
.toLowerCase().indexOf(input.toLowerCase()) >= 0} .toLowerCase().indexOf(input.toLowerCase()) >= 0}
onChange={value => setType(value)}
disabled={!editData.add}
> >
{modelTypes.map(m => <Select.Option value={m} key={m}>{m}</Select.Option>)} {modelTypes.map(m => <Select.Option value={m} key={m}>{m}</Select.Option>)}
</Select> </Select>
@ -133,7 +136,7 @@ const MetadataDatabaseModal = (props) => {
</Form.Item> </Form.Item>
{renderModelItems()} {renderModelItems()}
</Form> </Form>
</Modal> </Modal >
) )
} }
export default MetadataDatabaseModal; export default MetadataDatabaseModal;

5
web/client/src/sections/metadataManagement/constants/index.js

@ -1,3 +1,8 @@
'use strict'; 'use strict';
import React from 'react'; import React from 'react';
export const ModelTypes = ['目录', '库', '视图', '表', '字段', '索引', '外键', '主键', '唯一约束']; export const ModelTypes = ['目录', '库', '视图', '表', '字段', '索引', '外键', '主键', '唯一约束'];
export const ConfigurableTypes = {
'目录': ['库'],
'库': ['视图', '表'],
'表': ['字段', '索引', '外键', '主键', '唯一约束']
}

8
web/client/src/sections/metadataManagement/containers/databasesTable.js

@ -36,8 +36,8 @@ const DatabaseTable = (props) => {
} }
}) })
} }
const onView = (id) => { const onView = (record) => {
setView(id); setView({ path: '/' + resourceCatalogPath.join('/'), ...record });
} }
const onEdit = (record) => { const onEdit = (record) => {
dispatch(metadataManagement.getMetadataModels({ modelTypes: ModelTypes })).then(res => { dispatch(metadataManagement.getMetadataModels({ modelTypes: ModelTypes })).then(res => {
@ -118,7 +118,7 @@ const DatabaseTable = (props) => {
width: '8%', width: '8%',
render: (text, record) => { render: (text, record) => {
return <ButtonGroup> return <ButtonGroup>
<a onClick={() => onView(record.id)}>查看</a> <a onClick={() => onView(record)}>查看</a>
<a style={{ marginLeft: 10 }} onClick={() => onEdit(record)}>编辑</a> <a style={{ marginLeft: 10 }} onClick={() => onEdit(record)}>编辑</a>
<Popconfirm <Popconfirm
title="是否确认删除该元数据?若确认删除则关联的数据将一并删除!" title="是否确认删除该元数据?若确认删除则关联的数据将一并删除!"
@ -196,7 +196,7 @@ const DatabaseTable = (props) => {
<Button type='primary' onClick={() => { <Button type='primary' onClick={() => {
dispatch(metadataManagement.getMetadataModels({ modelTypes: ModelTypes })).then(res => { dispatch(metadataManagement.getMetadataModels({ modelTypes: ModelTypes })).then(res => {
if (res.success) { if (res.success) {
setEditData({ add: true, title: '新建库表元数据', record: { path: '/' + resourceCatalogPath.join('/') } }); setEditData({ add: true, title: '新建库表元数据', record: { path: '/' + resourceCatalogPath.join('/'), type: '目录' } });
setModalVisible(true); setModalVisible(true);
} }
}) })

7
web/client/src/sections/metadataManagement/containers/latestMetadata.js

@ -10,7 +10,7 @@ let expandedKeysData = [];
let allTreeNodeKeys = []; let allTreeNodeKeys = [];
const LatestMetadata = (props) => { const LatestMetadata = (props) => {
const { user, dispatch, actions, history, clientHeight, resourceCatalog, isRequesting, location } = props; const { user, dispatch, actions, history, clientHeight, resourceCatalog, isRequesting, location, match } = props;
const { metadataManagement } = actions; const { metadataManagement } = actions;
const [resourceCatalogData, setResourceCatalogData] = useState([]); const [resourceCatalogData, setResourceCatalogData] = useState([]);
const [selectedKeys, setSelectedKeys] = useState([]); const [selectedKeys, setSelectedKeys] = useState([]);
@ -159,10 +159,11 @@ const LatestMetadata = (props) => {
{location.pathname.indexOf('detail') > -1 ? {location.pathname.indexOf('detail') > -1 ?
<MetadataDetails resourceCatalogId={resourceCatalogId} <MetadataDetails resourceCatalogId={resourceCatalogId}
resourceCatalogKey={resourceCatalogKey} resourceCatalogKey={resourceCatalogKey}
resourceCatalogPath={resourceCatalogPath} history={history} /> : resourceCatalogPath={resourceCatalogPath}
match={match} /> :
<MetadataTab resourceCatalogId={resourceCatalogId} <MetadataTab resourceCatalogId={resourceCatalogId}
resourceCatalogKey={resourceCatalogKey} resourceCatalogKey={resourceCatalogKey}
resourceCatalogPath={resourceCatalogPath} history={history} /> resourceCatalogPath={resourceCatalogPath} />
} }
</Col> </Col>
</Row> </Row>

189
web/client/src/sections/metadataManagement/containers/metadataDetails.js

@ -1,7 +1,186 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { Tabs, Spin, Table, Button, Divider, message } from 'antd';
import moment from 'moment';
import { push } from 'react-router-redux';
import MetadataDatabaseModal from '../components/metadataDatabModal';
import { ModelTypes, ConfigurableTypes } from '../constants/index';
function MetadataDetails (props) { const MetadataDetails = (props) => {
return <>元数据详情</> const { user, actions, dispatch, clientHeight, metadataModels, isRequesting, resourceCatalogPath, match } = props;
} const { metadataManagement } = actions;
const [activeKey, setActiveKey] = useState('info');
const [databasesRecord, setDatabasesRecord] = useState(null);
const [databasesRecordId, setDatabasesRecordId] = useState(null);
const [tableData, setTableData] = useState([]);
const [tableDataCount, setTableDataCount] = useState(0);//Table数据
const [limit, setLimit] = useState(10);
const [currentPage, setCurrentPage] = useState(1);
const [modalVisible, setModalVisible] = useState(false);
const [editData, setEditData] = useState({});
const initData = () => {
dispatch(metadataManagement.getMetadataModels({ modelTypes: ModelTypes }));
dispatch(metadataManagement.getMetadataDatabasesById(match.params.id)).then(res => {
if (res.success) {
setDatabasesRecord(res.payload.data);
setDatabasesRecordId(res.payload.data.id);
initTableData({ id: res.payload.data.id, limit, offset: 0 });
}
});
}
useEffect(() => {
setActiveKey('info')
initData();
}, [match.params.id])
const onTabChange = (key) => {
setActiveKey(key)
}
const onView = (record) => {
setDatabasesRecordId(record.id);
dispatch(push(`/metadataManagement/latestMetadata/detail/${record.id}`));
}
const renderBasicInfo = () => {
return databasesRecord ? <div style={{ marginLeft: 24 }}>
{/* <Divider orientation="left" orientationMargin="0" plain>基本信息</Divider> */}
< div style={{ lineHeight: '35px', marginLeft: 32 }}>
<div > 元数据名称<span style={{ color: '#7F7F7F' }}>{databasesRecord.name}</span></div>
<div > 元数据代码<span style={{ color: '#7F7F7F' }}>{databasesRecord.code}</span></div>
<div > 元数据类型<span style={{ color: '#7F7F7F' }}>{databasesRecord.type}</span></div>
<div > 创建时间<span style={{ color: '#7F7F7F' }}>{moment(databasesRecord.createAt).format("YYYY-MM-DD HH:mm:ss")}</span></div>
<div > 修改时间<span style={{ color: '#7F7F7F' }}>{databasesRecord.updateAt ? moment(databasesRecord.updateAt).format("YYYY-MM-DD HH:mm:ss") : ''}</span></div>
<div > 上下文路径<span style={{ color: '#7F7F7F' }}>{'/' + resourceCatalogPath.join('/')}</span></div>
<div > 元数据详情<span style={{ color: '#7F7F7F' }}>{databasesRecord.description}</span></div>
</div >
<Divider orientation="left" orientationMargin="5" plain>属性</Divider>
< div style={{ lineHeight: '35px', marginLeft: 32 }}>
{databasesRecord.attributesParam ? metadataModels && metadataModels.filter(mm => mm.modelType === databasesRecord.type).map(mm =>
<div > {mm.attributeName}<span style={{ color: '#7F7F7F' }}>{databasesRecord.attributesParam[mm.attributeCode]}</span></div>) : ''}
</div >
</div > : <></>
}
const initTableData = (query = {}) => {
dispatch(metadataManagement.getMetadataDatabases({ ...query })).then(res => {
if (res.success) {
setTableData(res.payload.data.rows);
setTableDataCount(res.payload.data.count);
}
})
}
//新建
const onConfirm = (values) => {
let obj = {
parent: databasesRecord.id,
createBy: user.id, catalog: databasesRecord.catalog,
catalogKey: sessionStorage.getItem('jumpSelectedKey'), ...values
}
dispatch(metadataManagement.postMeatadataDatabases(obj)).then(() => {
setCurrentPage(1);
initTableData({ id: databasesRecord.id, limit, offset: 0 });
setModalVisible(false);
});
}
const renderConfigInfo = () => {
const columns = [
{
title: '元数据名称',
dataIndex: 'name',
key: 'name',
ellipsis: true
}, {
title: '元数据代码',
dataIndex: 'code',
key: 'code',
ellipsis: true
}, {
title: '元数据类型',
dataIndex: 'type',
key: 'type',
}, {
title: '操作',
dataIndex: 'action',
render: (text, record) => {
return <a onClick={() => onView(record)}>查看</a>
}
}];
return databasesRecord && ConfigurableTypes['表'].includes(databasesRecord.type) ? null : <Spin spinning={isRequesting}>
<div style={{ marginBottom: 16 }}>
<Button type='primary' onClick={() => {
setEditData({ add: true, title: '新建库表元数据', record: { path: '/' + resourceCatalogPath.join('/'), type: ConfigurableTypes[databasesRecord.type][0] } });
setModalVisible(true);
}}>新建</Button>
</div>
<Table
scroll={{ y: clientHeight - 320 }}
rowKey='id'
columns={columns}
dataSource={tableData}
pagination={{
current: currentPage,
pageSize: limit,
total: tableDataCount,
showSizeChanger: true,
// showQuickJumper: true,
showTotal: (total) => { return <span style={{ fontSize: 15 }}>{`${Math.ceil(total / limit)} 页,${total}`}</span> },
onShowSizeChange: (currentPage, pageSize) => {
setCurrentPage(currentPage);
setLimit(pageSize);
},
onChange: (page, pageSize) => {
setCurrentPage(page);
setLimit(pageSize);
let queryParams = {
id: databasesRecord.id,
page: page - 1,
size: pageSize
};
initTableData(queryParams);
}
}}
>
</Table>
{
modalVisible ?
<MetadataDatabaseModal
modelTypes={ConfigurableTypes[databasesRecord.type]}
metadataModels={metadataModels.filter(m => ConfigurableTypes[databasesRecord.type].includes(m.modelType))}
editData={editData}
onCancel={() => setModalVisible(false)}
onConfirm={onConfirm} /> : ''
}
</Spin >
export default MetadataDetails }
return <div>
<Tabs defaultActiveKey="info"
onChange={onTabChange}
activeKey={activeKey}
items={[
{
label: <span>基本信息</span>,
key: 'info', children: renderBasicInfo()
},
{
label: <span>组合</span>,
key: 'detailConfig', children: renderConfigInfo()
}
]}>
</Tabs>
{
}
</div >
}
function mapStateToProps(state) {
const { global, auth, metadataModels } = state;
return {
user: auth.user,
actions: global.actions,
clientHeight: global.clientHeight,
isRequesting: metadataModels.isRequesting,
metadataModels: metadataModels.data,
};
}
export default connect(mapStateToProps)(MetadataDetails)

7
web/client/src/sections/metadataManagement/containers/metadataTab.js

@ -4,9 +4,10 @@ import { Tabs } from 'antd';
import DatabaseTable from './databasesTable'; import DatabaseTable from './databasesTable';
import FilesTable from './filesTable'; import FilesTable from './filesTable';
import RestapisTable from './restapisTable'; import RestapisTable from './restapisTable';
import { push } from 'react-router-redux';
const MetadataTab = (props) => { const MetadataTab = (props) => {
const { resourceCatalogId, resourceCatalogKey, resourceCatalogPath, actions, dispatch, history } = props; const { resourceCatalogId, resourceCatalogKey, resourceCatalogPath, actions, dispatch } = props;
const [activeKey, setActiveKey] = useState('databases'); const [activeKey, setActiveKey] = useState('databases');
useEffect(() => { useEffect(() => {
setActiveKey('databases'); setActiveKey('databases');
@ -15,9 +16,9 @@ const MetadataTab = (props) => {
const onTabChange = (key) => { const onTabChange = (key) => {
setActiveKey(key) setActiveKey(key)
} }
const onView = (id) => { const onView = (record) => {
sessionStorage.setItem('jumpSelectedKey', resourceCatalogKey); sessionStorage.setItem('jumpSelectedKey', resourceCatalogKey);
history.push(`/metadataManagement/latestMetadata/detail/${id}`); dispatch(push(`/metadataManagement/latestMetadata/detail/${record.id}`));
} }
return <div> return <div>
<Tabs defaultActiveKey="databases" <Tabs defaultActiveKey="databases"

1
web/client/src/utils/webapi.js

@ -31,6 +31,7 @@ export const ApiTable = {
postMeatadataDatabases: 'meatadata/databases', postMeatadataDatabases: 'meatadata/databases',
putMeatadataDatabases: 'meatadata/databases/{id}', putMeatadataDatabases: 'meatadata/databases/{id}',
delMeatadataDatabases: 'meatadata/databases/{id}', delMeatadataDatabases: 'meatadata/databases/{id}',
getMetadataDatabasesById: 'metadata/databases/{id}',
//元数据采集-数据源管理 //元数据采集-数据源管理
pgCheckConnect: 'adapter/check/connect', pgCheckConnect: 'adapter/check/connect',

Loading…
Cancel
Save