Commit 9fc1bcf8 by zhaochengxiang

模型自动建表

parent ab53a797
......@@ -189,3 +189,15 @@ export function* autocomplete(payload) {
export function* recommandEnglishWords(payload) {
return yield call(datamodelerService.recommandEnglishWords, payload);
}
export function* getDatasourcesByEnv(payload) {
return yield call(datamodelerService.getDatasourcesByEnv, payload);
}
export function* getSchemasByDatasourceId(payload) {
return yield call(datamodelerService.getSchemasByDatasourceId, payload);
}
export function* autoCreateTable(payload) {
return yield call(datamodelerService.autoCreateTable, payload);
}
......@@ -144,3 +144,15 @@ export function autocomplete(payload) {
export function recommandEnglishWords(payload) {
return PostJSON("/datamodeler/easyDataModelerDesign/recommandEnglishWords", payload);
}
export function getDatasourcesByEnv (payload) {
return GetJSON("/metadatarepo/rest/metadata/findByModelAndSys", payload);
}
export function getSchemasByDatasourceId(payload) {
return GetJSON("/metadatarepo/rest/query/getChild", payload);
}
export function autoCreateTable(payload) {
return PostJSON("/metadataharvester/datasource/createTableByDDLList", payload);
}
import React from 'react';
import React, { useContext } from 'react';
import { Modal, Button, Select, Input } from 'antd';
import { showMessage } from '../../../../util';
......@@ -19,19 +19,52 @@ class ExportDDLModal extends React.Component {
ddlExportSuccess: false,
ddlExportStrings: [],
ddlExportString: '',
loadingDatabases: false,
databases: [],
filterDatabases: [],
currentDatabaseId: '',
loadingSchemas: false,
schemas: [],
currentSchemaId: ''
}
}
componentDidMount() {
this.init();
}
componentDidUpdate(preProps, preState) {
const { visible } = this.props;
if (visible!==preProps.visible && visible) {
this.init();
}
}
init = () => {
const { reference = 'exportDDL' } = this.props;
if (reference === 'exportDDL') {
this.getDDLGenerators();
} else if (reference === 'createTable') {
this.getDDLGeneratorsThenGetAllDatasource();
}
}
getDDLGeneratorsThenGetAllDatasource = () => {
this.getDDLGenerators(true);
}
getDDLGenerators = () => {
getDDLGenerators = (needDB = false) => {
this.setState({ loadingDDLGenerators: true }, () => {
dispatch({
type: 'datamodel.ddlGenerators',
callback: data => {
this.setState({ ddlGenerators: data, loadingDDLGenerators: false, selectDDLGeneratorName: (data||[]).length>0?data[0].name:'' });
this.setState({ ddlGenerators: data, loadingDDLGenerators: false, selectDDLGeneratorName: (data||[]).length>0?data[0].name:'' }, () => {
if (needDB) {
this.getDatabases();
}
});
},
error: () => {
this.setState({ loadingDDLGenerators: false });
......@@ -40,10 +73,64 @@ class ExportDDLModal extends React.Component {
})
}
handleOk = () => {
const { ids } = this.props;
const { ddlGenerators, loadingDDLGenerators, selectDDLGeneratorName } = this.state;
getDatabases = () => {
const { env } = this.props;
const { selectDDLGeneratorName } = this.state;
console.log('env', env);
this.setState({ loadingDatabases: true }, () => {
dispatch({
type: 'datamodel.getDatasourcesByEnv',
payload: {
catalog: env?.value,
model: 'Catalog,Database'
},
callback: data => {
let _filterData = [];
if (selectDDLGeneratorName === 'Greenplum') {
_filterData = data.filter(item => item.databaseType==='PostgreSQL');
} else if (selectDDLGeneratorName === 'MySQL') {
_filterData = data.filter(item => item.databaseType==='MySQL');
}
this.setState({ loadingDatabases: false, databases: data, filterDatabases: _filterData, currentDatabaseId: ((_filterData||[]).length>0)?_filterData[0]._id:'' }, () => {
if ((_filterData||[]).length>0) {
this.getSchemas(_filterData[0]);
} else {
this.setState({ schemas: [], currentSchemaId: '' });
}
});
},
error: () => {
this.setState({ loadingDatabases: false });
}
});
})
}
getSchemas = (db) => {
this.setState({ loadingSchemas: true }, () => {
dispatch({
type: 'datamodel.getSchemasByDatasourceId',
payload: {
parentId: db._id||''
},
callback: data => {
this.setState({ loadingSchemas: false, schemas: data, currentSchemaId: (data||[]).length>0?data[0]._id:'' });
},
error: () => {
this.setState({ loadingSchemas: false });
}
});
})
}
generatorDDLStrings = () => {
const { ids, reference } = this.props;
const { ddlGenerators, loadingDDLGenerators, selectDDLGeneratorName, currentSchemaId } = this.state;
if (loadingDDLGenerators) {
showMessage('info', '正在加载ddl支持的数据库类型');
......@@ -61,6 +148,11 @@ class ExportDDLModal extends React.Component {
return;
}
if (reference==='createTable' && (currentSchemaId||'')==='') {
showMessage('info', '请选择Schema');
return;
}
this.setState({ confirmLoading: true }, () => {
dispatch({
type: 'datamodel.exportDDLString',
......@@ -81,6 +173,64 @@ class ExportDDLModal extends React.Component {
}
createTable = () => {
const { onCancel } = this.props;
const { databases, schemas, currentDatabaseId, currentSchemaId, ddlExportStrings, selectDDLGeneratorName } = this.state;
let _currentDatabase = {}, _currentSchema = {};
(databases||[]).forEach(item => {
if (item._id === currentDatabaseId) {
_currentDatabase = item;
}
});
(schemas||[]).forEach(item => {
if (item._id === currentSchemaId) {
_currentSchema = item;
}
});
let namespace = '', scope = '', dbType = '';
if ((_currentSchema?.namePathList||[]).length>0) {
namespace = _currentSchema.namePathList[0];
}
if ((_currentSchema?.sysList||[]).length>0) {
scope = _currentSchema.sysList[0];
}
if (selectDDLGeneratorName === 'Greenplum') {
dbType = 'PGTarget';
} else if (selectDDLGeneratorName === 'MySQL') {
dbType = 'MysqlTarget';
}
this.setState({ confirmLoading: true }, () => {
dispatch({
type: 'datamodel.autoCreateTable',
payload: {
params: {
namespace,
scope,
dataSourceName: _currentDatabase?.name,
schema: _currentSchema?.name,
dbType,
},
data: ddlExportStrings
},
callback: () => {
this.setState({ confirmLoading: false });
this.reset();
onCancel && onCancel();
},
error: () => {
this.setState({ confirmLoading: false });
}
});
})
}
reset = () => {
this.setState({ ddlExportSuccess: false, ddlExportStrings: [] });
}
......@@ -91,16 +241,47 @@ class ExportDDLModal extends React.Component {
}
onDDLGeneratorChange = (value) => {
this.setState({ selectDDLGeneratorName: value||'' });
this.setState({ selectDDLGeneratorName: value||'' }, () => {
this.getDatabases();
});
}
onDatabaseChange = (value) => {
this.setState({ currentDatabaseId: value||'' }, () => {
this.getSchemas(value);
});
}
onSchemaChange = (value) => {
this.setState({ currentSchemaId: value||'' });
}
onDDLStringChange = (e) => {
const { reference = 'exportDDL' } = this.props;
const { ddlExportStrings, selectModalerNameKey } = this.state;
if (reference === 'createTable') {
const _newDDLExportStrings = [...ddlExportStrings];
_newDDLExportStrings[selectModalerNameKey] = e.target.value;
this.setState({ ddlExportString: e.target.value||'', ddlExportStrings: _newDDLExportStrings });
}
}
render() {
const { visible, onCancel, names, ids } = this.props;
const { ddlGenerators, loadingDDLGenerators, confirmLoading, selectDDLGeneratorName, ddlExportSuccess, ddlExportString, selectModalerNameKey } = this.state;
const { visible, onCancel, names, ids, reference } = this.props;
const { ddlGenerators, loadingDDLGenerators, confirmLoading, selectDDLGeneratorName, ddlExportSuccess, ddlExportString, selectModalerNameKey, loadingDatabases, loadingSchemas, databases, schemas, currentDatabaseId, currentSchemaId, filterDatabases } = this.state;
const title = ddlExportSuccess ? 'DDL导出详情' : 'DDL导出';
let title = '';
if (reference === 'exportDDL') {
title = ddlExportSuccess ? 'DDL导出详情' : 'DDL导出';
} else if (reference === 'createTable') {
title = ddlExportSuccess ? '模型自动建表详情' : '模型自动建表';
}
const footer = ddlExportSuccess ? ([
let footer = null;
if (reference === 'exportDDL') {
footer = ddlExportSuccess ? ([
<Button
key="0"
type="primary"
......@@ -136,27 +317,65 @@ class ExportDDLModal extends React.Component {
<Button
key="1"
type="primary"
onClick={this.handleOk}
onClick={this.generatorDDLStrings}
>
预览
</Button>
])
} else if (reference === 'createTable') {
footer = ddlExportSuccess ? ([
<Button
key="0"
type="primary"
onClick={() => {
this.reset();
onCancel && onCancel();
}}
>
取消
</Button>,
<Button
key="1"
type="primary"
onClick={this.createTable}
>
建表
</Button>
]) : ([
<Button
key="0"
type="primary"
onClick={() => {
this.reset();
onCancel && onCancel();
}}
>
取消
</Button>,
<Button
key="1"
type="primary"
onClick={this.generatorDDLStrings}
>
导出
预览
</Button>
])
}
return (
<Modal
visible={visible}
title={title}
loading={confirmLoading}
onOk={this.handleOk}
onCancel={() => {
this.reset();
onCancel && onCancel();
}}
footer={footer}
>
<>
<React.Fragment>
{
ddlExportSuccess ? <>
ddlExportSuccess ? <React.Fragment>
<div className='d-flex mb-5' style={{ alignItems: 'center' }}>
<span className='mr-2'>模型名称:</span>
<Select
......@@ -172,10 +391,10 @@ class ExportDDLModal extends React.Component {
}
</Select>
</div>
<Input.TextArea value={ddlExportString||''} autoSize={{minRows:4,maxRows:20}} ></Input.TextArea>
</> : <>
<Input.TextArea value={ddlExportString||''} autoSize={{minRows:4,maxRows:20}} onChange={this.onDDLStringChange} ></Input.TextArea>
</React.Fragment> : <React.Fragment>
<div className='d-flex' style={{ alignItems: 'center' }}>
<span className='mr-2' >数据库类型: </span>
<span className='mr-2' style={{ width: 85 }}>数据库类型: </span>
<Select
value={selectDDLGeneratorName}
loading={loadingDDLGenerators}
......@@ -190,9 +409,45 @@ class ExportDDLModal extends React.Component {
}
</Select>
</div>
</>
{
reference==='createTable' && <React.Fragment>
<div className='d-flex mt-3' style={{ alignItems: 'center' }}>
<span className='mr-2' style={{ width: 85 }}>数据源名称:</span>
<Select
value={currentDatabaseId}
style={{ width: 180 }}
placeholder='请选择数据源名称'
onChange={this.onDatabaseChange}
loading={loadingDatabases}
>
{
filterDatabases && filterDatabases.map((item, index) => {
return <Option key={index} value={item._id}>{item.name||''}</Option>
})
}
</Select>
</div>
<div className='d-flex mt-3' style={{ alignItems: 'center' }}>
<span className='mr-2' style={{ width: 85 }}>Schema名称:</span>
<Select
value={currentSchemaId}
style={{ width: 180 }}
placeholder='请选择Schema名称'
onChange={this.onSchemaChange}
loading={loadingSchemas}
>
{
schemas && schemas.map((item, index) => {
return <Option key={index} value={item._id}>{item.name||''}</Option>
})
}
</Select>
</div>
</React.Fragment>
}
</React.Fragment>
}
</>
</React.Fragment>
</Modal>
)
}
......
......@@ -419,20 +419,12 @@ const ImportActionTable = (props) => {
if (changedValues.nullable && allValues.partOfPrimaryKey) {
showMessage('info', '主键不允许为空');
}
} else if (changedValues.hasOwnProperty('partOfDistributionKey')) {
if (changedValues.partOfDistributionKey && !allValues.partOfPrimaryKey) {
showMessage('info', '分布键必须是主键的子集');
}
}
if (allValues.partOfPrimaryKey) {
form.setFieldsValue({
nullable: false
});
} else {
form.setFieldsValue({
partOfDistributionKey: false
})
}
};
......
......@@ -34,7 +34,7 @@ const ResizeableHeaderCell = props => {
const ModelTable = (props) => {
const { data, onChange, onItemAction, onSelect, catalogId, onSearchInputChange, onModelStateChange, loadingStates, currentModelState, modelStates, view, keyword, onRecatalog } = props;
const { data, onChange, onItemAction, onSelect, catalogId, onSearchInputChange, onModelStateChange, loadingStates, currentModelState, modelStates, view, keyword, onRecatalog, onAutoCreateTable } = props;
const [ selectedRowKeys, setSelectedRowKeys ] = useState([]);
const [ columns, setColumns ] = useState([
......@@ -71,15 +71,19 @@ const ModelTable = (props) => {
render: (_,record) => {
return (
<Space size='small'>
<Tooltip placement='bottom' title={'修改'}>
{
record.editable && <Tooltip placement='bottom' title={'修改'}>
<Button icon={<EditOutlined />} size='small' onClick={() => { editItem(record); }} />
</Tooltip>
}
<Tooltip placement='bottom' title={'详情'}>
<Button icon={<ReconciliationOutlined />} size='small' onClick={() => { detailItem(record); }} />
</Tooltip>
<Tooltip placement='bottom' title={'删除'}>
{
record.editable && <Tooltip placement='bottom' title={'删除'}>
<Button icon={<DeleteOutlined />} size='small' onClick={() => { deleteItem(record); }} />
</Tooltip>
}
{
(record?.state?.supportedActions||[]).length>0 && record?.state?.supportedActions.map((item, index) => {
return (
......@@ -92,6 +96,9 @@ const ModelTable = (props) => {
);
})
}
{
record?.deployable && <Button size='small' onClick={() => { deployAction(record); }} >建表</Button>
}
</Space>
)
}
......@@ -144,8 +151,11 @@ const ModelTable = (props) => {
onItemAction && onItemAction(record.id||'', 'detail');
}
const stateAction = (record, action) => {
const deployAction = (record) => {
onAutoCreateTable && onAutoCreateTable(record);
}
const stateAction = (record, action) => {
modal.confirm({
title: '提示!',
content: `您确定要${action.cnName||''}该模型吗?`,
......
......@@ -14,6 +14,7 @@ import RecatalogModal from './Component/RecatalogModal';
import { showMessage, showNotifaction } from '../../../util';
import { dispatch } from '../../../model';
import { Action, CatalogId, ModelerId, Hints } from '../../../util/constant';
import { AppContext } from '../../../App';
import './index.less';
......@@ -44,6 +45,8 @@ class Model extends React.Component {
modelStates: [],
currentModelState: '',
currentView: '',
exportDDLModalReference: 'exportDDL',
currentModel: {},
}
}
......@@ -247,7 +250,7 @@ class Model extends React.Component {
});
this.setState({ exportDDLModalVisible: true, selectModelerNames: _selectModelerNames });
this.setState({ exportDDLModalVisible: true, selectModelerNames: _selectModelerNames, exportDDLModalReference: 'exportDDL' });
}
onExportErwinBtnClick = () => {
......@@ -306,6 +309,11 @@ class Model extends React.Component {
this.setState({ recatalogModalVisible: true });
}
onAutoCreateTable = (item) => {
this.setState({ exportDDLModalVisible: true, selectModelerNames: [item.name||''], exportDDLModalReference: 'createTable', currentModel: item });
}
onImportExcelVisibleChange = (visible = false, hint = null) => {
this.setState({ importExcelVisible: visible });
}
......@@ -354,10 +362,26 @@ class Model extends React.Component {
}
render() {
const { importModalVisible, catalogId, loadingTableData, selectModelerIds, keyword, filterTableData, selectModelerNames, importModalAddMode, exportErwinLoading, exportDDLModalVisible, templateCURDDrawerVisible, wordTemplateModalVisible, constraintDetailDrawerVisible, importWordModalVisible, loadingStates, modelStates, currentModelState, currentView, recatalogModalVisible } = this.state;
const { importModalVisible, catalogId, loadingTableData, selectModelerIds, keyword, filterTableData, selectModelerNames, importModalAddMode, exportErwinLoading, exportDDLModalVisible, templateCURDDrawerVisible, wordTemplateModalVisible, constraintDetailDrawerVisible, importWordModalVisible, loadingStates, modelStates, currentModelState, currentView, recatalogModalVisible, exportDDLModalReference, currentModel } = this.state;
const content = (
<ModelTable loading={loadingTableData} catalogId={catalogId} data={filterTableData} view={currentView} loadingStates={loadingStates} modelStates={modelStates} currentModelState={currentModelState} keyword={keyword} onChange={this.onTableChange} onSelect={this.onTableSelect} onItemAction={this.onTableItemAction} onModelStateChange={this.onModelStateChange} onSearchInputChange={this.onSearchInputChange} onRecatalog={this.onRecatalogBtnClick} {...this.props} />
<ModelTable
loading={loadingTableData}
catalogId={catalogId}
data={filterTableData}
view={currentView}
loadingStates={loadingStates}
modelStates={modelStates}
currentModelState={currentModelState}
keyword={keyword}
onChange={this.onTableChange}
onSelect={this.onTableSelect}
onItemAction={this.onTableItemAction}
onModelStateChange={this.onModelStateChange}
onSearchInputChange={this.onSearchInputChange}
onRecatalog={this.onRecatalogBtnClick}
onAutoCreateTable={this.onAutoCreateTable}
{...this.props} />
);
return (
......@@ -447,12 +471,19 @@ class Model extends React.Component {
catalogId={catalogId}
/>
<ExportDDLModal
<AppContext.Consumer>
{
value => <ExportDDLModal
visible={exportDDLModalVisible}
ids={selectModelerIds}
reference={exportDDLModalReference}
ids={(exportDDLModalReference==='exportDDL')?selectModelerIds:[currentModel.id]}
names={selectModelerNames}
env={value?.env}
onCancel={this.onExportDDLModalCancel}
/>
}
</AppContext.Consumer>
<RecatalogModal
visible={recatalogModalVisible}
......
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