datasource.jsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import React from 'react'
  2. import { routerRedux } from 'dva/router'
  3. import { Tabs, Input, Button, Table, Icon, Tag, Menu, Dropdown, Divider } from 'antd'
  4. const { TabPane } = Tabs
  5. const { Search } = Input
  6. import { connect } from 'dva'
  7. import { Link } from 'react-router-dom'
  8. import DataConnectBox from './dataConnectBox'
  9. import dataSource from '../../models/dataSource'
  10. import dataConnect from '../../models/dataConnect'
  11. import './dataSource.less'
  12. class DataSource extends React.Component {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. loading: false,
  17. activeTab: 'dataSource',
  18. operation: 'create', // 打开数据编辑界面的类型
  19. visibleCreateBox: false,
  20. visibleBox: false, // 数据编辑界面显示标识
  21. selectedDataSourceCode: -1, // 当前选中的dataSource的code
  22. selectedDataConnectCode: -1, // 当前选中的dataConnect的code
  23. filterDropdownVisible: false,
  24. search: {} // 搜索条件
  25. }
  26. };
  27. componentDidMount() {
  28. this.setScrollTableHeight();
  29. }
  30. /**
  31. * 根据视图设置表格高度以呈现滚动条
  32. */
  33. setScrollTableHeight() {
  34. const mainContent = document.getElementsByClassName('main-content')[0];
  35. const tabBar = mainContent.getElementsByClassName('ant-tabs-bar')[0];
  36. const tableHeader = mainContent.getElementsByClassName('ant-table-header')[0];
  37. const tableBody = mainContent.getElementsByClassName('ant-table-body')[0];
  38. tableBody.style.maxHeight=`${mainContent.offsetHeight - tabBar.offsetHeight - tableHeader.offsetHeight - 38}px`;
  39. }
  40. showCreateBox = () => {
  41. this.setState({
  42. visibleCreateBox: true
  43. });
  44. }
  45. showDataConnectBox = (o) => {
  46. this.setState({
  47. operation: o,
  48. visibleBox: true
  49. });
  50. }
  51. hideDataConnectBox = () => {
  52. this.setState({
  53. visibleBox: false
  54. });
  55. }
  56. onInputChange = (name, value) => {
  57. const { search } = this.state;
  58. let newSearch = Object.assign({}, search );
  59. newSearch[name] = value;
  60. this.setState({ search: newSearch });
  61. }
  62. onSearch = () => {
  63. const { search } = this.state;
  64. const reg = new RegExp(search.name, 'gi');
  65. this.setState({
  66. filterDropdownVisible: false
  67. });
  68. }
  69. render() {
  70. const { dataSource, dataConnect, dispatch } = this.props;
  71. const { loading, activeTab, search, visibleBox, operation, selectedDataSourceCode, selectedDataConnectCode } = this.state;
  72. const moreOperatingMenu = (
  73. <Menu className='operationmenu'>
  74. <Menu.Item
  75. onClick={(e) => {
  76. let selectedModel = dataSource.list.find((i) => { return i.code == selectedDataSourceCode })
  77. dispatch({ type: 'dataSource/setNewModel', model: selectedModel });
  78. dispatch({type: 'main/redirect', path: {pathname: '/datasource/'+ selectedModel.type +'/' + selectedModel.code}});
  79. }}>
  80. <Icon type="info-circle-o" />属性设置
  81. </Menu.Item>
  82. <Menu.Item>
  83. {/* <Link to='/dataSource/1111'> */}
  84. <Icon type="table" />数据列设置
  85. {/* </Link> */}
  86. </Menu.Item>
  87. <Menu.Item><Icon type="search" />预览数据</Menu.Item>
  88. <Menu.Item><Icon type="lock" />权限设置</Menu.Item>
  89. <Menu.Divider />
  90. <Menu.Item
  91. onClick={(e) => {
  92. let selectedModel = dataSource.list.find((i) => { return i.code == selectedDataSourceCode })
  93. dispatch({ type: 'dataSource/delete', model: selectedModel });
  94. }}
  95. ><Icon type="delete" />删除</Menu.Item>
  96. </Menu>
  97. );
  98. const dataSourceColumns = [{
  99. title: '名称',
  100. dataIndex: 'name',
  101. key: 'name',
  102. width: 100,
  103. sorter: (a, b) => a.name.localeCompare(b.name, 'zh-Hans-CN', {sensitivity: 'accent'}),
  104. filterDropdown: (
  105. <div className="custom-filter-dropdown">
  106. <Input
  107. ref={ele => this.searchInput = ele}
  108. placeholder="Search name"
  109. value={this.state.search.name}
  110. onChange={(e) => { this.onInputChange('name', e.target.value) }}
  111. onPressEnter={this.onSearch}
  112. />
  113. <Button type="primary" onClick={this.onSearch}>Search</Button>
  114. </div>
  115. ),
  116. className: `column-${this.state.search.name?'filtered':'nofiltered'}`,
  117. filterIcon: <Icon type="smile-o"/>,
  118. filterDropdownVisible: this.state.filterDropdownVisible,
  119. onFilterDropdownVisibleChange: (visible) => {
  120. this.setState({
  121. filterDropdownVisible: visible,
  122. }, () => this.searchInput && this.searchInput.focus());
  123. },
  124. render: (text, record) => {
  125. return <div className='datasource-name'>
  126. <div className={`datasource-type type-${record.type.key}`}></div>
  127. <div>{text}</div>
  128. </div>
  129. }
  130. }, {
  131. title: '标签',
  132. dataIndex: 'tags',
  133. key: 'tag',
  134. width: 150,
  135. render: (text, record) => {
  136. text=text.join(',');
  137. let tags = text ? text.split(',').map((t, i) => {
  138. return <Tag className='datasource-tag' key={i}>{t}</Tag>
  139. }) : '';
  140. return (<div>
  141. {tags}
  142. </div>)
  143. }
  144. }, {
  145. title: '说明',
  146. dataIndex: 'description',
  147. key: 'description',
  148. width: 200
  149. }, {
  150. title: '创建人',
  151. dataIndex: 'creator',
  152. key: 'creator',
  153. width: 100
  154. }, {
  155. title: '创建时间',
  156. dataIndex: 'createTime',
  157. key: 'createTime',
  158. render: (text, record) => text.format('yyyy-MM-dd hh:mm:ss'),
  159. width: 100
  160. }, {
  161. title: '图表',
  162. dataIndex: 'chartSum',
  163. key: 'chartSum',
  164. width: 80
  165. }, {
  166. title: '操作',
  167. key: 'action',
  168. render: (text, record, index) => (
  169. <Dropdown code={record.code} overlay={moreOperatingMenu} trigger={['click']} >
  170. <Icon type="setting" />
  171. </Dropdown>
  172. ),
  173. width: 80
  174. }];
  175. const dataConnectColumns = [{
  176. title: '名称',
  177. dataIndex: 'name',
  178. key: 'name',
  179. width: 100,
  180. render: (text, record) => {
  181. return <div className='datasource-name'>
  182. <div className={`datasource-type type-${record.type.key}`}></div>
  183. <div>{text}</div>
  184. </div>
  185. }
  186. }, {
  187. title: '说明',
  188. dataIndex: 'description',
  189. key: 'description',
  190. width: 100
  191. }, {
  192. title: '操作',
  193. key: 'action',
  194. width: 300,
  195. render: (text, record) => (
  196. <div className='action-col'>
  197. <div className='operation' onClick={() => {
  198. let selectedModel = dataConnect.list.find((i) => { return i.code == record.code });
  199. dispatch({ type: 'dataConnect/setNewModel', model: selectedModel });
  200. this.showDataConnectBox('modify')
  201. }}><Icon type="info-circle-o"/>属性</div>
  202. <div className='operation'><Divider type="vertical" /></div>
  203. <div className='operation'><Icon type="plus"/>创建数据源</div>
  204. <div className='operation'><Divider type="vertical" /></div>
  205. <div className='operation' onClick={() => {
  206. let selectedModel = dataConnect.list.find((i) => { return i.code == record.code });
  207. dispatch({ type: 'dataConnect/delete', model: selectedModel });
  208. }}><Icon type="delete"/>删除</div>
  209. </div>
  210. ),
  211. width: 80
  212. }];
  213. return (
  214. <Tabs
  215. className='datasource-tabs'
  216. type="card"
  217. defaultActiveKey="1"
  218. tabBarExtraContent={
  219. <div className='datasource-tabs-tools'>
  220. <Button onClick={()=>{
  221. dispatch({type: activeTab=='dataConnect'?'dataConnect/testData':'dataSource/testData'});
  222. }}>测试数据</Button>
  223. <Search
  224. placeholder="请输入关键字"
  225. onSearch={value => console.log(value)}
  226. />
  227. <Dropdown overlay={(
  228. <Menu onClick={(item, key, keyPath) => {
  229. const type = item.key;
  230. dispatch({ type: 'dataSource/resetNewModel' });
  231. dispatch({ type: 'dataSource/setNewModelField', name: 'type', value: type });
  232. dispatch({type: 'main/redirect', path: {pathname: '/datasource/'+ type +'/create'}});
  233. }}>
  234. <Menu.Item key='database'>数据库</Menu.Item>
  235. <Menu.Item key='file'>文件</Menu.Item>
  236. </Menu>
  237. )} trigger={['click']}>
  238. <Button style={{ display: activeTab=='dataConnect'?'none':'inline-block' }}>
  239. <Icon type="plus" />添加数据源
  240. </Button>
  241. </Dropdown>
  242. <Button style={{ display: activeTab=='dataConnect'?'inline-block':'none' }} onClick={(e) => {
  243. this.showDataConnectBox('create')
  244. }}>
  245. <Icon type="plus" />添加数据连接
  246. </Button>
  247. <DataConnectBox operation={operation} visibleBox={visibleBox} hideBox={this.hideDataConnectBox} />
  248. </div>
  249. }
  250. onChange={(key) => {
  251. this.setState({
  252. activeTab: key == '1' ? 'dataSource' : 'dataConnect'
  253. });
  254. }}
  255. >
  256. <TabPane className='datasource-tab' tab="数据源" key="1" >
  257. <Table
  258. className='datasource-table datasource-table'
  259. columns={dataSourceColumns}
  260. dataSource={dataSource.list}
  261. loading={loading}
  262. size='small'
  263. scroll={{x: false, y: 471}}
  264. pagination={false}
  265. onRow={(record) => {
  266. return {
  267. onClick: () => {this.setState({ selectedDataSourceCode: record.code})}
  268. }
  269. }}
  270. />
  271. </TabPane>
  272. <TabPane className='dataconnect-tab dataconnect' tab="数据库连接" key="2" >
  273. <Table
  274. className='dataconnect-table dataconnect-table'
  275. columns={dataConnectColumns}
  276. dataSource={dataConnect.list}
  277. loading={loading}
  278. size='small'
  279. scroll={{x: false, y: 471}}
  280. pagination={false}
  281. />
  282. </TabPane>
  283. </Tabs>
  284. )
  285. }
  286. }
  287. function mapStateToProps({present: {dataSource, dataConnect}}) {
  288. return { dataSource, dataConnect }
  289. }
  290. export default connect(mapStateToProps)(DataSource)