| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Form, Row, Col, Button, notification, Select, Tooltip } from 'antd' |
| | | import { Form, Row, Col, Button, notification, Select, Tooltip, Modal, Switch, Radio } from 'antd' |
| | | import { QuestionCircleOutlined } from '@ant-design/icons' |
| | | import Toast from 'antd-mobile/es/components/toast' |
| | | import Dialog from 'antd-mobile/es/components/dialog' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import { checkSQL, getSearchFields } from '@/utils/utils-custom.js' |
| | | import CodeMirror from '@/templates/zshare/codemirror' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | | |
| | | class CustomForm extends Component { |
| | | static propTpyes = { |
| | | type: PropTypes.string, // 组件类型 |
| | | defaultsql: PropTypes.string, // 默认sql |
| | | setting: PropTypes.object, // 设置 |
| | | searches: PropTypes.array, // 搜索条件 |
| | | systemScripts: PropTypes.array, // 系统脚本 |
| | | scriptSubmit: PropTypes.func, // 脚本验证后提交 |
| | | scriptsChange: PropTypes.func // 脚本验证 |
| | | scriptsChange: PropTypes.func, |
| | | addProcess: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | skip: false, |
| | | editItem: null, |
| | | loading: false, |
| | | usefulFields: '' |
| | |
| | | UNSAFE_componentWillMount() { |
| | | const { searches } = this.props |
| | | |
| | | let _usefulFields = [] |
| | | searches.forEach(item => { |
| | | if (!item.field) return |
| | | |
| | | if (item.type === 'group') { |
| | | _usefulFields.push(item.field) |
| | | _usefulFields.push(item.datefield) |
| | | _usefulFields.push(item.datefield + '1') |
| | | } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { |
| | | _usefulFields.push(item.field) |
| | | _usefulFields.push(item.field + '1') |
| | | } else if (item.type === 'date' && _usefulFields.includes(item.field)) { |
| | | _usefulFields.push(item.field + '1') |
| | | } else { |
| | | _usefulFields.push(item.field) |
| | | } |
| | | }) |
| | | |
| | | this.setState({ |
| | | usefulFields: _usefulFields.join(', ') |
| | | usefulFields: getSearchFields(searches) |
| | | }) |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps (nextProps) { |
| | | if (!is(fromJS(this.props.searches), fromJS(nextProps.searches))) { |
| | | |
| | | let _usefulFields = [] |
| | | nextProps.searches.forEach(item => { |
| | | if (!item.field) return |
| | | |
| | | if (item.type === 'group') { |
| | | _usefulFields.push(item.field) |
| | | _usefulFields.push(item.datefield) |
| | | _usefulFields.push(item.datefield + '1') |
| | | } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) { |
| | | _usefulFields.push(item.field) |
| | | _usefulFields.push(item.field + '1') |
| | | } else if (item.type === 'date' && _usefulFields.includes(item.field)) { |
| | | _usefulFields.push(item.field + '1') |
| | | } else { |
| | | _usefulFields.push(item.field) |
| | | } |
| | | }) |
| | | |
| | | this.setState({ |
| | | usefulFields: _usefulFields.join(', ') |
| | | usefulFields: getSearchFields(nextProps.searches) |
| | | }) |
| | | } |
| | | } |
| | |
| | | }) |
| | | |
| | | this.props.form.setFieldsValue({ |
| | | sql: record.sql |
| | | sql: record.sql, |
| | | position: record.position || 'front' |
| | | }) |
| | | } |
| | | |
| | |
| | | editItem: null |
| | | }) |
| | | this.props.form.setFieldsValue({ |
| | | sql: ' ' |
| | | sql: ' ', |
| | | position: 'front' |
| | | }) |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | const { skip } = this.state |
| | | // 表单提交时检查输入值是否正确 |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | if (/^[\s\n]+$/.test(values.sql)) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请输入sql!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | values.uuid = this.state.editItem ? this.state.editItem.uuid : '' |
| | | |
| | | let _quot = values.sql.match(/'{1}/g) |
| | | let _lparen = values.sql.match(/\({1}/g) |
| | | let _rparen = values.sql.match(/\){1}/g) |
| | | let pass = checkSQL(values.sql, 'customscript') |
| | | |
| | | _quot = _quot ? _quot.length : 0 |
| | | _lparen = _lparen ? _lparen.length : 0 |
| | | _rparen = _rparen ? _rparen.length : 0 |
| | | if (!pass) return |
| | | |
| | | if (_quot % 2 !== 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: 'sql中\'必须成对出现', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } else if (_lparen !== _rparen) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: 'sql中()必须成对出现', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } else if (/--/ig.test(values.sql)) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '自定义sql语句中,不可出现字符 -- ,注释请用 /*内容*/', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let error = Utils.verifySql(values.sql, 'customscript') |
| | | |
| | | if (error) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: 'sql中不可使用' + error, |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | this.setState({loading: true}) |
| | | this.props.scriptsChange(values).then(() => { |
| | | if (skip) { |
| | | this.setState({ |
| | | editItem: null, |
| | | loading: false |
| | | skip: false |
| | | }) |
| | | |
| | | MKEmitter.emit('editLineId', values.uuid) |
| | | if (values.uuid) { |
| | | MKEmitter.emit('editLineId', values.uuid) |
| | | } |
| | | |
| | | this.props.form.setFieldsValue({ |
| | | sql: ' ' |
| | | }) |
| | | this.props.scriptSubmit(values) |
| | | }, () => { |
| | | this.setState({ |
| | | loading: false |
| | | } else { |
| | | this.setState({loading: true}) |
| | | this.props.scriptsChange(values).then(() => { |
| | | this.setState({ |
| | | editItem: null, |
| | | loading: false |
| | | }) |
| | | |
| | | if (values.uuid) { |
| | | MKEmitter.emit('editLineId', values.uuid) |
| | | } |
| | | |
| | | this.props.form.setFieldsValue({ |
| | | sql: ' ' |
| | | }) |
| | | this.props.scriptSubmit(values) |
| | | }, () => { |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | selectScript = (value, option) => { |
| | | const { setting } = this.props |
| | | |
| | | let _sql = this.props.form.getFieldValue('sql') |
| | | if (_sql === ' ') { |
| | | _sql = '' |
| | |
| | | |
| | | if (value === 'defaultsql') { |
| | | value = this.props.defaultsql |
| | | } else if (value === 'flowstart') { |
| | | value = `/* select a.*, w.remark as remark_w, w.statusname as statusname_w,w.status as status_w,w.works_flow_param,w.modifydate as modifydate_w from (select * from ${setting.tableName} where status=0 and deleted=0 $@ and createuserid=@userid@ @$) a |
| | | inner join (select * from s_my_works_flow where works_flow_code=@works_flow_code@ and status=0 and deleted=0) w on a.id=w.works_flow_id */` |
| | | this.props.addProcess() |
| | | } else if (value === 'flowcheck') { |
| | | value = `/* select a.*, w.remark as remark_w, w.statusname as statusname_w,w.status as status_w,w.works_flow_param,w.modifydate as modifydate_w |
| | | from (select * from ${setting.tableName} where status=0 and deleted=0 ) a |
| | | inner join (select * from s_my_works_flow where works_flow_code=@works_flow_code@ and status>0 and status<888 and deleted=0) w |
| | | on a.id=w.works_flow_id |
| | | $@ inner join (select works_flow_id from s_my_works_flow_role where userid=@userid@ and works_flow_code=@works_flow_code@ and deleted=0 ) r |
| | | on r.works_flow_id=w.works_flow_id @$ */` |
| | | this.props.addProcess() |
| | | } |
| | | |
| | | _sql = _sql.replace(/\s{6}$/, '') |
| | |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { systemScripts, setting } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { usefulFields } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | showError = (type) => { |
| | | let appType = sessionStorage.getItem('appType') |
| | | |
| | | if (type === 'S') { |
| | | if (appType === 'mob') { |
| | | Toast.show({ icon: 'success', content: '执行成功!', duration: 3000 }) |
| | | } else { |
| | | notification.success({ |
| | | top: 92, |
| | | message: '执行成功!', |
| | | duration: 2 |
| | | }) |
| | | } |
| | | |
| | | } else if (type === 'Y') { |
| | | if (appType === 'mob') { |
| | | Dialog.alert({content: '执行成功!', confirmText: '知道了'}) |
| | | } else { |
| | | Modal.success({ |
| | | title: '执行成功!' |
| | | }) |
| | | } |
| | | } else if (type === 'N') { |
| | | if (appType === 'mob') { |
| | | Dialog.alert({content: '执行失败!', confirmText: '知道了'}) |
| | | } else { |
| | | Modal.error({ |
| | | title: '执行失败!' |
| | | }) |
| | | } |
| | | } else { |
| | | if (appType === 'mob') { |
| | | Toast.show({ icon: 'fail', content: '执行失败!', duration: 3000 }) |
| | | } else { |
| | | notification.error({ |
| | | top: 92, |
| | | message: '执行失败!', |
| | | duration: 10 |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { systemScripts, setting, type } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { usefulFields, skip } = this.state |
| | | |
| | | let urlFields = window.GLOB.urlFields ? window.GLOB.urlFields.join(', ') : '' |
| | | |
| | | return ( |
| | | <Form {...formItemLayout} className="modal-menu-setting-script"> |
| | | <Form className="modal-source-setting-script"> |
| | | <Row gutter={24}> |
| | | {setting.tableName ? <Col span={8}> |
| | | <Form.Item label={'表名'} style={{whiteSpace: 'nowrap', margin: 0}}> |
| | | {setting.tableName ? <Col span={6}> |
| | | <Form.Item label="表名" style={{whiteSpace: 'nowrap', margin: 0}}> |
| | | {setting.tableName} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | <Form.Item label={'报错字段'} style={{margin: 0}}> |
| | | <Col span={18}> |
| | | <Form.Item label="报错字段" style={{margin: 0}}> |
| | | ErrorCode, retmsg |
| | | <span style={{marginLeft: 25}}> |
| | | 成功: |
| | | <span className="error-val" onClick={() => {this.showError('S')}}> S </span>、 |
| | | <span className="error-val" onClick={() => {this.showError('Y')}}> Y </span>、 |
| | | -1(不提示) |
| | | </span> |
| | | <span style={{marginLeft: 20}}> |
| | | 失败: |
| | | <span className="error-val" onClick={() => {this.showError('N')}}> N </span>、 |
| | | -2(不提示)、 |
| | | <span className="error-val" onClick={() => {this.showError('')}}> 其他 </span> |
| | | </span> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24} className="sqlfield"> |
| | | <Form.Item label={'可用字段'}> |
| | | <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'公共值,请按照@xxx@格式使用。'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id</span></Tooltip>, |
| | | <Col span={24}> |
| | | <Form.Item label="可用字段" className="field-able"> |
| | | <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'公共值,请按照@xxx@格式使用。'}><span style={{color: '#1890ff'}}>BID, LoginUID, SessionUid, UserID, Appkey, time_id, typename</span></Tooltip>, |
| | | <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'系统变量,系统会定义变量并赋值。'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>, |
| | | <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'排序、分页以及搜索条件变量,请按照@xxx@格式使用。'}>orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}</Tooltip> |
| | | <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'排序、分页以及搜索条件变量,请按照@xxx@格式使用。使用@pageSize@或@orderBy@代表自定义分页,总数请以mk_total返回。'}>orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}{type === 'calendar' ? ', mk_year' : ''}</Tooltip> |
| | | <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'url变量,请按照@xxx@格式使用。'}>{urlFields ? ', ' : ''}<span style={{color: '#13c2c2'}}>{urlFields}</span></Tooltip> |
| | | {window.GLOB.process ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'工作流变量,请按照@xxx@格式使用。'}>, <span style={{color: 'purple'}}>works_flow_code</span></Tooltip> : null} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={10} style={{width: '43%'}}> |
| | | <Form.Item label={'快捷添加'} labelCol={{xs: { span: 24 }, sm: { span: 6 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 18 }} } style={{marginBottom: 0}}> |
| | | <Col span={8} style={{whiteSpace: 'nowrap'}}> |
| | | <Form.Item style={{marginBottom: 0}} label={ |
| | | <Tooltip placement="bottomLeft" title={'自定义脚本与数据源位置关系。'}> |
| | | <QuestionCircleOutlined className="mk-form-tip" /> |
| | | 执行位置 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('position', { |
| | | initialValue: 'front' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="front">前置</Radio> |
| | | <Radio value="back">后置</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={8}> |
| | | <Form.Item label="快捷添加" labelCol={{xs: { span: 24 }, sm: { span: 6 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 18 }} } style={{marginBottom: 0}}> |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | onSelect={this.selectScript} |
| | | > |
| | | <Select.Option style={{whiteSpace: 'normal'}} key="default" value="defaultsql">默认sql</Select.Option> |
| | | {window.GLOB.process ? <Select.Option style={{whiteSpace: 'normal'}} key="flowstart" value="flowstart">默认sql(工作流-发起)</Select.Option> : null} |
| | | {window.GLOB.process ? <Select.Option style={{whiteSpace: 'normal'}} key="flowcheck" value="flowcheck">默认sql(工作流-审核)</Select.Option> : null} |
| | | <Select.Option key="debugger" value={`z_debug: select @ErrorCode='E',@retmsg='测试断点' goto aaa`}> |
| | | 测试断点 |
| | | </Select.Option> |
| | |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6} className="add"> |
| | | <Col span={5} style={{whiteSpace: 'nowrap'}}> |
| | | <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginTop: 5, marginBottom: 15, marginLeft: 30}}> |
| | | 保存 |
| | | </Button> |
| | | <Button onClick={this.handleCancel} style={{marginTop: 5, marginBottom: 15, marginLeft: 10}}> |
| | | 取消 |
| | | </Button> |
| | | </Col> |
| | | <Col span={3} style={{paddingTop: '15px', fontSize: '12px', whiteSpace: 'nowrap'}}> |
| | | 强制保存: |
| | | <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/> |
| | | </Col> |
| | | <Col span={24} className="sql"> |
| | | <Form.Item label="sql"> |
| | |
| | | message: '请输入sql!' |
| | | } |
| | | ] |
| | | })(<CodeMirror />)} |
| | | })(<CodeMirror/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |