Commit 5851a49f by fanyongjun

4.8

parents f46aab0e 38340f8d
...@@ -10,6 +10,7 @@ import Home from './view/Home'; ...@@ -10,6 +10,7 @@ import Home from './view/Home';
import Manage from './view/Manage'; import Manage from './view/Manage';
import Map from './view/Manage/Map'; import Map from './view/Manage/Map';
import Model from './view/Manage/Model'; import Model from './view/Manage/Model';
import Element from './view/Manage/Element';
export default class App extends React.Component { export default class App extends React.Component {
render() { render() {
...@@ -23,6 +24,7 @@ export default class App extends React.Component { ...@@ -23,6 +24,7 @@ export default class App extends React.Component {
<Route path={`${ContextPath}/manage`} component={Manage} /> <Route path={`${ContextPath}/manage`} component={Manage} />
<Route path={`/center-home/view/modelmap`} component={Map} exact /> <Route path={`/center-home/view/modelmap`} component={Map} exact />
<Route path={`/center-home/view/datamodel`} component={Model} exact /> <Route path={`/center-home/view/datamodel`} component={Model} exact />
<Route path={`/center-home/view/data-asset-element`} component={Element} exact />
</Switch> </Switch>
</Router> </Router>
</React.Fragment> </React.Fragment>
......
...@@ -84,5 +84,9 @@ div[id^='__qiankun_microapp_wrapper_'] { ...@@ -84,5 +84,9 @@ div[id^='__qiankun_microapp_wrapper_'] {
background-color: transparent !important; background-color: transparent !important;
} }
.yy-card-bordered {
border-color: #333333 !important;
}
...@@ -105,7 +105,7 @@ export const ManageLayout = function ({ content, location }) { ...@@ -105,7 +105,7 @@ export const ManageLayout = function ({ content, location }) {
</Menu> </Menu>
</Sider> </Sider>
<Content className="m-3" style={{ backgroundColor: '#ECEEF3', height: '100%' }}> <Content className="m-4" style={{ backgroundColor: '#ECEEF3', height: '100%' }}>
{content} {content}
</Content> </Content>
......
import * as service from '../service/dataassetmanager';
import { call } from 'redux-saga/effects';
export function* importElement(payload) {
return yield call(service.importElement, payload);
}
export function* getLogs(payload) {
return yield call(service.getLogs, payload);
}
...@@ -70,8 +70,11 @@ export function* extractExcelContent(payload) { ...@@ -70,8 +70,11 @@ export function* extractExcelContent(payload) {
return yield call(datamodelerService.extractExcelContent, payload); return yield call(datamodelerService.extractExcelContent, payload);
} }
export function* getAllConstraints() { export function* getAllConstraintsAndTemplates() {
return yield call(datamodelerService.constraints); const constraints = yield call(datamodelerService.constraints);
const templates = yield call(datamodelerService.templates);
return { constraints, templates };
} }
//获取初稿 //获取初稿
......
...@@ -8,9 +8,15 @@ import { reducers } from './reducer'; ...@@ -8,9 +8,15 @@ import { reducers } from './reducer';
import * as user from './user'; import * as user from './user';
import * as map from './map'; import * as map from './map';
import * as datamodel from './datamodel'; import * as datamodel from './datamodel';
<<<<<<< HEAD
import * as assetmanage from './assetmanage'; import * as assetmanage from './assetmanage';
const funcs = Connect({ user, datamodel, map,assetmanage }) const funcs = Connect({ user, datamodel, map,assetmanage })
=======
import * as dataassetelement from './dataassetelement';
const funcs = Connect({ user, datamodel, map, dataassetelement })
>>>>>>> 38340f8dec7bab08e4d6f7a73db93a2d59a4c42c
function* request(args) { function* request(args) {
const { type, payload, callback, error } = args.args; const { type, payload, callback, error } = args.args;
......
...@@ -22,6 +22,9 @@ export const routes = [ ...@@ -22,6 +22,9 @@ export const routes = [
{ {
name: 'assetmanage', name: 'assetmanage',
text: '资产管理', text: '资产管理',
},{
name: 'element',
text: '资产要素',
} }
] ]
} }
......
import { filePost, GetJSON } from "../util/axios"
export function importElement(payload) {
return filePost("/dataassetmanager/elementApi/import", payload);
}
export function getLogs(payload) {
return GetJSON("/dataassetmanager/elementApi/listOperationLogsByPage", payload);
}
...@@ -31,6 +31,11 @@ export function constraints() { ...@@ -31,6 +31,11 @@ export function constraints() {
return GetJSON("/datamodeler/easyDataModelerConstraint/constraints"); return GetJSON("/datamodeler/easyDataModelerConstraint/constraints");
} }
//模版
export function templates() {
return GetJSON("/datamodeler/easyDataModelerConstraint/templates");
}
//创建初稿 //创建初稿
export function draft(payload) { export function draft(payload) {
return PostJSON("/datamodeler/easyDataModelerDesign/draft", payload); return PostJSON("/datamodeler/easyDataModelerDesign/draft", payload);
......
import React, { useState } from 'react';
import { Modal, Button, Upload } from 'antd';
import { DownloadOutlined, UploadOutlined } from '@ant-design/icons';
import { dispatchLatest } from '../../../../model';
import { showMessage } from '../../../../util';
const ImportModal = (props) => {
const { onCancel, visible } = props;
const [ fileList, setFileList ] = useState([]);
const [ confirmLoading, setConfirmLoading ] = useState(false);
const downloadTemplate = () => {
window.open("/data-govern/docs/ElementModel.xlsx");
}
const uploadProps = {
onRemove: file => {
const index = fileList.indexOf(file);
const newFileList = fileList.slice();
newFileList.splice(index, 1);
setFileList(newFileList);
},
beforeUpload: file => {
setFileList([file]);
return false;
}
};
const handleOk = () => {
if ((fileList||[]).length === 0) {
showMessage('info', '请先选择模版上传');
return;
}
setConfirmLoading(true);
dispatchLatest({
type: 'dataassetelement.importElement',
payload: { fileList },
callback: () => {
setConfirmLoading(false);
onCancel && onCancel(true);
},
error: () => {
setConfirmLoading(false);
}
})
}
return (
<Modal
forceRender
confirmLoading={confirmLoading}
visible={visible}
title={"导入资产要素"}
onOk={handleOk}
onCancel={() => {
setConfirmLoading(false);
onCancel && onCancel();
}}
>
{
<>
<div>
<Button icon={<DownloadOutlined />} onClick={ downloadTemplate }>
模版下载
</Button>
</div>
<div className='mt-3'>
<Upload {...uploadProps}>
<Button icon={<UploadOutlined />}>
选择文件上传
</Button>
</Upload>
</div>
</>
}
</Modal>
)
}
export default ImportModal;
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { Button, Table, Pagination } from 'antd';
import { dispatchLatest } from '../../../model';
import ImportModal from './Component/ImportModal';
import './index.less';
const Element = (props) => {
const [ loading, setLoading ] = useState(false);
const [ tableData, setTableData ] = useState([]);
const [ total, setTotal ] = useState(0);
const [ pagination, setPagination ] = useState( { pageNum: 1, pageSize: 20 } );
const [ importModalVisible, setImportModalVisible ] = useState(false);
const { pageNum, pageSize } = pagination;
useEffect(() => {
getTableData();
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [pagination])
const columns = [
{
title: '序号',
dataIndex: 'key',
render: (text, record, index) => {
return (index+1).toString();
}
},
{
title: '操作时间',
dataIndex: 'createTimeDesc',
},
{
title: '操作人',
dataIndex: 'creator',
},
{
title: '操作类型',
dataIndex: 'operateType',
},
{
title: '状态',
dataIndex: 'status',
},
{
title: '变更内容',
dataIndex: 'content'
},
];
const onImportBtnClick = () => {
setImportModalVisible(true);
}
const onExportBtnClick = () => {
window.open('/api/dataassetmanager/elementApi/export');
}
const getTableData = () => {
setLoading(true);
dispatchLatest({
type: 'dataassetelement.getLogs',
payload: {
pageNum,
pageSize
},
callback: data => {
setTableData(data.data||[]);
setTotal(data.total);
setLoading(false);
},
error: () => {
setLoading(false);
}
})
}
const onImportModalCancel = (refresh = false) => {
setImportModalVisible(false);
if (refresh) {
setPagination({ pageNum: 1, pageSize: 20 });
}
}
return (
<div className='element' style={{ backgroundColor: '#fff' }}>
<div
className='p-3'
style={{
display: 'flex',
borderBottom: "1px solid #EFEFEF",
}}
>
<Button type="primary" className='ml-3' style={{ marginLeft: 'auto' }} onClick={onImportBtnClick}>导入</Button>
<Button type="primary" className='ml-3' onClick={onExportBtnClick}>导出</Button>
</div>
<div className='p-3'>
<Table
loading={loading}
columns={columns}
rowKey={'id'}
dataSource={tableData||[]}
pagination={false}
/>
<Pagination
size="small"
className="text-center mt-3"
showSizeChanger
showQuickJumper
onChange={(_pageNum, _pageSize) => {
setPagination({ pageNum: _pageNum, pageSize: _pageSize || 10 });
}}
onShowSizeChange={(_pageNum, _pageSize) => {
setPagination({ pageNum: _pageNum || 1, pageSize: _pageSize });
}}
current={pageNum}
pageSize={pageSize}
defaultCurrent={1}
total={total}
showTotal={total => `共 ${total} 条`}
/>
</div>
<ImportModal
visible={importModalVisible}
onCancel={onImportModalCancel}
/>
</div>
);
}
export default Element;
.element {
.yy-table {
height: calc(100vh - 64px - 30px - 53px - 20px) !important;
overflow: auto !important;
}
}
\ No newline at end of file
...@@ -67,7 +67,7 @@ class Org extends React.Component { ...@@ -67,7 +67,7 @@ class Org extends React.Component {
const bbox = text.getBBox(); const bbox = text.getBBox();
if (cfg.dbType==='Dir') { if (cfg.dbType==='Root' || cfg.dbType==='Dir') {
if (!cfg.children) { if (!cfg.children) {
group.addShape('marker', { group.addShape('marker', {
attrs: { attrs: {
...@@ -96,7 +96,7 @@ class Org extends React.Component { ...@@ -96,7 +96,7 @@ class Org extends React.Component {
rect.attr({ rect.attr({
x: bbox.minX - 10, x: bbox.minX - 10,
y: bbox.minY - 10, y: bbox.minY - 10,
width: bbox.width + (cfg.dbType==='Dir'&&(!cfg.children||((cfg.children||[]).length>0)) ? 38 : 20), width: bbox.width + ((cfg.dbType==='Root'||cfg.dbType==='Dir')&&(!cfg.children||((cfg.children||[]).length>0)) ? 38 : 20),
height: bbox.height + 20, height: bbox.height + 20,
}); });
...@@ -219,18 +219,48 @@ class Org extends React.Component { ...@@ -219,18 +219,48 @@ class Org extends React.Component {
}, },
}); });
const fittingString = (str, maxWidth, fontSize) => {
const ellipsis = '...';
const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
let currentWidth = 0;
let res = str;
const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
str.split('').forEach((letter, i) => {
if (currentWidth > maxWidth - ellipsisLength) return;
if (pattern.test(letter)) {
// Chinese charactors
currentWidth += fontSize;
} else {
// get the width of single letter according to the fontSize
currentWidth += G6.Util.getLetterWidth(letter, fontSize);
}
if (currentWidth > maxWidth - ellipsisLength) {
res = `${str.substr(0, i)}${ellipsis}`;
}
});
return res;
};
graph.node(function (node) {
return {
label: fittingString(node.text||'', maxTextWidth, globalFontSize),
};
});
this.layoutGraph(); this.layoutGraph();
graph.on('node:click', function (e) { graph.on('node:click', function (e) {
const node = e.item; const node = e.item;
const nodeId = node.get('id');
const model = node.getModel(); const model = node.getModel();
if (model.dbType==='Dir') { if (model.dbType==='Dir') {
const children = model.children; const children = model.children;
if (!children && loadMoreData) { if (!children && loadMoreData) {
loadMoreData(model.dirId||''); loadMoreData(model.dirId||'', nodeId);
} }
} else { } else if (model.dbType !== 'Root') {
//通过资产id跳转到资产详情页 //通过资产id跳转到资产详情页
// model.tableModelId // model.tableModelId
// history && history.push(`${ContextPath}/home`); // history && history.push(`${ContextPath}/home`);
...@@ -252,49 +282,36 @@ class Org extends React.Component { ...@@ -252,49 +282,36 @@ class Org extends React.Component {
const { data } = this.props; const { data } = this.props;
if(graph && data){ if(graph && data){
const fittingString = (str, maxWidth, fontSize) => {
const ellipsis = '...';
const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
let currentWidth = 0;
let res = str;
const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
str.split('').forEach((letter, i) => {
if (currentWidth > maxWidth - ellipsisLength) return;
if (pattern.test(letter)) {
// Chinese charactors
currentWidth += fontSize;
} else {
// get the width of single letter according to the fontSize
currentWidth += G6.Util.getLetterWidth(letter, fontSize);
}
if (currentWidth > maxWidth - ellipsisLength) {
res = `${str.substr(0, i)}${ellipsis}`;
}
});
return res;
};
graph.node(function (node) {
return {
label: fittingString(node.text||'', maxTextWidth, globalFontSize),
};
});
graph.data(data); graph.data(data);
graph.render(); graph.render();
graph.fitView(); graph.fitView();
} }
} }
componentDidUpdate(prevProps, prevState){ componentDidUpdate(prevProps, prevState) {
const { childData, parentNodeId } = this.props;
if (parentNodeId && parentNodeId!== prevProps.parentNodeId) {
const parentData = graph.findDataById(parentNodeId);
if (!parentData.children) {
parentData.children = [];
}
parentData.children = childData;
graph.changeData();
graph.updateItem(graph.findById(parentNodeId), {
collapsed: false,
});
} else {
this.layoutGraph(); this.layoutGraph();
} }
}
render() { render() {
const { type } = this.props; const { type } = this.props;
return ( return (
<div id={`container${type||''}`} style={{ width: '100%', height: '100%' }}></div> <div id={`container${type||''}`} style={{ width: '100%', height: '100%' }} ></div>
); );
} }
} }
......
...@@ -60,7 +60,7 @@ class Relation extends React.Component { ...@@ -60,7 +60,7 @@ class Relation extends React.Component {
x: 0, x: 0,
y: 0, y: 0,
r: cfg.size/2, r: cfg.size/2,
fill: colors[cfg.cluster % colors.length], fill: colors[cfg.depth % colors.length],
}, },
}); });
...@@ -78,7 +78,7 @@ class Relation extends React.Component { ...@@ -78,7 +78,7 @@ class Relation extends React.Component {
const bbox = text.getBBox(); const bbox = text.getBBox();
if (cfg.dbType==='Dir') { if (cfg.dbType==='Root' || cfg.dbType==='Dir') {
if (!cfg.children) { if (!cfg.children) {
group.addShape('marker', { group.addShape('marker', {
attrs: { attrs: {
...@@ -155,17 +155,11 @@ class Relation extends React.Component { ...@@ -155,17 +155,11 @@ class Relation extends React.Component {
], ],
}, },
layout: { layout: {
type: 'compactBox', type: 'dendrogram',
direction: 'RL', direction: 'RL',
getId: function getId(d) { getId: function getId(d) {
return d.id; return d.id;
}, },
getHeight: () => {
return 26;
},
getWidth: () => {
return 26;
},
getVGap: () => { getVGap: () => {
return 20; return 20;
}, },
...@@ -185,28 +179,50 @@ class Relation extends React.Component { ...@@ -185,28 +179,50 @@ class Relation extends React.Component {
type: 'cubic-horizontal', type: 'cubic-horizontal',
size: 2, size: 2,
color: '#e2e2e2', color: '#e2e2e2',
// style: {
// endArrow: {
// path: 'M 0,0 L 12, 6 L 9,0 L 12, -6 Z',
// fill: '#91d5ff',
// d: -40,
// },
// }
}, },
}); });
const fittingString = (str, maxWidth, fontSize) => {
const ellipsis = '...';
const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
let currentWidth = 0;
let res = str;
const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
str.split('').forEach((letter, i) => {
if (currentWidth > maxWidth - ellipsisLength) return;
if (pattern.test(letter)) {
// Chinese charactors
currentWidth += fontSize;
} else {
// get the width of single letter according to the fontSize
currentWidth += G6.Util.getLetterWidth(letter, fontSize);
}
if (currentWidth > maxWidth - ellipsisLength) {
res = `${str.substr(0, i)}${ellipsis}`;
}
});
return res;
};
graph.node(function (node) {
return {
label: fittingString(node.text||'', node.size-32, globalFontSize),
};
});
this.layoutGraph(); this.layoutGraph();
graph.on('node:click', function (e) { graph.on('node:click', function (e) {
const node = e.item; const node = e.item;
const nodeId = node.get('id');
const model = node.getModel(); const model = node.getModel();
if (model.dbType==='Dir') { if (model.dbType==='Dir') {
const children = model.children; const children = model.children;
if (!children && loadMoreData) { if (!children && loadMoreData) {
loadMoreData(model.dirId||''); loadMoreData(model.dirId||'', nodeId);
} }
} else { } else if (model.dbType !== 'Root') {
//通过资产id跳转到资产详情页 //通过资产id跳转到资产详情页
// model.tableModelId // model.tableModelId
// history && history.push(`${ContextPath}/home`); // history && history.push(`${ContextPath}/home`);
...@@ -228,56 +244,22 @@ class Relation extends React.Component { ...@@ -228,56 +244,22 @@ class Relation extends React.Component {
const { data } = this.props; const { data } = this.props;
if(graph && data){ if(graph && data){
const fittingString = (str, maxWidth, fontSize) => {
const ellipsis = '...';
const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
let currentWidth = 0;
let res = str;
const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
str.split('').forEach((letter, i) => {
if (currentWidth > maxWidth - ellipsisLength) return;
if (pattern.test(letter)) {
// Chinese charactors
currentWidth += fontSize;
} else {
// get the width of single letter according to the fontSize
currentWidth += G6.Util.getLetterWidth(letter, fontSize);
}
if (currentWidth > maxWidth - ellipsisLength) {
res = `${str.substr(0, i)}${ellipsis}`;
}
});
return res;
};
function recursionTreeData(treeData, depth, cluster = '') { function recursionTreeData(treeData, depth) {
if ((treeData||[]).length === 0) return; if ((treeData||[]).length === 0) return;
(treeData||[]).forEach((item, index) => { (treeData||[]).forEach((item, index) => {
let _cluster = 0;
if (depth === 1) {
_cluster = (index + 1);
} else {
_cluster = cluster;
}
item.size = (100-depth*20)>60?(100-depth*20):60; item.size = (100-depth*20)>60?(100-depth*20):60;
item.cluster = _cluster; item.depth = depth;
recursionTreeData(item.children||[], depth+1, _cluster); recursionTreeData(item.children||[], depth+1);
}) })
} }
data.size = 100; data.size = 100;
data.cluster = 0; data.depth = 0;
recursionTreeData(data.children||[], 1); recursionTreeData(data.children||[], 1);
graph.node(function (node) {
return {
label: fittingString(node.text||'', node.size-32, globalFontSize),
};
});
graph.data(data); graph.data(data);
graph.render(); graph.render();
graph.fitView(); graph.fitView();
...@@ -286,8 +268,32 @@ class Relation extends React.Component { ...@@ -286,8 +268,32 @@ class Relation extends React.Component {
} }
componentDidUpdate(prevProps, prevState){ componentDidUpdate(prevProps, prevState){
const { childData, parentNodeId } = this.props;
if (parentNodeId && parentNodeId!== prevProps.parentNodeId) {
const parentData = graph.findDataById(parentNodeId);
if (!parentData.children) {
parentData.children = [];
}
let depth = childData.depth+1;
(childData||[]).forEach((item, index) => {
item.size = (100-depth*20)>60?(100-depth*20):60;
item.depth = depth;
})
parentData.children = childData;
graph.changeData();
graph.updateItem(graph.findById(parentNodeId), {
collapsed: false,
});
} else {
this.layoutGraph(); this.layoutGraph();
} }
}
render() { render() {
const { type } = this.props; const { type } = this.props;
......
import React from 'react'; import React from 'react';
import { Card } from 'antd'; import { Card } from 'antd';
import { FolderAddOutlined, FileOutlined } from '@ant-design/icons';
import './SquareItem.less'; import './SquareItem.less';
...@@ -24,15 +25,17 @@ class SquareItem extends React.Component { ...@@ -24,15 +25,17 @@ class SquareItem extends React.Component {
{ {
item && ( item && (
item.dbType==='Dir' ? <Card title={ item.dbType==='Dir' ? <Card title={
<div className='pointer' onClick={this.onItemClick}> <div className='d-flex pointer' style={{ alignItems: 'center' }} onClick={this.onItemClick}>
{item.dirName||''} <FolderAddOutlined className='mr-1' />
<span>{item.dirName||''}</span>
</div> </div>
}> }>
<p>{`数据资产: ${item.tableModelCount}`}</p> <p>{`数据资产: ${item.tableModelCount}`}</p>
<p>{`资产编目: ${item.subDirCount}`}</p> <p>{`资产编目: ${item.subDirCount}`}</p>
</Card> : <Card title={ </Card> : <Card title={
<div className='pointer' onClick={this.onItemClick}> <div className='d-flex pointer' style={{ alignItems: 'center' }} onClick={this.onItemClick}>
{item.name||''} <FileOutlined className='mr-1' />
<span>{item.name||''}</span>
</div> </div>
}> }>
<p>{`所属系统: ${item.system||''}`}</p> <p>{`所属系统: ${item.system||''}`}</p>
......
.map-square-item { .map-square-item {
.yy-card-head { .yy-card-head {
background-color: #ff4d4f !important; background-color: #f4856f !important;
.yy-card-head-title { .yy-card-head-title {
color: #fff !important; color: #fff !important;
font-size: 20px !important;
font-weight: bold !important;
:hover { :hover {
color: #1890ff; color: #1890ff;
} }
} }
} }
.yy-card-body {
p {
color: #1890ff !important;
font-size: 18px !important;
}
}
} }
\ No newline at end of file
...@@ -68,7 +68,7 @@ class Tree extends React.Component { ...@@ -68,7 +68,7 @@ class Tree extends React.Component {
const bbox = text.getBBox(); const bbox = text.getBBox();
if (cfg.dbType==='Dir') { if (cfg.dbType==='Root' || cfg.dbType==='Dir') {
if (!cfg.children) { if (!cfg.children) {
group.addShape('marker', { group.addShape('marker', {
attrs: { attrs: {
...@@ -97,7 +97,7 @@ class Tree extends React.Component { ...@@ -97,7 +97,7 @@ class Tree extends React.Component {
rect.attr({ rect.attr({
x: bbox.minX - 10, x: bbox.minX - 10,
y: bbox.minY - 10, y: bbox.minY - 10,
width: bbox.width + (cfg.dbType==='Dir'&&(!cfg.children||((cfg.children||[]).length>0)) ? 38 : 20), width: bbox.width + ((cfg.dbType==='Root'||cfg.dbType==='Dir')&&(!cfg.children||((cfg.children||[]).length>0)) ? 38 : 20),
height: bbox.height + 20, height: bbox.height + 20,
}); });
...@@ -180,18 +180,48 @@ class Tree extends React.Component { ...@@ -180,18 +180,48 @@ class Tree extends React.Component {
}, },
}); });
const fittingString = (str, maxWidth, fontSize) => {
const ellipsis = '...';
const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
let currentWidth = 0;
let res = str;
const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
str.split('').forEach((letter, i) => {
if (currentWidth > maxWidth - ellipsisLength) return;
if (pattern.test(letter)) {
// Chinese charactors
currentWidth += fontSize;
} else {
// get the width of single letter according to the fontSize
currentWidth += G6.Util.getLetterWidth(letter, fontSize);
}
if (currentWidth > maxWidth - ellipsisLength) {
res = `${str.substr(0, i)}${ellipsis}`;
}
});
return res;
};
graph.node(function (node) {
return {
label: fittingString(node.text||'', maxTextWidth, globalFontSize),
};
});
this.layoutGraph(); this.layoutGraph();
graph.on('node:click', function (e) { graph.on('node:click', function (e) {
const node = e.item; const node = e.item;
const nodeId = node.get('id');
const model = node.getModel(); const model = node.getModel();
if (model.dbType==='Dir') { if (model.dbType==='Dir') {
const children = model.children; const children = model.children;
if (!children && loadMoreData) { if (!children && loadMoreData) {
loadMoreData(model.dirId||''); loadMoreData(model.dirId||'', nodeId);
} }
} else { } else if (model.dbType !== 'Root') {
//通过资产id跳转到资产详情页 //通过资产id跳转到资产详情页
// model.tableModelId // model.tableModelId
// history && history.push(`${ContextPath}/home`); // history && history.push(`${ContextPath}/home`);
...@@ -213,35 +243,6 @@ class Tree extends React.Component { ...@@ -213,35 +243,6 @@ class Tree extends React.Component {
const { data } = this.props; const { data } = this.props;
if(graph && data){ if(graph && data){
const fittingString = (str, maxWidth, fontSize) => {
const ellipsis = '...';
const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
let currentWidth = 0;
let res = str;
const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
str.split('').forEach((letter, i) => {
if (currentWidth > maxWidth - ellipsisLength) return;
if (pattern.test(letter)) {
// Chinese charactors
currentWidth += fontSize;
} else {
// get the width of single letter according to the fontSize
currentWidth += G6.Util.getLetterWidth(letter, fontSize);
}
if (currentWidth > maxWidth - ellipsisLength) {
res = `${str.substr(0, i)}${ellipsis}`;
}
});
return res;
};
graph.node(function (node) {
return {
label: fittingString(node.text||'', maxTextWidth, globalFontSize),
};
});
graph.data(data); graph.data(data);
graph.render(); graph.render();
graph.fitView(); graph.fitView();
...@@ -249,8 +250,24 @@ class Tree extends React.Component { ...@@ -249,8 +250,24 @@ class Tree extends React.Component {
} }
componentDidUpdate(prevProps, prevState){ componentDidUpdate(prevProps, prevState){
const { childData, parentNodeId } = this.props;
if (parentNodeId && parentNodeId!== prevProps.parentNodeId) {
const parentData = graph.findDataById(parentNodeId);
if (!parentData.children) {
parentData.children = [];
}
parentData.children = childData;
graph.changeData();
graph.updateItem(graph.findById(parentNodeId), {
collapsed: false,
});
} else {
this.layoutGraph(); this.layoutGraph();
} }
}
render() { render() {
const { type } = this.props; const { type } = this.props;
......
...@@ -19,8 +19,12 @@ class MapContent extends React.Component { ...@@ -19,8 +19,12 @@ class MapContent extends React.Component {
tableModelData: null, tableModelData: null,
curTableModelData: null, curTableModelData: null,
orgModelData: null, orgModelData: null,
orgChildData: null,
treeModelData: null, treeModelData: null,
treeChildData: null,
relationModelData: null, relationModelData: null,
relationChildData: null,
parentNodeId: null,
breadcrumbContents: null breadcrumbContents: null
}; };
} }
...@@ -41,7 +45,13 @@ class MapContent extends React.Component { ...@@ -41,7 +45,13 @@ class MapContent extends React.Component {
curTableModelData: data||[], curTableModelData: data||[],
breadcrumbContents: [{ data: data||[] }] breadcrumbContents: [{ data: data||[] }]
}, () => { }, () => {
this.setAllTreeGraphState(data||[]); const _treeData = this.convertTreeModelData(data||[]);
this.setState({
//深拷贝
orgModelData: JSON.parse(JSON.stringify(_treeData)),
treeModelData: JSON.parse(JSON.stringify(_treeData)),
relationModelData: JSON.parse(JSON.stringify(_treeData))
});
}); });
}, },
error: () => { error: () => {
...@@ -69,6 +79,7 @@ class MapContent extends React.Component { ...@@ -69,6 +79,7 @@ class MapContent extends React.Component {
return { return {
text: topic.name||'', text: topic.name||'',
id: `t${topic.id}`, id: `t${topic.id}`,
dbType: 'Root',
children: data children: data
}; };
} }
...@@ -83,7 +94,6 @@ class MapContent extends React.Component { ...@@ -83,7 +94,6 @@ class MapContent extends React.Component {
} }
onSquareItemClick = (item) => { onSquareItemClick = (item) => {
const { tableModelData } = this.state;
if (!item.children) { if (!item.children) {
dispatchLatest({ dispatchLatest({
type: 'map.getTableModelByDirIid', type: 'map.getTableModelByDirIid',
...@@ -92,14 +102,12 @@ class MapContent extends React.Component { ...@@ -92,14 +102,12 @@ class MapContent extends React.Component {
this.convertRemoteData(data||[]); this.convertRemoteData(data||[]);
item.children = (data||[]); item.children = (data||[]);
this.setSquareGraphState(item); this.setSquareGraphState(item);
this.setAllTreeGraphState(tableModelData);
} }
}) })
return; return;
} }
this.setSquareGraphState(item); this.setSquareGraphState(item);
this.setAllTreeGraphState(tableModelData);
} }
onBreadcrumbItemClick = (content, index) => { onBreadcrumbItemClick = (content, index) => {
...@@ -111,48 +119,27 @@ class MapContent extends React.Component { ...@@ -111,48 +119,27 @@ class MapContent extends React.Component {
}) })
} }
loadMoreData = (id) => { loadMoreData = (dirId, nodeId) => {
const { tableModelData } = this.state;
dispatchLatest({ dispatchLatest({
type: 'map.getTableModelByDirIid', type: 'map.getTableModelByDirIid',
payload: { dirId: id }, payload: { dirId },
callback: data => { callback: data => {
this.convertRemoteData(data||[]); this.convertRemoteData(data||[]);
function recursionData(_data) {
if ((_data||[]).length === 0)
return;
_data.forEach((item, index) => {
if (item.dirId === id) {
item.children = data;
} else {
recursionData(item.children||[]);
}
})
}
recursionData(tableModelData);
this.setAllTreeGraphState(tableModelData);
}
})
}
setAllTreeGraphState = (tableModelData) => {
const _treeData = this.convertTreeModelData(tableModelData);
this.setState({ this.setState({
orgModelData: JSON.parse(JSON.stringify(_treeData)), parentNodeId: nodeId,
treeModelData: JSON.parse(JSON.stringify(_treeData)), orgChildData: JSON.parse(JSON.stringify(data||[])),
relationModelData: JSON.parse(JSON.stringify(_treeData)) treeChildData: JSON.parse(JSON.stringify(data||[])),
relationChildData: JSON.parse(JSON.stringify(data)),
}); });
} }
})
}
render() { render() {
const { diagram, topic } = this.props; const { type, topic } = this.props;
const { curTableModelData, breadcrumbContents, orgModelData , treeModelData, relationModelData, loading } = this.state; const { curTableModelData, breadcrumbContents, orgModelData , treeModelData, relationModelData, loading, orgChildData, treeChildData, relationChildData, parentNodeId } = this.state;
let groups = []; let groups = [];
if (curTableModelData) { if (curTableModelData) {
...@@ -166,7 +153,7 @@ class MapContent extends React.Component { ...@@ -166,7 +153,7 @@ class MapContent extends React.Component {
{ {
loading ? <Spin /> : <> loading ? <Spin /> : <>
{ {
diagram==='square' && <> type==='square' && <>
{ {
breadcrumbContents && breadcrumbContents.length>1 && <Breadcrumb className='mb-3'> breadcrumbContents && breadcrumbContents.length>1 && <Breadcrumb className='mb-3'>
{ {
...@@ -204,13 +191,32 @@ class MapContent extends React.Component { ...@@ -204,13 +191,32 @@ class MapContent extends React.Component {
</> </>
} }
{ {
diagram==='org' && <Org data={orgModelData} type={`${topic.id||''}${diagram}`} {...this.props} loadMoreData={this.loadMoreData} /> type==='org' && <Org
data={orgModelData}
parentNodeId={parentNodeId}
childData={orgChildData}
type={`${topic.id||''}${type}`}
{...this.props}
loadMoreData={this.loadMoreData}
/>
} }
{ {
diagram==='tree' && <Tree data={treeModelData} type={`${topic.id||''}${diagram}`} {...this.props} loadMoreData={this.loadMoreData} /> type==='tree' && <Tree
data={treeModelData}
parentNodeId={parentNodeId}
childData={treeChildData}
type={`${topic.id||''}${type}`}
{...this.props}
loadMoreData={this.loadMoreData} />
} }
{ {
diagram==='relation' && <Relation data={relationModelData} type={`${topic.id||''}${diagram}`} {...this.props} loadMoreData={this.loadMoreData} /> type==='relation' && <Relation
data={relationModelData}
parentNodeId={parentNodeId}
childData={relationChildData}
type={`${topic.id||''}${type}`}
{...this.props}
loadMoreData={this.loadMoreData} />
} }
</> </>
} }
......
import React from 'react'; import React from 'react';
import { Tabs, Radio, Spin } from 'antd'; import { Tabs, Spin, Select } from 'antd';
import MapContent from './MapContent'; import MapContent from './MapContent';
import { dispatchLatest } from '../../../model'; import { dispatchLatest } from '../../../model';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const { Option } = Select;
const graphModes = [
{
title: '方块图',
key: 'square'
},
{
title: '组织图',
key: 'org',
},
{
title: '树形图',
key: 'tree',
},
{
title: '关系图',
key: 'relation'
}
];
class Map extends React.Component { class Map extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
diagram: 'square', type: 'square',
tabKey: '0', tabKey: '0',
loadingTopics: false, loadingTopics: false,
topics: null topics: null
...@@ -36,8 +56,8 @@ class Map extends React.Component { ...@@ -36,8 +56,8 @@ class Map extends React.Component {
}) })
} }
onRadioChange = e => { onTypeChange = value => {
this.setState({ diagram: e.target.value }); this.setState({ type: value||'' });
}; };
onTabChange = activeKey => { onTabChange = activeKey => {
...@@ -45,7 +65,7 @@ class Map extends React.Component { ...@@ -45,7 +65,7 @@ class Map extends React.Component {
} }
render() { render() {
const { diagram, tabKey, topics, loadingTopics } = this.state; const { type, tabKey, topics, loadingTopics } = this.state;
return ( return (
<div style={{ backgroundColor: '#fff', height: '100%' }}> <div style={{ backgroundColor: '#fff', height: '100%' }}>
{ {
...@@ -57,13 +77,21 @@ class Map extends React.Component { ...@@ -57,13 +77,21 @@ class Map extends React.Component {
centered centered
style={{ height: '100%' }} style={{ height: '100%' }}
tabBarExtraContent={{ tabBarExtraContent={{
left: <Radio.Group className='m-3' size='small' value={diagram} onChange={this.onRadioChange} > left: <div className='ml-3' style={{ width: 120, marginRight: 50 }} ></div>,
<Radio.Button value='square'>方块图</Radio.Button> right: (
<Radio.Button value='org'>组织图</Radio.Button> <Select
<Radio.Button value='tree'>树形图</Radio.Button> value={type}
<Radio.Button value='relation'>关系图</Radio.Button> className='mr-3'
</Radio.Group>, style={{ width: 120, marginLeft: 50 }}
right: <div style={{ width: 172 }}></div> onChange={this.onTypeChange}
>
{
graphModes && graphModes.map((mode, index) => {
return <Option key={index} value={mode.key||''}>{mode.title||''}</Option>
})
}
</Select>
)
}} }}
onChange={this.onTabChange} onChange={this.onTabChange}
> >
...@@ -71,7 +99,7 @@ class Map extends React.Component { ...@@ -71,7 +99,7 @@ class Map extends React.Component {
topics && topics.map((topic, index) => { topics && topics.map((topic, index) => {
return ( return (
<TabPane tab={topic.name||''} key={index.toString()} className='p-3' style={{ height: '100%' }}> <TabPane tab={topic.name||''} key={index.toString()} className='p-3' style={{ height: '100%' }}>
{ tabKey===index.toString() && <MapContent diagram={diagram} topic={topic} {...this.props} /> } { tabKey===index.toString() && <MapContent type={type} topic={topic} {...this.props} /> }
</TabPane> </TabPane>
); );
}) })
......
...@@ -3,16 +3,12 @@ import { Modal, Radio, Button } from 'antd'; ...@@ -3,16 +3,12 @@ import { Modal, Radio, Button } from 'antd';
const modes = [ const modes = [
{ {
title: '导出DDL',
},
{
title: '导出Erwin',
},
{
title: '导出Excel', title: '导出Excel',
key: 'excel',
}, },
{ {
title: '导出模型文档' title: '导出Word',
key: 'word',
}, },
] ]
...@@ -21,36 +17,47 @@ class ExportModal extends React.Component { ...@@ -21,36 +17,47 @@ class ExportModal extends React.Component {
constructor() { constructor() {
super(); super();
this.state = { this.state = {
confirmLoading: false selectedKey: '',
} }
} }
onModeClick = (index) => { onModeClick = (e) => {
this.setState({ selectedKey: e.target.value });
} }
handleOk = () => { handleOk = () => {
const { onCancel } = this.props; const { onCancel, ids } = this.props;
const { selectedKey } = this.state;
if (selectedKey === 'excel') {
window.open(`/api/datamodeler/easyDataModelerExport/excel?ids=${ids.join(',')}`);
} else if (selectedKey === 'word') {
window.open(`/api/datamodeler/easyDataModelerExport/word?ids=${ids.join(',')}`);
}
if (onCancel) { this.reset();
onCancel(); onCancel && onCancel();
} }
reset = () => {
this.setState({ selectedKey: '' });
} }
render() { render() {
const { visible, onCancel } = this.props; const { visible, onCancel } = this.props;
const { confirmLoading } = this.state; const { selectedKey } = this.state;
return ( return (
<Modal <Modal
visible={visible} visible={visible}
title={"导出方式"} title={"导出方式"}
destroyOnClose
onOk={this.handleOk} onOk={this.handleOk}
onCancel={onCancel} onCancel={() => {
this.reset();
onCancel && onCancel();
}}
footer={[ footer={[
<Button <Button
key="0" key="0"
loading={confirmLoading}
type="primary" type="primary"
onClick={this.handleOk} onClick={this.handleOk}
> >
...@@ -58,11 +65,11 @@ class ExportModal extends React.Component { ...@@ -58,11 +65,11 @@ class ExportModal extends React.Component {
</Button> </Button>
]} ]}
> >
<Radio.Group> <Radio.Group value={selectedKey} onChange={this.onModeClick}>
{ {
modes && modes.map((mode, index) => { modes && modes.map((mode, index) => {
return ( return (
<Radio key={index} value={index}> <Radio key={mode.key||''} value={mode.key||''}>
{ mode.title||'' } { mode.title||'' }
</Radio> </Radio>
); );
......
...@@ -14,6 +14,8 @@ const ImportAction = (props) => { ...@@ -14,6 +14,8 @@ const ImportAction = (props) => {
const [ constraints, setConstraints ] = useState([]); const [ constraints, setConstraints ] = useState([]);
const [ constraint, setConstraint ] = useState({}); const [ constraint, setConstraint ] = useState({});
const [ templates, setTemplates ] = useState([]);
const [ template, setTemplate ] = useState({});
const [ modelerData, setModelerData ] = useState(null); const [ modelerData, setModelerData ] = useState(null);
const [ supportedDatatypes, setSupportedDatatypes ] = useState([]); const [ supportedDatatypes, setSupportedDatatypes ] = useState([]);
...@@ -22,36 +24,46 @@ const ImportAction = (props) => { ...@@ -22,36 +24,46 @@ const ImportAction = (props) => {
useEffect(() =>{ useEffect(() =>{
if (mountRef.current) { if (action==='add' && (hints||[]).length === 0) return;
mountRef.current = false;
//初始化form状态
if (action==='add'||action==='edit') {
form.setFieldsValue({
cnName: '',
name: '',
remark: '',
});
}
if (action === 'detail') { if (action === 'detail') {
getCurrentDataModel(); getCurrentDataModel();
} else { } else {
dispatchLatest({ dispatchLatest({
type: 'datamodel.getAllConstraints', type: 'datamodel.getAllConstraintsAndTemplates',
callback: data => { callback: data => {
setConstraints(data||[]); setConstraints(data.constraints||[]);
setTemplates(data.templates||[]);
if (action === 'add') { if (action === 'add') {
setConstraint((data||[]).length>0?data[0]:{}); setConstraint((data.constraints||[]).length>0?data.constraints[0]:{});
getDraft((data||[]).length>0?data[0]:{}, hints); setTemplate((data.templates||[]).length>0?data.templates[0]:{});
getDraft((data.constraints||[]).length>0?data.constraints[0]:{}, (data.templates||[]).length>0?data.templates[0]:{} ,hints);
} else if(action === 'edit') { } else if(action === 'edit') {
getCurrentDataModel(); getCurrentDataModel();
} }
} }
}) })
} }
}
//eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, [action, hints, modelerId ]);
const getDraft = (_constraint, _hints) => { const getDraft = (_constraint, _template, _hints) => {
dispatchLatest({ dispatchLatest({
type: 'datamodel.getDraft', type: 'datamodel.getDraft',
payload: { payload: {
data: { data: {
hints, hints: _hints,
modelerModelingConstraint: _constraint modelerModelingConstraint: _constraint,
easyDataModelerModelingTemplate: _template
} }
}, },
callback: data => { callback: data => {
...@@ -99,11 +111,32 @@ const ImportAction = (props) => { ...@@ -99,11 +111,32 @@ const ImportAction = (props) => {
}); });
(modelerData.easyDataModelerDataModelAttributes||[]).forEach((_attribute, index) => { (modelerData.easyDataModelerDataModelAttributes||[]).forEach((_attribute, index) => {
_hints.push(_attribute.cnName||''); if (_attribute.name && _attribute.name!=='') {
_hints.push(_attribute.cnName);
}
}); });
setConstraint(currentConstraint); setConstraint(currentConstraint);
getDraft(currentConstraint, _hints); getDraft(currentConstraint, template, _hints);
}
const onTemplateChange = (value) => {
let currentTemplate = null, _hints = [];
(templates||[]).forEach((_template, index) => {
if (_template.id === value) {
currentTemplate = _template;
}
});
(modelerData.easyDataModelerDataModelAttributes||[]).forEach((_attribute, index) => {
if (_attribute.name && _attribute.name!=='') {
_hints.push(_attribute.cnName);
}
});
setTemplate(currentTemplate);
getDraft(constraint, currentTemplate, _hints);
} }
const getSupportedDatatypes = () => { const getSupportedDatatypes = () => {
...@@ -136,6 +169,15 @@ const ImportAction = (props) => { ...@@ -136,6 +169,15 @@ const ImportAction = (props) => {
}) })
} }
</Select> </Select>
<Select className='ml-3' value={template.id?template.id:null} placeholder='请选择模版' style={{ minWidth: 100 }} onChange={onTemplateChange}>
{
(templates||[]).map((template, index) => {
return (
<Option key={index} value={template.id}>{ template.cnName||'' }</Option>
)
})
}
</Select>
</div> </div>
} }
<ImportActionHeader <ImportActionHeader
...@@ -154,6 +196,7 @@ const ImportAction = (props) => { ...@@ -154,6 +196,7 @@ const ImportAction = (props) => {
<ImportActionTable <ImportActionTable
modelerData={modelerData||{}} modelerData={modelerData||{}}
constraint={constraint} constraint={constraint}
template={template}
supportedDatatypes={supportedDatatypes} supportedDatatypes={supportedDatatypes}
onChange={onTableChange} onChange={onTableChange}
editable={action!=='detail'} /> editable={action!=='detail'} />
......
...@@ -89,6 +89,7 @@ const DatatypeInput = ({ value = {}, datatypes, onChange }) => { ...@@ -89,6 +89,7 @@ const DatatypeInput = ({ value = {}, datatypes, onChange }) => {
onChange={(value) => { onChange={(value) => {
onParameterValuesChange(value, index); onParameterValuesChange(value, index);
}} }}
min={0}
value={parameterValues[index]} value={parameterValues[index]}
style={{ width: 60 }} style={{ width: 60 }}
/> />
...@@ -214,7 +215,7 @@ const DragableBodyRow = ({ index, moveRow, className, style, ...restProps }) => ...@@ -214,7 +215,7 @@ const DragableBodyRow = ({ index, moveRow, className, style, ...restProps }) =>
}; };
const ImportActionTable = (props) => { const ImportActionTable = (props) => {
const { modelerData, onChange, editable, supportedDatatypes, constraint } = props; const { modelerData, onChange, editable, supportedDatatypes, constraint, template } = props;
const data = modelerData.easyDataModelerDataModelAttributes||[]; const data = modelerData.easyDataModelerDataModelAttributes||[];
const [form] = Form.useForm(); const [form] = Form.useForm();
const [editingKey, setEditingKey] = useState(''); const [editingKey, setEditingKey] = useState('');
...@@ -223,7 +224,7 @@ const ImportActionTable = (props) => { ...@@ -223,7 +224,7 @@ const ImportActionTable = (props) => {
//规则改变的时候 数据表为可编辑状态 //规则改变的时候 数据表为可编辑状态
useEffect(() => { useEffect(() => {
setEditingKey(''); setEditingKey('');
}, [constraint]) }, [constraint, template])
const isEditing = (record) => record.iid === editingKey; const isEditing = (record) => record.iid === editingKey;
...@@ -424,24 +425,6 @@ const ImportActionTable = (props) => { ...@@ -424,24 +425,6 @@ const ImportActionTable = (props) => {
return columns; return columns;
} }
// const mergedColumns = columns.map((col) => {
// if (!col.editable) {
// return col;
// }
// return {
// ...col,
// onCell: (record) => ({
// record,
// inputType: 'text',
// dataIndex: col.dataIndex,
// title: col.title,
// editing: isEditing(record),
// datatypes: supportedDatatypes,
// }),
// };
// });
const moveRow = useCallback( const moveRow = useCallback(
(dragIndex, hoverIndex) => { (dragIndex, hoverIndex) => {
...@@ -505,7 +488,7 @@ const ImportActionTable = (props) => { ...@@ -505,7 +488,7 @@ const ImportActionTable = (props) => {
suggests && suggests.map((suggest, index) => { suggests && suggests.map((suggest, index) => {
return ( return (
<Radio key={index} value={index} className='mt-3' style={{ display: 'block' }}> <Radio key={index} value={index} className='mt-3' style={{ display: 'block' }}>
{`${suggest.name||''}`} {`中文名称: ${suggest.cnName||''} 英文名称: ${suggest.name||''} 描述: ${suggest.remark||''}`}
</Radio> </Radio>
) )
}) })
......
...@@ -13,18 +13,18 @@ const modes = [ ...@@ -13,18 +13,18 @@ const modes = [
{ {
title: 'Excel导入', title: 'Excel导入',
}, },
{ // {
title: 'Excel复制粘贴', // title: 'Excel复制粘贴',
}, // },
{ // {
title: 'Erwin', // title: 'Erwin',
}, // },
{ // {
title: '元数据输入', // title: '元数据输入',
}, // },
{ // {
title: '数据模型输入', // title: '数据模型输入',
} // }
] ]
const ImportModal = (props) => { const ImportModal = (props) => {
...@@ -150,9 +150,6 @@ const ImportModal = (props) => { ...@@ -150,9 +150,6 @@ const ImportModal = (props) => {
setHints([]); setHints([]);
setModelerData({}); setModelerData({});
setConfirmLoading(false); setConfirmLoading(false);
if (form && form.resetFields) {
form.resetFields();
}
} }
const onActionChange = (data) => { const onActionChange = (data) => {
...@@ -243,7 +240,7 @@ const ImportModal = (props) => { ...@@ -243,7 +240,7 @@ const ImportModal = (props) => {
forceRender forceRender
visible={visible} visible={visible}
title={title} title={title}
width={1000} width={step===2?1000:520}
maskClosable={false} maskClosable={false}
destroyOnClose destroyOnClose
onCancel={() => { onCancel={() => {
...@@ -256,7 +253,7 @@ const ImportModal = (props) => { ...@@ -256,7 +253,7 @@ const ImportModal = (props) => {
<> <>
{ {
step===0 && <> step===0 && <>
<Radio.Group onChange={onRadioChange}> <Radio.Group value={radioValue} onChange={onRadioChange}>
{ {
modes && modes.map((mode, index) => { modes && modes.map((mode, index) => {
return ( return (
......
import React, { useState } from "react"; import React, { useState, useEffect } from "react";
import { Table, Space, Button, Tooltip, Modal } from 'antd'; import { Table, Space, Button, Tooltip, Modal } from 'antd';
import { EditOutlined, CheckOutlined, ReconciliationOutlined, DeleteOutlined } from '@ant-design/icons'; import { EditOutlined, ReconciliationOutlined, DeleteOutlined } from '@ant-design/icons';
import { dispatchLatest } from '../../../../model'; import { dispatchLatest } from '../../../../model';
import { showMessage } from '../../../../util'; import { showMessage } from '../../../../util';
...@@ -8,13 +8,29 @@ import './ModelTable.less'; ...@@ -8,13 +8,29 @@ import './ModelTable.less';
const ModelTable = (props) => { const ModelTable = (props) => {
const { data, onChange, loading, onItemAction } = props; const { data, onChange, loading, onItemAction, onSelect, catalogId } = props;
const [ selectedRowKeys, setSelectedRowKeys ] = useState([]); const [ selectedRowKeys, setSelectedRowKeys ] = useState([]);
const [modal, contextHolder] = Modal.useModal(); const [modal, contextHolder] = Modal.useModal();
useEffect(() => {
setSelectedRowKeys([]);
onSelect && onSelect([]);
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ catalogId ]);
const columns = [ const columns = [
{ {
title: '序号',
dataIndex: 'key',
editable: false,
render: (text, record, index) => {
return (index+1).toString();
}
},
{
title: '模型名称', title: '模型名称',
dataIndex: 'name', dataIndex: 'name',
}, },
...@@ -38,9 +54,9 @@ const ModelTable = (props) => { ...@@ -38,9 +54,9 @@ const ModelTable = (props) => {
<Tooltip placement='bottom' title={'详情'}> <Tooltip placement='bottom' title={'详情'}>
<Button icon={<ReconciliationOutlined />} size='small' onClick={() => { detailItem(record); }} /> <Button icon={<ReconciliationOutlined />} size='small' onClick={() => { detailItem(record); }} />
</Tooltip> </Tooltip>
<Tooltip placement='bottom' title={'提交审核'}> {/* <Tooltip placement='bottom' title={'提交审核'}>
<Button icon={<CheckOutlined />} size='small' /> <Button icon={<CheckOutlined />} size='small' />
</Tooltip> </Tooltip> */}
<Tooltip placement='bottom' title={'删除'}> <Tooltip placement='bottom' title={'删除'}>
<Button icon={<DeleteOutlined />} size='small' onClick={() => { deleteItem(record); }} /> <Button icon={<DeleteOutlined />} size='small' onClick={() => { deleteItem(record); }} />
</Tooltip> </Tooltip>
...@@ -74,6 +90,14 @@ const ModelTable = (props) => { ...@@ -74,6 +90,14 @@ const ModelTable = (props) => {
callback: () => { callback: () => {
showMessage('success', '模型删除成功'); showMessage('success', '模型删除成功');
onChange && onChange(); onChange && onChange();
const index = selectedRowKeys.findIndex((rowKey) => rowKey === record.id);
if (index !== -1) {
const newSelectedRowKeys = [...selectedRowKeys];
newSelectedRowKeys.splice(index, 1);
setSelectedRowKeys(newSelectedRowKeys);
onSelect && onSelect(newSelectedRowKeys);
}
} }
}) })
} }
...@@ -82,6 +106,7 @@ const ModelTable = (props) => { ...@@ -82,6 +106,7 @@ const ModelTable = (props) => {
const onSelectChange = keys => { const onSelectChange = keys => {
setSelectedRowKeys(keys); setSelectedRowKeys(keys);
onSelect && onSelect(keys);
}; };
const rowSelection = { const rowSelection = {
......
.model-table { .model-table {
.yy-table { .yy-table {
height: calc(100vh - 64px - 20px - 53px - 20px) !important; height: calc(100vh - 64px - 30px - 53px - 20px) !important;
overflow: auto !important; overflow: auto !important;
} }
} }
\ No newline at end of file
.model-tree { .model-tree {
.yy-tree-list { .yy-tree-list {
height: calc(100vh - 64px - 20px - 53px - 20px) !important; height: calc(100vh - 64px - 30px - 53px - 20px) !important;
overflow: auto !important; overflow: auto !important;
} }
} }
\ No newline at end of file
...@@ -89,6 +89,8 @@ const UpdateTreeItemModal = (props) => { ...@@ -89,6 +89,8 @@ const UpdateTreeItemModal = (props) => {
_action = item ? 'sub' : 'root'; _action = item ? 'sub' : 'root';
} }
form.setFields([{ name: 'name', errors: [] }, { name: 'remark', errors: [] }]);
if (type === 'add') { if (type === 'add') {
form.setFieldsValue({ action: _action, name: '', remark: '' }); form.setFieldsValue({ action: _action, name: '', remark: '' });
} else { } else {
...@@ -144,7 +146,7 @@ const UpdateTreeItemModal = (props) => { ...@@ -144,7 +146,7 @@ const UpdateTreeItemModal = (props) => {
} }
}); });
} catch (errInfo) { } catch (errInfo) {
console.log('Validate Failed:', errInfo); setConfirmLoading(false);
} }
} }
......
...@@ -19,11 +19,12 @@ class Model extends React.Component { ...@@ -19,11 +19,12 @@ class Model extends React.Component {
importModalAction: '', importModalAction: '',
tableData: [], tableData: [],
loadingTableData: false, loadingTableData: false,
selectModelerIds: [],
} }
} }
onTreeSelect = (key) => { onTreeSelect = (key) => {
this.setState({ catalogId: key }, () => { this.setState({ catalogId: key, selectModelerIds: [] }, () => {
if (!key || key==='') { if (!key || key==='') {
this.setState({ tableData: [] }); this.setState({ tableData: [] });
} else { } else {
...@@ -51,6 +52,10 @@ class Model extends React.Component { ...@@ -51,6 +52,10 @@ class Model extends React.Component {
}) })
} }
onTableSelect = (ids) => {
this.setState({ selectModelerIds: ids });
}
onTableItemAction = (id, action) => { onTableItemAction = (id, action) => {
this.setState({ importModalVisible: true, importModalAction: action, modelerId: id }); this.setState({ importModalVisible: true, importModalAction: action, modelerId: id });
} }
...@@ -66,6 +71,12 @@ class Model extends React.Component { ...@@ -66,6 +71,12 @@ class Model extends React.Component {
} }
onExportBtnClick = () => { onExportBtnClick = () => {
const { selectModelerIds } = this.state;
if ((selectModelerIds||[]).length === 0) {
showMessage('info', '请先选择模型');
return;
}
this.setState({ exportModalVisible: true }); this.setState({ exportModalVisible: true });
} }
...@@ -79,13 +90,13 @@ class Model extends React.Component { ...@@ -79,13 +90,13 @@ class Model extends React.Component {
} }
render() { render() {
const { importModalVisible, exportModalVisible, catalogId, importModalAction, tableData, loadingTableData, modelerId } = this.state; const { importModalVisible, exportModalVisible, catalogId, importModalAction, tableData, loadingTableData, modelerId, selectModelerIds } = this.state;
return ( return (
<div style={{ backgroundColor: '#ECEEF3', height: '100%' }}> <div style={{ backgroundColor: '#ECEEF3' }}>
<Row style={{ height: '100%' }}> <Row>
<Col span={6} style={{ height: '100%' }} > <Col span={6} >
<div className='mr-3' style={{ backgroundColor: '#fff' }}> <div className='mr-4' style={{ backgroundColor: '#fff' }}>
<ModelTree onSelect={this.onTreeSelect} /> <ModelTree onSelect={this.onTreeSelect} />
</div> </div>
</Col> </Col>
...@@ -98,12 +109,12 @@ class Model extends React.Component { ...@@ -98,12 +109,12 @@ class Model extends React.Component {
borderBottom: "1px solid #EFEFEF", borderBottom: "1px solid #EFEFEF",
}} }}
> >
<Button type="primary" style={{ marginLeft: 'auto' }}>提交审核</Button> {/* <Button type="primary" style={{ marginLeft: 'auto' }}>提交审核</Button> */}
<Button type="primary" className='ml-3' onClick={this.onImportBtnClick}>模型创建</Button> <Button type="primary" className='ml-3' style={{ marginLeft: 'auto' }} onClick={this.onImportBtnClick}>模型创建</Button>
<Button type="primary" className='ml-3' onClick={this.onExportBtnClick}>模型导出</Button> <Button type="primary" className='ml-3' onClick={this.onExportBtnClick}>模型导出</Button>
</div> </div>
<div className='p-3'> <div className='p-3'>
<ModelTable loading={loadingTableData} data={tableData} onChange={this.onTableChange} onItemAction={this.onTableItemAction} /> <ModelTable loading={loadingTableData} catalogId={catalogId} data={tableData} onChange={this.onTableChange} onSelect={this.onTableSelect} onItemAction={this.onTableItemAction} />
</div> </div>
</div> </div>
</Col> </Col>
...@@ -119,6 +130,7 @@ class Model extends React.Component { ...@@ -119,6 +130,7 @@ class Model extends React.Component {
<ExportModal <ExportModal
visible={exportModalVisible} visible={exportModalVisible}
ids={selectModelerIds}
onCancel={this.onExportModalCancel} onCancel={this.onExportModalCancel}
/> />
</div> </div>
......
...@@ -8,6 +8,7 @@ import { ManageLayout } from "../../layout"; ...@@ -8,6 +8,7 @@ import { ManageLayout } from "../../layout";
import Map from './Map'; import Map from './Map';
import Model from './Model'; import Model from './Model';
import AssetManage from './AssetManage'; import AssetManage from './AssetManage';
import Element from './Element';
class Manage extends Component { class Manage extends Component {
constructor(props) { constructor(props) {
...@@ -31,7 +32,7 @@ class Manage extends Component { ...@@ -31,7 +32,7 @@ class Manage extends Component {
<Route path={`${match.path}/map`} component={Map} /> <Route path={`${match.path}/map`} component={Map} />
<Route path={`${match.path}/model`} component={Model} /> <Route path={`${match.path}/model`} component={Model} />
<Route path={`${match.path}/assetmanage`} component={AssetManage} /> <Route path={`${match.path}/assetmanage`} component={AssetManage} />
<Route path={`${match.path}/element`} component={Element} />
</Switch> </Switch>
) : ( ) : (
<GetSession {...this.props} /> <GetSession {...this.props} />
......
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