import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Modal, Button, Popconfirm, message, notification } from 'antd'
|
import { StopTwoTone, DatabaseOutlined, CopyOutlined, CheckCircleTwoTone, DeleteOutlined, PlusOutlined, SwapOutlined } from '@ant-design/icons'
|
|
import Utils from '@/utils/utils.js'
|
import asyncComponent from '@/utils/asyncComponent'
|
import MKEmitter from '@/utils/events.js'
|
import './index.scss'
|
|
const DataSource = asyncComponent(() => import('@/menu/datasource'))
|
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
|
|
class InterfaceController extends Component {
|
static propTpyes = {
|
config: PropTypes.object, // 页面配置
|
updateConfig: PropTypes.func // 更新
|
}
|
|
state = {
|
visible: false,
|
interfaces: [],
|
columns: [
|
{
|
title: '名称',
|
dataIndex: 'name',
|
width: '50%'
|
},
|
{
|
title: '状态',
|
dataIndex: 'status',
|
width: '20%',
|
render: (text, record) => record.status !== 'true' ?
|
(
|
<div>
|
禁用
|
<StopTwoTone style={{marginLeft: '5px'}} twoToneColor="#ff4d4f" />
|
</div>
|
) :
|
(
|
<div>
|
启用
|
<CheckCircleTwoTone style={{marginLeft: '5px'}} twoToneColor="#52c41a" />
|
</div>
|
)
|
},
|
{
|
title: '操作',
|
align: 'center',
|
width: '30%',
|
dataIndex: 'operation',
|
render: (text, record) =>
|
(<div style={{textAlign: 'center'}}>
|
<DataSource config={record} updateConfig={this.update}/>
|
<span onClick={() => this.handleStatus(record)} style={{color: '#8E44AD', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><SwapOutlined /></span>
|
<span onClick={() => this.copy(record)} style={{color: '#26C281', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><CopyOutlined /></span>
|
<Popconfirm
|
overlayClassName="popover-confirm"
|
title="确定删除?"
|
onConfirm={() => this.deleteScript(record)
|
}>
|
<span style={{color: '#ff4d4f', cursor: 'pointer', fontSize: '16px'}}><DeleteOutlined /></span>
|
</Popconfirm>
|
</div>)
|
}
|
]
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
copy = (item) => {
|
let msg = { key: 'interface', type: 'line', data: item }
|
|
let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
|
if (srcid) {
|
msg.$srcId = srcid
|
}
|
|
try {
|
msg = window.btoa(window.encodeURIComponent(JSON.stringify(msg)))
|
} catch (e) {
|
console.warn('Stringify Failure')
|
msg = ''
|
}
|
|
if (msg) {
|
let oInput = document.createElement('input')
|
oInput.value = msg
|
document.body.appendChild(oInput)
|
oInput.select()
|
document.execCommand('Copy')
|
document.body.removeChild(oInput)
|
message.success('复制成功。')
|
}
|
}
|
|
trigger = () => {
|
const { config } = this.props
|
let interfaces = config.interfaces ? fromJS(config.interfaces).toJS() : []
|
|
this.setState({
|
visible: true,
|
interfaces
|
})
|
}
|
|
handleStatus = (record) => {
|
const { config } = this.props
|
|
if (record.status === 'false') {
|
if (record.setting.interType === 'system' && record.setting.execute !== 'false' && !record.setting.dataresource) {
|
notification.warning({
|
top: 92,
|
message: '未设置数据源,不可启用!',
|
duration: 5
|
})
|
return
|
} else if (!record.setting.primaryKey) {
|
notification.warning({
|
top: 92,
|
message: '未设置主键,不可启用!',
|
duration: 5
|
})
|
return
|
} else if (record.columns.length === 0) {
|
notification.warning({
|
top: 92,
|
message: '未添加字段集,不可启用!',
|
duration: 5
|
})
|
return
|
}
|
}
|
|
record = fromJS(record).toJS()
|
record.status = record.status === 'false' ? 'true' : 'false'
|
|
let interfaces = this.state.interfaces.map(item => {
|
if (item.uuid !== record.uuid) {
|
return item
|
}
|
return record
|
})
|
|
this.setState({ interfaces })
|
this.props.updateConfig({...config, interfaces})
|
}
|
|
deleteScript = (record) => {
|
const { config } = this.props
|
let interfaces = this.state.interfaces.filter(item => item.uuid !== record.uuid)
|
|
this.setState({ interfaces })
|
this.props.updateConfig({...config, interfaces})
|
}
|
|
changeScripts = (interfaces) => {
|
const { config } = this.props
|
|
interfaces = interfaces.map(item => {
|
item.$tables = this.getTables(item)
|
return item
|
})
|
|
this.setState({ interfaces })
|
this.props.updateConfig({...config, interfaces})
|
}
|
|
getTables = (record) => {
|
let tables = []
|
let cuts = []
|
let cutreg = /(from|update|insert\s+into)\s+(@db@)?[a-z_]+/ig
|
let trimreg = /(from|update|insert\s+into)\s+(@db@)?/ig
|
|
if (record.setting.interType === 'system') {
|
if (record.setting.execute !== 'false') {
|
let tbs = record.setting.dataresource.match(cutreg)
|
tbs && cuts.push(...tbs)
|
}
|
record.scripts && record.scripts.forEach(script => {
|
if (script.status === 'false') return
|
let tbs = script.sql.match(cutreg)
|
tbs && cuts.push(...tbs)
|
})
|
} else {
|
let tb = record.setting.tableName.replace(/@db@|\s+/ig, '')
|
if (/[a-z_]+/ig.test(tb)) {
|
tables.push(tb)
|
}
|
}
|
|
cuts = cuts.map(item => item.replace(trimreg, ''))
|
tables.push(...cuts)
|
tables = tables.filter(Boolean)
|
tables = Array.from(new Set(tables))
|
|
return tables
|
}
|
|
update = (record) => {
|
const { config } = this.props
|
|
if (record.setting.primaryKey && record.columns.length > 0) {
|
record.status = 'true'
|
} else if (record.columns.length === 0) {
|
record.status = 'false'
|
}
|
record.name = record.setting.name
|
record.$tables = this.getTables(record)
|
|
let interfaces = this.state.interfaces.map(item => {
|
if (item.uuid !== record.uuid) {
|
return item
|
}
|
return record
|
})
|
|
this.setState({ interfaces })
|
this.props.updateConfig({...config, interfaces})
|
|
setTimeout(() => {
|
MKEmitter.emit('mkUpdateInter', record, {delay: 0})
|
}, 10)
|
}
|
|
addInterface = () => {
|
const { config } = this.props
|
let interfaces = fromJS(this.state.interfaces).toJS()
|
|
interfaces.push({
|
uuid: Utils.getuuid(),
|
name: '数据源' + (interfaces.length + 1),
|
status: 'false',
|
format: 'array',
|
type: 'interface',
|
pageable: false,
|
setting: { interType: 'system', name: '数据源' + (interfaces.length + 1), status: 'false' },
|
columns: [],
|
scripts: [],
|
})
|
|
this.setState({
|
interfaces
|
})
|
this.props.updateConfig({...config, interfaces})
|
}
|
|
render() {
|
const { visible, columns, interfaces } = this.state
|
|
return (
|
<div className="mk-sys-interface" style={{display: 'inline-block'}}>
|
<Button className="mk-border-green" onClick={this.trigger}><DatabaseOutlined /> 公共数据源</Button>
|
<Modal
|
title="公共数据源"
|
wrapClassName="interface-controller-modal"
|
visible={visible}
|
width={800}
|
maskClosable={false}
|
onCancel={() => {this.setState({visible: false})}}
|
footer={[
|
<Button key="colse" onClick={() => {this.setState({visible: false})}}>
|
关闭
|
</Button>
|
]}
|
destroyOnClose
|
>
|
<PlusOutlined key="add-interface" onClick={this.addInterface}/>
|
<EditTable key="manage-interface" actions={['copy']} type="interface" data={interfaces} columns={columns} onChange={this.changeScripts}/>
|
</Modal>
|
</div>
|
)
|
}
|
}
|
|
export default InterfaceController
|