| | |
| | | { |
| | | "appId": "202108312122504607B107A83F55B40C98CCF", |
| | | "appkey": "20210831212235413F287EC3BF489424496C8", |
| | | "appId": "201912040924165801464FF1788654BC5AC73", |
| | | "appkey": "20191106103859640976D6E924E464D029CF0", |
| | | "mainSystemApi": "http://sso.mk9h.cn/cloud/webapi/dostars", |
| | | "systemType": "", |
| | | "externalDatabase": "false", |
| | | "lineColor": "", |
| | | "filter": "false", |
| | | "defaultApp": "mkindustry", |
| | | "defaultApp": "mk", |
| | | "defaultLang": "zh-CN", |
| | | "WXAppID": "", |
| | | "debugger": false, |
| | |
| | | "probation": "", |
| | | "keepPassword": "true", |
| | | "platforms": ["H5", "wechat", "android", "ios"], |
| | | "host": "http://demo.mk9h.cn", |
| | | "service": "erp_new/" |
| | | "host": "http://qingqiumarket.cn", |
| | | "service": "MKWMS/" |
| | | } |
| | |
| | | // ) |
| | | } else if (card.eleType === 'picture') { |
| | | let _imagestyle = {} |
| | | let url = card.url !== '@icon@' ? card.url : sessionStorage.getItem('CloudAvatar') |
| | | |
| | | if (card.url) { |
| | | _imagestyle = {backgroundImage: `url('${card.url}')`} |
| | | if (url) { |
| | | _imagestyle = {backgroundImage: `url('${url}')`} |
| | | } else { |
| | | let index = card.uuid.match(/\d{1}/g) |
| | | index = index.slice(-1)[0] % 5 |
| | |
| | | min: 0, |
| | | label: '内容', |
| | | initVal: card.value || '', |
| | | tooltip: '文本类型,会替换内容中的@username@、@fullName@、@login_city@。', |
| | | tooltip: '文本类型,会替换内容中的@username@、@fullName@、@login_city@、@appname@。', |
| | | required: true |
| | | }, |
| | | { |
| | |
| | | |
| | | getFields() { |
| | | const { getFieldDecorator } = this.props.form |
| | | const { interType } = this.state |
| | | const fields = [] |
| | | |
| | | this.state.formlist.forEach((item, index) => { |
| | |
| | | max: formRule.func.max, |
| | | message: formRule.func.maxMessage |
| | | }] |
| | | } else if (item.key === 'output') { |
| | | if (interType === 'system') { |
| | | _rules = [{ |
| | | pattern: /^@[0-9a-zA-Z_]*$/, |
| | | message: '变量以@符开头,可使用字母、数字以及_' |
| | | }, { |
| | | max: 100, |
| | | message: '最多100个字符。' |
| | | }] |
| | | } else { |
| | | _rules = [{ |
| | | pattern: /^[0-9a-zA-Z_]*$/, |
| | | message: '字段可使用字母、数字以及_' |
| | | }, { |
| | | max: 100, |
| | | message: '最多100个字符。' |
| | | }] |
| | | } |
| | | } else { |
| | | _rules = [{ |
| | | max: formRule.input.max, |
| | |
| | | type: 'text', |
| | | key: 'output', |
| | | label: '返回值', |
| | | tooltip: '执行成功后的返回值。例如:@id', |
| | | tooltip: '执行成功后的返回值。系统函数可指定返回的变量(以@符开头,如@id);自定义函数可指定返回字段(如id)。', |
| | | initVal: card.output || '', |
| | | required: false |
| | | }, |
| | |
| | | { pattern: formRule.func.pattern, message: formRule.func.message }, |
| | | { max: formRule.func.max, message: formRule.func.maxMessage } |
| | | ) |
| | | } else if (item.key === 'output') { |
| | | if (this.record.intertype === 'system') { |
| | | rules = [{ |
| | | pattern: /^@[0-9a-zA-Z_]*$/, |
| | | message: '变量以@符开头,可使用字母、数字以及_' |
| | | }, { |
| | | max: 100, |
| | | message: '最多100个字符。' |
| | | }] |
| | | } else { |
| | | rules = [{ |
| | | pattern: /^[0-9a-zA-Z_]*$/, |
| | | message: '字段可使用字母、数字以及_' |
| | | }, { |
| | | max: 100, |
| | | message: '最多100个字符。' |
| | | }] |
| | | } |
| | | } else { |
| | | rules.push({ max: formRule.input.max, message: formRule.input.message }) |
| | | } |
| | |
| | | |
| | | fields.push( |
| | | <Col span={span} key={index}> |
| | | <Form.Item className={className} help={item.help || null} label={item.tooltip ? |
| | | <Form.Item className={className} help={item.help} label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <QuestionCircleOutlined className="mk-form-tip" /> |
| | | {item.label} |
| | |
| | | type: 'text', |
| | | key: 'output', |
| | | label: '返回值', |
| | | tooltip: '执行成功后的返回值。例如:@id', |
| | | tooltip: '执行成功后的返回值。系统函数可指定返回的变量(以@符开头,如@id);自定义函数可指定返回字段(如id)。', |
| | | initVal: card.output || '', |
| | | required: false, |
| | | forbid: viewType === 'popview' |
| | |
| | | const { url, visible } = this.state |
| | | const { type } = this.props |
| | | let name = url ? url.slice(url.lastIndexOf('/') + 1) : '' |
| | | // url !== '@icon@' |
| | | |
| | | return ( |
| | | <div className="mk-source-wrap"> |
| | |
| | | <Radio.Button value="upload" size="small" onClick={() => this.handleChange('upload')}>上传</Radio.Button> |
| | | <Radio.Button value="system" size="small" onClick={() => this.handleChange('system')}>系统</Radio.Button> |
| | | </Radio.Group> : null} |
| | | {url ? <div className={'mk-source-item-info' + (type !== 'video' ? ' picture' : '')}> |
| | | {type === 'video' ? <PaperClipOutlined /> : <img src={url} alt="" />} |
| | | {url && type === 'video' ? <div className="mk-source-item-info"> |
| | | <PaperClipOutlined /> |
| | | <a target="_blank" rel="noopener noreferrer" href={url}>{name}</a> |
| | | <DeleteOutlined title="删除文件" onClick={this.deleteUrl}/> |
| | | </div> : null} |
| | | {url && type !== 'video' && url !== '@icon@' ? <div className="mk-source-item-info picture"> |
| | | <img src={url} alt="" /> |
| | | <a target="_blank" rel="noopener noreferrer" href={url}>{name}</a> |
| | | <DeleteOutlined title="删除文件" onClick={this.deleteUrl}/> |
| | | </div> : null} |
| | | {url && type !== 'video' && url === '@icon@' ? <div className="mk-source-item-info avatar"> |
| | | <span className="mk-avatar">{name}</span> |
| | | <DeleteOutlined title="删除文件" onClick={this.deleteUrl}/> |
| | | </div> : null} |
| | | <Modal |
| | | visible={!!visible} |
| | | width={visible !== 'system' ? 600 : 1000} |
| | |
| | | top: 3px; |
| | | right: 0px; |
| | | padding-right: 6px; |
| | | color: rgba(0,0,0,.45); |
| | | color: #f5222d; |
| | | cursor: pointer; |
| | | display: none; |
| | | } |
| | |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | } |
| | | .mk-avatar { |
| | | color: #1890ff; |
| | | display: inline-block; |
| | | width: 100%; |
| | | padding-left: 5px; |
| | | padding-right: 14px; |
| | | overflow: hidden; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | height: 32px; |
| | | line-height: 32px; |
| | | } |
| | | } |
| | | .mk-source-item-info.picture { |
| | | display: flex; |
| | |
| | | top: 8px; |
| | | } |
| | | } |
| | | .mk-source-item-info.avatar { |
| | | display: flex; |
| | | top: 0px; |
| | | .anticon-delete { |
| | | top: 8px; |
| | | } |
| | | } |
| | | .mk-source-item-info:hover { |
| | | background-color: #e6f7ff; |
| | | .anticon-delete { |
| | |
| | | |
| | | selectScript = (value, option) => { |
| | | let _sql = this.props.form.getFieldValue('sql') |
| | | if (_sql) { |
| | | if (_sql === ' ') { |
| | | _sql = '' |
| | | } else if (_sql) { |
| | | _sql = _sql + ` |
| | | |
| | | ` |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Form, Tabs, Popconfirm, notification, Modal, Typography, Spin, message } from 'antd' |
| | | import { StopOutlined, CheckCircleOutlined, EditOutlined, SwapOutlined, DeleteOutlined, CopyOutlined } from '@ant-design/icons' |
| | | import { Form, Tabs, Popconfirm, notification, Modal, Typography, Spin, message, Button } from 'antd' |
| | | import { StopOutlined, CheckCircleOutlined, EditOutlined, SwapOutlined, DeleteOutlined, CopyOutlined, BorderOutlined } from '@ant-design/icons' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | |
| | | import CustomScriptsForm from './customscript' |
| | | import SettingForm from './settingform' |
| | | import SettingUtils from './utils' |
| | | import MinView from '@/assets/img/minview.png' |
| | | import './index.scss' |
| | | |
| | | const { TabPane } = Tabs |
| | | const { Paragraph } = Typography |
| | | |
| | | const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror')) |
| | | const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent')) |
| | | const EditTable = asyncComponent(() => import('@/templates/zshare/editTable')) |
| | | |
| | |
| | | defaultsql: '', // 默认Sql |
| | | defaultSearch: '', |
| | | systemScripts: [], |
| | | visible: false, |
| | | script: null, |
| | | scriptValue: '', |
| | | colColumns: [ |
| | | { |
| | | title: '名称', |
| | |
| | | } |
| | | |
| | | deleteScript = (record) => { |
| | | this.setState({ scripts: this.state.scripts.filter(item => item.uuid !== record.uuid) }) |
| | | const { script, scripts } = this.state |
| | | |
| | | if (script && script.uuid === record.uuid) { |
| | | this.setState({script: null}) |
| | | } |
| | | |
| | | this.setState({ scripts: scripts.filter(item => item.uuid !== record.uuid) }) |
| | | } |
| | | |
| | | handleEdit = (record) => { |
| | |
| | | } |
| | | } |
| | | |
| | | triggerConfirm = () => { |
| | | const { script, scriptValue, scripts } = this.state |
| | | let _scripts = fromJS(scripts).toJS() |
| | | |
| | | if (!scriptValue) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请输入sql!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | if (script) { |
| | | _scripts = _scripts.map(item => { |
| | | if (script.uuid === item.uuid) { |
| | | item.sql = scriptValue |
| | | } |
| | | return item |
| | | }) |
| | | } else { |
| | | let _script = { |
| | | uuid: Utils.getuuid(), |
| | | sql: scriptValue, |
| | | $index: _scripts.length + 1, |
| | | status: 'true' |
| | | } |
| | | |
| | | _scripts.push(_script) |
| | | } |
| | | |
| | | this.setState({loading: true}) |
| | | |
| | | this.sqlverify(() => {this.setState({scripts: _scripts, script: null, scriptValue: '', loading: false})}, () => {this.setState({loading: false})}, false, _scripts) |
| | | } |
| | | |
| | | updatefields = (columns) => { |
| | | this.setState({ |
| | | columns: columns |
| | |
| | | |
| | | render() { |
| | | const { config } = this.props |
| | | const { columns, setting, scripts, colColumns, scriptsColumns, activeKey, loading, searches, defaultsql } = this.state |
| | | const { columns, setting, scripts, colColumns, scriptsColumns, activeKey, loading, searches, defaultsql, visible, script, scriptValue } = this.state |
| | | |
| | | return ( |
| | | <div id="model-data-source-wrap"> |
| | |
| | | {scripts.length ? <span className="count-tip">{scripts.length}</span> : null} |
| | | </span> |
| | | } key="scripts"> |
| | | <BorderOutlined className="full-scripts" onClick={() => { |
| | | if (this.scriptsForm && (this.scriptsForm.state.editItem || (this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))))) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请保存自定义脚本!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | this.setState({visible: true, script: null, scriptValue: ''}) |
| | | }}/> |
| | | <CustomScriptsForm |
| | | setting={setting} |
| | | searches={searches} |
| | |
| | | <EditTable actions={['move']} data={scripts} columns={scriptsColumns} onChange={this.changeScripts}/> |
| | | </TabPane> |
| | | </Tabs> |
| | | <Modal |
| | | wrapClassName="model-custom-view-scripts-modal" |
| | | title="自定义脚本" |
| | | visible={visible} |
| | | width={'95vw'} |
| | | maskClosable={false} |
| | | destroyOnClose |
| | | > |
| | | <img className="unfull-scripts" src={MinView} onClick={() => this.setState({visible: false, script: null})} alt=""/> |
| | | <div className="script-table-wrap"> |
| | | {scripts.map(item => { |
| | | let title = item.sql.match(/^\s*\/\*.+\*\//) |
| | | title = title && title[0] ? title[0] : '' |
| | | let _text = title ? item.sql.replace(title, '') : item.sql |
| | | |
| | | return ( |
| | | <div className={'script-item ' + (script && script.uuid === item.uuid ? 'active' : '') } key={item.uuid}> |
| | | <div style={{cursor: 'pointer'}} onClick={() => { |
| | | this.setState({script: item, scriptValue: item.sql}) |
| | | }}> |
| | | {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null} |
| | | <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph> |
| | | <div>{item.status === 'false' ? |
| | | <span style={{color: '#ff4d4f', marginLeft: '20px'}}> |
| | | 禁用 |
| | | <StopOutlined style={{marginLeft: '5px'}} /> |
| | | </span> : |
| | | <span style={{color: '#26C281', marginLeft: '20px'}}> |
| | | 启用 |
| | | <CheckCircleOutlined style={{marginLeft: '5px'}}/> |
| | | </span>} |
| | | </div> |
| | | </div> |
| | | <div style={{textAlign: 'right'}}> |
| | | <span className="operation-btn" onClick={() => this.handleStatus(item)} style={{color: '#8E44AD'}}><SwapOutlined /></span> |
| | | <Popconfirm |
| | | overlayClassName="popover-confirm" |
| | | title={this.props.dict['model.query.delete']} |
| | | onConfirm={() => this.deleteScript(item) |
| | | }> |
| | | <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span> |
| | | </Popconfirm> |
| | | </div> |
| | | </div> |
| | | ) |
| | | })} |
| | | </div> |
| | | <div className="script-button"> |
| | | <Button onClick={this.triggerConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}> |
| | | {script ? '保存' : '添加'} |
| | | </Button> |
| | | <Button onClick={() => {this.setState({script: null, scriptValue: ''})}} style={{marginBottom: 15, marginLeft: 10}}> |
| | | 取消 |
| | | </Button> |
| | | </div> |
| | | <CodeMirror value={scriptValue} onChange={(val) => {this.setState({scriptValue: val})}}></CodeMirror> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .full-scripts { |
| | | position: absolute; |
| | | right: 0px; |
| | | top: -40px; |
| | | font-size: 18px; |
| | | color: #1890ff; |
| | | } |
| | | } |
| | | .model-custom-view-scripts-modal { |
| | | .ant-modal { |
| | | top: 30px; |
| | | .ant-modal-header { |
| | | padding: 10px 24px; |
| | | } |
| | | .ant-modal-footer { |
| | | display: none; |
| | | } |
| | | .ant-modal-close { |
| | | display: none; |
| | | } |
| | | .ant-modal-body { |
| | | padding: 0; |
| | | height: calc(100vh - 100px); |
| | | overflow: hidden; |
| | | display: flex; |
| | | |
| | | .script-table-wrap { |
| | | width: 240px; |
| | | overflow-y: auto; |
| | | overflow-x: hidden; |
| | | height: calc(100vh - 100px); |
| | | |
| | | .operation-btn { |
| | | display: inline-block; |
| | | font-size: 16px; |
| | | padding: 0 5px; |
| | | cursor: pointer; |
| | | margin-left: 5px; |
| | | } |
| | | |
| | | .script-item { |
| | | border-bottom: 1px solid #eeeeee; |
| | | padding: 15px 10px 5px; |
| | | } |
| | | .script-item.active { |
| | | background-color: #bae7ff; |
| | | } |
| | | .ant-typography { |
| | | margin-bottom: 5px; |
| | | } |
| | | } |
| | | |
| | | .script-table-wrap::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .script-table-wrap::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); |
| | | background: rgba(0, 0, 0, 0.13); |
| | | } |
| | | .script-table-wrap::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | |
| | | .unfull-scripts { |
| | | position: absolute; |
| | | right: 20px; |
| | | z-index: 2; |
| | | top: 10px; |
| | | color: #1890ff; |
| | | width: 26px; |
| | | cursor: pointer; |
| | | padding: 5px; |
| | | } |
| | | |
| | | .script-button { |
| | | position: absolute; |
| | | top: 10px; |
| | | z-index: 1; |
| | | left: 240px; |
| | | .ant-btn { |
| | | height: 28px; |
| | | } |
| | | .mk-green { |
| | | margin-left: 0!important; |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | .code-mirror-wrap { |
| | | .CodeMirror { |
| | | height: calc(100vh - 100px); |
| | | border-radius: 0; |
| | | } |
| | | .code-mirror-area { |
| | | border-radius: 0; |
| | | width: calc(95vw - 240px); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | if (card.datatype === 'static') { |
| | | url = card.url || '' |
| | | if (url === '@icon@') { |
| | | url = sessionStorage.getItem('avatar') || '' |
| | | } |
| | | } else { |
| | | url = data[card.field] || '' |
| | | } |
| | |
| | | if (btn.output) { |
| | | id = res.mk_b_id || res[btn.output] || '' |
| | | } |
| | | if (res.mk_icon) { |
| | | sessionStorage.setItem('avatar', res.mk_icon) |
| | | } |
| | | let tabId = '' |
| | | if (btn.refreshTab && btn.refreshTab.length > 0) { |
| | | tabId = btn.refreshTab[btn.refreshTab.length - 1] |
| | |
| | | // 系统打印数据,校验data字段 |
| | | if (btn.verify.printMode !== 'custom' && (!cell.data || cell.data.length === 0)) return |
| | | |
| | | cell.templateID = baseTemp |
| | | cell.printType = baseType |
| | | cell.printCount = 0 |
| | | let templateID = baseTemp |
| | | let printType = baseType |
| | | let printCount = 0 |
| | | |
| | | Object.keys(cell).forEach(key => { |
| | | if (!cell[key]) return |
| | |
| | | let _key = key.toLowerCase() |
| | | |
| | | if (_key === 'templateid') { |
| | | cell.templateID = cell[key] |
| | | templateID = cell[key] |
| | | } else if (_key === 'printtype') { |
| | | cell.printType = cell[key] |
| | | printType = cell[key] |
| | | } else if (_key === 'printcount') { |
| | | cell.printCount = +cell[key] |
| | | printCount = +cell[key] |
| | | } |
| | | }) |
| | | |
| | | cell.templateID = templateID |
| | | cell.printType = printType |
| | | cell.printCount = printCount |
| | | |
| | | if (isNaN(cell.printCount) || cell.printCount < 1) { |
| | | cell.printCount = baseCount |
| | | } |
| | |
| | | let icon = '' |
| | | |
| | | marks.some(mark => { |
| | | let originVal = record[mark.field] + '' |
| | | let originVal = record[mark.field] |
| | | let contrastVal = '' |
| | | if (mark.contrastType === 'static') { |
| | | contrastVal = mark.contrastValue + '' |
| | | contrastVal = mark.contrastValue |
| | | } else { |
| | | contrastVal = record[mark.contrastField] + '' |
| | | contrastVal = record[mark.contrastField] |
| | | } |
| | | |
| | | if (originVal === undefined || contrastVal === undefined) return false |
| | | |
| | | if (mark.match === '=') { |
| | | className = originVal === contrastVal ? mark.color[1] : '' |
| | | } else if (mark.match === '!=') { |
| | | className = originVal !== contrastVal ? mark.color[1] : '' |
| | | } else if (mark.match === 'like') { |
| | | originVal = originVal + '' |
| | | contrastVal = contrastVal + '' |
| | | className = originVal.indexOf(contrastVal) > -1 ? mark.color[1] : '' |
| | | } else if (mark.match === '>') { |
| | | try { |
| | | originVal = parseFloat(originVal) |
| | | contrastVal = parseFloat(contrastVal) |
| | | } catch (e) { |
| | | originVal = NaN |
| | | } |
| | | |
| | | if (!isNaN(originVal) && !isNaN(contrastVal) && originVal > contrastVal) { |
| | | if (parseFloat(originVal) > parseFloat(contrastVal)) { |
| | | className = mark.color[1] |
| | | } |
| | | } else if (mark.match === '<') { |
| | | try { |
| | | originVal = parseFloat(originVal) |
| | | contrastVal = parseFloat(contrastVal) |
| | | } catch (e) { |
| | | originVal = NaN |
| | | } |
| | | |
| | | if (!isNaN(originVal) && !isNaN(contrastVal) && originVal < contrastVal) { |
| | | if (parseFloat(originVal) < parseFloat(contrastVal)) { |
| | | className = mark.color[1] |
| | | } |
| | | } |
| | |
| | | let _display = display |
| | | if (appType === 'mob' && display === 'modal') { |
| | | _display = 'drawer' |
| | | } else if (appType !== 'mob' && display === 'dialog') { |
| | | _display = 'modal' |
| | | } |
| | | |
| | | this.setState({ |
| | |
| | | <Radio value="drawer">抽屉</Radio> |
| | | <Radio value="prompt">是否框</Radio> |
| | | <Radio value="exec">直接执行</Radio> |
| | | {/* <Radio value="dialog" disabled={dialogInput !== true}>对话框</Radio> */} |
| | | {appType !== 'mob' ? null : <Radio value="dialog">弹窗</Radio>} |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | |
| | | })(<InputNumber min={10} max={2000} precision={0} onPressEnter={this.handleSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {display === 'drawer' || display === 'modal' ? <Col span={12}> |
| | | {['dialog', 'drawer', 'modal'].includes(display) ? <Col span={12}> |
| | | <Form.Item label="初始焦点"> |
| | | {getFieldDecorator('focus', { |
| | | initialValue: config.setting.focus || '' |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {display === 'drawer' || display === 'modal' ? <Col span={12}> |
| | | {['drawer', 'modal'].includes(display) ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="执行失败时需要聚焦的表单。"> |
| | | <QuestionCircleOutlined className="mk-form-tip" /> |
| | |
| | | </Radio.Group>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {display === 'drawer' || display === 'modal' ? <Col span={12}> |
| | | {['drawer', 'modal'].includes(display) ? <Col span={12}> |
| | | <Form.Item label="完成后"> |
| | | {getFieldDecorator('finish', { |
| | | initialValue: config.setting.finish || 'close' |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {display === 'drawer' || display === 'modal' ? <Col span={12}> |
| | | {['dialog', 'drawer', 'modal'].includes(display) ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="需要通过数据源查询的选项,是否使用缓存。"> |
| | | <QuestionCircleOutlined className="mk-form-tip" /> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {display === 'drawer' || display === 'modal' ? <Col span={12}> |
| | | {['dialog', 'drawer', 'modal'].includes(display) ? <Col span={12}> |
| | | <Form.Item label="点击蒙层"> |
| | | {getFieldDecorator('clickouter', { |
| | | initialValue: config.setting.clickouter || 'unclose' |
| | |
| | | { pattern: formRule.func.pattern, message: formRule.func.message }, |
| | | { max: formRule.func.max, message: formRule.func.maxMessage } |
| | | ) |
| | | } else if (item.key === 'output') { |
| | | if (this.record.intertype === 'system') { |
| | | rules = [{ |
| | | pattern: /^@[0-9a-zA-Z_]*$/, |
| | | message: '变量以@符开头,可使用字母、数字以及_' |
| | | }, { |
| | | max: 100, |
| | | message: '最多100个字符。' |
| | | }] |
| | | } else { |
| | | rules = [{ |
| | | pattern: /^[0-9a-zA-Z_]*$/, |
| | | message: '字段可使用字母、数字以及_' |
| | | }, { |
| | | max: 100, |
| | | message: '最多100个字符。' |
| | | }] |
| | | } |
| | | } else { |
| | | rules.push({ max: formRule.input.max, message: formRule.input.message }) |
| | | } |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Form, notification, Modal, Spin, Tabs } from 'antd' |
| | | import { Form, notification, Modal, Spin, Tabs, Typography, Popconfirm, Button } from 'antd' |
| | | import { CheckCircleOutlined, StopOutlined, SwapOutlined, DeleteOutlined, BorderOutlined } from '@ant-design/icons' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | |
| | | import SettingUtils from './utils.jsx' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import DataSource from './datasource' |
| | | import MinView from '@/assets/img/minview.png' |
| | | import './index.scss' |
| | | |
| | | const { TabPane } = Tabs |
| | | const { Paragraph } = Typography |
| | | const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror')) |
| | | const CustomScript = asyncComponent(() => import('@/templates/zshare/customscript')) |
| | | const SimpleScript = asyncComponent(() => import('./simplescript')) |
| | | |
| | |
| | | regoptions: [], |
| | | setting: null, |
| | | defaultSql: '', |
| | | visible: false, |
| | | script: null, |
| | | scriptValue: '', |
| | | status: {} |
| | | } |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | triggerConfirm = () => { |
| | | const { script, scriptValue, scripts } = this.state |
| | | let _scripts = fromJS(scripts).toJS() |
| | | |
| | | if (!scriptValue) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请输入sql!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | if (script) { |
| | | _scripts = _scripts.map(item => { |
| | | if (script.uuid === item.uuid) { |
| | | item.sql = scriptValue |
| | | } |
| | | return item |
| | | }) |
| | | } else { |
| | | let _script = { |
| | | uuid: Utils.getuuid(), |
| | | sql: scriptValue, |
| | | $index: _scripts.length + 1, |
| | | status: 'true' |
| | | } |
| | | |
| | | _scripts.push(_script) |
| | | } |
| | | |
| | | this.setState({loading: true}) |
| | | |
| | | this.sqlverify(() => {this.setState({scripts: _scripts, script: null, scriptValue: '', loading: false})}, () => {this.setState({loading: false})}, 'verify', _scripts) |
| | | } |
| | | |
| | | // 自定义脚本更新 |
| | | scriptsUpdate = (scripts) => { |
| | | this.setState({scripts}) |
| | |
| | | this.setState({cbScripts}) |
| | | } |
| | | |
| | | handleDelete = (item) => { |
| | | const { script, scripts } = this.state |
| | | |
| | | if (script && script.uuid === item.uuid) { |
| | | this.setState({script: null}) |
| | | } |
| | | this.setState({scripts: scripts.filter(cell => cell.uuid !== item.uuid)}) |
| | | } |
| | | |
| | | handleStatus = (item) => { |
| | | item.status = item.status === 'false' ? 'true' : 'false' |
| | | |
| | | this.setState({scripts: this.state.scripts.map(cell => { |
| | | if (cell.uuid === item.uuid) { |
| | | return item |
| | | } |
| | | return cell |
| | | })}) |
| | | } |
| | | |
| | | updateStatus = (status) => { |
| | | let _status = {...this.state.status, ...status} |
| | | this.setState({status: _status}) |
| | |
| | | |
| | | render() { |
| | | const { config, menu, dict } = this.props |
| | | const { loading, activeKey, setting, defaultSql, columns, scripts, preScripts, cbScripts, status, regoptions } = this.state |
| | | const { loading, activeKey, setting, defaultSql, columns, scripts, preScripts, cbScripts, status, regoptions, visible, script, scriptValue } = this.state |
| | | |
| | | return ( |
| | | <div className="model-table-setting-form-box" id="model-setting-form-body"> |
| | |
| | | {scripts.length ? <span className="count-tip">{scripts.length}</span> : null} |
| | | </span> |
| | | } disabled={!(status.interType === 'system' || (status.interType === 'custom' && status.requestMode === 'system'))} key="scripts"> |
| | | <BorderOutlined className="full-scripts" onClick={() => { |
| | | if (this.scriptsForm && (this.scriptsForm.state.editItem || (this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))))) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请保存自定义脚本!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | this.setState({visible: true, script: null, scriptValue: ''}) |
| | | }}/> |
| | | <CustomScript |
| | | dict={dict} |
| | | setting={setting} |
| | |
| | | /> |
| | | </TabPane> |
| | | </Tabs> |
| | | <Modal |
| | | wrapClassName="model-custom-table-scripts-modal" |
| | | title="自定义脚本" |
| | | visible={visible} |
| | | width={'95vw'} |
| | | maskClosable={false} |
| | | destroyOnClose |
| | | > |
| | | <img className="unfull-scripts" src={MinView} onClick={() => this.setState({visible: false, script: null})} alt=""/> |
| | | <div className="script-table-wrap"> |
| | | {scripts.map(item => { |
| | | let title = item.sql.match(/^\s*\/\*.+\*\//) |
| | | title = title && title[0] ? title[0] : '' |
| | | let _text = title ? item.sql.replace(title, '') : item.sql |
| | | |
| | | return ( |
| | | <div className={'script-item ' + (script && script.uuid === item.uuid ? 'active' : '') } key={item.uuid}> |
| | | <div style={{cursor: 'pointer'}} onClick={() => { |
| | | this.setState({script: item, scriptValue: item.sql}) |
| | | }}> |
| | | {title ? <div style={{color: '#a50', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}}>{title}</div> : null} |
| | | <Paragraph copyable={{ text: item.sql }} ellipsis={{ rows: 4 }}>{_text}</Paragraph> |
| | | <div>{item.status === 'false' ? |
| | | <span style={{color: '#ff4d4f', marginLeft: '20px'}}> |
| | | 禁用 |
| | | <StopOutlined style={{marginLeft: '5px'}} /> |
| | | </span> : |
| | | <span style={{color: '#26C281', marginLeft: '20px'}}> |
| | | 启用 |
| | | <CheckCircleOutlined style={{marginLeft: '5px'}}/> |
| | | </span>} |
| | | </div> |
| | | </div> |
| | | <div style={{textAlign: 'right'}}> |
| | | <span className="operation-btn" onClick={() => this.handleStatus(item)} style={{color: '#8E44AD'}}><SwapOutlined /></span> |
| | | <Popconfirm |
| | | overlayClassName="popover-confirm" |
| | | title={this.props.dict['model.query.delete']} |
| | | onConfirm={() => this.handleDelete(item) |
| | | }> |
| | | <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span> |
| | | </Popconfirm> |
| | | </div> |
| | | </div> |
| | | ) |
| | | })} |
| | | </div> |
| | | <div className="script-button"> |
| | | <Button onClick={this.triggerConfirm} loading={loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}> |
| | | {script ? '保存' : '添加'} |
| | | </Button> |
| | | <Button onClick={() => {this.setState({script: null, scriptValue: ''})}} style={{marginBottom: 15, marginLeft: 10}}> |
| | | 取消 |
| | | </Button> |
| | | </div> |
| | | <CodeMirror value={scriptValue} onChange={(val) => {this.setState({scriptValue: val})}}></CodeMirror> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | .ant-tabs-nav-wrap { |
| | | text-align: center; |
| | | } |
| | | .full-scripts { |
| | | position: absolute; |
| | | right: 0px; |
| | | top: 18px; |
| | | font-size: 18px; |
| | | color: #1890ff; |
| | | } |
| | | } |
| | | |
| | | .model-custom-table-scripts-modal { |
| | | .ant-modal { |
| | | top: 30px; |
| | | .ant-modal-header { |
| | | padding: 10px 24px; |
| | | } |
| | | .ant-modal-footer { |
| | | display: none; |
| | | } |
| | | .ant-modal-close { |
| | | display: none; |
| | | } |
| | | .ant-modal-body { |
| | | padding: 0; |
| | | height: calc(100vh - 100px); |
| | | overflow: hidden; |
| | | display: flex; |
| | | |
| | | .script-table-wrap { |
| | | width: 240px; |
| | | overflow-y: auto; |
| | | overflow-x: hidden; |
| | | height: calc(100vh - 100px); |
| | | |
| | | .operation-btn { |
| | | display: inline-block; |
| | | font-size: 16px; |
| | | padding: 0 5px; |
| | | cursor: pointer; |
| | | margin-left: 5px; |
| | | } |
| | | |
| | | .script-item { |
| | | border-bottom: 1px solid #eeeeee; |
| | | padding: 15px 10px 5px; |
| | | } |
| | | .script-item.active { |
| | | background-color: #bae7ff; |
| | | } |
| | | .ant-typography { |
| | | margin-bottom: 5px; |
| | | } |
| | | } |
| | | |
| | | .script-table-wrap::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .script-table-wrap::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); |
| | | background: rgba(0, 0, 0, 0.13); |
| | | } |
| | | .script-table-wrap::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | |
| | | .unfull-scripts { |
| | | position: absolute; |
| | | right: 20px; |
| | | z-index: 2; |
| | | top: 10px; |
| | | color: #1890ff; |
| | | width: 26px; |
| | | cursor: pointer; |
| | | padding: 5px; |
| | | } |
| | | |
| | | .script-button { |
| | | position: absolute; |
| | | top: 10px; |
| | | z-index: 1; |
| | | left: 240px; |
| | | .ant-btn { |
| | | height: 28px; |
| | | } |
| | | .mk-green { |
| | | margin-left: 0!important; |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | .code-mirror-wrap { |
| | | .CodeMirror { |
| | | height: calc(100vh - 100px); |
| | | border-radius: 0; |
| | | } |
| | | .code-mirror-area { |
| | | border-radius: 0; |
| | | width: calc(95vw - 240px); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | type: 'text', |
| | | key: 'output', |
| | | label: '返回值', |
| | | tooltip: '执行成功后的返回值。例如:@id', |
| | | tooltip: '执行成功后的返回值。系统函数可指定返回的变量(以@符开头,如@id);自定义函数可指定返回字段(如id)。', |
| | | initVal: card.output || '', |
| | | required: false |
| | | }, |
| | |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | const { type } = this.props |
| | | const { editItem } = this.state |
| | | // 表单提交时检查输入值是否正确 |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (type === 'fullscreen' && err) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请输入sql!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | if (!err) { |
| | | values.uuid = editItem ? editItem.uuid : '' |
| | | values.position = values.position || (editItem ? editItem.position : 'front') |
| | |
| | | render() { |
| | | const { usefulfields, systemScripts, btn, type } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { editItem } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | |
| | | </Col> : null} |
| | | <Col span={6} className="add"> |
| | | <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}> |
| | | 保存 |
| | | {_type === 'fullscreen' && !editItem ? '添加' : '保存'} |
| | | </Button> |
| | | <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}> |
| | | 取消 |
| | |
| | | {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null} |
| | | </span> |
| | | } key="6"> |
| | | |
| | | <BorderOutlined className="full-scripts" onClick={() => { |
| | | if (this.scriptsForm && (this.scriptsForm.state.editItem || (this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))))) { |
| | | notification.warning({ |
| | |
| | | style = JSON.parse(JSON.stringify(style)) |
| | | |
| | | marks.some(mark => { |
| | | let originVal = record[mark.field[0]] + '' |
| | | let originVal = record[mark.field[0]] |
| | | let contrastVal = '' |
| | | let result = false |
| | | |
| | | if (mark.field[1] === 'static') { |
| | | contrastVal = mark.contrastValue + '' |
| | | contrastVal = mark.contrastValue |
| | | } else { |
| | | contrastVal = record[mark.field[2]] + '' |
| | | contrastVal = record[mark.field[2]] |
| | | } |
| | | |
| | | if (originVal === undefined || contrastVal === undefined) return false |
| | | |
| | | if (mark.match === '=') { |
| | | result = originVal === contrastVal |
| | | } else if (mark.match === '!=') { |
| | | result = originVal !== contrastVal |
| | | } else if (mark.match === 'like') { |
| | | originVal = originVal + '' |
| | | contrastVal = contrastVal + '' |
| | | result = originVal.indexOf(contrastVal) > -1 |
| | | } else if (mark.match === '>') { |
| | | result = parseFloat(originVal) > parseFloat(contrastVal) |