Commit 90accdb2 by zhaochengxiang

数据地图增加接口

parent 9d285bda
......@@ -49,6 +49,6 @@
"last 1 safari version"
]
},
"proxy": "http://139.198.126.96:9011",
"proxy": "http://139.198.127.28:18762",
"homepage": "http://myhost/data-govern"
}
......@@ -9,8 +9,9 @@ import { reducers } from './reducer';
import * as user from './user';
import * as assets from './assets';
import * as metadata from './metadata';
import * as map from './map';
const funcs = Connect({ user, assets, metadata })
const funcs = Connect({ user, assets, metadata, map })
function* request(args) {
const { type, payload, callback, error } = args.args;
......
import * as service from '../service/map';
import { call } from 'redux-saga/effects';
export function* getAllTopics() {
return yield call(service.getAllTopics);
}
export function* getTableAndTreeModelByTid(payload) {
const tables = yield call(service.getTableModelByTid, payload);
const trees = yield call(service.getTreeModel);
return {tables: tables||[], trees: ((trees||[]).length>0)?trees[0]:{}};
}
import { GetJSON } from "../util/axios"
export function getAllTopics() {
return GetJSON("/datacatalog/countCtrl/queryAllTopics");
}
export function getTableModelByTid(payload) {
return GetJSON("/datacatalog/countCtrl/getTableModelInfoByDirId", payload);
}
export function getTreeModel() {
return GetJSON("/datacatalog/countCtrl/queryAllDirAsTree");
}
\ No newline at end of file
......@@ -23,140 +23,143 @@ class Relation extends React.Component {
componentDidMount() {
const { data, type, history } = this.props;
const container = document.getElementById(`container${type||''}`);
const width = container.scrollWidth;
const height = container.scrollHeight || 500;
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}`;
}
setTimeout(() => {
const container = document.getElementById(`container${type||''}`);
const width = container.scrollWidth;
const height = container.scrollHeight || 500;
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 refreshDragedNodePosition(e) {
const model = e.item.get('model');
model.fx = e.x;
model.fy = e.y;
}
const tooltip = new G6.Tooltip({
offsetX: 10,
offsetY: 10,
// the types of items that allow the tooltip show up
// 允许出现 tooltip 的 item 类型
itemTypes: ['node'],
// custom the tooltip's content
// 自定义 tooltip 内容
getContent: (e) => {
const outDiv = document.createElement('div');
outDiv.style.width = 'fit-content';
//outDiv.style.padding = '0px 0px 20px 0px';
outDiv.innerHTML = `
<h4>${e.item.getModel().text||''}</h4>
`;
return outDiv;
},
});
return res;
};
function refreshDragedNodePosition(e) {
const model = e.item.get('model');
model.fx = e.x;
model.fy = e.y;
}
const tooltip = new G6.Tooltip({
offsetX: 10,
offsetY: 10,
// the types of items that allow the tooltip show up
// 允许出现 tooltip 的 item 类型
itemTypes: ['node'],
// custom the tooltip's content
// 自定义 tooltip 内容
getContent: (e) => {
const outDiv = document.createElement('div');
outDiv.style.width = 'fit-content';
//outDiv.style.padding = '0px 0px 20px 0px';
outDiv.innerHTML = `
<h4>${e.item.getModel().name||''}</h4>
`;
return outDiv;
},
});
const graph = new G6.Graph({
container: `container${type||''}`,
width,
height,
plugins: [tooltip],
layout: {
type: 'force',
preventOverlap: true,
linkDistance: (d) => {
return 200;
const graph = new G6.Graph({
container: `container${type||''}`,
width,
height,
plugins: [tooltip],
layout: {
type: 'force',
preventOverlap: true,
linkDistance: (d) => {
return 200;
},
nodeStrength: (d) => {
if (d.isLeaf) {
return -50;
}
return -10;
},
edgeStrength: (d) => {
return 0.7;
},
},
nodeStrength: (d) => {
if (d.isLeaf) {
return -50;
}
return -10;
defaultNode: {
color: '#5B8FF9',
},
edgeStrength: (d) => {
return 0.7;
modes: {
default: ['drag-canvas'],
},
},
defaultNode: {
color: '#5B8FF9',
},
modes: {
default: ['drag-canvas'],
},
});
const nodes = data.nodes;
const clusterMap = new Map();
let clusterId = 0;
nodes.forEach(function (node) {
// cluster
if (node.cluster && clusterMap.get(node.cluster) === undefined) {
clusterMap.set(node.cluster, clusterId);
clusterId++;
}
const cid = clusterMap.get(node.cluster);
if (!node.style) {
node.style = {};
});
const nodes = data.nodes;
const clusterMap = new Map();
let clusterId = 0;
nodes.forEach(function (node) {
// cluster
if (node.cluster && clusterMap.get(node.cluster) === undefined) {
clusterMap.set(node.cluster, clusterId);
clusterId++;
}
const cid = clusterMap.get(node.cluster);
if (!node.style) {
node.style = {};
}
node.style.fill = colors[cid % colors.length];
});
data.nodes.forEach(function (node) {
node.label = fittingString(node.label, node.size, globalFontSize);
});
graph.data({
nodes,
edges: data.edges.map(function (edge, i) {
edge.id = 'edge' + i;
return Object.assign({}, edge);
}),
});
graph.render();
graph.on('node:dragstart', function (e) {
graph.layout();
refreshDragedNodePosition(e);
});
graph.on('node:drag', function (e) {
refreshDragedNodePosition(e);
});
graph.on('node:dragend', function (e) {
e.item.get('model').fx = null;
e.item.get('model').fy = null;
});
graph.on('node:click', function (e) {
// const node = e.item;
// const model = node.getModel();
history && history.push(`${ContextPath}/home`);
});
if (typeof window !== 'undefined') {
window.onresize = () => {
if (!graph || graph.get('destroyed')) return;
if (!container || !container.scrollWidth || !container.scrollHeight) return;
graph.changeSize(container.scrollWidth, container.scrollHeight);
};
}
node.style.fill = colors[cid % colors.length];
});
data.nodes.forEach(function (node) {
node.label = fittingString(node.label, node.size, globalFontSize);
});
graph.data({
nodes,
edges: data.edges.map(function (edge, i) {
edge.id = 'edge' + i;
return Object.assign({}, edge);
}),
});
graph.render();
graph.on('node:dragstart', function (e) {
graph.layout();
refreshDragedNodePosition(e);
});
graph.on('node:drag', function (e) {
refreshDragedNodePosition(e);
});
graph.on('node:dragend', function (e) {
e.item.get('model').fx = null;
e.item.get('model').fy = null;
});
graph.on('node:click', function (e) {
const node = e.item;
const model = node.getModel();
history && history.push(`${ContextPath}/home`);
});
if (typeof window !== 'undefined') {
window.onresize = () => {
if (!graph || graph.get('destroyed')) return;
if (!container || !container.scrollWidth || !container.scrollHeight) return;
graph.changeSize(container.scrollWidth, container.scrollHeight);
};
}
}, 100);
}
render() {
......
......@@ -4,7 +4,7 @@ import { Card } from 'antd';
class SquareItem extends React.Component {
onItemClick = () => {
const { item, onClick, history } = this.props;
const { item, onClick } = this.props;
if (onClick) {
onClick(item);
}
......@@ -15,11 +15,11 @@ class SquareItem extends React.Component {
return (
<Card title={
<div className='pointer' onClick={this.onItemClick}>
{item.title||''}
{item.dirName||''}
</div>
}>
<p>{`数据资产: ${item.assetCount||''}`}</p>
<p>{`资产编目: ${item.assetDirCount||''}`}</p>
<p>{`数据资产: ${item.tableModelCount}`}</p>
<p>{`资产编目: ${item.subDirCount}`}</p>
</Card>
);
}
......
......@@ -49,7 +49,7 @@ class Tree extends React.Component {
graph.node(function (node) {
return {
label: node.title||'',
label: node.text||'',
labelCfg: {
position: node.children && node.children.length > 0 ? 'left' : 'right',
offset: 5,
......@@ -62,8 +62,8 @@ class Tree extends React.Component {
graph.fitView();
graph.on('node:click', function (e) {
const node = e.item;
const model = node.getModel();
// const node = e.item;
// const model = node.getModel();
history && history.push(`${ContextPath}/home`);
});
......
......@@ -2,6 +2,7 @@ import React from 'react';
import { Tabs, Radio } from 'antd';
import MapContent from './MapContent';
import { dispatchLatest } from '../../../model';
const { TabPane } = Tabs;
......@@ -10,10 +11,28 @@ class Map extends React.Component {
super(props);
this.state = {
diagram: 'square',
tabKey: '1'
tabKey: '0',
loadingTopics: false,
topics: null
};
}
componentDidMount() {
this.setState({ loadingTopics: true }, () => {
dispatchLatest({
type: 'map.getAllTopics',
payload: null,
callback: data => {
this.setState({
loadingTopics: false,
topics: data
});
}
})
})
}
onRadioChange = e => {
this.setState({ diagram: e.target.value });
};
......@@ -23,34 +42,36 @@ class Map extends React.Component {
}
render() {
const { diagram, tabKey } = this.state;
const { diagram, tabKey, topics } = this.state;
return (
<div style={{ backgroundColor: '#fff', height: '100%' }}>
<Tabs
activeKey={tabKey}
size='large'
centered
style={{ height: '100%' }}
tabBarExtraContent={{
left: <Radio.Group className='m-3' size='small' value={diagram} onChange={this.onRadioChange} >
<Radio.Button value='square'>方块图</Radio.Button>
<Radio.Button value='tree'>树形图</Radio.Button>
<Radio.Button value='relation'>关系图</Radio.Button>
</Radio.Group>,
right: <div style={{ width: 172 }}></div>
}}
onChange={this.onTabChange}
>
<TabPane tab='业务' key='1' className='p-3' style={{ height: '100%' }}>
{ tabKey==='1' && <MapContent diagram={diagram} type='business' {...this.props} /> }
</TabPane>
<TabPane tab='主题' key='2' className='p-3' style={{ height: '100%' }}>
{ tabKey==='2' && <MapContent diagram={diagram} type='theme' {...this.props} /> }
</TabPane>
<TabPane tab='来源' key='3' className='p-3' style={{ height: '100%' }}>
{ tabKey==='3' && <MapContent diagram={diagram} type='source' {...this.props} /> }
</TabPane>
</Tabs>
{
topics && topics.length>0 && <Tabs
activeKey={tabKey}
size='large'
centered
style={{ height: '100%' }}
tabBarExtraContent={{
left: <Radio.Group className='m-3' size='small' value={diagram} onChange={this.onRadioChange} >
<Radio.Button value='square'>方块图</Radio.Button>
<Radio.Button value='tree'>树形图</Radio.Button>
<Radio.Button value='relation'>关系图</Radio.Button>
</Radio.Group>,
right: <div style={{ width: 172 }}></div>
}}
onChange={this.onTabChange}
>
{
topics && topics.map((topic, index) => {
return (
<TabPane tab='业务' key={index.toString()} className='p-3' style={{ height: '100%' }}>
{ tabKey===index.toString() && <MapContent diagram={diagram} tid={topic.id||''} type='business' {...this.props} /> }
</TabPane>
);
})
}
</Tabs>
}
</div>
);
}
......
......@@ -24,16 +24,13 @@ class Manage extends Component {
<ManageLayout
{...this.props}
content={
<Switch>
<Route path={`${match.path}/map`} component={Map} {...this.props} />
</Switch>
// session && session.userId ? (
// <Switch>
// <Route path={`${match.path}/map`} component={Map} />
// </Switch>
// ) : (
// <GetSession {...this.props} />
// )
session && session.userId ? (
<Switch>
<Route path={`${match.path}/map`} component={Map} />
</Switch>
) : (
<GetSession {...this.props} />
)
}
/>
</React.Fragment>
......
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