| | |
| | | { |
| | | "appId": "201912040924165801464FF1788654BC5AC73", |
| | | "appkey": "20191106103859640976D6E924E464D029CF0", |
| | | "mainSystemApi": "http://cloud.mk9h.cn/webapi/dostars", |
| | | "mainSystemApi": "http://sso.mk9h.cn/cloud/webapi/dostars", |
| | | "systemType": "", |
| | | "lineColor": "", |
| | | "filter": "false" |
| | |
| | | if (config.mainSystemApi) { |
| | | let systemApi = config.mainSystemApi |
| | | |
| | | if (/^(http|https):\/\//ig.test(systemApi)) { |
| | | let _systemApi = /^(http|https):\/\/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62}|(:[0-9]{1,4}))+\.?/ig.exec(systemApi) |
| | | // if (/^(http|https):\/\//ig.test(systemApi)) { |
| | | // let _systemApi = /^(http|https):\/\/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62}|(:[0-9]{1,4}))+\.?/ig.exec(systemApi) |
| | | |
| | | systemApi = _systemApi ? _systemApi[0] : '' |
| | | } else { |
| | | // systemApi = _systemApi ? _systemApi[0] : '' |
| | | // } else { |
| | | // systemApi = '' |
| | | // } |
| | | |
| | | // // 业务系统连接云端时,格式化处理 |
| | | // if (systemApi && systemApi === /^(http|https):\/\/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62}|(:[0-9]{1,4}))+\.?/ig.exec(options.cloudServiceApi)[0]) { |
| | | // window.GLOB.dataFormat = true |
| | | // } |
| | | |
| | | // if (systemApi) { |
| | | // systemApi = systemApi + '/webapi/dostars' |
| | | // } |
| | | |
| | | // 业务系统不允许连接云端,业务系统连接sso.mk9h.cn时,数据虚化处理 |
| | | if (systemApi && systemApi.indexOf('cloud.mk9h.cn') > -1) { |
| | | systemApi = '' |
| | | } |
| | | |
| | | // 业务系统连接云端时,格式化处理 |
| | | if (systemApi && systemApi === /^(http|https):\/\/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62}|(:[0-9]{1,4}))+\.?/ig.exec(options.cloudServiceApi)[0]) { |
| | | } else if (systemApi && systemApi.indexOf('sso.mk9h.cn') > -1) { |
| | | window.GLOB.dataFormat = true |
| | | } |
| | | |
| | | if (systemApi) { |
| | | systemApi = systemApi + '/webapi/dostars' |
| | | } |
| | | |
| | | window.GLOB.mainSystemApi = systemApi |
| | |
| | | |
| | | // 测试系统打印查询语句 |
| | | if (options.sysType === 'local' && !window.GLOB.systemType) { |
| | | param.custom_script && console.log(`${LText ? '' : '/*不执行默认sql*/\n'}${param.custom_script}`) |
| | | LText && console.log(LText) |
| | | param.custom_script && console.log(param.custom_script) |
| | | } |
| | | |
| | | param.custom_script = Utils.formatOptions(param.custom_script) |
| | |
| | | |
| | | // 测试系统打印查询语句 |
| | | if (options.sysType === 'local' && !window.GLOB.systemType) { |
| | | param.custom_script && console.log(`${LText ? '' : '/*不执行默认sql*/\n'}${param.custom_script}`) |
| | | LText && console.log(LText) |
| | | param.custom_script && console.log(param.custom_script) |
| | | } |
| | | |
| | | param.custom_script = Utils.formatOptions(param.custom_script) |
| | |
| | | |
| | | // 测试系统打印查询语句 |
| | | if (options.sysType === 'local' && !window.GLOB.systemType) { |
| | | param.custom_script && console.log(`${LText ? '' : '/*不执行默认sql*/\n'}${param.custom_script}`) |
| | | LText && console.log(LText) |
| | | param.custom_script && console.log(param.custom_script) |
| | | } |
| | | |
| | | param.custom_script = Utils.formatOptions(param.custom_script) |
| | |
| | | |
| | | // 测试系统打印查询语句 |
| | | if (options.sysType === 'local' && !window.GLOB.systemType) { |
| | | param.custom_script && console.log(`${LText ? '' : '/*不执行默认sql*/\n'}${param.custom_script}`) |
| | | LText && console.log(LText) |
| | | param.custom_script && console.log(param.custom_script) |
| | | } |
| | | |
| | | param.custom_script = Utils.formatOptions(param.custom_script) |
| | |
| | | class Calendar extends Component { |
| | | static propTpyes = { |
| | | data: PropTypes.any, // 事件数据 |
| | | levels: PropTypes.any |
| | | calendar: PropTypes.any, |
| | | loading: false |
| | | } |
| | | |
| | | state = { |
| | |
| | | selectYear: moment().format('YYYY'), |
| | | selectMonth: moment().format('MM'), |
| | | datelist: null, |
| | | monthlist: null, |
| | | monthlist: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { levels } = this.props |
| | | const { calendar, data } = this.props |
| | | |
| | | let yearlist = [] |
| | | let _selectYear = +this.state.selectYear |
| | |
| | | } |
| | | |
| | | let datelist = this.getDateList(this.state.selectYear) |
| | | let _levels = null |
| | | |
| | | if (!levels) { |
| | | _levels = ['day', 'month', 'year'] |
| | | } else { |
| | | _levels = levels |
| | | if (data && data.length > 0) { |
| | | datelist = this.mountdata(datelist, data) |
| | | } |
| | | |
| | | |
| | | let _levels = calendar.levels |
| | | let level = _levels[0] |
| | | let monthlist = null |
| | | level = 'month' |
| | | |
| | | if (_levels.includes('month')) { |
| | | monthlist = datelist.filter(item => item.month === moment().format('MM'))[0] |
| | |
| | | |
| | | UNSAFE_componentWillReceiveProps(nextProps) { |
| | | if (!is(fromJS(this.props.data), fromJS(nextProps.data))) { |
| | | |
| | | let datelist = this.mountdata(this.state.datelist, nextProps.data) |
| | | let monthlist = null |
| | | |
| | | if (this.state.levels.includes('month')) { |
| | | monthlist = datelist.filter(item => item.month === this.state.selectMonth)[0] |
| | | } |
| | | |
| | | this.setState({ |
| | | datelist: datelist, |
| | | monthlist |
| | | }) |
| | | } else if (!is(fromJS(this.props.calendar), fromJS(nextProps.calendar))) { |
| | | this.setState({ |
| | | levels: nextProps.calendar.levels |
| | | }) |
| | | } |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | mountdata = (datelist, data) => { |
| | | const { calendar } = this.props |
| | | |
| | | let datalist = [] |
| | | let levels = { |
| | | black: 1, |
| | | red: 2, |
| | | orange: 3, |
| | | yellow: 4, |
| | | green: 5, |
| | | lightgreen: 6, |
| | | cyan: 7, |
| | | blue: 8, |
| | | purple: 9, |
| | | white: 10 |
| | | } |
| | | |
| | | data.forEach(item => { |
| | | let startTime = item[calendar.startfield] |
| | | let endTime = item[calendar.endfield] |
| | | let color = item[calendar.colorfield] |
| | | |
| | | if (!startTime || !/^(1|2)\d{3}(-|\/)\d{2}(-|\/)\d{2}/.test(startTime)) return |
| | | if (!endTime || !/^(1|2)\d{3}(-|\/)\d{2}(-|\/)\d{2}/.test(endTime)) return |
| | | if (!item[calendar.remarkfield]) return |
| | | |
| | | datalist.push({ |
| | | color: color, |
| | | level: color && levels[color] ? levels[color] : 100, |
| | | remark: item[calendar.remarkfield], |
| | | startMonth: startTime.substr(0, 4) + startTime.substr(5, 2), |
| | | endMonth: endTime.substr(0, 4) + endTime.substr(5, 2), |
| | | start: startTime.substr(0, 4) + startTime.substr(5, 2) + startTime.substr(8, 2), |
| | | startTime: `${startTime.substr(5, 2)}-${startTime.substr(8, 2)}`, |
| | | end: endTime.substr(0, 4) + endTime.substr(5, 2) + endTime.substr(8, 2), |
| | | endTime: `${endTime.substr(5, 2)}-${endTime.substr(8, 2)}` |
| | | }) |
| | | }) |
| | | |
| | | if (datalist.length === 0) return datelist |
| | | |
| | | datalist.sort((a, b) => a.level - b.level) |
| | | |
| | | let styles = [ |
| | | {background: 'black', color: '#ffffff'}, |
| | | {background: 'red', color: '#ffffff'}, |
| | | {background: 'orange', color: '#ffffff'}, |
| | | {background: 'yellow', color: 'rgba(0,0,0,.65)'}, |
| | | {background: 'green', color: '#ffffff'}, |
| | | {background: 'lightgreen', color: 'rgba(0,0,0,.65)'}, |
| | | {background: 'cyan', color: 'rgba(0,0,0,.65)'}, |
| | | {background: 'blue', color: '#ffffff'}, |
| | | {background: 'purple', color: '#ffffff'}, |
| | | {background: 'white', color: 'rgba(0,0,0,.65)'}, |
| | | ] |
| | | |
| | | return datelist.map(month => { |
| | | datalist.forEach(item => { |
| | | if (item.startMonth <= month.time && item.endMonth >= month.time) { |
| | | month.subData.push(item) |
| | | } |
| | | }) |
| | | month.sublist = month.sublist.map(week => { |
| | | week.sublist = week.sublist.map(day => { |
| | | if (!day) return null |
| | | |
| | | datalist.forEach(item => { |
| | | if (item.start <= day.time && item.end >= day.time) { |
| | | day.subData.push(item) |
| | | } |
| | | }) |
| | | |
| | | if (day.subData[0]) { |
| | | day.style = styles[day.subData[0].level - 1] || null |
| | | } |
| | | |
| | | return day |
| | | }) |
| | | |
| | | return week |
| | | }) |
| | | |
| | | return month |
| | | }) |
| | | } |
| | | |
| | | getDateList = (selectYear) => { |
| | |
| | | } |
| | | |
| | | for (let i = 1; i <= end; i++) { |
| | | let _day = i < 10 ? `0${i}` : `${i}` |
| | | |
| | | if (_weeklist[_weeklist.length - 1].sublist.length < 7) { |
| | | _weeklist[_weeklist.length - 1].sublist.push({day: i < 10 ? `0${i}` : `${i}`, label: i}) |
| | | _weeklist[_weeklist.length - 1].sublist.push({day: _day, time: selectYear + month + _day, label: i, subData: []}) |
| | | } else { |
| | | let _week = {week: _weeklist.length + 1, sublist: [{day: i < 10 ? `0${i}` : `${i}`, label: i}]} |
| | | let _week = {week: _weeklist.length + 1, sublist: [{day: _day, time: selectYear + month + _day, label: i, subData: []}]} |
| | | _weeklist.push(_week) |
| | | } |
| | | } |
| | |
| | | |
| | | datelist.push({ |
| | | month: month, |
| | | time: selectYear + month, |
| | | label: monthName[month], |
| | | sublist: _weeklist |
| | | sublist: _weeklist, |
| | | subData: [] |
| | | }) |
| | | }) |
| | | |
| | |
| | | } |
| | | |
| | | this.setState({ selectYear: value, datelist, monthlist }) |
| | | |
| | | if (this.props.changeDate) { |
| | | this.props.changeDate(value) |
| | | } |
| | | } |
| | | |
| | | monthChange = (value) => { |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { loading } = this.props |
| | | const { level, selectMonth, selectYear, yearlist, levels, datelist, monthlist } = this.state |
| | | const _levelName = {day: '日', month: '月', year: '年'} |
| | | const listData = [ |
| | | { type: 'orange', content: 'This is error event 2.' }, |
| | | { type: 'cyan', content: 'This is error event 3.' }, |
| | | { type: 'green', content: 'This is error event 4.' }, |
| | | ] |
| | | |
| | | console.log(loading) |
| | | return ( |
| | | <div className="mk-calendar"> |
| | | <div className="mk-calendar-control"> |
| | |
| | | <tr key={cell.week}> |
| | | {cell.sublist.map((d, i) => ( |
| | | <td key={i}> |
| | | {d ? <div className={'day-wrap ' + d.class} onClick={() => this.triggerDay(d)}> |
| | | {d.label ? <Popover mouseEnterDelay={0.3} overlayClassName="calendar-day-pop" content={ |
| | | {d ? <div className={'day-wrap ' + d.class} style={d.style || null} onClick={() => this.triggerDay(d)}> |
| | | {d.subData.length > 0 ? <Popover mouseEnterDelay={0.3} overlayClassName="calendar-day-pop" content={ |
| | | <div> |
| | | {listData.map((data, index) => ( |
| | | {d.subData.map((data, index) => ( |
| | | <div key={index} className="message"> |
| | | <Badge color={data.type} text={data.content} /> |
| | | <Badge color={data.color} text={ |
| | | <span> |
| | | {data.remark} |
| | | <span style={{color: 'rgba(0,0,0,.45)'}}>({data.startTime + ' ~ ' + data.endTime})</span> |
| | | </span>} |
| | | /> |
| | | </div> |
| | | ))} |
| | | </div> |
| | |
| | | <tr key={cell.week}> |
| | | {cell.sublist.map((d, i) => ( |
| | | <td key={i}> |
| | | {d ? <div className="month-wrap" onClick={() => this.triggerDay(d)}> |
| | | {d ? <div className="month-wrap" style={d.style || null} onClick={() => this.triggerDay(d)}> |
| | | <div className="header"> |
| | | {d.label} |
| | | </div> |
| | | <ul className="content"> |
| | | {[1,3,7,18,22].includes(d.label) && listData.map((data, index) => ( |
| | | <li key={index} className="message" title={data.content}> |
| | | <Badge color={data.type} text={data.content} /> |
| | | {d.subData.map((data, index) => ( |
| | | <li key={index} className="message" title={data.remark}> |
| | | <Badge color={data.color} text={data.remark} /> |
| | | </li> |
| | | ))} |
| | | </ul> |
| | |
| | | {item.label} |
| | | </div> |
| | | <ul className="content"> |
| | | {['01', '05', '10'].includes(item.month) && listData.map((data, index) => ( |
| | | <li key={index} className="message" title={data.content}> |
| | | <Badge color={data.type} text={data.content} /> |
| | | {item.subData.map((data, index) => ( |
| | | <li key={index} className="message" title={data.remark}> |
| | | <Badge color={data.color} text={data.remark} /> |
| | | </li> |
| | | ))} |
| | | </ul> |
| | |
| | | .mk-calendar { |
| | | width: 100%; |
| | | padding: 10px; |
| | | padding: 20px; |
| | | |
| | | .mk-calendar-control { |
| | | text-align: right; |
| | |
| | | right: 0; |
| | | .message { |
| | | width: 100%; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | // white-space: nowrap; |
| | | // overflow: hidden; |
| | | // text-overflow: ellipsis; |
| | | .ant-badge-status-text { |
| | | color: inherit; |
| | | } |
| | | } |
| | | } |
| | | .content::-webkit-scrollbar { |
| | |
| | | .message { |
| | | .ant-badge-status-text { |
| | | display: inline-block; |
| | | min-width: 100px; |
| | | max-width: 200px; |
| | | white-space: nowrap; |
| | | min-width: 200px; |
| | | max-width: 350px; |
| | | // white-space: nowrap; |
| | | vertical-align: middle; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | // overflow: hidden; |
| | | // text-overflow: ellipsis; |
| | | } |
| | | } |
| | | .ant-popover-inner-content { |
| | |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | | import { formRule } from '@/utils/option.js' |
| | | import { formRule, calendarColors } from '@/utils/option.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import FileUpload from '../fileupload' |
| | | import './index.scss' |
| | |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'color') { // 颜色选择 |
| | | fields.push( |
| | | <Col span={24 / cols} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.field, { |
| | | initialValue: item.initval, |
| | | rules: [ |
| | | { |
| | | required: item.required === 'true', |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select onChange={(value, option) => {this.selectChange(item, value, option)}} disabled={item.readonly === 'true'}> |
| | | {calendarColors.map(option => |
| | | <Select.Option key={option.name} style={{background: option.name, color: option.value}} value={option.name}>{option.name}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'select' || item.type === 'link') { // 下拉搜索 |
| | | let hasSubField = false |
| | | if (item.linkSubField && item.linkSubField.length > 0) { // 存在关联字段,数据存储 |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Select, Checkbox } from 'antd' |
| | | import './index.scss' |
| | | |
| | | class MainTab extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.object, // 页面配置 |
| | | dict: PropTypes.object, // 字典项 |
| | | calendar: PropTypes.any // 日历配置信息 |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { getFieldDecorator } = this.props.form |
| | | const { calendar, config } = this.props |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 10 } |
| | | } |
| | | } |
| | | return ( |
| | | <Form {...formItemLayout} className="model-calendar-form"> |
| | | <Row gutter={24}> |
| | | <Col span={24}> |
| | | <Form.Item label={'开始时间'}> |
| | | {getFieldDecorator('startfield', { |
| | | initialValue: calendar.startfield, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '开始时间!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select> |
| | | {config.columns.map(option => |
| | | <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item label={'结束时间'}> |
| | | {getFieldDecorator('endfield', { |
| | | initialValue: calendar.endfield, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '结束时间!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select> |
| | | {config.columns.map(option => |
| | | <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item label={'信息字段'}> |
| | | {getFieldDecorator('remarkfield', { |
| | | initialValue: calendar.remarkfield, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '信息字段!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select> |
| | | {config.columns.map(option => |
| | | <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item label={'颜色字段'}> |
| | | {getFieldDecorator('colorfield', { |
| | | initialValue: calendar.colorfield, |
| | | rules: [ |
| | | { |
| | | required: false, |
| | | message: this.props.dict['form.required.select'] + '颜色字段!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select> |
| | | {config.columns.map(option => |
| | | <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item label={'日历等级'}> |
| | | {getFieldDecorator('levels', { |
| | | initialValue: calendar.levels, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '日历等级!' |
| | | } |
| | | ] |
| | | })( |
| | | <Checkbox.Group options={[{ value: 'day', label: '日' }, { value: 'month', label: '月' }, { value: 'year', label: '年' }]}/> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(MainTab) |
New file |
| | |
| | | .model-calendar-form { |
| | | min-height: 180px; |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import CalendarForm from './calendarform' |
| | | |
| | | import './index.scss' |
| | | |
| | | class SettingComponent extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, // 标签 |
| | | updateConfig: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | calendar: null, // 日历设置 |
| | | visible: false, // 模态框控制 |
| | | } |
| | | |
| | | /** |
| | | * @description 保存页面配置信息 |
| | | */ |
| | | calendarSave = () => { |
| | | const { config } = this.props |
| | | |
| | | this.calendarRef.handleConfirm().then(res => { |
| | | this.setState({ |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, calendar: res}) |
| | | }) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 添加或修改标签 |
| | | */ |
| | | handleTab = (e) => { |
| | | const { config } = this.props |
| | | e.stopPropagation() |
| | | |
| | | let calendar = fromJS(config.calendar).toJS() |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | calendar |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { config } = this.props |
| | | const { dict, visible, calendar } = this.state |
| | | |
| | | return ( |
| | | <div className="model-calendar-setting"> |
| | | <Icon type="edit" onClick={this.handleTab} /> |
| | | {/* 设置全局配置及列表数据源 */} |
| | | <Modal |
| | | wrapClassName="model-calendar-setting-modal" |
| | | title={dict['model.edit']} |
| | | visible={visible} |
| | | width={700} |
| | | maskClosable={false} |
| | | onCancel={() => { this.setState({ visible: false })}} |
| | | cancelText={this.state.dict['model.cancel']} |
| | | okText={this.state.dict['model.confirm']} |
| | | onOk={this.calendarSave} |
| | | destroyOnClose |
| | | > |
| | | <CalendarForm |
| | | dict={dict} |
| | | config={config} |
| | | calendar={calendar} |
| | | wrappedComponentRef={(inst) => this.calendarRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default SettingComponent |
New file |
| | |
| | | .model-calendar-setting { |
| | | position: absolute; |
| | | right: 0; |
| | | top: 0; |
| | | >.anticon-edit { |
| | | font-size: 18px; |
| | | padding: 5px; |
| | | margin-right: 10px; |
| | | color: #1890ff; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | |
| | | .model-calendar-setting-modal { |
| | | .ant-modal { |
| | | top: 50px; |
| | | padding-bottom: 5px; |
| | | .ant-modal-body { |
| | | max-height: calc(100vh - 190px); |
| | | overflow-y: auto; |
| | | } |
| | | .ant-modal-body::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .ant-modal-body::-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); |
| | | } |
| | | .ant-modal-body::-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); |
| | | } |
| | | .ant-empty-normal { |
| | | margin: 5px 0px; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import {connect} from 'react-redux' |
| | | import { is, fromJS } from 'immutable' |
| | | import { DndProvider } from 'react-dnd' |
| | | import HTML5Backend from 'react-dnd-html5-backend' |
| | | import { Button, Card, Modal, Collapse, notification, Spin, Icon, Switch } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import { getMainMenuForm } from '@/templates/zshare/formconfig' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import SearchComponent from '@/templates/sharecomponent/searchcomponent' |
| | | |
| | | import MenuForm from '@/templates/zshare/menuform' |
| | | // import EditComponent from '@/templates/zshare/editcomponent' |
| | | import SourceElement from '@/templates/zshare/dragsource' |
| | | import Source from './source' |
| | | import './index.scss' |
| | | |
| | | const { Panel } = Collapse |
| | | const { confirm } = Modal |
| | | |
| | | const SettingComponent = asyncComponent(() => import('@/templates/sharecomponent/datasourcecomponent')) |
| | | const TabComponent = asyncComponent(() => import('./tabcomponent')) |
| | | const CalComponent = asyncComponent(() => import('./calcomponent')) |
| | | const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent')) |
| | | const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent')) |
| | | const CalendarComponent = asyncComponent(() => import('@/tabviews/zshare/calendar')) |
| | | |
| | | class SubTableConfig extends Component { |
| | | static propTpyes = { |
| | | menu: PropTypes.any, |
| | | optionLibs: PropTypes.any, |
| | | reloadmenu: PropTypes.func, |
| | | handleView: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, // 字典 |
| | | config: null, // 页面配置 |
| | | visible: false, // 搜索条件、按钮、显示列,模态框显示控制 |
| | | tableFields: [], // 已选表字段集 |
| | | fields: null, // 搜索条件及显示列,可选字段 |
| | | menuformlist: null, // 基本信息表单字段 |
| | | formlist: null, // 搜索条件、按钮、显示列表单字段 |
| | | menuloading: false, // 菜单保存中 |
| | | menucloseloading: false, // 菜单关闭时,选择保存 |
| | | loading: false, // 加载中,页面spin |
| | | closeVisible: false, // 关闭模态框 |
| | | originConfig: null, // 原配置 |
| | | tabviews: [], // 所有标签页 |
| | | optionLibs: null, // 自定义下拉选项库 |
| | | activeKey: '0', // 默认展开基本信息 |
| | | pasteContent: null, // 粘贴内容 |
| | | openEdition: '', // 编辑版本标记,防止多人操作 |
| | | mockdata: [], // 测试数据 |
| | | mockloading: false // 数据加载中 |
| | | } |
| | | |
| | | /** |
| | | * @description 数据预处理 |
| | | * 1、设置页面配置信息,新建或无配置信息时(切换模板后无配置信息),使用模板默认配置 |
| | | * 2、设置操作类型、原始菜单信息(每次保存后重置)、已使用表及基本信息表单 |
| | | */ |
| | | UNSAFE_componentWillMount () { |
| | | const { menu, optionLibs } = this.props |
| | | let _LongParam = menu.LongParam |
| | | let _config = '' |
| | | |
| | | if (!_LongParam) { |
| | | _config = fromJS(Source.baseConfig).toJS() |
| | | _config.isAdd = true |
| | | } else { |
| | | _config = _LongParam |
| | | _config.search.forEach(item => { |
| | | if ( |
| | | (item.type === 'select' || item.type === 'multiselect' || item.type === 'link') && |
| | | item.resourceType === '0' && |
| | | item.options && item.options.length > 0 |
| | | ) { |
| | | optionLibs.set(menu.MenuID + item.uuid, { |
| | | uuid: menu.MenuID + item.uuid, |
| | | label: item.label, |
| | | parname: menu.MenuName, |
| | | type: 'search', |
| | | options: item.options |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | this.setState({ |
| | | openEdition: menu.open_edition || '', |
| | | optionLibs: optionLibs, |
| | | activeKey: menu.activeKey || '0', |
| | | config: _config, |
| | | originMenu: fromJS(menu).toJS(), |
| | | menuformlist: getMainMenuForm(menu, _config), |
| | | mockdata: this.getMockData(moment().format('YYYY')) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 加载完成后 |
| | | * 1、获取系统可使用表 |
| | | * 2、根据配置信息中已使用表获取相关字段信息 |
| | | */ |
| | | componentDidMount () { |
| | | this.reloadTab(false) |
| | | } |
| | | |
| | | getMockData = (year) => { |
| | | let msgs = [ |
| | | {color: 'red', remark: '服务器异常,请联系运维人员!'}, |
| | | {color: 'orange', remark: '系统异常,请及时处理!'}, |
| | | {color: 'yellow', remark: '您的订单异常,请联系客服!'}, |
| | | {color: 'green', remark: '您的订单已完成。'}, |
| | | {color: 'lightgreen', remark: '消息已发送,请及时查收。'}, |
| | | {color: 'cyan', remark: '您有一条新的消息。'}, |
| | | {color: 'blue', remark: '任务未完成,请注意后续工作。'}, |
| | | {color: 'purple', remark: '您有新的任务等待处理!'} |
| | | ] |
| | | let mockdata = [] |
| | | |
| | | for (let i = 1; i <= 12; i++) { |
| | | if (Math.random() > 0.5) { |
| | | let cell = {uuid: Utils.getuuid()} |
| | | let msg = msgs[Math.floor(Math.random() * 8)] |
| | | let day = Math.floor(Math.random() * 28 + 1) |
| | | |
| | | cell.color = msg.color |
| | | cell.remark = msg.remark |
| | | cell.start = `${year}-${i < 10 ? '0' + i : i}-${day < 10 ? '0' + day : day}` |
| | | cell.end = moment(cell.start, 'YYYY-MM-DD').add(Math.floor(Math.random() * 10), 'days').format('YYYY-MM-DD') |
| | | |
| | | mockdata.push(cell) |
| | | |
| | | if (Math.random() > 0.5) { |
| | | let _cell = {uuid: Utils.getuuid()} |
| | | let _msg = msgs[Math.floor(Math.random() * 8)] |
| | | let _day = Math.floor(Math.random() * 28 + 1) |
| | | |
| | | _cell.color = _msg.color |
| | | _cell.remark = _msg.remark |
| | | _cell.start = `${year}-${i < 10 ? '0' + i : i}-${_day < 10 ? '0' + _day : _day}` |
| | | _cell.end = moment(_cell.start, 'YYYY-MM-DD').add(Math.floor(Math.random() * 10), 'days').format('YYYY-MM-DD') |
| | | |
| | | mockdata.push(_cell) |
| | | } |
| | | } |
| | | } |
| | | |
| | | return mockdata |
| | | } |
| | | |
| | | /** |
| | | * @description 加载或刷新标签信息 |
| | | */ |
| | | reloadTab = (type) => { |
| | | this.setState({ |
| | | loading: type, |
| | | tabviews: [] |
| | | }) |
| | | Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => { |
| | | if (res.status) { |
| | | let _tabviews = [] |
| | | res.UserTemp.forEach(temp => { |
| | | let item = { |
| | | uuid: temp.MenuID, |
| | | value: temp.MenuID, |
| | | text: temp.MenuName, |
| | | type: temp.Template, |
| | | MenuNo: temp.MenuNo |
| | | } |
| | | |
| | | _tabviews.push(item) |
| | | }) |
| | | |
| | | this.setState({ |
| | | loading: false, |
| | | tabviews: _tabviews |
| | | }) |
| | | |
| | | if (type) { |
| | | notification.success({ |
| | | top: 92, |
| | | message: '刷新成功。', |
| | | duration: 2 |
| | | }) |
| | | } |
| | | } else { |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.message, |
| | | duration: 5 |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | } |
| | | |
| | | // 页面返回 |
| | | handleViewBack = () => { |
| | | let param = { |
| | | editMenu: null, |
| | | optionLibs: null, |
| | | editTab: null, |
| | | tabConfig: null, |
| | | subTabConfig: null, |
| | | btnTab: null, |
| | | btnTabConfig: null, |
| | | editAction: null, |
| | | subConfig: null, |
| | | tabview: '' |
| | | } |
| | | |
| | | this.props.handleView(param) |
| | | } |
| | | |
| | | getFuncNames = (data, funcNames, tableNames) => { |
| | | data.forEach(item => { |
| | | if (item.subfuncs) { |
| | | this.getFuncNames(item.subfuncs, funcNames, tableNames) |
| | | } else { |
| | | if (item.tableName) { |
| | | tableNames.push(item.tableName) |
| | | } |
| | | if (item.innerFunc) { |
| | | funcNames.push({func: item.innerFunc, label: item.label || ''}) |
| | | } |
| | | |
| | | if (item.callbackFunc) { |
| | | funcNames.push({func: item.callbackFunc, label: item.label || ''}) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | return { |
| | | func: funcNames, |
| | | table: tableNames |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 三级菜单保存 |
| | | */ |
| | | submitConfig = () => { |
| | | const { menu } = this.props |
| | | const { originMenu, openEdition } = this.state |
| | | |
| | | let config = fromJS(this.state.config).toJS() |
| | | |
| | | this.menuformRef.handleConfirm().then(res => { |
| | | if (config.isAdd) { |
| | | config.search = config.search.filter(item => !item.origin) |
| | | } |
| | | |
| | | let _LongParam = '' |
| | | let _config = {...config, easyCode: res.easyCode} |
| | | let _pageParam = {...menu.PageParam, OpenType: res.opentype} |
| | | |
| | | // 未设置数据源或标签不合法时,启用状态为false |
| | | let vresult = this.verifyconfig(_config) |
| | | if (vresult !== true) { |
| | | _config.enabled = false |
| | | } |
| | | |
| | | _config.funcs = [] // 页面及子页面存储过程集 |
| | | |
| | | _config.funcs.push({ |
| | | type: 'view', |
| | | subtype: 'view', |
| | | uuid: menu.MenuID, |
| | | intertype: _config.setting.interType || 'inner', |
| | | interface: _config.setting.interface || '', |
| | | tableName: _config.setting.tableName || '', |
| | | innerFunc: _config.setting.innerFunc || '', |
| | | outerFunc: _config.setting.outerFunc || '' |
| | | }) |
| | | |
| | | if (_config.tab) { |
| | | _config.funcs.push({ |
| | | type: 'tab', |
| | | subtype: 'tab', |
| | | uuid: _config.tab.uuid, |
| | | label: _config.tab.label, |
| | | linkTab: _config.tab.linkTab |
| | | }) |
| | | } |
| | | |
| | | if (this.state.closeVisible) { // 显示关闭对话框时,模态框中保存按钮,显示保存中状态 |
| | | this.setState({ |
| | | menucloseloading: true |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | menuloading: true |
| | | }) |
| | | } |
| | | |
| | | new Promise(resolve => { |
| | | if (_config.tab) { |
| | | Api.getSystemConfig({ |
| | | func: 'sPC_Get_LongParam', |
| | | MenuID: _config.tab.linkTab |
| | | }).then(result => { |
| | | if (result.status && result.LongParam) { |
| | | let _LongParam = '' |
| | | |
| | | if (result.LongParam) { |
| | | try { |
| | | _LongParam = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) |
| | | } catch (e) { |
| | | console.warn('Parse Failure') |
| | | _LongParam = '' |
| | | } |
| | | } |
| | | |
| | | if (_LongParam) { |
| | | _config.funcs[1].menuNo = _LongParam.tabNo || '' |
| | | _config.funcs[1].subfuncs = _LongParam.funcs || [] |
| | | } |
| | | } |
| | | resolve() |
| | | }) |
| | | } else { |
| | | resolve() |
| | | } |
| | | }).then(() => { |
| | | // 保存时删除配置类型,system 、user |
| | | delete _config.type |
| | | delete _config.isAdd |
| | | |
| | | try { |
| | | _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config))) |
| | | } catch (e) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '编译错误', |
| | | duration: 5 |
| | | }) |
| | | this.setState({ |
| | | menucloseloading: false, |
| | | menuloading: false |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let tabParam = { // 添加菜单tab页 |
| | | func: 'sPC_sMenusTab_AddUpt', |
| | | MenuID: menu.MenuID |
| | | } |
| | | |
| | | if (_config.tab) { |
| | | tabParam.LText = Utils.formatOptions(`select '${menu.MenuID}' as MenuID ,'${_config.tab.linkTab}' as Tabid,'${_config.tab.label}' as TabName ,'0' as Sort`) |
| | | } else { |
| | | tabParam.LText = Utils.formatOptions(`select '${menu.MenuID}' as MenuID ,'' as Tabid,'' as TabName ,'0' as Sort`) |
| | | } |
| | | |
| | | tabParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | tabParam.secretkey = Utils.encrypt(tabParam.LText, tabParam.timestamp) |
| | | |
| | | let _vals = this.getFuncNames(_config.funcs, [], []) |
| | | let _tables = Array.from(new Set(_vals.table)) |
| | | |
| | | let param = { |
| | | func: 'sPC_TrdMenu_AddUpt', |
| | | FstID: res.fstMenuId, |
| | | SndID: res.parentId, |
| | | ParentID: res.parentId, |
| | | MenuID: menu.MenuID, |
| | | MenuNo: res.MenuNo, |
| | | EasyCode: res.easyCode, |
| | | Template: menu.PageParam.Template || '', |
| | | MenuName: res.MenuName, |
| | | PageParam: JSON.stringify(_pageParam), |
| | | LongParam: _LongParam, |
| | | LText: _vals.func.map(item => `select '${menu.MenuID}' as MenuID,'${item.func}' as ProcName,'${item.label}' as MenuName`), |
| | | LTexttb: _tables.map(item => `select '${menu.MenuID}' as MenuID,'${item}' as tbName`) |
| | | } |
| | | |
| | | if (menu.menuSort) { // 菜单新建时设置排序 |
| | | param.Sort = menu.menuSort |
| | | } |
| | | |
| | | param.LText = param.LText.join(' union all ') |
| | | param.LText = Utils.formatOptions(param.LText) |
| | | param.LTexttb = param.LTexttb.join(' union all ') |
| | | param.LTexttb = Utils.formatOptions(param.LTexttb) |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | param.secretkey = Utils.encrypt(param.LText, param.timestamp) |
| | | |
| | | if (openEdition) { // 版本管理 |
| | | param.open_edition = openEdition |
| | | } |
| | | |
| | | // 保存本地 |
| | | let localParam = fromJS(param).toJS() |
| | | |
| | | Api.getSystemConfig(param).then(response => { |
| | | if (response.status) { |
| | | let _FMenu = originMenu.fstMenuList.filter(fstM => fstM.MenuID === res.fstMenuId)[0] |
| | | let _supMenuList = [] |
| | | if (_FMenu) { |
| | | _supMenuList = _FMenu.options |
| | | } |
| | | |
| | | this.setState({ |
| | | config: _config, |
| | | openEdition: response.open_edition || '', |
| | | originMenu: { |
| | | ...originMenu, |
| | | LongParam: _config, |
| | | PageParam: _pageParam, |
| | | MenuName: res.MenuName, |
| | | MenuNo: res.MenuNo, |
| | | ParentID: res.parentId, |
| | | fstMenuId: res.fstMenuId, |
| | | supMenuList: _supMenuList |
| | | } |
| | | }) |
| | | |
| | | this.props.reloadmenu() |
| | | |
| | | // 标签信息保存 |
| | | Api.getSystemConfig(tabParam).then(result => { |
| | | if (result.status) { |
| | | notification.success({ |
| | | top: 92, |
| | | message: '保存成功', |
| | | duration: 2 |
| | | }) |
| | | if (this.state.closeVisible) { |
| | | this.handleViewBack() |
| | | } else { |
| | | this.setState({ |
| | | menuloading: false, |
| | | menucloseloading: false |
| | | }) |
| | | } |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 5 |
| | | }) |
| | | this.setState({ |
| | | menuloading: false, |
| | | menucloseloading: false |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | localParam.func = 'sPC_TrdMenu_AddUpt_For_Local' |
| | | delete localParam.LongParam |
| | | delete localParam.PageParam |
| | | delete localParam.Template |
| | | delete localParam.Sort |
| | | delete localParam.EasyCode |
| | | delete localParam.open_edition |
| | | |
| | | Api.getLocalConfig(localParam) |
| | | } else { |
| | | this.setState({ |
| | | menuloading: false, |
| | | menucloseloading: false |
| | | }) |
| | | notification.warning({ |
| | | top: 92, |
| | | message: response.message, |
| | | duration: 5 |
| | | }) |
| | | } |
| | | }) |
| | | }) |
| | | }, () => { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: this.state.dict['model.menu.basemsg'], |
| | | duration: 5 |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | cancelConfig = () => { |
| | | const { menu } = this.props |
| | | const { config, originMenu } = this.state |
| | | |
| | | let _this = this |
| | | |
| | | if (config.isAdd) { |
| | | confirm({ |
| | | content: '菜单尚未提交,确定放弃保存吗?', |
| | | okText: this.state.dict['model.confirm'], |
| | | cancelText: this.state.dict['model.cancel'], |
| | | onOk() { |
| | | _this.props.handleView() |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } else { |
| | | this.menuformRef.handleConfirm().then(res => { |
| | | let _config = {...config, easyCode: res.easyCode} |
| | | let _pageParam = {...menu.PageParam, OpenType: res.opentype} |
| | | let _originMenu = { |
| | | ...originMenu, |
| | | LongParam: _config, |
| | | PageParam: _pageParam, |
| | | MenuName: res.MenuName, |
| | | MenuNo: res.MenuNo, |
| | | ParentID: res.parentId, |
| | | fstMenuId: res.fstMenuId |
| | | } |
| | | |
| | | if (!is(fromJS(originMenu), fromJS(_originMenu))) { |
| | | this.setState({ |
| | | closeVisible: true |
| | | }) |
| | | } else { |
| | | this.props.handleView() |
| | | } |
| | | }, () => { |
| | | this.setState({ |
| | | closeVisible: true |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 设置可配置按钮 |
| | | */ |
| | | setSubConfig = () => { |
| | | const { menu } = this.props |
| | | const { config, originMenu, optionLibs, activeKey, openEdition } = this.state |
| | | |
| | | if (config.isAdd) { // 新建菜单,提示菜单尚未保存 |
| | | notification.warning({ |
| | | top: 92, |
| | | message: this.state.dict['header.menu.config.notsave'], |
| | | duration: 5 |
| | | }) |
| | | } else { |
| | | this.menuformRef.handleConfirm().then(res => { |
| | | let _config = {...config, easyCode: res.easyCode} |
| | | let _pageParam = {...menu.PageParam, OpenType: res.opentype} |
| | | let _originMenu = { |
| | | ...originMenu, |
| | | LongParam: _config, |
| | | PageParam: _pageParam, |
| | | MenuName: res.MenuName, |
| | | MenuNo: res.MenuNo, |
| | | ParentID: res.parentId, |
| | | fstMenuId: res.fstMenuId |
| | | } |
| | | |
| | | if (!is(fromJS(originMenu), fromJS(_originMenu))) { // 菜单信息变化时,提示保存 |
| | | notification.warning({ |
| | | top: 92, |
| | | message: this.state.dict['header.menu.config.update'], |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | // 菜单信息验证通过后,跳转子配置页面 |
| | | _originMenu.activeKey = activeKey // 保存当前打开页签 |
| | | _originMenu.open_edition = openEdition // 更新版本号 |
| | | |
| | | let param = { |
| | | optionLibs: optionLibs, |
| | | editMenu: _originMenu, |
| | | editTab: fromJS(config.tab).toJS(), |
| | | tabConfig: null, |
| | | editSubTab: null, |
| | | subTabConfig: null, |
| | | btnTab: null, |
| | | btnTabConfig: null, |
| | | editAction: '', |
| | | subConfig: '', |
| | | tabview: config.tab.type |
| | | } |
| | | |
| | | // 当子表使用主页搜索条件时,将主页搜索向下传递 |
| | | if (param.editTab && param.editTab.searchPass === 'true') { |
| | | param.editTab.mainsearch = fromJS(_config.search).toJS() |
| | | } |
| | | |
| | | this.setState({ |
| | | loading: true |
| | | }) |
| | | |
| | | Api.getSystemConfig({ |
| | | func: 'sPC_Get_LongParam', |
| | | MenuID: config.tab.linkTab |
| | | }).then(res => { |
| | | if (res.status) { |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | let _LongParam = '' |
| | | if (res.LongParam) { |
| | | try { |
| | | _LongParam = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam))) |
| | | } catch (e) { |
| | | console.warn('Parse Failure') |
| | | _LongParam = '' |
| | | } |
| | | } |
| | | |
| | | if (_LongParam && param.tabview === 'SubTable' && _LongParam.Template === 'SubTable') { |
| | | param.subConfig = _LongParam |
| | | } |
| | | |
| | | if (param.editTab) { |
| | | param.editTab.open_edition = res.open_edition || '' |
| | | } |
| | | |
| | | this.props.handleView(param) |
| | | } else { |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.message, |
| | | duration: 5 |
| | | }) |
| | | } |
| | | }) |
| | | }, () => { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: this.state.dict['header.menu.config.update'], |
| | | duration: 5 |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 切换标签是否启用 |
| | | */ |
| | | onEnabledChange = () => { |
| | | const { config } = this.state |
| | | |
| | | let _enabled = !config.enabled |
| | | let result = this.verifyconfig(config) |
| | | |
| | | if (_enabled && result !== true) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result, |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | this.setState({ |
| | | config: {...config, enabled: _enabled} |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 校验配置信息的合法性 |
| | | */ |
| | | verifyconfig = (config) => { |
| | | let hasKey = false |
| | | let chartcols = [] |
| | | config.columns.forEach(col => { |
| | | if (col.field) { |
| | | chartcols.push(col.field) |
| | | } |
| | | if (config.setting.primaryKey === col.field) { |
| | | hasKey = true |
| | | } |
| | | }) |
| | | |
| | | if (config.setting.interType === 'inner' && !config.setting.innerFunc && config.setting.default !== 'false' && !config.setting.dataresource) { |
| | | return '菜单尚未设置数据源,不可启用!' |
| | | } else if (!config.setting.primaryKey) { |
| | | return '菜单尚未设置主键,不可启用!' |
| | | } else if (!hasKey) { |
| | | return '显示列中不存在主键字段,不可启用!' |
| | | } else { |
| | | return true |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 编辑功能完成更新,包括解冻按钮、粘贴、替换等 |
| | | */ |
| | | updateConfig = (res) => { |
| | | if (res.type === 'thaw') { |
| | | this.setState({ |
| | | config: res.config |
| | | }) |
| | | } else if (res.type === 'paste') { |
| | | this.setState({ |
| | | pasteContent: res.content |
| | | }, () => { |
| | | this.setState({ |
| | | pasteContent: null |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 更新搜索条件配置信息 |
| | | */ |
| | | updatesearch = (config, options) => { |
| | | const { optionLibs } = this.state |
| | | |
| | | this.setState({ |
| | | config: config, |
| | | optionLibs: options || optionLibs |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 更新显示列配置信息 |
| | | */ |
| | | updateconfig = (config) => { |
| | | this.setState({ |
| | | config: config |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 更新常用表信息,快捷添加后更新配置信息 |
| | | */ |
| | | updatetable = (config, fields) => { |
| | | const { tableFields } = this.state |
| | | |
| | | this.setState({ |
| | | config: config, |
| | | tableFields: fields ? fields : tableFields |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 批量添加,更新配置信息 |
| | | */ |
| | | updatefield = (config) => { |
| | | this.setState({ |
| | | config: config |
| | | }) |
| | | } |
| | | |
| | | // 年切换时重新生成数据 |
| | | changeDate = (year) => { |
| | | this.setState({mockloading: true}, () => { |
| | | this.setState({ |
| | | mockloading: false, |
| | | mockdata: this.getMockData(year) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { activeKey, config, tabviews, mockdata, mockloading } = this.state |
| | | |
| | | return ( |
| | | <div className="model-subtable-board"> |
| | | <DndProvider backend={HTML5Backend}> |
| | | {/* 工具栏 */} |
| | | <div className="tools"> |
| | | <Collapse accordion defaultActiveKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}> |
| | | {/* 基本信息 */} |
| | | <Panel forceRender={true} header={'标签基本信息'} key="0" id="subtable-basedata"> |
| | | {/* 菜单信息 */} |
| | | <MenuForm |
| | | dict={this.state.dict} |
| | | formlist={this.state.menuformlist} |
| | | wrappedComponentRef={(inst) => this.menuformRef = inst} |
| | | /> |
| | | {/* 表名添加 */} |
| | | <TableComponent |
| | | config={config} |
| | | containerId="subtable-basedata" |
| | | updatetable={this.updatetable} |
| | | /> |
| | | </Panel> |
| | | {/* 搜索条件添加 */} |
| | | <Panel header={this.state.dict['header.menu.search']} key="1"> |
| | | <div className="search-element"> |
| | | {Source.searchItems.map((item, index) => { |
| | | return (<SourceElement key={index} content={item}/>) |
| | | })} |
| | | </div> |
| | | <FieldsComponent |
| | | config={config} |
| | | type="search" |
| | | tableFields={this.state.tableFields} |
| | | updatefield={this.updatefield} |
| | | /> |
| | | </Panel> |
| | | </Collapse> |
| | | </div> |
| | | <div className="setting"> |
| | | <Card title={ |
| | | <div> |
| | | 日历页面配置 |
| | | <Icon type="redo" style={{marginLeft: '10px'}} title="刷新标签列表" onClick={() => this.reloadTab(true)} /> |
| | | </div> |
| | | } bordered={false} extra={ |
| | | <div> |
| | | {/* <EditComponent dict={this.state.dict} type="subtable" config={this.state.config} refresh={this.updateConfig}/> */} |
| | | <Switch className="big" checkedChildren="启" unCheckedChildren="停" checked={this.state.config.enabled} onChange={this.onEnabledChange} /> |
| | | <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['model.save']}</Button> |
| | | <Button onClick={this.cancelConfig}>{this.state.dict['model.back']}</Button> |
| | | </div> |
| | | } style={{ width: '100%' }}> |
| | | <SettingComponent |
| | | type="subtable" |
| | | config={config} |
| | | MenuID={config.uuid} |
| | | menuformRef={this.menuformRef} |
| | | permFuncField={this.props.permFuncField} |
| | | updateConfig={this.updateconfig} |
| | | /> |
| | | <SearchComponent |
| | | menu={{MenuID: config.uuid, MenuName: config.tabName}} |
| | | config={config} |
| | | pasteContent={this.state.pasteContent} |
| | | sysRoles={this.props.sysRoles} |
| | | optionLibs={this.state.optionLibs} |
| | | updatesearch={this.updatesearch} |
| | | /> |
| | | <div className="calendar-wrap"> |
| | | <TabComponent config={config} updateConfig={this.updateconfig} tabviews={tabviews} setSubConfig={this.setSubConfig} /> |
| | | <CalComponent config={config} updateConfig={this.updateconfig} /> |
| | | <CalendarComponent calendar={{ |
| | | levels: config.calendar.levels, startfield: 'start', endfield: 'end', colorfield: 'color', remarkfield: 'remark' |
| | | }} loading={mockloading} data={mockdata} changeDate={this.changeDate}/> |
| | | </div> |
| | | </Card> |
| | | </div> |
| | | </DndProvider> |
| | | <Modal |
| | | bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}} |
| | | closable={false} |
| | | maskClosable={false} |
| | | visible={this.state.closeVisible} |
| | | onCancel={() => { this.setState({closeVisible: false}) }} |
| | | footer={[ |
| | | <Button key="save" className="mk-btn mk-green" loading={this.state.menucloseloading} onClick={this.submitConfig}>{this.state.dict['model.save']}</Button>, |
| | | <Button key="confirm" className="mk-btn mk-yellow" onClick={this.handleViewBack}>{this.state.dict['model.notsave']}</Button>, |
| | | <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>{this.state.dict['model.cancel']}</Button> |
| | | ]} |
| | | destroyOnClose |
| | | > |
| | | {this.state.dict['header.menu.config.placeholder']} |
| | | </Modal> |
| | | {this.state.loading && <Spin size="large" />} |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | const mapStateToProps = (state) => { |
| | | return { |
| | | sysRoles: state.sysRoles, |
| | | permFuncField: state.permFuncField, |
| | | memberLevel: state.memberLevel |
| | | } |
| | | } |
| | | |
| | | const mapDispatchToProps = () => { |
| | | return {} |
| | | } |
| | | |
| | | export default connect(mapStateToProps, mapDispatchToProps)(SubTableConfig) |
New file |
| | |
| | | .model-subtable-board { |
| | | position: fixed; |
| | | z-index: 1070; |
| | | padding-top: 48px; |
| | | top: 0px; |
| | | left: 0px; |
| | | right: 0px; |
| | | bottom: 0px; |
| | | background: rgba(0, 0, 0, 0.35); |
| | | display: flex; |
| | | .tools { |
| | | flex: 1; |
| | | background: #ffffff; |
| | | border-right: 1px solid #d9d9d9; |
| | | height: 100%; |
| | | overflow-y: hidden; |
| | | padding-bottom: 30px; |
| | | .ant-collapse-item { |
| | | position: relative; |
| | | border: 0; |
| | | } |
| | | .ant-input-search { |
| | | margin-top: 10px; |
| | | } |
| | | .ant-collapse-item.ant-collapse-item-active { |
| | | border-bottom: 1px solid #d9d9d9; |
| | | } |
| | | .ant-collapse .ant-collapse-header { |
| | | padding: 11px 16px 10px 40px; |
| | | border-bottom: 1px solid #d9d9d9; |
| | | background: #1890ff; |
| | | color: #ffffff; |
| | | } |
| | | .ant-collapse-content-box { |
| | | .ant-form-item { |
| | | margin-bottom: 10px; |
| | | .ant-form-item-label { |
| | | text-align: left; |
| | | height: 25px; |
| | | line-height: 25px; |
| | | } |
| | | } |
| | | } |
| | | .search-element { |
| | | padding-top: 10px; |
| | | li { |
| | | padding: 0px 16px 10px; |
| | | div { |
| | | cursor: move; |
| | | } |
| | | } |
| | | } |
| | | .config-btn { |
| | | position: relative; |
| | | |
| | | .config-btn-title { |
| | | margin-top: 20px; |
| | | margin-bottom: 10px; |
| | | color: #1890ff; |
| | | border-bottom: 1px solid #e8e8e8; |
| | | } |
| | | } |
| | | .ant-list { |
| | | margin-top: 20px; |
| | | .ant-list-item { |
| | | display: -webkit-box; |
| | | padding-right: 20px; |
| | | position: relative; |
| | | padding-left: 5px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | -webkit-line-clamp: 2; |
| | | -webkit-box-orient: vertical; |
| | | min-height: 55px; |
| | | width: 100%; |
| | | .anticon { |
| | | position: absolute; |
| | | top: 0px; |
| | | right: 0px; |
| | | padding: 3px 3px 10px 10px; |
| | | cursor: pointer; |
| | | } |
| | | .bottom-mask { |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 8px; |
| | | bottom: 0; |
| | | left: 0; |
| | | background: #ffffff; |
| | | border-radius: 8px; |
| | | } |
| | | } |
| | | } |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .config-button { |
| | | min-width: 65px; |
| | | } |
| | | } |
| | | .tools:hover { |
| | | overflow-y: auto; |
| | | } |
| | | .tools::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .tools::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | .tools::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | .tools:hover::-webkit-scrollbar-thumb { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); |
| | | background: rgba(0, 0, 0, 0.13); |
| | | } |
| | | .tools:hover::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | } |
| | | .setting { |
| | | position: relative; |
| | | width: calc(100vw - 235px); |
| | | height: 100%; |
| | | background: #ffffff; |
| | | .ant-switch.big { |
| | | min-width: 60px; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | margin-top: -2px; |
| | | .ant-switch-inner { |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | .ant-switch.big::after { |
| | | width: 24px; |
| | | height: 24px; |
| | | } |
| | | .ant-card-head { |
| | | min-height: 44px; |
| | | } |
| | | .ant-card-head-title { |
| | | padding: 5px 0; |
| | | color: #1890ff; |
| | | } |
| | | .ant-card-extra { |
| | | padding: 5px 0; |
| | | button { |
| | | margin-left: 20px; |
| | | } |
| | | } |
| | | .ant-card-body { |
| | | position: relative; |
| | | padding: 0; |
| | | |
| | | .chart-view { |
| | | margin-bottom: 70px; |
| | | |
| | | .chart-title { |
| | | position: relative; |
| | | color: rgba(0, 0, 0, 0.65); |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | margin: 0 20px; |
| | | padding: 10px 5px 5px; |
| | | } |
| | | } |
| | | > .anticon-setting { |
| | | position: absolute; |
| | | font-size: 18px; |
| | | right: 7px; |
| | | top: 10px; |
| | | } |
| | | .calendar-wrap { |
| | | position: relative; |
| | | padding-top: 10px; |
| | | } |
| | | } |
| | | } |
| | | .setting { |
| | | overflow-y: scroll; |
| | | } |
| | | .setting::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .setting::-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); |
| | | display: none; |
| | | } |
| | | .setting::-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); |
| | | } |
| | | .setting:hover::-webkit-scrollbar-thumb { |
| | | display: block; |
| | | } |
| | | .ant-spin { |
| | | position: absolute; |
| | | margin-left: calc(50vw - 22px); |
| | | margin-top: 30vh; |
| | | } |
| | | } |
New file |
| | |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | |
| | | const CommonDict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | |
| | | class CalendarBaseData { |
| | | baseConfig = { |
| | | version: '1.0', |
| | | type: 'system', |
| | | Template: 'CalendarPage', |
| | | enabled: false, |
| | | tabName: '', |
| | | tabNo: '', |
| | | Remark: '', |
| | | uuid: Utils.getuuid(), |
| | | setting: { |
| | | tableName: '', |
| | | primaryKey: '', |
| | | dataresource: '', |
| | | interType: 'inner', |
| | | innerFunc: '', |
| | | interface: '', |
| | | outerFunc: '' |
| | | }, |
| | | columns: [], |
| | | scripts: [], |
| | | tables: [], |
| | | tab: null, |
| | | calendar: { |
| | | levels: ['day', 'month', 'year'], |
| | | startfield: '', |
| | | endfield: '', |
| | | colorfield: '', |
| | | remarkfield: '' |
| | | }, |
| | | search: [ |
| | | { |
| | | origin: true, |
| | | uuid: Utils.getuuid(), |
| | | label: 'label', |
| | | field: '', |
| | | initval: '', |
| | | type: 'text', |
| | | resourceType: '0', |
| | | setAll: 'false', |
| | | options: [], |
| | | orderType: 'asc', |
| | | match: 'like', |
| | | display: 'dropdown' |
| | | }, { |
| | | origin: true, |
| | | uuid: Utils.getuuid(), |
| | | label: 'label', |
| | | field: '', |
| | | initval: '', |
| | | type: 'select', |
| | | resourceType: '0', |
| | | setAll: 'false', |
| | | options: [], |
| | | orderType: 'asc', |
| | | match: 'equal', |
| | | display: 'dropdown' |
| | | }, { |
| | | origin: true, |
| | | uuid: Utils.getuuid(), |
| | | label: 'label', |
| | | field: '', |
| | | initval: '', |
| | | type: 'date', |
| | | resourceType: '0', |
| | | setAll: 'false', |
| | | options: [], |
| | | orderType: 'asc', |
| | | match: 'greater', |
| | | display: 'dropdown' |
| | | } |
| | | ] |
| | | } |
| | | |
| | | searchItems = [ |
| | | { |
| | | type: 'search', |
| | | label: CommonDict['model.form.text'], |
| | | subType: 'text', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'search', |
| | | label: CommonDict['model.form.select'], |
| | | subType: 'select', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'search', |
| | | label: CommonDict['model.form.multiselect'], |
| | | subType: 'multiselect', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'search', |
| | | label: CommonDict['model.form.link'], |
| | | subType: 'link', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'search', |
| | | label: CommonDict['model.form.dateday'], |
| | | subType: 'date', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'search', |
| | | label: CommonDict['model.form.dateweek'], |
| | | subType: 'dateweek', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'search', |
| | | label: CommonDict['model.form.datemonth'], |
| | | subType: 'datemonth', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'search', |
| | | label: CommonDict['model.form.daterange'], |
| | | subType: 'daterange', |
| | | url: '' |
| | | }, |
| | | { |
| | | type: 'search', |
| | | label: CommonDict['model.form.dategroup'], |
| | | subType: 'group', |
| | | url: '' |
| | | } |
| | | ] |
| | | } |
| | | |
| | | export default new CalendarBaseData() |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import { getTabForm } from '@/templates/zshare/formconfig' |
| | | import TabForm from './tabform' |
| | | import './index.scss' |
| | | |
| | | const { confirm } = Modal |
| | | |
| | | class SettingComponent extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, // 标签 |
| | | tabviews: PropTypes.array, // 标签集 |
| | | updateConfig: PropTypes.func, |
| | | setSubConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | menu: null, // 菜单信息 |
| | | formlist: null, // 表单信息 |
| | | visible: false // 模态框控制 |
| | | } |
| | | |
| | | /** |
| | | * @description 保存页面配置信息 |
| | | */ |
| | | tabSave = () => { |
| | | const { config } = this.props |
| | | |
| | | this.tabRef.handleConfirm().then(res => { |
| | | this.setState({ |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, tab: res}) |
| | | }) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) || !is(fromJS(this.props.config.tab), fromJS(nextProps.config.tab)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 添加或修改标签 |
| | | */ |
| | | handleTab = (e) => { |
| | | e.stopPropagation() |
| | | const { config } = this.props |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | formlist: getTabForm(config.tab || {}, '', [], '', [], config.Template) |
| | | }) |
| | | } |
| | | |
| | | closeTab = (e) => { |
| | | const { config } = this.props |
| | | const _this = this |
| | | e.stopPropagation() |
| | | |
| | | confirm({ |
| | | content: '确定删除标签吗?', |
| | | okText: this.state.dict['model.confirm'], |
| | | cancelText: this.state.dict['model.cancel'], |
| | | onOk() { |
| | | _this.props.updateConfig({...config, tab: ''}) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { tabviews, config } = this.props |
| | | const { dict, visible } = this.state |
| | | |
| | | return ( |
| | | <div className="model-calendar-tab"> |
| | | {config.tab ? <div className="tab-control"> |
| | | <span onDoubleClick={this.props.setSubConfig}>{config.tab.label}</span> |
| | | <Icon type="edit" onClick={this.handleTab} /> |
| | | <Icon type="close" onClick={this.closeTab} /> |
| | | </div> : <Icon title="添加标签" type="plus" onClick={this.handleTab} />} |
| | | {/* 设置全局配置及列表数据源 */} |
| | | <Modal |
| | | wrapClassName="model-calendar-tab-modal" |
| | | title={dict['model.edit']} |
| | | visible={visible} |
| | | width={900} |
| | | maskClosable={false} |
| | | onCancel={() => { this.setState({ visible: false })}} |
| | | cancelText={this.state.dict['model.cancel']} |
| | | okText={this.state.dict['model.confirm']} |
| | | onOk={this.tabSave} |
| | | destroyOnClose |
| | | > |
| | | <TabForm |
| | | tabs={tabviews} |
| | | dict={dict} |
| | | inputSubmit={this.tabSave} |
| | | formlist={this.state.formlist} |
| | | wrappedComponentRef={(inst) => this.tabRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default SettingComponent |
New file |
| | |
| | | .model-calendar-tab { |
| | | position: absolute; |
| | | top: 0; |
| | | >.anticon-plus { |
| | | position: absolute; |
| | | font-size: 18px; |
| | | left: 10px; |
| | | top: 10px; |
| | | color: #26c281; |
| | | cursor: pointer; |
| | | } |
| | | .tab-control { |
| | | position: absolute; |
| | | padding: 15px 0px 0px 10px; |
| | | left: 0px; |
| | | top: 0px; |
| | | |
| | | span { |
| | | display: inline-block; |
| | | white-space: nowrap; |
| | | font-size: 16px; |
| | | cursor: pointer; |
| | | padding: 0 10px; |
| | | border-bottom: 2px solid #1890ff; |
| | | } |
| | | |
| | | .anticon-edit { |
| | | position: absolute; |
| | | font-size: 14px; |
| | | left: 10px; |
| | | top: 2px; |
| | | color: #1890ff; |
| | | cursor: pointer; |
| | | display: none; |
| | | } |
| | | .anticon-close { |
| | | position: absolute; |
| | | font-size: 14px; |
| | | left: 35px; |
| | | top: 2px; |
| | | color: #ff4d4f; |
| | | cursor: pointer; |
| | | display: none; |
| | | } |
| | | } |
| | | .tab-control:hover { |
| | | .anticon-edit { |
| | | display: inline-block; |
| | | } |
| | | .anticon-close { |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .model-calendar-tab-modal { |
| | | .ant-modal { |
| | | top: 50px; |
| | | padding-bottom: 5px; |
| | | .ant-modal-body { |
| | | max-height: calc(100vh - 190px); |
| | | overflow-y: auto; |
| | | // .ant-empty { |
| | | // margin: 15vh 8px; |
| | | // } |
| | | } |
| | | .ant-modal-body::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .ant-modal-body::-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); |
| | | } |
| | | .ant-modal-body::-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); |
| | | } |
| | | .ant-empty-normal { |
| | | margin: 5px 0px; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Select, Icon, Tooltip, Radio, InputNumber } from 'antd' |
| | | import { formRule } from '@/utils/option.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import './index.scss' |
| | | |
| | | class MainTab extends Component { |
| | | static propTpyes = { |
| | | tabs: PropTypes.array, // 可关联标签集 |
| | | dict: PropTypes.object, // 字典项 |
| | | formlist: PropTypes.any, // 表单 |
| | | inputSubmit: PropTypes.any // 回车提交事件 |
| | | } |
| | | |
| | | state = { |
| | | formlist: null // 表单 |
| | | } |
| | | |
| | | /** |
| | | * @description 表单预处理 |
| | | */ |
| | | UNSAFE_componentWillMount () { |
| | | const { formlist } = this.props |
| | | |
| | | let type = formlist.filter(cell => cell.key === 'type')[0].initVal |
| | | |
| | | let _tabs = this.props.tabs.filter(tab => tab.type === type) |
| | | |
| | | this.setState({ |
| | | formlist: formlist.map(item => { |
| | | if (item.key === 'linkTab') { |
| | | item.options = [ |
| | | { |
| | | value: '', |
| | | text: '新建' |
| | | }, |
| | | ..._tabs |
| | | ] |
| | | } |
| | | |
| | | return item |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 标签页类型切换 |
| | | */ |
| | | openTypeChange = (key, value) => { |
| | | const { formlist } = this.state |
| | | |
| | | if (key === 'type') { |
| | | let _tabs = this.props.tabs.filter(tab => tab.type === value) |
| | | |
| | | this.setState({ |
| | | formlist: formlist.map(item => { |
| | | if (item.key === 'linkTab') { |
| | | item.options = [ |
| | | { |
| | | value: '', |
| | | text: '新建' |
| | | }, |
| | | ..._tabs |
| | | ] |
| | | item.initVal = '' |
| | | } |
| | | return item |
| | | }) |
| | | }, () => { |
| | | if (this.props.form.getFieldValue('linkTab') !== undefined) { |
| | | this.props.form.setFieldsValue({linkTab: ''}) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | getFields() { |
| | | const { getFieldDecorator } = this.props.form |
| | | const fields = [] |
| | | |
| | | this.state.formlist.forEach((item, index) => { |
| | | if (item.hidden || item.forbid) return |
| | | |
| | | if (item.type === 'text') { |
| | | let rules = [] |
| | | |
| | | if (item.key === 'foreignKey') { |
| | | rules.push({ |
| | | pattern: /^[a-zA-Z_]*$/ig, |
| | | message: item.label + '字段只允许包含字母及下划线!' |
| | | }) |
| | | } |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={ |
| | | item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.input'] + item.label + '!' |
| | | }, |
| | | { |
| | | max: formRule.input.max, |
| | | message: formRule.input.message |
| | | }, |
| | | ...rules |
| | | ] |
| | | })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'number') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={ |
| | | item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.input'] + item.label + '!' |
| | | } |
| | | ] |
| | | })(<InputNumber disabled={item.readonly} min={item.min} max={item.max} precision={0} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'select') { // 下拉搜索 |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | onChange={(value) => {this.openTypeChange(item.key, value)}} |
| | | > |
| | | {item.options.map((option, i) => |
| | | <Select.Option id={'mk' + i} title={option.text} key={'mk' + i} value={option.value}> |
| | | {item.key === 'icon' && i !== 0 ? <Icon type={option.text} /> : option.text} |
| | | </Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'mutilselect') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={ |
| | | item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal |
| | | })( |
| | | <Select |
| | | mode="multiple" |
| | | style={{ width: '100%' }} |
| | | placeholder="" |
| | | > |
| | | {item.options.map((option, index) => |
| | | <Select.Option id={option.uuid} title={option.label} key={index} value={option.uuid}>{option.label}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'radio') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Radio.Group> |
| | | { |
| | | item.options.map(option => { |
| | | return ( |
| | | <Radio key={option.value} value={option.value}>{option.text}</Radio> |
| | | ) |
| | | }) |
| | | } |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } |
| | | }) |
| | | |
| | | return fields |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | |
| | | if (!values.linkTab) { // 没有关联标签(新建时),创建新标签Id |
| | | values.linkTab = Utils.getuuid() |
| | | } |
| | | |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | return ( |
| | | <Form {...formItemLayout} className="model-tab-form"> |
| | | <Row gutter={24}>{this.getFields()}</Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(MainTab) |
New file |
| | |
| | | .model-tab-form { |
| | | min-height: 180px; |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | .ant-input-number-input:read-only { |
| | | color: red; |
| | | :hover { |
| | | border-color: #d9d9d9; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | _LText = _LText.join(' union all ') |
| | | |
| | | // 清空菜单下关联的标签 |
| | | if (!_LText) { |
| | | _LText = `select '${menu.MenuID}' as MenuID ,'' as Tabid,'' as TabName ,'0' as Sort` |
| | | } |
| | | |
| | | tabParam.LText = Utils.formatOptions(_LText) |
| | | tabParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | tabParam.secretkey = Utils.encrypt(tabParam.LText, tabParam.timestamp) |
| | |
| | | new Promise(resolve => { |
| | | let deffers = [] |
| | | |
| | | if (tabParam.LText) { |
| | | let defer = new Promise(resolve => { |
| | | Api.getSystemConfig(tabParam).then(result => { |
| | | resolve(result) |
| | | }) |
| | | let defer = new Promise(resolve => { |
| | | Api.getSystemConfig(tabParam).then(result => { |
| | | resolve(result) |
| | | }) |
| | | deffers.push(defer) |
| | | } |
| | | }) |
| | | deffers.push(defer) |
| | | |
| | | if (btnParam.LText) { |
| | | let defer = new Promise(resolve => { |
| | |
| | | const { menu } = this.props |
| | | const { config, originMenu, optionLibs, activeKey, openEdition } = this.state |
| | | |
| | | if (!originMenu.MenuID) { // menuID不存在时,为新建菜单,提示菜单尚未保存 |
| | | if (config.isAdd) { // 新建菜单,提示菜单尚未保存 |
| | | notification.warning({ |
| | | top: 92, |
| | | message: this.state.dict['header.menu.config.notsave'], |
| | |
| | | /** |
| | | * @description 更新标签配置信息 |
| | | */ |
| | | updatetabs = (config, delcards) => { |
| | | const { delActions } = this.state |
| | | updatetabs = (config) => { |
| | | |
| | | this.setState({ |
| | | config: config, |
| | | delActions: delcards ? [...delActions, ...delcards] : delActions |
| | | config: config |
| | | }) |
| | | } |
| | | |
| | |
| | | |
| | | const ComTableConfig = asyncLoadComponent(() => import('@/templates/comtableconfig')) |
| | | const TreePageConfig = asyncLoadComponent(() => import('@/templates/treepageconfig')) |
| | | const CalendarPageConfig = asyncLoadComponent(() => import('@/templates/calendarconfig')) |
| | | const FormTabConfig = asyncLoadComponent(() => import('@/templates/formtabconfig')) |
| | | const ModalConfig = asyncLoadComponent(() => import('@/templates/modalconfig')) |
| | | const SubTable = asyncLoadComponent(() => import('@/templates/subtableconfig')) |
| | |
| | | |
| | | const illust = { // 模板图片,用于已使用模板 |
| | | CommonTable: mainsubtable, |
| | | TreePage: treepage |
| | | TreePage: treepage, |
| | | CalendarPage: treepage |
| | | } |
| | | |
| | | class EditMenu extends Component { |
| | |
| | | btnTabConfig: null, // 打开新标签按钮配置 |
| | | handleMVisible: false, // 添加或修改菜单模态框(角色权限分配等) |
| | | sysMenu: false, // 添加或编辑菜单(角色权限分配等) |
| | | optionLibs: [], // 自定义下拉选项库 |
| | | optionLibs: null, // 自定义下拉选项库 |
| | | fstMenuId: null, // 一级菜单Id |
| | | fstMenuList: null // 一级菜单列表 |
| | | } |
| | |
| | | handleView={this.handleView} |
| | | /> : null |
| | | } |
| | | {this.state.tabview === 'CalendarPage' ? |
| | | <CalendarPageConfig |
| | | menu={this.state.editMenu} |
| | | optionLibs={this.state.optionLibs} |
| | | reloadmenu={() => {this.props.reload()}} |
| | | handleView={this.handleView} |
| | | /> : null |
| | | } |
| | | {this.state.tabview === 'CommonTable' ? |
| | | <ComTableConfig |
| | | menu={this.state.editMenu} |
| | |
| | | } |
| | | } |
| | | |
| | | let formItem = null |
| | | if (card.type === 'text') { |
| | | formItem = (<Input style={{marginTop: '4px'}} defaultValue={card.initval} />) |
| | | } else if (card.type === 'number') { |
| | | formItem = (<InputNumber defaultValue={card.initval} precision={card.decimal} />) |
| | | } else if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link' || card.type === 'color') { |
| | | formItem = (<Select defaultValue={selectval}></Select>) |
| | | } else if (card.type === 'date') { |
| | | formItem = (<DatePicker defaultValue={card.initval ? moment().subtract(card.initval, 'days') : null} />) |
| | | } else if (card.type === 'datemonth') { |
| | | formItem = (<MonthPicker defaultValue={card.initval ? moment().subtract(card.initval, 'month') : null} />) |
| | | } else if (card.type === 'datetime') { |
| | | formItem = (<DatePicker showTime defaultValue={card.initval ? moment().subtract(card.initval, 'days') : null} />) |
| | | } else if (card.type === 'textarea') { |
| | | formItem = (<TextArea defaultValue={card.initval} autosize={{ minRows: 2, maxRows: 6 }} />) |
| | | } else if (card.type === 'fileupload') { |
| | | formItem = (<Button style={{marginTop: '3px'}}><Icon type="upload" /> 点击上传 </Button>) |
| | | } else if (card.type === 'funcvar') { |
| | | formItem = (<Input style={{marginTop: '4px'}} defaultValue={card.linkfield} />) |
| | | } else if (card.type === 'linkMain') { |
| | | formItem = (<Input style={{marginTop: '4px'}} />) |
| | | } |
| | | |
| | | return ( |
| | | <div className="page-card" style={{ opacity: opacity}}> |
| | | <div ref={node => drag(drop(node))}> |
| | |
| | | <Icon className="edit copy" type="copy" onClick={copy} /> |
| | | </div> |
| | | <div className={'ant-col ant-form-item-control-wrapper ant-col-xs-24 ' + wrapCol}> |
| | | {card.type === 'text' && |
| | | <Input style={{marginTop: '4px'}} defaultValue={card.initval} /> |
| | | } |
| | | {card.type === 'number' && |
| | | <InputNumber defaultValue={card.initval} precision={card.decimal} /> |
| | | } |
| | | {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') && |
| | | <Select defaultValue={selectval}></Select> |
| | | } |
| | | {card.type === 'date' && |
| | | <DatePicker defaultValue={card.initval ? moment().subtract(card.initval, 'days') : null} /> |
| | | } |
| | | {card.type === 'datemonth' ? |
| | | <MonthPicker defaultValue={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null |
| | | } |
| | | {card.type === 'datetime' && |
| | | <DatePicker showTime defaultValue={card.initval ? moment().subtract(card.initval, 'days') : null} /> |
| | | } |
| | | {card.type === 'textarea' && |
| | | <TextArea defaultValue={card.initval} autosize={{ minRows: 2, maxRows: 6 }} /> |
| | | } |
| | | {card.type === 'fileupload' && |
| | | <Button style={{marginTop: '3px'}}> |
| | | <Icon type="upload" /> 点击上传 |
| | | </Button> |
| | | } |
| | | {card.type === 'funcvar' && |
| | | <Input style={{marginTop: '4px'}} defaultValue={card.linkfield} /> |
| | | } |
| | | {card.type === 'linkMain' && |
| | | <Input style={{marginTop: '4px'}} /> |
| | | } |
| | | {formItem} |
| | | <div className="input-mask"></div> |
| | | </div> |
| | | </div>} |
| | | </div> |
| | | {/* <Icon className="edit" type="edit" onClick={edit} /> |
| | | <Icon className="edit close" type="close" onClick={close} /> |
| | | <Icon className="edit copy" type="copy" onClick={copy} /> */} |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | // 导入和导出excel,按钮名称直接为导入、导出 |
| | | newcard.label = item.label |
| | | newcard.class = 'border-dgreen' |
| | | newcard.Ot = 'notRequired' |
| | | } else if (item.subType === 'excelOut') { |
| | | newcard.label = item.label |
| | | newcard.intertype = setting.interType |
| | |
| | | values.uuid = this.state.editItem ? this.state.editItem.uuid : '' |
| | | |
| | | if (/^Nvarchar/ig.test(values.type)) { |
| | | values.limit = values.type.match(/\d+/)[0] |
| | | values.limit = values.type.match(/\d+/) ? values.type.match(/\d+/)[0] : '20000' |
| | | } else if (/^Decimal/ig.test(values.type)) { |
| | | values.limit = values.type.match(/\d+/ig)[1] |
| | | } else { |
| | |
| | | <Select.Option value="Nvarchar(20)"> Nvarchar(20) </Select.Option> |
| | | <Select.Option value="Nvarchar(50)"> Nvarchar(50) </Select.Option> |
| | | <Select.Option value="Nvarchar(100)"> Nvarchar(100) </Select.Option> |
| | | <Select.Option value="Nvarchar(256)"> Nvarchar(256) </Select.Option> |
| | | <Select.Option value="Nvarchar(512)"> Nvarchar(512) </Select.Option> |
| | | <Select.Option value="Nvarchar(1024)"> Nvarchar(1024) </Select.Option> |
| | | <Select.Option value="Nvarchar(2048)"> Nvarchar(2048) </Select.Option> |
| | | <Select.Option value="Nvarchar(max)"> Nvarchar(max) </Select.Option> |
| | | <Select.Option value="Int"> Int </Select.Option> |
| | | <Select.Option value="Decimal(18,0)"> Decimal(18,0) </Select.Option> |
| | | <Select.Option value="Decimal(18,2)"> Decimal(18,2) </Select.Option> |
| | |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { columns, card } = this.props |
| | | let _verify = fromJS(card.verify || {}).toJS() |
| | | let _verify = fromJS(card.verify || {range: 1}).toJS() |
| | | let _columns = _verify.columns || [] |
| | | |
| | | // 同步显示列 |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import VerifyCard from './verifycard' |
| | | import './index.scss' |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | sourcelist: [], |
| | | visible: false, |
| | | loading: false, |
| | | setting: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | this.setState({setting: fromJS(config.setting).toJS()}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | editDataSource = () => { |
| | | this.setState({ |
| | | visible: true |
| | | }) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | |
| | | this.setState({loading: true}) |
| | | this.verifyRef.submitDataSource().then(res => { |
| | | |
| | | this.setState({loading: false, visible: false}) |
| | | this.props.updateConfig({...config, ...res}) |
| | | }, () => { |
| | | this.setState({loading: false}) |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { config } = this.props |
| | | const { visible, dict, loading } = this.state |
| | | |
| | | return ( |
| | | <div className="model-datasource"> |
| | | <Icon type="setting" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="model-datasource-verify-modal popview-modal" |
| | | title={'数据源配置'} |
| | | visible={visible} |
| | | width={'75vw'} |
| | | maskClosable={false} |
| | | style={{minWidth: '900px', maxWidth: '1200px'}} |
| | | okText={dict['model.submit']} |
| | | cancelText={dict['model.cancel']} |
| | | onOk={this.verifySubmit} |
| | | confirmLoading={loading} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <VerifyCard |
| | | dict={dict} |
| | | config={config} |
| | | menuId={this.props.config.uuid} |
| | | searches={config.search} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
New file |
| | |
| | | .model-datasource { |
| | | position: absolute; |
| | | right: 7px; |
| | | top: 5px; |
| | | z-index: 1; |
| | | |
| | | >.anticon-setting { |
| | | font-size: 18px; |
| | | padding: 10px; |
| | | } |
| | | |
| | | .model-input-group-wrapper { |
| | | padding: 0 20px; |
| | | display: inline-block; |
| | | width: 100%; |
| | | text-align: start; |
| | | vertical-align: top; |
| | | margin-bottom: 15px; |
| | | |
| | | .model-input-wrapper { |
| | | position: relative; |
| | | display: table; |
| | | width: 100%; |
| | | border-collapse: separate; |
| | | border-spacing: 0; |
| | | |
| | | .model-input-value { |
| | | display: table-cell; |
| | | width: 100%; |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 4px 0px 0px 4px; |
| | | overflow: hidden; |
| | | text-overflow:ellipsis; |
| | | white-space: nowrap; |
| | | padding: 2px 10px; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .model-input-group-addon { |
| | | display: table-cell; |
| | | width: 1px; |
| | | position: relative; |
| | | padding: 0 11px; |
| | | color: rgba(0, 0, 0, 0.65); |
| | | font-weight: normal; |
| | | font-size: 14px; |
| | | line-height: 1; |
| | | text-align: center; |
| | | background-color: #fafafa; |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 0px 4px 4px 0px; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .model-input-insert { |
| | | display: table-cell; |
| | | width: 100%; |
| | | border: 1px dotted #d9d9d9; |
| | | border-radius: 4px; |
| | | text-align: center; |
| | | cursor: pointer; |
| | | |
| | | .anticon-plus { |
| | | padding: 6px; |
| | | font-size: 16px; |
| | | color: rgb(38, 194, 129); |
| | | } |
| | | } |
| | | } |
| | | .anticon-setting { |
| | | margin-right: 5px; |
| | | padding: 6px; |
| | | cursor: pointer; |
| | | } |
| | | .anticon-setting:hover { |
| | | color: #1890ff; |
| | | } |
| | | .anticon-close { |
| | | padding: 6px; |
| | | cursor: pointer; |
| | | } |
| | | .anticon-close:hover { |
| | | color: #ff4d4f; |
| | | } |
| | | } |
| | | } |
| | | .model-datasource-verify-modal { |
| | | .ant-modal { |
| | | top: 50px; |
| | | .ant-modal-body { |
| | | max-height: calc(100vh - 190px); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Select, Button, Input } from 'antd' |
| | | import './index.scss' |
| | | |
| | | |
| | | class UniqueForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | columnChange: PropTypes.func // 修改函数 |
| | | } |
| | | |
| | | state = { |
| | | editItem: null // 编辑元素 |
| | | } |
| | | |
| | | edit = (record) => { |
| | | this.setState({ |
| | | editItem: record |
| | | }) |
| | | |
| | | this.props.form.setFieldsValue({ |
| | | label: record.label, |
| | | field: record.field, |
| | | datatype: record.datatype |
| | | }) |
| | | } |
| | | |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | values.uuid = this.state.editItem ? this.state.editItem.uuid : '' |
| | | |
| | | this.setState({ |
| | | editItem: null |
| | | }, () => { |
| | | this.props.columnChange(values) |
| | | }) |
| | | this.props.form.setFieldsValue({ |
| | | label: '', |
| | | field: '' |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { getFieldDecorator } = this.props.form |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <Form {...formItemLayout} className="verify-form" id="verifycard1"> |
| | | <Row gutter={24}> |
| | | <Col span={7}> |
| | | <Form.Item label={'名称'}> |
| | | {getFieldDecorator('label', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '名称!' |
| | | } |
| | | ] |
| | | })(<Input placeholder="" autoComplete="off" />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={7}> |
| | | <Form.Item label={'字段'}> |
| | | {getFieldDecorator('field', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '字段!' |
| | | } |
| | | ] |
| | | })(<Input placeholder="" autoComplete="off" />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={7}> |
| | | <Form.Item label={'数据类型'}> |
| | | {getFieldDecorator('datatype', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '数据类型!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select> |
| | | <Select.Option value="Nvarchar(50)"> Nvarchar(50) </Select.Option> |
| | | <Select.Option value="Nvarchar(100)"> Nvarchar(100) </Select.Option> |
| | | <Select.Option value="Nvarchar(512)"> Nvarchar(512) </Select.Option> |
| | | <Select.Option value="Nvarchar(1024)"> Nvarchar(1024) </Select.Option> |
| | | <Select.Option value="Nvarchar(2048)"> Nvarchar(2048) </Select.Option> |
| | | <Select.Option value="Nvarchar(max)"> Nvarchar(max) </Select.Option> |
| | | <Select.Option value="Int"> Int </Select.Option> |
| | | <Select.Option value="Decimal(18,0)"> Decimal(18,0) </Select.Option> |
| | | <Select.Option value="Decimal(18,1)"> Decimal(18,1) </Select.Option> |
| | | <Select.Option value="Decimal(18,2)"> Decimal(18,2) </Select.Option> |
| | | <Select.Option value="Decimal(18,3)"> Decimal(18,3) </Select.Option> |
| | | <Select.Option value="Decimal(18,4)"> Decimal(18,4) </Select.Option> |
| | | <Select.Option value="Decimal(18,5)"> Decimal(18,5) </Select.Option> |
| | | <Select.Option value="Decimal(18,6)"> Decimal(18,6) </Select.Option> |
| | | <Select.Option value="Decimal(18,7)"> Decimal(18,7) </Select.Option> |
| | | <Select.Option value="Decimal(18,8)"> Decimal(18,8) </Select.Option> |
| | | <Select.Option value="Decimal(18,9)"> Decimal(18,9) </Select.Option> |
| | | <Select.Option value="Decimal(18,10)"> Decimal(18,10) </Select.Option> |
| | | <Select.Option value="Decimal(18,11)"> Decimal(18,11) </Select.Option> |
| | | <Select.Option value="Decimal(18,12)"> Decimal(18,12) </Select.Option> |
| | | <Select.Option value="Decimal(18,13)"> Decimal(18,13) </Select.Option> |
| | | <Select.Option value="Decimal(18,14)"> Decimal(18,14) </Select.Option> |
| | | <Select.Option value="Decimal(18,15)"> Decimal(18,15) </Select.Option> |
| | | <Select.Option value="Decimal(18,16)"> Decimal(18,16) </Select.Option> |
| | | <Select.Option value="Decimal(18,17)"> Decimal(18,17) </Select.Option> |
| | | <Select.Option value="Decimal(18,18)"> Decimal(18,18) </Select.Option> |
| | | {/* <Select.Option value="date"> date </Select.Option> */} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={3} className="add"> |
| | | <Button onClick={this.handleConfirm} type="primary" className="mk-green"> |
| | | 保存 |
| | | </Button> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(UniqueForm) |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Button, notification, Select } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import CodeMirror from '@/templates/zshare/codemirror' |
| | | import './index.scss' |
| | | |
| | | class CustomForm extends Component { |
| | | static propTpyes = { |
| | | type: PropTypes.string, // 菜单类型 |
| | | dict: PropTypes.object, // 字典项 |
| | | setting: PropTypes.object, // 设置 |
| | | searches: PropTypes.array, // 搜索条件 |
| | | swhere: PropTypes.string, // where条件 |
| | | arr_field: PropTypes.string, // 列字段 |
| | | regoptions: PropTypes.array, // 正则替换 |
| | | systemScripts: PropTypes.array, // 系统脚本 |
| | | scriptSubmit: PropTypes.func, // 脚本验证后提交 |
| | | scriptsChange: PropTypes.func // 脚本验证 |
| | | } |
| | | |
| | | state = { |
| | | editItem: null, |
| | | loading: false, |
| | | usefulFields: '' |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { searches } = this.props |
| | | |
| | | let _usefulFields = [] |
| | | searches.forEach(item => { |
| | | if (!item.field) return |
| | | |
| | | if (item.type === 'group') { |
| | | if (item.transfer === 'true') { |
| | | _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 (_usefulFields.includes(item.field)) { |
| | | _usefulFields.push(item.field + '1') |
| | | } else { |
| | | _usefulFields.push(item.field) |
| | | } |
| | | }) |
| | | |
| | | this.setState({ |
| | | usefulFields: _usefulFields.join(', ') |
| | | }) |
| | | } |
| | | |
| | | edit = (record) => { |
| | | this.setState({ |
| | | editItem: record |
| | | }) |
| | | |
| | | this.props.form.setFieldsValue({ |
| | | sql: record.sql |
| | | }) |
| | | } |
| | | |
| | | handleCancel = () => { |
| | | this.setState({ |
| | | editItem: null |
| | | }) |
| | | this.props.form.setFieldsValue({ |
| | | sql: '' |
| | | }) |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | 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) |
| | | |
| | | _quot = _quot ? _quot.length : 0 |
| | | _lparen = _lparen ? _lparen.length : 0 |
| | | _rparen = _rparen ? _rparen.length : 0 |
| | | |
| | | 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(() => { |
| | | this.setState({ |
| | | editItem: null, |
| | | loading: false |
| | | }) |
| | | this.props.form.setFieldsValue({ |
| | | sql: '' |
| | | }) |
| | | this.props.scriptSubmit(values) |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | selectScript = (value, option) => { |
| | | let _sql = this.props.form.getFieldValue('sql') |
| | | if (_sql) { |
| | | _sql = _sql + ` |
| | | |
| | | ` |
| | | } |
| | | |
| | | _sql = _sql.replace(/\s{6}$/, '') |
| | | _sql = _sql + `/*${option.props.children}*/ |
| | | ` |
| | | _sql = _sql.replace(/\s{4}$/, '') |
| | | _sql = _sql + value |
| | | |
| | | this.props.form.setFieldsValue({ |
| | | sql: _sql |
| | | }) |
| | | } |
| | | |
| | | 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 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <Form {...formItemLayout} className="modal-menu-setting-script"> |
| | | <Row gutter={24}> |
| | | {setting.tableName ? <Col span={8}> |
| | | <Form.Item label={'表名'} style={{whiteSpace: 'nowrap', margin: 0}}> |
| | | {setting.tableName} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={16}> |
| | | <Form.Item label={'报错字段'} style={{margin: 0}}> |
| | | ErrorCode, retmsg |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24} className="sqlfield"> |
| | | <Form.Item label={'可用字段'}> |
| | | id, bid, loginuid, sessionuid, userid, appkey, time_id{usefulFields ? ', ' + usefulFields : ''} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={10}> |
| | | <Form.Item label={'快捷添加'} style={{marginBottom: 0}}> |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | onChange={this.selectScript} |
| | | > |
| | | {systemScripts.map((option, i) => |
| | | <Select.Option style={{whiteSpace: 'normal'}} key={i} value={option.value}>{option.name}</Select.Option> |
| | | )} |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6} className="add"> |
| | | <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={24} className="sql"> |
| | | <Form.Item label={'sql'}> |
| | | {getFieldDecorator('sql', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + 'sql!' |
| | | } |
| | | ] |
| | | })(<CodeMirror />)} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(CustomForm) |
New file |
| | |
| | | .modal-menu-setting-script { |
| | | .sqlfield { |
| | | .ant-form-item { |
| | | margin-bottom: 5px; |
| | | } |
| | | .ant-form-item-control { |
| | | line-height: 24px; |
| | | } |
| | | .ant-form-item-label { |
| | | line-height: 25px; |
| | | } |
| | | .ant-form-item-children { |
| | | line-height: 22px; |
| | | } |
| | | .ant-col-sm-8 { |
| | | width: 10.5%; |
| | | } |
| | | .ant-col-sm-16 { |
| | | width: 89.5%; |
| | | } |
| | | } |
| | | .sql { |
| | | .ant-col-sm-8 { |
| | | width: 10.5%; |
| | | } |
| | | .ant-col-sm-16 { |
| | | width: 89.5%; |
| | | padding-top: 4px; |
| | | } |
| | | .CodeMirror { |
| | | height: 350px; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Form, Tabs, Table, Popconfirm, Icon, notification, Modal, Typography, Spin } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | | import Utils from '@/utils/utils.js' |
| | | |
| | | import ColForm from './columnform' |
| | | import CustomScriptsForm from './customscript' |
| | | import SettingForm from './settingform' |
| | | import SettingUtils from './utils' |
| | | import './index.scss' |
| | | |
| | | const { TabPane } = Tabs |
| | | const { Paragraph } = Typography |
| | | |
| | | class VerifyCard extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | config: PropTypes.object, // 数据源信息 |
| | | menuId: PropTypes.string, // 菜单Id |
| | | searches: PropTypes.array, // 搜索条件 |
| | | } |
| | | |
| | | state = { |
| | | columns: [], |
| | | activeKey: 'setting', |
| | | loading: false, |
| | | initsql: '', // sql验证时变量声明及赋值 |
| | | usefulfields: '', |
| | | defaultsql: '', // 默认Sql |
| | | systemScripts: [{ |
| | | name: '默认sql', |
| | | value: '' |
| | | }], |
| | | colColumns: [ |
| | | { |
| | | title: '名称', |
| | | dataIndex: 'label', |
| | | width: '25%' |
| | | }, |
| | | { |
| | | title: '字段', |
| | | dataIndex: 'field', |
| | | width: '25%' |
| | | }, |
| | | { |
| | | title: '数据类型', |
| | | dataIndex: 'datatype', |
| | | width: '25%', |
| | | }, |
| | | { |
| | | title: '操作', |
| | | align: 'center', |
| | | width: '25%', |
| | | dataIndex: 'operation', |
| | | render: (text, record) => |
| | | (<div> |
| | | <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span> |
| | | <Popconfirm |
| | | title={this.props.dict['model.query.delete']} |
| | | okText={this.props.dict['model.confirm']} |
| | | cancelText={this.props.dict['model.cancel']} |
| | | onConfirm={() => this.deleteColumn(record) |
| | | }> |
| | | <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span> |
| | | </Popconfirm> |
| | | </div>) |
| | | } |
| | | ], |
| | | scriptsColumns: [ |
| | | { |
| | | title: 'SQL', |
| | | dataIndex: 'sql', |
| | | width: '60%', |
| | | render: (text) => ( |
| | | <Paragraph copyable ellipsis={{ rows: 5, expandable: true }}>{text}</Paragraph> |
| | | ) |
| | | }, |
| | | { |
| | | title: '状态', |
| | | dataIndex: 'status', |
| | | width: '20%', |
| | | render: (text, record) => record.status === 'false' ? |
| | | ( |
| | | <div> |
| | | {this.props.dict['model.status.forbidden']} |
| | | <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" /> |
| | | </div> |
| | | ) : |
| | | ( |
| | | <div> |
| | | {this.props.dict['model.status.open']} |
| | | <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" /> |
| | | </div> |
| | | ) |
| | | }, |
| | | { |
| | | title: '操作', |
| | | align: 'center', |
| | | width: '20%', |
| | | dataIndex: 'operation', |
| | | render: (text, record) => |
| | | (<div> |
| | | <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span> |
| | | <span className="operation-btn" onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> |
| | | <span className="operation-btn" onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> |
| | | <span className="operation-btn" title={this.props.dict['model.status.change']} onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span> |
| | | <Popconfirm |
| | | title={this.props.dict['model.query.delete']} |
| | | okText={this.props.dict['model.confirm']} |
| | | cancelText={this.props.dict['model.cancel']} |
| | | onConfirm={() => this.deleteScript(record) |
| | | }> |
| | | <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span> |
| | | </Popconfirm> |
| | | </div>) |
| | | } |
| | | ] |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { config } = this.props |
| | | |
| | | this.setState({ |
| | | columns: fromJS(config.columns).toJS(), |
| | | setting: fromJS(config.setting).toJS(), |
| | | scripts: fromJS(config.scripts).toJS() |
| | | }) |
| | | |
| | | this.getsysScript() |
| | | } |
| | | |
| | | getsysScript = () => { |
| | | let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort` |
| | | |
| | | _scriptSql = Utils.formatOptions(_scriptSql) |
| | | |
| | | let _sParam = { |
| | | func: 'sPC_Get_SelectedList', |
| | | LText: _scriptSql, |
| | | obj_name: 'data', |
| | | arr_field: 'funcname,longparam' |
| | | } |
| | | |
| | | _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp) |
| | | |
| | | _sParam.open_key = Utils.encrypt(_sParam.secretkey, _sParam.timestamp, true) // 云端数据验证 |
| | | |
| | | Api.getSystemConfig(_sParam).then(res => { |
| | | if (res.status) { |
| | | let _scripts = [] |
| | | |
| | | res.data.forEach(item => { |
| | | let _item = { |
| | | name: item.funcname, |
| | | value: Utils.formatOptions(item.longparam, true) |
| | | } |
| | | |
| | | _scripts.push(_item) |
| | | }) |
| | | |
| | | this.setState({ |
| | | systemScripts: [...this.state.systemScripts, ..._scripts] |
| | | }) |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.message, |
| | | duration: 5 |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | columnChange = (values) => { |
| | | let columns = fromJS(this.state.columns).toJS() |
| | | |
| | | if (values.uuid) { |
| | | columns = columns.map(item => { |
| | | if (item.uuid === values.uuid) { |
| | | return values |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | } else { |
| | | values.uuid = Utils.getuuid() |
| | | columns.push(values) |
| | | } |
| | | |
| | | this.setState({ columns }) |
| | | } |
| | | |
| | | deleteColumn = (record) => { |
| | | this.setState({ columns: this.state.columns.filter(item => item.uuid !== record.uuid) }) |
| | | } |
| | | |
| | | deleteScript = (record) => { |
| | | this.setState({ scripts: this.state.scripts.filter(item => item.uuid !== record.uuid) }) |
| | | } |
| | | |
| | | handleEdit = (record, type) => { |
| | | if (type === 'scripts') { |
| | | this.scriptsForm.edit(record) |
| | | } else if (type === 'columns') { |
| | | this.contrastForm.edit(record) |
| | | } |
| | | |
| | | let node = document.getElementById('model-verify-card-box-tab').parentNode |
| | | |
| | | if (node && node.scrollTop) { |
| | | let inter = Math.ceil(node.scrollTop / 10) |
| | | |
| | | let timer = setInterval(() => { |
| | | if (node.scrollTop - inter > 0) { |
| | | node.scrollTop = node.scrollTop - inter |
| | | } else { |
| | | node.scrollTop = 0 |
| | | clearInterval(timer) |
| | | } |
| | | }, 10) |
| | | } |
| | | } |
| | | |
| | | handleStatus = (record) => { |
| | | let scripts = fromJS(this.state.scripts).toJS() |
| | | record.status = record.status === 'false' ? 'true' : 'false' |
| | | |
| | | scripts = scripts.map(item => { |
| | | if (item.uuid === record.uuid) { |
| | | return record |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | |
| | | this.setState({ scripts }) |
| | | } |
| | | |
| | | handleUpDown = (record, direction) => { |
| | | let scripts = fromJS(this.state.scripts).toJS() |
| | | let index = 0 |
| | | |
| | | scripts = scripts.filter((item, i) => { |
| | | if (item.uuid === record.uuid) { |
| | | index = i |
| | | } |
| | | |
| | | return item.uuid !== record.uuid |
| | | }) |
| | | if ((index === 0 && direction === 'up') || (index === scripts.length && direction === 'down')) { |
| | | return |
| | | } |
| | | |
| | | if (direction === 'up') { |
| | | scripts.splice(index - 1, 0, record) |
| | | } else { |
| | | scripts.splice(index + 1, 0, record) |
| | | } |
| | | |
| | | this.setState({ scripts }) |
| | | } |
| | | |
| | | scriptsChange = (values) => { |
| | | let scripts = fromJS(this.state.scripts).toJS() |
| | | |
| | | if (values.uuid) { |
| | | scripts = scripts.map(item => { |
| | | if (item.uuid === values.uuid) { |
| | | return values |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | } else { |
| | | scripts.push(values) |
| | | } |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | this.sqlverify(resolve, reject, false, scripts) |
| | | }) |
| | | } |
| | | |
| | | scriptSubmit = (values) => { |
| | | let scripts = fromJS(this.state.scripts).toJS() |
| | | |
| | | if (values.uuid) { |
| | | scripts = scripts.map(item => { |
| | | if (item.uuid === values.uuid) { |
| | | return values |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | } else { |
| | | values.uuid = Utils.getuuid() |
| | | scripts.push(values) |
| | | } |
| | | |
| | | this.setState({ scripts }) |
| | | } |
| | | |
| | | changeTab = (val) => { |
| | | const { activeKey } = this.state |
| | | |
| | | this.setState({loading: true}) |
| | | if (activeKey === 'setting') { |
| | | this.settingForm.handleConfirm().then(res => { |
| | | this.setState({ |
| | | setting: res |
| | | }, () => { |
| | | this.sqlverify(() => { // 验证成功 |
| | | this.setState({ |
| | | activeKey: val, |
| | | loading: false |
| | | }) |
| | | }, () => { // 验证失败 |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | }, true) |
| | | }) |
| | | }, () => { |
| | | this.setState({loading: false}) |
| | | }) |
| | | } else if (activeKey === 'columns') { |
| | | this.sqlverify(() => { // 验证成功 |
| | | this.setState({ |
| | | activeKey: val, |
| | | loading: false |
| | | }) |
| | | }, () => { // 验证失败 |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | }, true) |
| | | } else if (activeKey === 'scripts') { |
| | | let _loading = false |
| | | if (this.scriptsForm && this.scriptsForm.state.editItem) { |
| | | _loading = true |
| | | } else if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql')) { |
| | | _loading = true |
| | | } |
| | | |
| | | if (_loading) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!', |
| | | duration: 5 |
| | | }) |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | return |
| | | } |
| | | |
| | | this.sqlverify(() => { // 验证成功 |
| | | this.setState({ |
| | | activeKey: val, |
| | | loading: false |
| | | }) |
| | | }, () => { // 验证失败 |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | }, true) |
| | | } |
| | | } |
| | | |
| | | submitDataSource = () => { |
| | | const { activeKey, setting, columns, scripts } = this.state |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | if (activeKey === 'setting') { |
| | | this.settingForm.handleConfirm().then(res => { |
| | | this.setState({ |
| | | setting: res |
| | | }, () => { |
| | | this.sqlverify(() => { resolve({setting: res, columns, scripts }) }, reject, false) |
| | | }) |
| | | }, () => { |
| | | reject() |
| | | }) |
| | | } else if (activeKey === 'columns') { |
| | | this.sqlverify(() => { resolve({setting, columns, scripts }) }, reject, false) |
| | | } else if (activeKey === 'scripts') { |
| | | let _loading = false |
| | | if (this.scriptsForm && this.scriptsForm.state.editItem) { |
| | | _loading = true |
| | | } else if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql')) { |
| | | _loading = true |
| | | } |
| | | |
| | | if (_loading) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!', |
| | | duration: 5 |
| | | }) |
| | | reject() |
| | | return |
| | | } |
| | | |
| | | this.sqlverify(() => { resolve({setting, columns, scripts }) }, reject, false) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | sqlverify = (resolve, reject, change = false, testScripts) => { |
| | | const { searches } = this.props |
| | | const { columns, setting, scripts } = this.state |
| | | |
| | | let _scripts = scripts.filter(item => item.status !== 'false') |
| | | |
| | | if (testScripts) { |
| | | _scripts = testScripts.filter(item => item.status !== 'false') |
| | | } |
| | | if (!change && setting.interType === 'inner' && !setting.innerFunc && setting.execute === 'false' && _scripts.length === 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '不执行默认sql时,请添加自定义脚本!', |
| | | duration: 5 |
| | | }) |
| | | reject() |
| | | return |
| | | } |
| | | |
| | | if ((setting.interType === 'inner' && !setting.innerFunc && setting.execute !== 'false') || _scripts.length > 0) { |
| | | let param = { |
| | | func: 's_debug_sql', |
| | | LText: SettingUtils.getDebugSql(setting, _scripts, columns, searches) |
| | | } |
| | | param.LText = Utils.formatOptions(param.LText) |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | param.secretkey = Utils.encrypt(param.LText, param.timestamp) |
| | | |
| | | Api.getLocalConfig(param).then(result => { |
| | | if (result.status) { |
| | | resolve() |
| | | } else { |
| | | reject() |
| | | Modal.error({ |
| | | title: result.message |
| | | }) |
| | | } |
| | | }) |
| | | } else { |
| | | resolve() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { columns, setting, scripts, colColumns, scriptsColumns, activeKey, loading } = this.state |
| | | |
| | | return ( |
| | | <div id="model-verify-card-box-tab"> |
| | | {loading && <Spin size="large" />} |
| | | <Tabs activeKey={activeKey} className="verify-card-box" onChange={this.changeTab}> |
| | | <TabPane tab="数据源" key="setting"> |
| | | <SettingForm |
| | | menuId={this.props.menuId} |
| | | dict={this.props.dict} |
| | | columns={columns} |
| | | setting={setting} |
| | | scripts={scripts} |
| | | wrappedComponentRef={(inst) => this.settingForm = inst} |
| | | /> |
| | | </TabPane> |
| | | <TabPane tab="字段集" key="columns"> |
| | | <ColForm |
| | | dict={this.props.dict} |
| | | columnChange={this.columnChange} |
| | | wrappedComponentRef={(inst) => this.contrastForm = inst} |
| | | /> |
| | | <Table |
| | | bordered |
| | | rowKey="uuid" |
| | | className="custom-table" |
| | | dataSource={columns} |
| | | columns={colColumns} |
| | | pagination={false} |
| | | /> |
| | | </TabPane> |
| | | <TabPane tab="自定义脚本" key="scripts"> |
| | | <CustomScriptsForm |
| | | setting={setting} |
| | | searches={this.props.searches} |
| | | initsql={this.state.initsql} |
| | | dict={this.props.dict} |
| | | customScripts={scripts} |
| | | systemScripts={this.state.systemScripts} |
| | | scriptsChange={this.scriptsChange} |
| | | scriptSubmit={this.scriptSubmit} |
| | | wrappedComponentRef={(inst) => this.scriptsForm = inst} |
| | | /> |
| | | <Table |
| | | bordered |
| | | rowKey="uuid" |
| | | className="custom-table" |
| | | dataSource={scripts} |
| | | columns={scriptsColumns} |
| | | pagination={false} |
| | | /> |
| | | </TabPane> |
| | | </Tabs> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(VerifyCard) |
New file |
| | |
| | | #model-verify-card-box-tab { |
| | | .ant-spin { |
| | | position: absolute; |
| | | left: calc(50% - 16px); |
| | | top: 220px; |
| | | z-index: 1; |
| | | } |
| | | .verify-card-box { |
| | | .ant-tabs-nav-scroll { |
| | | text-align: center; |
| | | } |
| | | .ant-tabs-content { |
| | | min-height: 40vh; |
| | | } |
| | | table tr td { |
| | | word-wrap: break-word; |
| | | word-break: break-word; |
| | | } |
| | | .verify-form { |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | .sql { |
| | | .ant-col-sm-8 { |
| | | width: 10.5%; |
| | | } |
| | | .ant-col-sm-16 { |
| | | width: 89.5%; |
| | | padding-top: 4px; |
| | | } |
| | | } |
| | | .sqlfield { |
| | | .ant-form-item { |
| | | margin-bottom: 5px; |
| | | } |
| | | .ant-form-item-control { |
| | | line-height: 24px; |
| | | } |
| | | .ant-form-item-label { |
| | | line-height: 25px; |
| | | } |
| | | .ant-form-item-children { |
| | | line-height: 22px; |
| | | } |
| | | .ant-col-sm-8 { |
| | | width: 10.5%; |
| | | } |
| | | .ant-col-sm-16 { |
| | | width: 89.5%; |
| | | } |
| | | } |
| | | .add { |
| | | padding-top: 4px; |
| | | } |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | } |
| | | .custom-table .ant-empty { |
| | | margin: 20px 8px!important; |
| | | } |
| | | .errorval { |
| | | display: inline-block; |
| | | width: 30px; |
| | | } |
| | | .operation-btn { |
| | | display: inline-block; |
| | | font-size: 16px; |
| | | padding: 0 5px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Radio, Select, Tooltip, Icon, notification } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | | import Utils from '@/utils/utils.js' |
| | | import CodeMirror from '@/templates/zshare/codemirror' |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | menuId: PropTypes.string, // 菜单Id |
| | | setting: PropTypes.object, // 数据源配置 |
| | | columns: PropTypes.array, // 列设置 |
| | | scripts: PropTypes.array, // 自定义脚本 |
| | | } |
| | | |
| | | state = { |
| | | interType: this.props.setting.interType || 'inner', |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | const { setting } = this.props |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | // 数据源前端验证 |
| | | if (values.interType === 'inner' && !values.innerFunc && values.execute !== 'false' && !values.dataresource) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请填写内部函数或数据源!', |
| | | duration: 5 |
| | | }) |
| | | reject() |
| | | return |
| | | } else if (values.interType === 'inner' && !values.innerFunc && values.execute !== 'false' && values.dataresource) { |
| | | let _quot = values.dataresource.match(/'{1}/g) |
| | | let _lparen = values.dataresource.match(/\({1}/g) |
| | | let _rparen = values.dataresource.match(/\){1}/g) |
| | | |
| | | _quot = _quot ? _quot.length : 0 |
| | | _lparen = _lparen ? _lparen.length : 0 |
| | | _rparen = _rparen ? _rparen.length : 0 |
| | | |
| | | if (_quot % 2 !== 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '数据源中\'必须成对出现', |
| | | duration: 5 |
| | | }) |
| | | reject() |
| | | return |
| | | } else if (_lparen !== _rparen) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '数据源中()必须成对出现', |
| | | duration: 5 |
| | | }) |
| | | reject() |
| | | return |
| | | } else if (/--/ig.test(values.dataresource)) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '数据源中,不可出现字符 -- ,注释请用 /*内容*/', |
| | | duration: 5 |
| | | }) |
| | | reject() |
| | | return |
| | | } |
| | | |
| | | let error = Utils.verifySql(values.dataresource) |
| | | |
| | | if (error) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '数据源中不可使用' + error, |
| | | duration: 5 |
| | | }) |
| | | reject() |
| | | return |
| | | } |
| | | } |
| | | |
| | | // 数据源保存 |
| | | if ( |
| | | values.interType === 'inner' && !values.innerFunc && values.execute !== 'false' && |
| | | /[^\s]+\s+[^\s]+/ig.test(values.dataresource) && setting.dataresource !== values.dataresource |
| | | ) { |
| | | let param = { |
| | | func: 's_DataSrc_Save', |
| | | LText: values.dataresource, |
| | | MenuID: this.props.menuId |
| | | } |
| | | |
| | | param.LText = Utils.formatOptions(param.LText) |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' |
| | | param.secretkey = Utils.encrypt(param.LText, param.timestamp) |
| | | |
| | | Api.getLocalConfig(param) |
| | | } |
| | | |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | onRadioChange = (e, key) => { |
| | | let value = e.target.value |
| | | |
| | | if (key === 'interType') { |
| | | this.setState({ |
| | | interType: value |
| | | }) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { columns, setting } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { interType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-datasource-setting-form-box"> |
| | | <Form {...formItemLayout} className="model-setting-form"> |
| | | <Row gutter={24}> |
| | | <Col span={8}> |
| | | <Form.Item label="表名"> |
| | | {getFieldDecorator('tableName', { |
| | | initialValue: setting.tableName, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '表名!' |
| | | }, |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={8}> |
| | | <Form.Item label="接口类型"> |
| | | {getFieldDecorator('interType', { |
| | | initialValue: interType, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '接口类型!' |
| | | }, |
| | | ] |
| | | })( |
| | | <Radio.Group onChange={(e) => {this.onRadioChange(e, 'interType')}}> |
| | | <Radio value="inner">内部</Radio> |
| | | <Radio value="outer">外部</Radio> |
| | | </Radio.Group>)} |
| | | </Form.Item> |
| | | </Col> |
| | | {interType === 'inner' ? <Col span={8}> |
| | | <Form.Item label="内部函数"> |
| | | {getFieldDecorator('innerFunc', { |
| | | initialValue: setting.innerFunc || '', |
| | | rules: [ |
| | | |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {interType === 'outer' ? <Col span={8}> |
| | | <Form.Item label="接口地址"> |
| | | {getFieldDecorator('interface', { |
| | | initialValue: setting.interface || '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '接口地址!' |
| | | }, |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {interType === 'outer' ? <Col span={8}> |
| | | <Form.Item label="外部函数"> |
| | | {getFieldDecorator('outerFunc', { |
| | | initialValue: setting.outerFunc || '', |
| | | rules: [ |
| | | |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {interType === 'inner' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}> |
| | | <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={ |
| | | <Tooltip placement="topLeft" title={'使用系统函数时,需填写数据源。注:数据权限替换符 $@ -> /* 或 \'\'、 @$ -> */ 或 \'\''}> |
| | | <Icon type="question-circle" /> |
| | | 数据源 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('dataresource', { |
| | | initialValue: setting.dataresource || '' |
| | | })(<CodeMirror />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {interType === 'inner' ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'查询时,搜索条件以where条件拼接进入sql,统计时,将数据源中以“@+搜索字段+@”的内容,以搜索条件中的值进行替换后,提交查询,注:查询类型仅在使用系统函数时有效。'}> |
| | | <Icon type="question-circle" /> |
| | | 查询类型 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('queryType', { |
| | | initialValue: setting.queryType || 'query' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="query">查询</Radio> |
| | | <Radio value="statistics">统计</Radio> |
| | | </Radio.Group>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | <Form.Item label="主键"> |
| | | {getFieldDecorator('primaryKey', { |
| | | initialValue: setting.primaryKey || '' |
| | | })( |
| | | <Select onChange={(value) => {this.selectChange('primaryKey', value)}}> |
| | | {columns.map((option, i) => |
| | | <Select.Option key={i} value={option.value}> |
| | | {option.text} |
| | | </Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {interType === 'inner' ? <Col span={8}> |
| | | <Form.Item label="默认sql"> |
| | | {getFieldDecorator('execute', { |
| | | initialValue: setting.execute || 'true' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">执行</Radio> |
| | | <Radio value="false">不执行</Radio> |
| | | </Radio.Group>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | <Form.Item label="初始化"> |
| | | {getFieldDecorator('onload', { |
| | | initialValue: setting.onload || 'true' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">加载数据</Radio> |
| | | <Radio value="false">不加载数据</Radio> |
| | | </Radio.Group>)} |
| | | </Form.Item> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(SettingForm) |
New file |
| | |
| | | .model-datasource-setting-form-box { |
| | | position: relative; |
| | | |
| | | .model-setting-form { |
| | | .data-source { |
| | | .ant-form-item-label { |
| | | width: 11%; |
| | | } |
| | | .ant-form-item-control-wrapper { |
| | | width: 89%; |
| | | } |
| | | .CodeMirror { |
| | | height: 150px; |
| | | } |
| | | } |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | |
| | | export default class SettingUtils { |
| | | /** |
| | | * @description 生成页面查询语句 |
| | | * @return {String} arr_field 显示列字段 |
| | | * @return {String} search 搜索条件 |
| | | * @return {Object} setting 页面设置 |
| | | * @return {Array} regoptions 搜索条件正则替换 |
| | | */ |
| | | static getDebugSql (setting, arr_field, regoptions, search) { |
| | | let sql = '' |
| | | let _dataresource = setting.dataresource |
| | | let _customScript = setting.customScript |
| | | |
| | | if (setting.interType === 'inner' && !setting.innerFunc && setting.default === 'false') { |
| | | _dataresource = '' |
| | | } |
| | | |
| | | if (_dataresource) { |
| | | _dataresource = _dataresource.replace(/@\$|\$@/ig, '') |
| | | } |
| | | if (_customScript) { |
| | | _customScript = _customScript.replace(/@\$|\$@/ig, '') |
| | | } |
| | | |
| | | // 正则替换 |
| | | let _regoptions = regoptions.map(item => { |
| | | return { |
| | | reg: new RegExp('@' + item.key + '@', 'ig'), |
| | | value: `'${item.value}'` |
| | | } |
| | | }) |
| | | let _search = search |
| | | |
| | | if (setting.queryType === 'statistics' && _dataresource) { |
| | | _regoptions.forEach(item => { |
| | | _dataresource = _dataresource.replace(item.reg, item.value) |
| | | }) |
| | | |
| | | _search = '' |
| | | } |
| | | |
| | | if (_customScript) { |
| | | _regoptions.push({ |
| | | reg: new RegExp('@orderBy@', 'ig'), |
| | | value: setting.order |
| | | }) |
| | | if (setting.laypage !== 'false') { |
| | | _regoptions.push({ |
| | | reg: new RegExp('@pageSize@', 'ig'), |
| | | value: 10 |
| | | }, { |
| | | reg: new RegExp('@pageIndex@', 'ig'), |
| | | value: 1 |
| | | }) |
| | | } |
| | | _regoptions.forEach(item => { |
| | | _customScript = _customScript.replace(item.reg, item.value) |
| | | }) |
| | | } |
| | | |
| | | // 数据源处理, 存在显示列时 |
| | | if (arr_field && _dataresource) { |
| | | if (/\s/.test(_dataresource)) { |
| | | _dataresource = '(' + _dataresource + ') tb' |
| | | } |
| | | |
| | | _dataresource = `select ${setting.laypage !== 'false' ? 'top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage !== 'false' ? 'where rows > 0' : ''} order by tmptable.rows` |
| | | } |
| | | |
| | | if (_customScript) { |
| | | sql = `${_customScript} |
| | | ${_dataresource} |
| | | aaa: |
| | | if @ErrorCode!='' |
| | | insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ |
| | | ` |
| | | } else { |
| | | sql = _dataresource |
| | | } |
| | | |
| | | return sql |
| | | } |
| | | } |
New file |
| | |
| | | |
| | | export default class SettingUtils { |
| | | /** |
| | | * @description 生成页面查询语句 |
| | | * @return {String} scripts 自定义脚本 |
| | | * @return {String} searches 搜索条件 |
| | | * @return {Object} setting 页面设置 |
| | | * @return {Array} columns 显示字段 |
| | | */ |
| | | static getDebugSql (setting, scripts, columns, searches) { |
| | | let sql = '' |
| | | let _dataresource = '' |
| | | let _customScript = '' |
| | | let arr_field = columns.map(item => item.field).join(',') |
| | | |
| | | if (scripts.length > 0) { |
| | | scripts.forEach(item => { |
| | | _customScript += ` |
| | | ${item.sql} |
| | | ` |
| | | }) |
| | | } |
| | | |
| | | if (_customScript) { |
| | | _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000) select @ErrorCode='',@retmsg ='' |
| | | ${_customScript} |
| | | ` |
| | | } |
| | | |
| | | if (setting.interType === 'inner' && !setting.innerFunc && setting.execute !== 'false') { |
| | | _dataresource = setting.dataresource |
| | | } |
| | | |
| | | if (_dataresource) { |
| | | _dataresource = _dataresource.replace(/@\$|\$@/ig, '') |
| | | } |
| | | if (_customScript) { |
| | | _customScript = _customScript.replace(/@\$|\$@/ig, '') |
| | | } |
| | | |
| | | // 正则替换 |
| | | let _regoptions = searches.map(item => { |
| | | return { |
| | | reg: new RegExp('@' + item.key + '@', 'ig'), |
| | | value: `'${item.value}'` |
| | | } |
| | | }) |
| | | let _search = '' |
| | | |
| | | if (setting.queryType === 'statistics' && _dataresource) { |
| | | _regoptions.forEach(item => { |
| | | _dataresource = _dataresource.replace(item.reg, item.value) |
| | | }) |
| | | |
| | | _search = '' |
| | | } |
| | | |
| | | if (_customScript) { |
| | | _regoptions.push({ |
| | | reg: new RegExp('@orderBy@', 'ig'), |
| | | value: setting.order |
| | | }) |
| | | if (setting.laypage !== 'false') { |
| | | _regoptions.push({ |
| | | reg: new RegExp('@pageSize@', 'ig'), |
| | | value: 10 |
| | | }, { |
| | | reg: new RegExp('@pageIndex@', 'ig'), |
| | | value: 1 |
| | | }) |
| | | } |
| | | _regoptions.forEach(item => { |
| | | _customScript = _customScript.replace(item.reg, item.value) |
| | | }) |
| | | } |
| | | |
| | | // 数据源处理, 存在显示列时 |
| | | if (arr_field && _dataresource) { |
| | | if (/\s/.test(_dataresource)) { |
| | | _dataresource = '(' + _dataresource + ') tb' |
| | | } |
| | | |
| | | _dataresource = `select ${setting.laypage !== 'false' ? 'top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage !== 'false' ? 'where rows > 0' : ''} order by tmptable.rows` |
| | | } |
| | | |
| | | if (_customScript) { |
| | | sql = `${_customScript} |
| | | ${_dataresource} |
| | | aaa: |
| | | if @ErrorCode!='' |
| | | insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ |
| | | ` |
| | | } else { |
| | | sql = _dataresource |
| | | } |
| | | |
| | | return sql |
| | | } |
| | | } |
| | |
| | | _this.setState({ |
| | | tabgroups: tabgroups |
| | | }, () => { |
| | | _this.props.updatetabs({...config, tabgroups: tabgroups}, [card]) |
| | | _this.props.updatetabs({...config, tabgroups: tabgroups}) |
| | | }) |
| | | }, |
| | | onCancel() {} |
| | |
| | | }, { |
| | | value: 'line-chart', |
| | | text: 'line-chart' |
| | | }] |
| | | }], |
| | | forbid: type === 'CalendarPage', |
| | | }, |
| | | { |
| | | type: 'select', |
| | |
| | | label: Formdict['header.form.supTab'], |
| | | initVal: supMenu, |
| | | required: false, |
| | | options: menus |
| | | options: menus, |
| | | forbid: type === 'CalendarPage', |
| | | }, |
| | | { |
| | | type: 'mutilselect', |
| | |
| | | tooltip: '如果子标签中含有刷新同级标签的按钮,在此处添加需要刷新的标签。', |
| | | initVal: equalTab, |
| | | required: false, |
| | | options: equalTabs |
| | | options: equalTabs, |
| | | forbid: type === 'CalendarPage', |
| | | }, |
| | | { |
| | | type: 'text', |
| | |
| | | initVal: card.searchPass || 'false', |
| | | tooltip: '使用主表搜索条件时,主表的搜索条件会传入子表中。', |
| | | required: false, |
| | | forbid: type !== 'CommonTable', |
| | | forbid: type !== 'CommonTable' && type !== 'CalendarPage', |
| | | options: [{ |
| | | value: 'true', |
| | | text: '使用' |
| | |
| | | datemonth: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist'], |
| | | datetime: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist'], |
| | | textarea: ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden', 'readin', 'blacklist', 'fieldlength', 'maxRows', 'encryption', 'interception'], |
| | | color: ['label', 'field', 'type', 'blacklist', 'required', 'hidden', 'readin'], |
| | | color: ['label', 'field', 'type', 'blacklist', 'readonly', 'required', 'hidden', 'readin'], |
| | | funcvar: ['label', 'field', 'type', 'blacklist', 'hidden'], |
| | | linkMain: ['label', 'field', 'type', 'readonly', 'required', 'hidden', 'fieldlength', 'blacklist'] |
| | | } |
| | |
| | | isSystem: true |
| | | }, |
| | | { |
| | | title: '日历', |
| | | type: 'CalendarPage', |
| | | url: treepage, |
| | | baseconfig: '', |
| | | isSystem: true |
| | | }, |
| | | { |
| | | title: '角色权限分配', |
| | | type: 'RolePermission', |
| | | url: rolemanage, |
| | |
| | | text: '白底紫框' |
| | | }] |
| | | |
| | | export const calendarColors = [ |
| | | {name: 'black', value: '#ffffff'}, |
| | | {name: 'red', value: '#ffffff'}, |
| | | {name: 'orange', value: '#ffffff'}, |
| | | {name: 'yellow', value: 'rgba(0,0,0,.65)'}, |
| | | {name: 'green', value: '#ffffff'}, |
| | | {name: 'lightgreen', value: 'rgba(0,0,0,.65)'}, |
| | | {name: 'cyan', value: 'rgba(0,0,0,.65)'}, |
| | | {name: 'blue', value: '#ffffff'}, |
| | | {name: 'purple', value: '#ffffff'}, |
| | | {name: 'white', value: 'rgba(0,0,0,.65)'} |
| | | ] |
| | | |
| | | // 显示列标记色系 |
| | | export const colorTransform = { |
| | | 'dust-red-1': '#fff1f0', |
| | | 'dust-red-2': '#ffccc7', |
| | |
| | | value: 'DustRed', |
| | | label: '薄暮', |
| | | children: [ |
| | | // { value: 'dust-red-1', label: 'dust-red-1' }, |
| | | { value: 'dust-red-2', label: 'dust-red-2' }, |
| | | // { value: 'dust-red-3', label: 'dust-red-3' }, |
| | | { value: 'dust-red-4', label: 'dust-red-4' }, |
| | | // { value: 'dust-red-5', label: 'dust-red-5' }, |
| | | { value: 'dust-red-6', label: 'dust-red-6' }, |
| | | // { value: 'dust-red-7', label: 'dust-red-7' }, |
| | | { value: 'dust-red-8', label: 'dust-red-8' }, |
| | | // { value: 'dust-red-9', label: 'dust-red-9' }, |
| | | { value: 'dust-red-10', label: 'dust-red-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'Volcano', |
| | | label: '火山', |
| | | children: [ |
| | | // { value: 'volcano-1', label: 'volcano-1' }, |
| | | { value: 'volcano-2', label: 'volcano-2' }, |
| | | // { value: 'volcano-3', label: 'volcano-3' }, |
| | | { value: 'volcano-4', label: 'volcano-4' }, |
| | | // { value: 'volcano-5', label: 'volcano-5' }, |
| | | { value: 'volcano-6', label: 'volcano-6' }, |
| | | // { value: 'volcano-7', label: 'volcano-7' }, |
| | | { value: 'volcano-8', label: 'volcano-8' }, |
| | | // { value: 'volcano-9', label: 'volcano-9' }, |
| | | { value: 'volcano-10', label: 'volcano-10' } |
| | | ], |
| | | }, |
| | |
| | | value: 'SunsetOrange', |
| | | label: '日暮', |
| | | children: [ |
| | | // { value: 'orange-1', label: 'orange-1' }, |
| | | { value: 'orange-2', label: 'orange-2' }, |
| | | // { value: 'orange-3', label: 'orange-3' }, |
| | | { value: 'orange-4', label: 'orange-4' }, |
| | | // { value: 'orange-5', label: 'orange-5' }, |
| | | { value: 'orange-6', label: 'orange-6' }, |
| | | // { value: 'orange-7', label: 'orange-7' }, |
| | | { value: 'orange-8', label: 'orange-8' }, |
| | | // { value: 'orange-9', label: 'orange-9' }, |
| | | { value: 'orange-10', label: 'orange-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'CalendulaGold', |
| | | label: '金盏花', |
| | | children: [ |
| | | // { value: 'gold-1', label: 'gold-1' }, |
| | | { value: 'gold-2', label: 'gold-2' }, |
| | | // { value: 'gold-3', label: 'gold-3' }, |
| | | { value: 'gold-4', label: 'gold-4' }, |
| | | // { value: 'gold-5', label: 'gold-5' }, |
| | | { value: 'gold-6', label: 'gold-6' }, |
| | | // { value: 'gold-7', label: 'gold-7' }, |
| | | { value: 'gold-8', label: 'gold-8' }, |
| | | // { value: 'gold-9', label: 'gold-9' }, |
| | | { value: 'gold-10', label: 'gold-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'SunriseYellow', |
| | | label: '日出', |
| | | children: [ |
| | | // { value: 'yellow-1', label: 'yellow-1' }, |
| | | { value: 'yellow-2', label: 'yellow-2' }, |
| | | // { value: 'yellow-3', label: 'yellow-3' }, |
| | | { value: 'yellow-4', label: 'yellow-4' }, |
| | | // { value: 'yellow-5', label: 'yellow-5' }, |
| | | { value: 'yellow-6', label: 'yellow-6' }, |
| | | // { value: 'yellow-7', label: 'yellow-7' }, |
| | | { value: 'yellow-8', label: 'yellow-8' }, |
| | | // { value: 'yellow-9', label: 'yellow-9' }, |
| | | { value: 'yellow-10', label: 'yellow-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'Lime', |
| | | label: '青柠', |
| | | children: [ |
| | | // { value: 'lime-1', label: 'lime-1' }, |
| | | { value: 'lime-2', label: 'lime-2' }, |
| | | // { value: 'lime-3', label: 'lime-3' }, |
| | | { value: 'lime-4', label: 'lime-4' }, |
| | | // { value: 'lime-5', label: 'lime-5' }, |
| | | { value: 'lime-6', label: 'lime-6' }, |
| | | // { value: 'lime-7', label: 'lime-7' }, |
| | | { value: 'lime-8', label: 'lime-8' }, |
| | | // { value: 'lime-9', label: 'lime-9' }, |
| | | { value: 'lime-10', label: 'lime-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'PolarGreen', |
| | | label: '极光绿', |
| | | children: [ |
| | | // { value: 'green-1', label: 'green-1' }, |
| | | { value: 'green-2', label: 'green-2' }, |
| | | // { value: 'green-3', label: 'green-3' }, |
| | | { value: 'green-4', label: 'green-4' }, |
| | | // { value: 'green-5', label: 'green-5' }, |
| | | { value: 'green-6', label: 'green-6' }, |
| | | // { value: 'green-7', label: 'green-7' }, |
| | | { value: 'green-8', label: 'green-8' }, |
| | | // { value: 'green-9', label: 'green-9' }, |
| | | { value: 'green-10', label: 'green-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'Cyan', |
| | | label: '明青', |
| | | children: [ |
| | | // { value: 'cyan-1', label: 'cyan-1' }, |
| | | { value: 'cyan-2', label: 'cyan-2' }, |
| | | // { value: 'cyan-3', label: 'cyan-3' }, |
| | | { value: 'cyan-4', label: 'cyan-4' }, |
| | | // { value: 'cyan-5', label: 'cyan-5' }, |
| | | { value: 'cyan-6', label: 'cyan-6' }, |
| | | // { value: 'cyan-7', label: 'cyan-7' }, |
| | | { value: 'cyan-8', label: 'cyan-8' }, |
| | | // { value: 'cyan-9', label: 'cyan-9' }, |
| | | { value: 'cyan-10', label: 'cyan-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'DaybreakBlue', |
| | | label: '拂晓蓝', |
| | | children: [ |
| | | // { value: 'blue-1', label: 'blue-1' }, |
| | | { value: 'blue-2', label: 'blue-2' }, |
| | | // { value: 'blue-3', label: 'blue-3' }, |
| | | { value: 'blue-4', label: 'blue-4' }, |
| | | // { value: 'blue-5', label: 'blue-5' }, |
| | | { value: 'blue-6', label: 'blue-6' }, |
| | | // { value: 'blue-7', label: 'blue-7' }, |
| | | { value: 'blue-8', label: 'blue-8' }, |
| | | // { value: 'blue-9', label: 'blue-9' }, |
| | | { value: 'blue-10', label: 'blue-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'GeekBlue', |
| | | label: '极客蓝', |
| | | children: [ |
| | | // { value: 'geekblue-1', label: 'geekblue-1' }, |
| | | { value: 'geekblue-2', label: 'geekblue-2' }, |
| | | // { value: 'geekblue-3', label: 'geekblue-3' }, |
| | | { value: 'geekblue-4', label: 'geekblue-4' }, |
| | | // { value: 'geekblue-5', label: 'geekblue-5' }, |
| | | { value: 'geekblue-6', label: 'geekblue-6' }, |
| | | // { value: 'geekblue-7', label: 'geekblue-7' }, |
| | | { value: 'geekblue-8', label: 'geekblue-8' }, |
| | | // { value: 'geekblue-9', label: 'geekblue-9' }, |
| | | { value: 'geekblue-10', label: 'geekblue-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'GoldenPurple', |
| | | label: '酱紫', |
| | | children: [ |
| | | // { value: 'purple-1', label: 'purple-1' }, |
| | | { value: 'purple-2', label: 'purple-2' }, |
| | | // { value: 'purple-3', label: 'purple-3' }, |
| | | { value: 'purple-4', label: 'purple-4' }, |
| | | // { value: 'purple-5', label: 'purple-5' }, |
| | | { value: 'purple-6', label: 'purple-6' }, |
| | | // { value: 'purple-7', label: 'purple-7' }, |
| | | { value: 'purple-8', label: 'purple-8' }, |
| | | // { value: 'purple-9', label: 'purple-9' }, |
| | | { value: 'purple-10', label: 'purple-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'Magenta', |
| | | label: '法式洋红', |
| | | children: [ |
| | | // { value: 'magenta-1', label: 'magenta-1' }, |
| | | { value: 'magenta-2', label: 'magenta-2' }, |
| | | // { value: 'magenta-3', label: 'magenta-3' }, |
| | | { value: 'magenta-4', label: 'magenta-4' }, |
| | | // { value: 'magenta-5', label: 'magenta-5' }, |
| | | { value: 'magenta-6', label: 'magenta-6' }, |
| | | // { value: 'magenta-7', label: 'magenta-7' }, |
| | | { value: 'magenta-8', label: 'magenta-8' }, |
| | | // { value: 'magenta-9', label: 'magenta-9' }, |
| | | { value: 'magenta-10', label: 'magenta-10' } |
| | | ] |
| | | }, |
| | |
| | | value: 'Gray', |
| | | label: '中性色', |
| | | children: [ |
| | | // { value: 'gray-1', label: 'gray-1' }, |
| | | { value: 'gray-2', label: 'gray-2' }, |
| | | // { value: 'gray-3', label: 'gray-3' }, |
| | | { value: 'gray-4', label: 'gray-4' }, |
| | | // { value: 'gray-5', label: 'gray-5' }, |
| | | { value: 'gray-6', label: 'gray-6' }, |
| | | // { value: 'gray-7', label: 'gray-7' }, |
| | | { value: 'gray-8', label: 'gray-8' }, |
| | | // { value: 'gray-9', label: 'gray-9' }, |
| | | { value: 'gray-10', label: 'gray-10' } |
| | | ] |
| | | } |
| | |
| | | |
| | | val = val.replace(/(^\s*$)|\t*|\v*/ig, '') |
| | | |
| | | if (!val && col.required === 'true') { // 必填校验 |
| | | if (!val && col.required === 'true') { // 必填校验 |
| | | errors.push(_position + dict['main.excel.content.emptyerror']) |
| | | } else if (val.length > col.limit) { // 长度校验 |
| | | } else if (col.limit && val.length > col.limit) { // 长度校验 |
| | | errors.push(_position + dict['main.excel.content.maxlimit']) |
| | | } else { // 关键字校验 |
| | | } else { // 关键字校验 |
| | | keys.forEach(key => { |
| | | let _patten = new RegExp('(^' + key + '\\s+)|(\\s+' + key + '\\s+)', 'ig') |
| | | if (_patten.test(val)) { |
| | |
| | | margin-right: 0; |
| | | border-radius: 0; |
| | | text-align: center; |
| | | font-size: 18px; |
| | | font-size: 17px; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | overflow: hidden; |
| | |
| | | } |
| | | } |
| | | .login-form-1 { |
| | | .ant-tabs-tab { |
| | | text-align: left!important; |
| | | padding-left: 1.6vw!important; |
| | | line-height: 60px!important; |
| | | .ant-tabs.ant-tabs-card { |
| | | .ant-tabs-card-bar { |
| | | .ant-tabs-tab { |
| | | font-size: 18px; |
| | | text-align: left!important; |
| | | padding-left: 1.6vw!important; |
| | | line-height: 60px!important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .login-middle { |