|
|
@@ -1,9 +1,10 @@
|
|
|
import React from 'react'
|
|
|
-import { Layout, Row, Col, Input, Button, Table, Icon, Menu, Dropdown, Card } from 'antd'
|
|
|
+import { Layout, Row, Col, Input, Button, Icon, Menu, Dropdown, Card } from 'antd'
|
|
|
import { connect } from 'dva'
|
|
|
import DeleteBox from '../common/deleteBox/deleteBox'
|
|
|
import DataConnectBox from '../dataSourceDetail/dataConnectBox'
|
|
|
import './list.less'
|
|
|
+const CardGrid = Card.Grid
|
|
|
const { Content } = Layout
|
|
|
const { Search } = Input
|
|
|
|
|
|
@@ -11,26 +12,25 @@ class DataConnect extends React.Component {
|
|
|
constructor(props) {
|
|
|
super(props);
|
|
|
this.state = {
|
|
|
- selectedRecord: null, // 当前选中的dataSource
|
|
|
visibleDeleteBox: false,
|
|
|
}
|
|
|
};
|
|
|
componentDidMount() {
|
|
|
const { dispatch } = this.props;
|
|
|
- this.setScrollTableHeight();
|
|
|
+ // this.setScrollTableHeight();
|
|
|
dispatch({ type: 'dataConnect/fetchList' });
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据视图设置表格高度以呈现滚动条
|
|
|
*/
|
|
|
- setScrollTableHeight() {
|
|
|
- const mainContent = document.getElementsByClassName('main-content')[0];
|
|
|
- const toolbar = mainContent.getElementsByClassName('dataconnect-tools')[0];
|
|
|
- const tableHeader = mainContent.getElementsByClassName('ant-table-header')[0];
|
|
|
- const tableBody = mainContent.getElementsByClassName('ant-table-body')[0];
|
|
|
- tableBody.style.maxHeight=`${mainContent.offsetHeight - toolbar.offsetHeight - tableHeader.offsetHeight - 58}px`;
|
|
|
- }
|
|
|
+ // setScrollTableHeight() {
|
|
|
+ // const mainContent = document.getElementsByClassName('main-content')[0];
|
|
|
+ // const toolbar = mainContent.getElementsByClassName('dataconnect-tools')[0];
|
|
|
+ // const tableHeader = mainContent.getElementsByClassName('ant-table-header')[0];
|
|
|
+ // const tableBody = mainContent.getElementsByClassName('ant-table-body')[0];
|
|
|
+ // tableBody.style.maxHeight=`${mainContent.offsetHeight - toolbar.offsetHeight - tableHeader.offsetHeight - 58}px`;
|
|
|
+ // }
|
|
|
|
|
|
onSearch(list, text) {
|
|
|
const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
|
|
|
@@ -58,29 +58,27 @@ class DataConnect extends React.Component {
|
|
|
this.setState({ visibleGroupMenu: flag });
|
|
|
}
|
|
|
|
|
|
- render() {
|
|
|
-
|
|
|
+ generateCard() {
|
|
|
const { dataConnect, dispatch } = this.props;
|
|
|
- const { selectedRecord, visibleDeleteBox } = this.state;
|
|
|
-
|
|
|
+ const { selected } = dataConnect;
|
|
|
const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
|
|
|
let filterLabel = dataConnect.filterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
|
|
|
|
|
|
- const moreOperatingMenu = (
|
|
|
- <Menu className='operationmenu' visible={true}>
|
|
|
- {selectedRecord && <Menu.Item onClick={(e) => {
|
|
|
- dispatch({ type: 'dataConnect/setNewModel', model: selectedRecord });
|
|
|
+ const operationMenu = (
|
|
|
+ <Menu className='menu-operation'>
|
|
|
+ <Menu.Item onClick={(e) => {
|
|
|
+ dispatch({ type: 'dataConnect/setNewModel', model: selected });
|
|
|
dispatch({ type: 'dataConnect/setNewModelFields', fields: [
|
|
|
{ name: 'visibleBox', value: true },
|
|
|
{ name: 'boxOperation', value: 'modify' }
|
|
|
] });
|
|
|
}}>
|
|
|
<Icon type="info-circle-o" />属性设置
|
|
|
- </Menu.Item>}
|
|
|
+ </Menu.Item>
|
|
|
<Menu.Divider />
|
|
|
- { selectedRecord && <Menu.Item
|
|
|
+ <Menu.Item
|
|
|
onClick={(e) => {
|
|
|
- dispatch({ type: 'dataConnect/setNewModel', model: { ...selectedRecord, code: null } });
|
|
|
+ dispatch({ type: 'dataConnect/setNewModel', model: { ...selected, code: null } });
|
|
|
dispatch({ type: 'dataConnect/setNewModelFields', fields: [
|
|
|
{ name: 'visibleBox', value: true },
|
|
|
{ name: 'boxOperation', value: 'create' }
|
|
|
@@ -88,115 +86,98 @@ class DataConnect extends React.Component {
|
|
|
}}
|
|
|
>
|
|
|
<Icon type="copy" />复制新增
|
|
|
- </Menu.Item>}
|
|
|
- { selectedRecord && <Menu.Item
|
|
|
+ </Menu.Item>
|
|
|
+ <Menu.Item
|
|
|
onClick={(e) => {
|
|
|
this.setState({ visibleDeleteBox: true})
|
|
|
}}
|
|
|
>
|
|
|
<Icon type="delete" />删除
|
|
|
- </Menu.Item>}
|
|
|
+ </Menu.Item>
|
|
|
</Menu>
|
|
|
- );
|
|
|
- const dataConnectColumns = [{
|
|
|
- title: '连接名',
|
|
|
- dataIndex: 'name',
|
|
|
- key: 'name',
|
|
|
- width: 200,
|
|
|
- render: (text, record) => {
|
|
|
- return <div className='dataconnect-name'>
|
|
|
- <div>
|
|
|
- <span>
|
|
|
- { filterLabel ?
|
|
|
- ((text || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
|
|
|
- return (
|
|
|
- fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
|
|
|
- <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
|
|
|
- fragment
|
|
|
- )
|
|
|
- }
|
|
|
- )) : text
|
|
|
- }
|
|
|
- </span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- }
|
|
|
- }, {
|
|
|
- title: '数据库类型',
|
|
|
- dataIndex: 'dbType',
|
|
|
- key: 'dbType',
|
|
|
- width: 120
|
|
|
- }, {
|
|
|
- title: '数据库地址',
|
|
|
- dataIndex: 'address',
|
|
|
- key: 'address',
|
|
|
- width: 120
|
|
|
- }, {
|
|
|
- title: '端口',
|
|
|
- dataIndex: 'port',
|
|
|
- key: 'port',
|
|
|
- width: 100
|
|
|
- }, {
|
|
|
- title: '数据库名',
|
|
|
- dataIndex: 'dbName',
|
|
|
- key: 'dbName',
|
|
|
- width: 100
|
|
|
- }, {
|
|
|
- title: '用户名',
|
|
|
- dataIndex: 'userName',
|
|
|
- key: 'userName',
|
|
|
- width: 150
|
|
|
- }, {
|
|
|
- title: '说明',
|
|
|
- dataIndex: 'description',
|
|
|
- key: 'description',
|
|
|
- render: (text, record) => {
|
|
|
- return <div className='dataconnect-name'>
|
|
|
- <div>
|
|
|
- <span>
|
|
|
- { filterLabel ?
|
|
|
- ((text || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
|
|
|
- return (
|
|
|
- fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
|
|
|
- <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
|
|
|
- fragment
|
|
|
- )
|
|
|
+ )
|
|
|
+
|
|
|
+ let cards = dataConnect.list.filter(l => {
|
|
|
+ return ((l.name || '').search(new RegExp('(' + filterLabel + '){1}', 'ig')) !== -1);
|
|
|
+ }).map( (l, i) => (
|
|
|
+ <CardGrid className='dataconnect-card' key={i}>
|
|
|
+ <Card
|
|
|
+ title={
|
|
|
+ <Row type='flex' justify='start'>
|
|
|
+ <Col className='label'>
|
|
|
+ { filterLabel ?
|
|
|
+ ((l.name || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
|
|
|
+ return (
|
|
|
+ fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
|
|
|
+ <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
|
|
|
+ fragment
|
|
|
+ )
|
|
|
+ }
|
|
|
+ )) : l.name
|
|
|
}
|
|
|
- )) : text
|
|
|
- }
|
|
|
- </span>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ }
|
|
|
+ onClick={() => {
|
|
|
+ // 选中项设置
|
|
|
+ dispatch({ type: 'dataConnect/setSelected', selected: l });
|
|
|
+ dispatch({ type: 'dataConnect/setNewModel', model: l });
|
|
|
+ dispatch({ type: 'dataConnect/setNewModelFields', fields: [
|
|
|
+ { name: 'visibleBox', value: true },
|
|
|
+ { name: 'boxOperation', value: 'modify' }
|
|
|
+ ] });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div className='content'>
|
|
|
+ <Row className='address'>
|
|
|
+ {l.address}
|
|
|
+ </Row>
|
|
|
+ <Row className='username'>
|
|
|
+ {l.userName}
|
|
|
+ </Row>
|
|
|
+ <Row className='bottom' type='flex' justify='space-between'>
|
|
|
+ <Col>{l.dbType}</Col>
|
|
|
+ <Col>
|
|
|
+ <Dropdown overlay={operationMenu} trigger={['click']}>
|
|
|
+ <Icon type="ellipsis" />
|
|
|
+ </Dropdown>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- }
|
|
|
- }, {
|
|
|
- title: '操作',
|
|
|
- key: 'action',
|
|
|
- render: (text, record, index) => (
|
|
|
- <Dropdown code={record.code} overlay={moreOperatingMenu} trigger={['click']} >
|
|
|
- <Icon type="setting" />
|
|
|
- </Dropdown>
|
|
|
- ),
|
|
|
- width: 50
|
|
|
- }];
|
|
|
+ </Card>
|
|
|
+ </CardGrid>
|
|
|
+ ))
|
|
|
|
|
|
- return (
|
|
|
- <Layout className='dataconnect-view'>
|
|
|
+ if(cards.length === 0) {
|
|
|
+ return (<div className="ant-empty ant-empty-normal"><div className="ant-empty-image"><img alt="暂无数据" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAxKSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgIDxlbGxpcHNlIGZpbGw9IiNGNUY1RjUiIGN4PSIzMiIgY3k9IjMzIiByeD0iMzIiIHJ5PSI3Ii8+CiAgICA8ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0iI0Q5RDlEOSI+CiAgICAgIDxwYXRoIGQ9Ik01NSAxMi43Nkw0NC44NTQgMS4yNThDNDQuMzY3LjQ3NCA0My42NTYgMCA0Mi45MDcgMEgyMS4wOTNjLS43NDkgMC0xLjQ2LjQ3NC0xLjk0NyAxLjI1N0w5IDEyLjc2MVYyMmg0NnYtOS4yNHoiLz4KICAgICAgPHBhdGggZD0iTTQxLjYxMyAxNS45MzFjMC0xLjYwNS45OTQtMi45MyAyLjIyNy0yLjkzMUg1NXYxOC4xMzdDNTUgMzMuMjYgNTMuNjggMzUgNTIuMDUgMzVoLTQwLjFDMTAuMzIgMzUgOSAzMy4yNTkgOSAzMS4xMzdWMTNoMTEuMTZjMS4yMzMgMCAyLjIyNyAxLjMyMyAyLjIyNyAyLjkyOHYuMDIyYzAgMS42MDUgMS4wMDUgMi45MDEgMi4yMzcgMi45MDFoMTQuNzUyYzEuMjMyIDAgMi4yMzctMS4zMDggMi4yMzctMi45MTN2LS4wMDd6IiBmaWxsPSIjRkFGQUZBIi8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K"/></div><p className="ant-empty-description">暂无数据</p></div>)
|
|
|
+ }
|
|
|
+
|
|
|
+ return cards;
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ const { dataConnect, dispatch } = this.props;
|
|
|
+ const { selected } = dataConnect;
|
|
|
+ const { visibleDeleteBox } = this.state;
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Layout className='layout-dataconnect'>
|
|
|
<Content>
|
|
|
- <Card className='dataconnect-body' title={
|
|
|
- <Row className='dataconnect-tools' type='flex' justify='space-between'>
|
|
|
+ <Card title={
|
|
|
+ <Row className='tools' type='flex' justify='space-between'>
|
|
|
<Col style={{ display: 'flex' }}>
|
|
|
</Col>
|
|
|
<Col className='search'>
|
|
|
- <Col>
|
|
|
+ <Col style={{ padding: '0 5px' }}>
|
|
|
<Search
|
|
|
- value={dataConnect.filterLabel}
|
|
|
placeholder="请输入关键字"
|
|
|
+ value={dataConnect.filterLabel}
|
|
|
onChange={e => {
|
|
|
dispatch({ type: 'dataConnect/setFilterLabel', label: e.target.value });
|
|
|
}}
|
|
|
/>
|
|
|
</Col>
|
|
|
- <Col>
|
|
|
+ <Col >
|
|
|
<Button onClick={() => {
|
|
|
dispatch({ type: 'dataConnect/setNewModel', model: { dbType: 'oracle' } });
|
|
|
dispatch({ type: 'dataConnect/setNewModelFields', fields: [
|
|
|
@@ -210,42 +191,26 @@ class DataConnect extends React.Component {
|
|
|
</Col>
|
|
|
</Row>
|
|
|
}>
|
|
|
- <Table
|
|
|
- className='dataconnect-table'
|
|
|
- columns={dataConnectColumns}
|
|
|
- dataSource={
|
|
|
- this.onSort(
|
|
|
- this.onSearch(dataConnect.list, dataConnect.filterLabel)
|
|
|
- )
|
|
|
- }
|
|
|
- size='small'
|
|
|
- scroll={{x: false, y: true}}
|
|
|
- pagination={false}
|
|
|
- onRow={(record) => {
|
|
|
- return {
|
|
|
- onClick: () => {this.setState({ selectedRecord: record})}
|
|
|
- }
|
|
|
- }}
|
|
|
- />
|
|
|
- {visibleDeleteBox && <DeleteBox
|
|
|
- visibleBox={visibleDeleteBox}
|
|
|
- text={<div><span>确定要删除数据连接【{selectedRecord.name}】吗?</span></div>}
|
|
|
- hideBox={() => {
|
|
|
- this.setState({
|
|
|
- visibleDeleteBox: false
|
|
|
- })
|
|
|
- }}
|
|
|
- okHandler={() =>{
|
|
|
- dispatch({ type: 'dataConnect/remoteDelete', code: selectedRecord.code })
|
|
|
- }}
|
|
|
- />}
|
|
|
- <DataConnectBox />
|
|
|
+ <div className='body'>
|
|
|
+ { this.generateCard() }
|
|
|
+ </div>
|
|
|
</Card>
|
|
|
</Content>
|
|
|
+ {visibleDeleteBox && <DeleteBox
|
|
|
+ visibleBox={visibleDeleteBox}
|
|
|
+ text={<div><span>确定要删除数据连接【{selected.name}】吗?</span></div>}
|
|
|
+ hideBox={() => {
|
|
|
+ this.setState({
|
|
|
+ visibleDeleteBox: false
|
|
|
+ })
|
|
|
+ }}
|
|
|
+ okHandler={() =>{
|
|
|
+ dispatch({ type: 'dataConnect/remoteDelete', code: selected.code })
|
|
|
+ }}
|
|
|
+ />}
|
|
|
+ <DataConnectBox />
|
|
|
</Layout>
|
|
|
)
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
|