king
2019-12-10 bd06958321afa706f32287c71bd219eb0622c86c
2019-12-10
17个文件已修改
2个文件已添加
725 ■■■■ 已修改文件
src/api/index.js 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/comtable.js 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/comtable.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/mainAction/index.jsx 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/mutilform/index.jsx 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/mutilform/index.scss 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/actionform/index.jsx 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/actionform/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/colspanform/index.jsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/dragelement/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.jsx 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/modalform/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/source.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js
@@ -129,27 +129,43 @@
    if (window.GLOB.mainSystemApi) {
      param.rduri = window.GLOB.mainSystemApi
    }
    if (param.isCache) { // 数据需要缓存时
      delete param.isCache
      
      if (GlobMap.has(param)) {
        return Promise.resolve(GlobMap.get(param))
    return axios({
      url: '/webapi/dostar',
      data: param
    })
  }
  /**
   * @description 获取系统配置,优先从缓存中取值,增加appkey
   */
  getSystemCacheConfig (param) {
    param.userid = sessionStorage.getItem('UserID')
    param.lang = localStorage.getItem('lang') || ''
    param.SessionUid = sessionStorage.getItem('SessionUid') || ''
    param.LoginUID = sessionStorage.getItem('LoginUID') || ''
    param.appkey = window.GLOB.appkey || ''
    if (window.GLOB.mainSystemApi) {
      param.rduri = window.GLOB.mainSystemApi
    }
    let _param = JSON.parse(JSON.stringify(param)) // 缓存校验,去除时间和加密字符
    delete _param.timestamp
    delete _param.secretkey
    _param = JSON.stringify(_param)
    if (GlobMap.has(_param)) {
      return Promise.resolve(GlobMap.get(_param))
      } else {
        return new Promise(resolve => {
          axios({
            url: '/webapi/dostar',
            data: param
          }).then(res => {
            console.log(res)
            GlobMap.set(param, res)
          GlobMap.set(_param, res)
            resolve(res)
          })
        })
      }
    } else {
      return axios({
        url: '/webapi/dostar',
        data: param
      })
    }
  }
src/assets/css/main.scss
@@ -157,3 +157,14 @@
    color: #ffffff;
  }
}
// 重置提示框
.ant-tooltip {
  z-index: 1090!important;
  .ant-tooltip-inner {
    letter-spacing: 1px;
  }
}
.ant-tooltip.middle {
  max-width: 320px!important;
}
src/components/header/index.jsx
@@ -108,15 +108,6 @@
        sessionStorage.clear()
        _this.props.logout()
        _this.props.history.replace('/login')
        // return Api.logoutsystem().then(res => {
        //   if (res.status) {
        //     sessionStorage.removeItem('UserID')
        //     _this.props.resetState()
        //     _this.props.history.replace('/login')
        //   } else {
        //     message.warning(res.message)
        //   }
        // })
      },
      onCancel() {}
    })
@@ -240,7 +231,7 @@
          {this.state.dict['header.edit']}
          <Switch size="small" className="edit-switch" disabled={!!this.props.editLevel} onChange={this.changeEditState} />
        </Menu.Item>}
        <Menu.Item key="1" onClick={this.changePassword}>{this.state.dict['header.password']}</Menu.Item>
        {/* <Menu.Item key="1" onClick={this.changePassword}>{this.state.dict['header.password']}</Menu.Item> */}
        <Menu.Item key="2" onClick={this.logout}>{this.state.dict['header.logout']}</Menu.Item>
      </Menu>
    )
src/locales/en-US/comtable.js
@@ -140,11 +140,14 @@
  'header.form.style': '风格',
  'header.form.color': '颜色',
  'header.form.order': '排列',
  'header.form.horizontal': '水平',
  'header.form.vertical': '垂直',
  'header.form.horizontal': '横向',
  'header.form.vertical': '纵向',
  'header.form.topPicBottomText': '上图下文',
  'header.form.leftPicRightText': '左图右文',
  'header.form.selectItem.error': '下拉选项设置错误!',
  'header.form.request.method': '请求方式',
  'header.form.readonly': '是否只读',
  'header.form.field.required': '是否必填',
  'form.required.input': 'Please enter the ',
  'form.required.select': '请选择'
}
src/locales/zh-CN/comtable.js
@@ -118,8 +118,8 @@
  'header.form.resourceType': '选项来源',
  'header.form.custom': '自定义',
  'header.form.datasource': '数据源',
  'header.form.actionhelp.datasource': '使用系统函数时,请填写数据源。',
  'header.form.actionhelp.sqlType': '使用系统函数时,请选择类型。',
  'header.form.actionhelp.datasource': '使用系统函数时,请填写数据源,使用自定义函数时,可忽略。',
  'header.form.actionhelp.sqlType': '使用系统函数时,请选择类型,使用自定义函数时,可忽略。',
  'header.form.action.type': '操作类型',
  'header.form.action.insert': '添加',
  'header.form.action.update': '修改',
@@ -140,11 +140,14 @@
  'header.form.style': '风格',
  'header.form.color': '颜色',
  'header.form.order': '排列',
  'header.form.horizontal': '水平',
  'header.form.vertical': '垂直',
  'header.form.horizontal': '横向',
  'header.form.vertical': '纵向',
  'header.form.topPicBottomText': '上图下文',
  'header.form.leftPicRightText': '左图右文',
  'header.form.selectItem.error': '下拉选项设置错误!',
  'header.form.request.method': '请求方式',
  'header.form.readonly': '是否只读',
  'header.form.field.required': '是否必填',
  'form.required.input': '请输入',
  'form.required.select': '请选择'
}
src/tabviews/commontable/index.jsx
@@ -38,17 +38,16 @@
    orderColumn: '',
    orderType: 'asc',
    search: '',
    fixed: {}
    configMap: {}
  }
  async loadconfig () {
    // 获取主菜单
    let param = {
      func: 'sPC_Get_LongParam',
      MenuID: this.props.MenuID,
      isCache: true
      MenuID: this.props.MenuID
    }
    let result = await Api.getSystemConfig(param)
    let result = await Api.getSystemCacheConfig(param)
    if (result.status && result.LongParam) {
      let config = window.decodeURIComponent(window.atob(result.LongParam))
@@ -132,6 +131,7 @@
        loading: true
      }, () => {
        this.improveSearch()
        this.improveAction()
        this.loadmaindata()
      })
    } else {
@@ -153,8 +153,6 @@
    searchlist.forEach(item => {
      if (item.type !== 'select' && item.type !== 'link') return
      let unloaded = item.options.length === 0
      if (item.setAll === 'true') {
        item.options.unshift({
          key: Utils.getuuid(),
@@ -163,7 +161,7 @@
        })
      }
      if (item.resourceType === '1' && item.dataSource && unloaded) {
      if (item.resourceType === '1' && item.dataSource) {
        let param = {
          func: 'sPC_Get_SelectedList',
          LText: item.dataSourceSql,
@@ -175,7 +173,7 @@
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        let defer = new Promise(resolve => {
          Api.getSystemConfig(param).then(res => {
          Api.getSystemCacheConfig(param).then(res => {
            res.search = item
            resolve(res)
          })
@@ -218,6 +216,40 @@
        }
      })
      this.setState({searchlist})
    })
  }
  improveAction = () => {
    const { config } = this.state
    config.action.forEach(item => {
      if (item.OpenType !== 'pop' && item.OpenType !== 'tab' && item.OpenType !== 'blank') return
      Api.getSystemCacheConfig({
        func: 'sPC_Get_LongParam',
        MenuID: item.uuid
      }).then(res => {
        if (res.status) {
          let _LongParam = ''
          if (res.LongParam) {
            _LongParam = window.decodeURIComponent(window.atob(res.LongParam))
            try {
              _LongParam = JSON.parse(_LongParam)
            } catch (e) {
              _LongParam = ''
            }
          }
          this.setState({
            configMap: {...this.state.configMap, [item.uuid]: _LongParam}
          })
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
        }
      })
    })
  }
@@ -350,6 +382,7 @@
          <MainAction
            MenuID={this.props.MenuID}
            setting={setting}
            configMap={this.state.configMap}
            refreshdata={this.refreshbyaction}
            gettableselected={this.gettableselected}
            actions={actions}
src/tabviews/commontable/mainAction/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
// import { is, fromJS } from 'immutable'
import { Button, Affix, Modal, notification } from 'antd'
import MutilForm from '@/components/mutilform'
import MutilForm from '../mutilform'
import Api from '@/api'
import './index.scss'
@@ -13,7 +13,8 @@
    MenuID: PropTypes.string,
    actions: PropTypes.array, // 搜索条件列表
    dict: PropTypes.object, // 字典项
    setting: PropTypes.any
    setting: PropTypes.any,
    configMap: PropTypes.object
  }
  state = {
@@ -29,7 +30,7 @@
    this.props.refreshdata(item, type)
  }
  actionTrigger = (item) => {
    const { setting } = this.props
    const { setting, configMap } = this.props
    let _this = this
    let data = this.props.gettableselected() || []
@@ -74,6 +75,22 @@
      this.execSubmit(item, data, () => {
        this.setState({loadingUuid: ''})
      })
    } else if (item.OpenType === 'pop') {
      let param = configMap[item.uuid]
      if (!param || param.type !== 'Modal') {
        notification.warning({
          top: 92,
          message: '未获取到按钮配置信息!',
          duration: 10
        })
      } else {
        this.setState({
          visible: true,
          execAction: {...param, ...item},
          tabledata: data
        })
      }
    } else {
      notification.warning({
        top: 92,
@@ -442,53 +459,31 @@
    })
  }
  getModels = () => {
    return (
      <Modal
        wrapClassName='action-modal'
        title={(this.state.execAction && this.state.execAction.MenuName) || ''}
        visible={this.state.visible}
        width={(this.state.execAction && +this.state.execAction.PopWidth) || 520}
        onOk={this.handleOk}
        confirmLoading={this.state.confirmLoading}
        onCancel={this.handleCancel}
      >
        {this.state.formdata &&
          <MutilForm
            dict={this.props.dict}
            formlist={this.state.formdata}
            data={this.state.tabledata}
            wrappedComponentRef={(inst) => this.formRef = inst}
          />}
      </Modal>
    )
  }
  handleOk = () => {
    this.formRef.handleConfirm().then(res => {
      this.setState({
        confirmLoading: true
      })
      console.log(res)
      Api.setActionSubmit({
        func: 'SetActionSubmitSuccess'
      }).then((res) => {
        if (res.status) {
          notification.success({
            top: 92,
            message: this.props.dict['main.action.confirm.success']
          })
          this.setState({
            confirmLoading: false,
            visible: false
          })
        } else {
          notification.error({
            top: 92,
            message: res.message
          })
        }
      })
      // Api.setActionSubmit({
      //   func: 'SetActionSubmitSuccess'
      // }).then((res) => {
      //   if (res.status) {
      //     notification.success({
      //       top: 92,
      //       message: this.props.dict['main.action.confirm.success']
      //     })
      //     this.setState({
      //       confirmLoading: false,
      //       visible: false
      //     })
      //   } else {
      //     notification.error({
      //       top: 92,
      //       message: res.message
      //     })
      //   }
      // })
    }, () => {})
  }
@@ -496,7 +491,36 @@
    this.setState({
      visible: false
    })
    this.formRef.handleReset()
  }
  getModels = () => {
    const { execAction } = this.state
    let title = ''
    let width = '62vw'
    if (execAction && execAction.setting) {
      title = execAction.setting.title
      width = execAction.setting.width + 'vw'
    }
    return (
      <Modal
        wrapClassName='action-modal'
        title={title}
        visible={this.state.visible}
        width={width}
        onOk={this.handleOk}
        confirmLoading={this.state.confirmLoading}
        onCancel={this.handleCancel}
        destroyOnClose
      >
        <MutilForm
          dict={this.props.dict}
          action={execAction}
          data={this.state.tabledata}
          wrappedComponentRef={(inst) => this.formRef = inst}
        />
      </Modal>
    )
  }
  render() {
@@ -557,6 +581,7 @@
              )
            }
          })}
          {this.getModels()}
        </div>
      )
    }
src/tabviews/commontable/mutilform/index.jsx
New file
@@ -0,0 +1,298 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, InputNumber, Select, DatePicker } from 'antd'
import moment from 'moment'
import './index.scss'
const {MonthPicker} = DatePicker
class MainSearch extends Component {
  static propTpyes = {
    action: PropTypes.object, // 搜索条件列表
    dict: PropTypes.object, // 字典项
    data: PropTypes.any // 表格数据
  }
  state = {
    datatype: null,
    formlist: []
  }
  componentDidMount () {
    const { action } = this.props
    let datatype = {}
    let formlist = []
    if (action.groups.length > 0) {
      action.groups.forEach(group => {
        if (group.sublist.length === 0) return
        if (!group.default) {
          formlist.push({
            type: 'title',
            label: group.label,
            uuid: group.uuid
          })
        }
        group.sublist.forEach(item => {
          datatype[item.field] = item.type
          formlist.push(item)
        })
      })
    } else {
      formlist = action.fields.map(item => {
        datatype[item.field] = item.type
        return item
      })
    }
    this.setState({
      datatype: datatype,
      formlist: formlist
    })
  }
  getFields() {
    const { getFieldDecorator } = this.props.form
    const fields = []
    let cols = 2
    if (this.props.form.setting && this.props.form.setting.cols) {
      cols = parseInt(this.props.form.setting.cols)
      if (cols > 3 || cols < 1) {
        cols = 2
      }
    }
    this.state.formlist.forEach((item, index) => {
      if (!item.field && item.type !== 'title') return
      if (item.type === 'title') {
        fields.push(
          <Col span={24 / cols} key={index}>
            <p>{item.label}</p>
          </Col>
        )
      } else if (item.type === 'text') {
        fields.push(
          <Col span={24 / cols} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.field, {
                initialValue: this.props.data ? this.props.data[item.field] : item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly === 'true'} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'number') { // 数字
        let min = (item.min || item.min === 0) ? item.min : -Infinity
        let max = (item.max || item.max === 0) ? item.max : Infinity
        let _initval = this.props.data ? this.props.data[item.field] : item.initval
        let precision = (item.decimal || item.decimal === 0) ? item.decimal : null
        fields.push(
          <Col span={24 / cols} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.field, {
                initialValue: _initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(
                precision === null ?
                <InputNumber initialValue={_initval} min={min} max={max} disabled={item.readonly === 'true'} /> :
                <InputNumber initialValue={_initval} min={min} max={max} precision={precision} disabled={item.readonly === 'true'} />
                )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select') { // 下拉搜索
        fields.push(
          <Col span={24 / cols} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.field, {
                initialValue: this.props.data ? this.props.data[item.field] : item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Select
                  showSearch
                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  getPopupContainer={() => document.getElementById('form-box')}
                >
                  {item.options.map(option =>
                    <Select.Option id={option.key} title={option.Text} key={option.key} value={option.Value}>{option.Text}</Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'date') { // 时间搜索
        let _initval = this.props.data ? this.props.data[item.field] : ''
        if (_initval) {
          _initval = moment(_initval, 'YYYY-MM-DD')
        } else {
          _initval = item.initval ? moment().subtract(item.initval, 'days') : null
        }
        fields.push(
          <Col span={24 / cols} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.field, {
                initialValue: _initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <DatePicker getCalendarContainer={() => document.getElementById('form-box')} />
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'datemonth') {
        let _initval = this.props.data ? this.props.data[item.field] : ''
        if (_initval) {
          _initval = moment(_initval, 'YYYY-MM')
        } else {
          _initval = item.initval ? moment().subtract(item.initval, 'month') : null
        }
        fields.push(
          <Col span={24 / cols} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.field, {
                initialValue: _initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <MonthPicker getCalendarContainer={() => document.getElementById('form-box')} />
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'datetime') {
        let _initval = this.props.data ? this.props.data[item.field] : ''
        if (_initval) {
          _initval = moment(_initval, 'YYYY-MM-DD HH:mm:ss')
        } else {
          _initval = item.initval ? moment().subtract(item.initval, 'days') : null
        }
        fields.push(
          <Col span={24 / cols} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.field, {
                initialValue: _initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <DatePicker showTime getCalendarContainer={() => document.getElementById('form-box')} />
              )}
            </Form.Item>
          </Col>
        )
      }
    })
    return fields
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let search = []
          Object.keys(values).forEach(key => {
            if (this.state.style[key] === 'datetime') {
              let _value = ''
              if (values[key]) {
                _value = moment(values[key]).format('YYYY-MM-DD HH:mm:ss')
              }
              search.push({
                type: this.state.style[key],
                key: key,
                value: _value
              })
            } else if (this.state.style[key] === 'datemonth') {
              let _value = ''
              if (values[key]) {
                _value = moment(values[key]).format('YYYY-MM')
              }
              search.push({
                type: this.state.style[key],
                key: key,
                value: _value
              })
            } else if (this.state.style[key] === 'date') {
              let _value = ''
              if (values[key]) {
                _value = moment(values[key]).format('YYYY-MM-DD')
              }
              search.push({
                type: this.state.style[key],
                key: key,
                value: _value
              })
            } else {
              search.push({
                type: this.state.style[key],
                key: key,
                value: values[key].replace(/(^\s*|\s*$)/ig, '')
              })
            }
          })
          resolve(search)
        } else {
          reject(err)
        }
      })
    })
  }
  handleReset = () => {
    // 重置
    this.props.form.resetFields()
  }
  render() {
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <Form {...formItemLayout} className="ant-advanced-search-form" id="form-box">
        <Row gutter={24}>{this.getFields()}</Row>
      </Form>
    )
  }
}
export default Form.create()(MainSearch)
src/tabviews/commontable/mutilform/index.scss
New file
@@ -0,0 +1,20 @@
.ant-advanced-search-form.main-search {
  padding: 0px 24px 20px;
  border-bottom: 1px solid #d9d9d9;
  .ant-form-item {
    display: flex;
    margin-bottom: 10px;
  }
  .ant-form-item-control-wrapper {
    flex: 1;
  }
  .ant-form-item-label {
    width: 100px;
  }
}
.ant-advanced-search-form {
  position: relative;
}
.ant-advanced-search-form .ant-input-number {
  width: 100%;
}
src/templates/comtableconfig/actionform/index.jsx
@@ -1,6 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Select, Icon, Radio, notification } from 'antd'
import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip } from 'antd'
import './index.scss'
const { TextArea } = Input
@@ -261,13 +261,14 @@
      if (item.hidden) return
      if (item.type === 'text') { // 文本搜索
        let help = ''
        if (item.key === 'sql') {
          help = this.props.dict['header.form.actionhelp.datasource']
        }
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label} help={help}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
@@ -281,13 +282,14 @@
          </Col>
        )
      } else if (item.type === 'select') { // 下拉搜索
        let help = ''
        if (item.key === 'sqlType') {
          help = this.props.dict['header.form.actionhelp.sqlType']
        }
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label} help={help}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
src/templates/comtableconfig/actionform/index.scss
@@ -12,4 +12,9 @@
      width: 86%;
    }
  }
  .anticon-question-circle {
    color: #c49f47;
    position: relative;
    left: -3px;
  }
}
src/templates/comtableconfig/colspanform/index.jsx
@@ -137,6 +137,28 @@
              )}
            </Form.Item>
          </Col>
          <Col span={12}>
            <Form.Item label={this.props.dict['header.form.order']}>
              {getFieldDecorator('order', {
                initialValue: this.props.card.order,
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.select'] + this.props.dict['header.form.order'] + '!'
                  }
                ]
              })(
                <Select
                  getPopupContainer={() => document.getElementById('columncolspan')}
                >
                  <Select.Option value="vertical">{this.props.dict['header.form.vertical']}</Select.Option>
                  <Select.Option value="horizontal">{this.props.dict['header.form.horizontal']}</Select.Option>
                  <Select.Option value="topPicBottomText">{this.props.dict['header.form.topPicBottomText']}</Select.Option>
                  <Select.Option value="leftPicRightText">{this.props.dict['header.form.leftPicRightText']}</Select.Option>
                </Select>
              )}
            </Form.Item>
          </Col>
          <Col span={24}>
            <TransferForm dict={this.props.dict} columns={this.props.columns} ref="column-transfer" selected={this.props.card.sublist}/>
          </Col>
src/templates/comtableconfig/dragelement/index.jsx
@@ -122,6 +122,7 @@
        if (item.subType === 'colspan') {
          newcard.sublist = []
          newcard.IsSort = 'false'
          newcard.order = 'vertical'
        }
      }
      
src/templates/comtableconfig/index.jsx
@@ -3,7 +3,7 @@
import { is, fromJS } from 'immutable'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { Button, Card, Modal, Collapse, notification, Spin, Select, List, Icon, Empty, Switch } from 'antd'
import { Button, Card, Modal, Collapse, notification, Spin, Select, List, Icon, Empty, Switch, Tooltip } from 'antd'
import moment from 'moment'
import DragElement from './dragelement'
import SourceElement from './dragelement/source'
@@ -542,6 +542,11 @@
          key: 'innerFunc',
          label: this.state.dict['header.form.innerFunc'],
          initVal: card.innerFunc,
          tooltip: <div>
            <p>内部接口: 可自定义数据处理函数,未设置时会调用系统函数,使用系统函数需完善数据源及操作类型;</p>
            <p>外部接口: 可自定义数据处理函数,提交数据经过内部函数处理后,传入外部接口,未设置时,数据会直接传入外部接口。</p>
          </div>,
          tooltipClass: 'middle',
          required: false,
          readonly: false
        },
@@ -660,6 +665,7 @@
          key: 'sql',
          label: this.state.dict['header.form.datasource'],
          initVal: card.sql || this.state.config.setting.tableName || '',
          tooltip: this.state.dict['header.form.actionhelp.datasource'],
          required: false
        },
        {
@@ -667,6 +673,7 @@
          key: 'sqlType',
          label: this.state.dict['header.form.action.type'],
          initVal: card.sqlType || 'insert',
          tooltip: this.state.dict['header.form.actionhelp.sqlType'],
          required: false,
          options: [{
            MenuID: 'insert',
@@ -1674,8 +1681,11 @@
                />
                {/* 表名添加 */}
                <div className="ant-col ant-form-item-label">
                  <label title={this.state.dict['header.menu.table.add']}>
                  <label>
                    <Tooltip placement="topLeft" title="此处可以添加配置相关的常用表,在添加搜索条件和显示列时,可通过工具栏中的添加按钮,批量添加表格相关字段。">
                      <Icon type="question-circle" />
                    {this.state.dict['header.menu.table.add']}
                    </Tooltip>
                  </label>
                </div>
                <Select
@@ -1724,7 +1734,12 @@
                  })}
                </div>
                {configAction.length > 0 ?
                  <p className="config-btn-title">{this.state.dict['header.menu.action.configurable']}</p> : null
                  <p className="config-btn-title">
                    <Tooltip placement="topLeft" title="点击按钮,可完成或查看按钮配置信息。">
                      <Icon type="question-circle" />
                    </Tooltip>
                    {this.state.dict['header.menu.action.configurable']}
                  </p> : null
                }
                {configAction.map((item, index) => {
                  return (
@@ -1752,7 +1767,7 @@
          <div className="setting">
            <Card title={this.state.dict['header.menu.page.configurable']} bordered={false} extra={
              <div>
                <Switch className="big" checkedChildren="启" unCheckedChildren="关" defaultChecked={this.state.config.enabled} onChange={this.onEnabledChange} />
                <Switch className="big" checkedChildren="启" unCheckedChildren="停" defaultChecked={this.state.config.enabled} onChange={this.onEnabledChange} />
                <Button type="primary" onClick={this.changeTemplate}>{this.state.dict['header.menu.template.change']}</Button>
                <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['header.save']}</Button>
                <Button onClick={this.cancelConfig}>{this.state.dict['header.return']}</Button>
@@ -1760,6 +1775,9 @@
            } style={{ width: '100%' }}>
              <Icon type="setting" onClick={this.changeSetting} />
              <div className="search-list">
                <Tooltip placement="bottomLeft" overlayClassName="middle" title="在左侧工具栏《搜索》中,选择对应搜索框拖至此处添加;或点击按钮《添加搜索条件》批量添加,选择批量添加时,需提前选择使用表。">
                  <Icon type="question-circle" />
                </Tooltip>
                {!this.state.searchloading ?
                  <DragElement
                    list={this.state.config.search}
@@ -1772,6 +1790,9 @@
                }
              </div>
              <div className="action-list">
                <Tooltip placement="bottomLeft" overlayClassName="middle" title="在左侧工具栏《按钮》中,选择对应类型的按钮拖至此处添加,如选择按钮类型为表单、新标签页等含有配置页面的按钮,可在左侧工具栏-按钮-可配置按钮处,点击按钮完成相关配置。注:当设置按钮显示位置为表格时,显示列会增加操作列。">
                  <Icon type="question-circle" />
                </Tooltip>
                {!this.state.actionloading ?
                  <DragElement
                    list={this.state.config.action}
@@ -1785,6 +1806,9 @@
                }
              </div>
              <div className="column-list">
                <Tooltip placement="bottomLeft" overlayClassName="middle" title="在左侧工具栏《显示列》中,选择对应类型的显示列拖至此处添加;或点击《添加显示列》按钮批量添加,选择批量添加时,需提前选择使用表。注:添加合并列时,需设置可选列。">
                  <Icon type="question-circle" />
                </Tooltip>
                {!this.state.columnsloading ?
                  <DragElement
                    list={this.state.config.columns}
src/templates/comtableconfig/index.scss
@@ -92,6 +92,10 @@
        }
      }
    }
    .anticon-question-circle {
      color: #c49f47;
      margin-right: 3px;
    }
  }
  .tools:hover {
    overflow-y: auto;
@@ -354,6 +358,12 @@
        top: 10px;
      }
    }
    .anticon-question-circle {
      color: #c49f47;
      position: relative;
      left: -15px;
      top: 5px;
    }
  }
  .setting:hover {
    overflow-y: auto;
src/templates/modalconfig/dragelement/index.jsx
@@ -77,12 +77,8 @@
      newcard.orderBy = ''
      newcard.orderType = 'asc'
      newcard.readonly = 'false'
      newcard.required = 'false'
      
      // let indexes = cards.map(car => {return car.id})
      // let newid = 0
      // while (indexes.includes(newid)) {
      //   newid++
      // }
      newcard.id = Utils.getuuid()
      let targetId = cards.length > 0 ? cards[cards.length - 1].id : 0
src/templates/modalconfig/index.jsx
@@ -454,6 +454,19 @@
            value: 'false',
            text: this.state.dict['header.form.false']
          }]
        },
        {
          type: 'radio',
          key: 'required',
          label: this.state.dict['header.form.field.required'],
          initVal: card.required || 'false',
          options: [{
            value: 'true',
            text: this.state.dict['header.form.true']
          }, {
            value: 'false',
            text: this.state.dict['header.form.false']
          }]
        }
      ]
    })
@@ -468,7 +481,7 @@
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = JSON.parse(JSON.stringify(this.state.config))
      console.log(res)
      if ((res.type === 'select' || res.type === 'link') && res.resourceType === '1') {
        let sql = 'select ' + res.valueField + ',' + res.valueText + ' from (' + res.dataSource + ')'
        if (res.orderBy) {
@@ -477,6 +490,17 @@
        res.dataSourceSql = Utils.formatOptions(sql)
      }
      if (_config.groups.length > 0) {
        _config.groups.forEach(group => {
          group.sublist = group.sublist.map(item => {
            if (item.uuid === res.uuid) {
              return res
            } else {
              return item
            }
          })
        })
      } else {
      _config.fields = _config.fields.map(item => {
        if (item.uuid === res.uuid) {
          return res
@@ -484,6 +508,8 @@
          return item
        }
      })
      }
      _config.fields = _config.fields.filter(item => !item.origin)
      this.setState({
@@ -510,13 +536,15 @@
      cancelText: this.state.dict['header.cancel'],
      onOk() {
        let _config = JSON.parse(JSON.stringify(_this.state.config))
        _config.fields = _config.fields.filter(item => {
          if (item.uuid === card.uuid) {
            return false
          } else {
            return true
          }
        if (_config.groups.length > 0) {
          _config.groups.forEach(group => {
            group.sublist = group.sublist.filter(item => !(item.uuid === card.uuid))
        })
        } else {
          _config.fields = _config.fields.filter(item => !(item.uuid === card.uuid))
        }
        _this.setState({
          config: _config,
          loading: true
@@ -742,7 +770,8 @@
          valueText: '',
          orderBy: '',
          orderType: 'asc',
          readonly: 'false'
          readonly: 'false',
          required: 'false'
        }
      })
      _config.groups[_config.groups.length - 1].sublist = [..._config.groups[_config.groups.length - 1].sublist, ..._additems]
@@ -786,7 +815,8 @@
            valueText: '',
            orderBy: '',
            orderType: 'asc',
            readonly: 'false'
            readonly: 'false',
            required: 'false'
          }
  
          items.push(newcard)
src/templates/modalconfig/modalform/index.jsx
@@ -29,7 +29,7 @@
    let type = formlist.filter(cell => cell.key === 'type')[0].initVal
    let resourceType = formlist.filter(cell => cell.key === 'resourceType')[0].initVal
    let _options = ['label', 'field', 'initval', 'type', 'readonly'] // 默认显示项
    let _options = ['label', 'field', 'initval', 'type', 'readonly', 'required'] // 默认显示项
    if ((type === 'select' || type === 'link') && resourceType === '0') { // 选择类型、自定义资源
      _options = [..._options, 'resourceType', 'setAll', 'options']
@@ -62,7 +62,7 @@
  openTypeChange = (key, value) => {
    if (key === 'type') {
      let _options = ['label', 'field', 'initval', 'type', 'readonly']
      let _options = ['label', 'field', 'initval', 'type', 'readonly', 'required']
      if ((value === 'select' || value === 'link') && this.state.resourceType === '0') { // 选择类型、自定义资源
        _options = [..._options, 'resourceType', 'setAll', 'options']
@@ -113,7 +113,7 @@
    const { openType } = this.state
    let value = e.target.value
    if (key === 'resourceType') {
      let _options = ['label', 'field', 'initval', 'type', 'resourceType', 'setAll', 'readonly']
      let _options = ['label', 'field', 'initval', 'type', 'resourceType', 'setAll', 'readonly', 'required']
      if (value === '0') {
        _options = [..._options, 'options']
      } else if (value === '1') {
src/templates/modalconfig/source.jsx
@@ -32,7 +32,8 @@
        valueText: '',
        orderBy: '',
        orderType: 'asc',
        readonly: 'false'
        readonly: 'false',
        required: 'false'
      }, {
        origin: true,
        id: Utils.getuuid(),
@@ -50,7 +51,8 @@
        valueText: '',
        orderBy: '',
        orderType: 'asc',
        readonly: 'false'
        readonly: 'false',
        required: 'false'
      }, {
        origin: true,
        id: Utils.getuuid(),
@@ -68,7 +70,8 @@
        valueText: '',
        orderBy: '',
        orderType: 'asc',
        readonly: 'false'
        readonly: 'false',
        required: 'false'
      }
    ]
  }