king
2019-12-06 d05e0494d938c165d328c37ba452a2a8579ed724
2019-12-06
21个文件已修改
4个文件已添加
882 ■■■■■ 已修改文件
src/api/index.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/editmenu/index.jsx 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/editsecmenu/index.jsx 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/editthdmenu/index.jsx 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/comtable.js 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/header.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/comtable.js 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/header.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/actionform/index.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/dragelement/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.jsx 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.scss 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/source.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/groupform/index.jsx 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/groupform/index.scss 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.jsx 414 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.scss 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/settingform/index.jsx 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/source.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/transferform/index.jsx 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/transferform/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js
@@ -32,6 +32,7 @@
axios.interceptors.response.use((response) => {
  if (response.data.ErrCode === 'LoginError') {
    // setCurrentUrl()
    return Promise.resolve(response.data)
  } else {
    return Promise.resolve(response.data)
  }
src/components/header/editmenu/index.jsx
@@ -4,6 +4,7 @@
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { notification, Modal, Button, Spin } from 'antd'
import moment from 'moment'
import TransferForm from '@/components/transferform'
import DragElement from '../dragelement'
import MenuForm from '../menuform'
@@ -232,14 +233,18 @@
      })
    } else if (type === 'confirm' && _menuchange) {
      let _this = this
      let param  = {}
      param.func = 'sPC_Menu_SortUpt'
      let _text = []
      previewList.forEach((item, index) => {
        _text.push('select \'' + item.MenuID + '\' as Menuid,' + (index + 1) * 10 + ' as sort')
      })
      _text = _text.join(' union ')
      param.LText = Utils.formatOptions(_text)
      let param  = {
        func: 'sPC_Menu_SortUpt',
        LText: previewList.map((item, index) => {
          return 'select \'' + item.MenuID + '\' as Menuid,' + (index + 1) * 10 + ' as sort'
        })
      }
      param.LText = param.LText.join(' union ') // sql拼接
      param.LText = Utils.formatOptions(param.LText) // 关键字符替换,base64加密
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' // 时间戳
      param.secretkey = Utils.encrypt(param.LText, param.timestamp) // md5密钥
      confirm({
        title: this.state.dict['header.menu.resetorder'],
        content: '',
src/components/sidemenu/editsecmenu/index.jsx
@@ -4,6 +4,7 @@
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { notification, Modal, Button, Spin, Icon } from 'antd'
import moment from 'moment'
import TransferForm from '@/components/transferform'
import Utils from '@/utils/utils.js'
import DragElement from '../menuelement'
@@ -188,14 +189,18 @@
    } else if (type === 'confirm') { // 确定时入顺序改变,则提示保存,否则退出编辑
      if (previewList && !is(fromJS(previewList), fromJS(this.state.subMenulist))) {
        let _this = this
        let param  = {}
        param.func = 'sPC_Menu_SortUpt'
        let _text = []
        previewList.forEach((item, index) => {
          _text.push('select \'' + item.MenuID + '\' as Menuid,' + (index + 1) * 10 + ' as sort')
        })
        _text = _text.join(' union ')
        param.LText = Utils.formatOptions(_text)
        let param  = {
          func: 'sPC_Menu_SortUpt',
          LText: previewList.map((item, index) => {
            return 'select \'' + item.MenuID + '\' as Menuid,' + (index + 1) * 10 + ' as sort'
          })
        }
        param.LText = param.LText.join(' union ') // sql拼接
        param.LText = Utils.formatOptions(param.LText) // 关键字符替换,base64加密
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' // 时间戳
        param.secretkey = Utils.encrypt(param.LText, param.timestamp) // md5密钥
        confirm({
          title: this.state.dict['header.menu.resetorder'],
          content: '',
src/components/sidemenu/editthdmenu/index.jsx
@@ -4,6 +4,7 @@
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { notification, Modal, Button, Spin, Icon, Col, Card, Tabs, Row, Input } from 'antd'
import moment from 'moment'
import Preview from '@/components/preview'
import TransferForm from '@/components/transferform'
import Utils from '@/utils/utils.js'
@@ -195,14 +196,17 @@
    } else if (type === 'confirm') {
      if (previewList && !is(fromJS(previewList), fromJS(this.state.subMenulist))) {
        let _this = this
        let param  = {}
        param.func = 'sPC_Menu_SortUpt'
        let _text = []
        previewList.forEach((item, index) => {
          _text.push('select \'' + item.MenuID + '\' as Menuid,' + (index + 1) * 10 + ' as sort')
        })
        _text = _text.join(' union ')
        param.LText = Utils.formatOptions(_text)
        let param  = {
          func: 'sPC_Menu_SortUpt',
          LText: previewList.map((item, index) => {
            return 'select \'' + item.MenuID + '\' as Menuid,' + (index + 1) * 10 + ' as sort'
          })
        }
        param.LText = param.LText.join(' union ') // sql拼接
        param.LText = Utils.formatOptions(param.LText) // 关键字符替换,base64加密
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000' // 时间戳
        param.secretkey = Utils.encrypt(param.LText, param.timestamp) // md5密钥
        confirm({
          title: this.state.dict['header.menu.resetorder'],
src/locales/en-US/comtable.js
@@ -6,12 +6,28 @@
  'header.edit': 'Edit',
  'header.return': 'Back',
  'header.save': 'Save',
  'header.notsave': '不保存',
  'header.notsave': 'Do not save',
  'header.close': 'Close',
  'header.menu.basemsg': '请完善菜单基本信息!',
  'header.menu.template.change': '切换模板',
  'header.menu.basemsg': 'Please complete the basic information !',
  'header.menu.template.change': 'Switch the template',
  'header.menu.addtitle': 'The new menu',
  'header.menu.editTitle': 'The edit menu',
  'header.menu.basedata': 'The basic information',
  'header.menu.table.add': 'Add tables',
  'header.menu.table.placeholder': 'Please select a table',
  'header.menu.config.placeholder': 'Configuration has been modified, do you want to save configuration information ?',
  'header.menu.form': 'The form',
  'header.menu.form.add': 'Add form',
  'header.menu.form.configurable': 'Configuration of forms',
  'header.menu.group.add': '添加分组',
  'header.menu.group.manage': '分组管理',
  'header.menu.search': 'Search',
  'header.menu.search.add': 'Add searches',
  'header.menu.action': 'Button',
  'header.menu.action.configurable': 'Configurable Button',
  'header.menu.column': 'Column',
  'header.menu.column.add': 'Add columns',
  'header.menu.page.configurable': 'Configuration Page',
  'header.menu.menuID': 'Menu ID',
  'header.menu.menuName': 'Menu Name',
  'header.menu.menuNo': 'Menu Parameter',
@@ -21,30 +37,29 @@
  'header.menu.openType.menu': 'Menu',
  'header.menu.openType.newWindow': 'A new window',
  'header.menu.newpage.service': 'Customer Service',
  'header.form.search.placeholder': '请添加搜索条件',
  'header.form.modal.placeholder': '请添加表单',
  'header.form.action.placeholder': '请添加按钮',
  'header.form.column.placeholder': '请添加显示列',
  'header.form.column.source': '显示列',
  'header.form.search.placeholder': 'Please add search criteria',
  'header.form.modal.placeholder': 'Please add the form',
  'header.form.action.placeholder': 'Please add buttons',
  'header.form.column.placeholder': 'Please add columns',
  'header.form.column.source': 'Columns',
  'header.form.column.target': '已添加',
  'header.form.column.itemUnit': '项',
  'header.form.column.itemsUnit': '项',
  'header.form.column.itemUnit': 'Item',
  'header.form.column.itemsUnit': 'Items',
  'header.form.column.action': 'Action',
  'header.form.name': 'Name',
  'header.form.field': '字段',
  'header.form.func': '函数名',
  'header.form.innerFunc': '内部函数',
  'header.form.outerFunc': '外部函数',
  'header.form.callbackFunc': '回调函数',
  'header.form.position': '显示位置',
  'header.form.execSuccess': '执行成功',
  'header.form.execError': '执行失败',
  'header.form.refresh.never': '不刷新',
  'header.form.refresh.view': '刷新页面',
  'header.form.refresh.grid': '刷新表格',
  'header.form.toolbar': '工具栏',
  'header.form.grid': '表格',
  'header.form.intertype': '接口类型',
  'header.form.field': 'Field',
  'header.form.innerFunc': 'Internal function',
  'header.form.outerFunc': 'External function',
  'header.form.callbackFunc': 'Callback function',
  'header.form.position': 'Position',
  'header.form.execSuccess': 'Success',
  'header.form.execError': 'Failure',
  'header.form.refresh.never': 'Don\'t refresh',
  'header.form.refresh.view': 'Refresh the page',
  'header.form.refresh.grid': 'Refresh the table',
  'header.form.toolbar': 'The toolbar',
  'header.form.grid': 'Table',
  'header.form.intertype': 'The interface type',
  'header.form.interface': '接口地址',
  'header.form.interface.inner': '内部',
  'header.form.interface.outer': '外部',
src/locales/en-US/header.js
@@ -24,7 +24,6 @@
  'header.menu.update': 'Are you sure to modify the configuration information of the menu <<@M>> ?',
  'header.menu.presave': 'Menu order has been adjusted, Please save!',
  'header.menu.resetorder': 'Are you sure to adjust the menu sequence ?',
  'header.menu.basemsg': '请完善菜单基本信息!',
  'header.menu.template.empty': '菜单模板丢失,请重新选择模板!',
  'header.menu.template.change': '切换模板',
  'header.menu.addtitle': 'The new menu',
src/locales/zh-CN/comtable.js
@@ -12,6 +12,22 @@
  'header.menu.template.change': '切换模板',
  'header.menu.addtitle': '新建菜单',
  'header.menu.editTitle': '编辑菜单',
  'header.menu.basedata': '基本信息',
  'header.menu.table.add': '添加表名',
  'header.menu.table.placeholder': '请选择表名',
  'header.menu.config.placeholder': '配置已修改,是否保存配置信息?',
  'header.menu.form': '表单',
  'header.menu.form.add': '添加表单',
  'header.menu.form.configurable': '表单配置',
  'header.menu.group.add': '添加分组',
  'header.menu.group.manage': '分组管理',
  'header.menu.search': '搜索',
  'header.menu.search.add': '添加搜索条件',
  'header.menu.action': '按钮',
  'header.menu.action.configurable': '可配置按钮',
  'header.menu.column': '显示列',
  'header.menu.column.add': '添加显示列',
  'header.menu.page.configurable': '页面配置',
  'header.menu.menuID': '菜单ID',
  'header.menu.menuName': '菜单名称',
  'header.menu.menuNo': '菜单参数',
@@ -32,7 +48,6 @@
  'header.form.column.action': '操作',
  'header.form.name': '名称',
  'header.form.field': '字段',
  'header.form.func': '函数名',
  'header.form.innerFunc': '内部函数',
  'header.form.outerFunc': '外部函数',
  'header.form.callbackFunc': '回调函数',
src/locales/zh-CN/header.js
@@ -24,7 +24,6 @@
  'header.menu.update': '确定修改菜单《@M》的配置信息吗?',
  'header.menu.presave': '菜单顺序已调整,请保存!',
  'header.menu.resetorder': '确认调整菜单顺序吗?',
  'header.menu.basemsg': '请完善菜单基本信息!',
  'header.menu.template.empty': '菜单模板丢失,请重新选择模板!',
  'header.menu.template.change': '切换模板',
  'header.menu.addtitle': '新建菜单',
src/tabviews/commontable/index.jsx
@@ -2,6 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { BackTop, notification} from 'antd'
import moment from 'moment'
import Api from '@/api'
import MainSearch from './mainSearch'
import MainAction from './mainAction'
@@ -168,6 +169,10 @@
          obj_name: 'data',
          arr_field: item.valueField + ',' + item.valueText
        }
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        let defer = new Promise(resolve => {
          Api.getSystemConfig(param).then(res => {
            res.search = item
@@ -228,7 +233,10 @@
    let DateCount = `select count(1) as total from ${setting.dataresource} ${search}`
    param.LText = Utils.formatOptions(LText)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    param.DateCount = Utils.formatOptions(DateCount)
    let result = await Api.genericInterface(param)
    if (result.status) {
      this.setState({
src/templates/comtableconfig/actionform/index.jsx
@@ -92,14 +92,7 @@
    }, {
      MenuID: 'requiredOnce',
      text: this.props.dict['header.form.requiredOnce']
    }],
    // [{
    //   MenuID: 'toolbar',
    //   text: this.state.dict['header.form.toolbar']
    // }, {
    //   MenuID: 'grid',
    //   text: this.state.dict['header.form.grid']
    // }]
    }]
  }
  
src/templates/comtableconfig/dragelement/index.jsx
@@ -89,7 +89,7 @@
          _match = 'between'
        }
        newcard.uuid = Utils.getuuid()
        newcard.label = 'fieldName'
        newcard.label = 'label'
        newcard.field = ''
        newcard.initval = ''
        newcard.type = item.subType
@@ -126,7 +126,7 @@
      } else if (item.type === 'columns') {
        newcard.uuid = Utils.getuuid()
        newcard.Align = 'left'
        newcard.label = 'fieldName'
        newcard.label = 'label'
        newcard.field = ''
        newcard.Hide = 'false'
        newcard.IsSort = 'true'
src/templates/comtableconfig/index.jsx
@@ -4,6 +4,7 @@
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { Button, Card, Modal, Collapse, notification, Spin, Select, List, Icon, Empty } from 'antd'
import moment from 'moment'
import DragElement from './dragelement'
import SourceElement from './dragelement/source'
import Api from '@/api'
@@ -146,10 +147,19 @@
   * 2、根据配置信息中已使用表获取相关字段信息
   */
  componentDidMount () {
    let _text = 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0'
    _text = Utils.formatOptions(_text)
    let param = {
      func: 'sPC_Get_SelectedList',
      LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
      obj_name: 'data',
      arr_field: 'TbName,Remark'
    }
    Api.getSystemConfig({func: 'sPC_Get_SelectedList', LText: _text, obj_name: 'data', arr_field: 'TbName,Remark'}).then(res => {
    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.getSystemConfig(param).then(res => {
      console.log(res)
      if (res.status) {
        this.setState({
          tables: res.data
@@ -1503,21 +1513,26 @@
          {/* 工具栏 */}
          <div className="tools">
            <Collapse accordion defaultActiveKey="0" bordered={false}>
              <Panel header="基本信息" key="0" id="common-basedata">
              {/* 基本信息 */}
              <Panel header={this.state.dict['header.menu.basedata']} key="0" id="common-basedata">
                {/* 菜单信息 */}
                <MenuForm
                  dict={this.state.dict}
                  formlist={this.state.menuformlist}
                  wrappedComponentRef={(inst) => this.menuformRef = inst}
                />
                {/* 表名添加 */}
                <div className="ant-col ant-form-item-label">
                  <label title="添加表名">添加表名</label>
                  <label title={this.state.dict['header.menu.table.add']}>
                    {this.state.dict['header.menu.table.add']}
                  </label>
                </div>
                <Select
                  showSearch
                  className="tables"
                  style={{ width: '100%' }}
                  optionFilterProp="children"
                  value={'请选择表名'}
                  value={this.state.dict['header.menu.table.placeholder']}
                  onChange={this.onTableChange}
                  showArrow={false}
                  getPopupContainer={() => document.getElementById('common-basedata')}
@@ -1541,15 +1556,17 @@
                  </List.Item>}
                />}
              </Panel>
              <Panel header="搜索" key="1">
              {/* 搜索条件添加 */}
              <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>
                <Button type="primary" block onClick={() => this.queryField('search')}>添加搜索条件</Button>
                <Button type="primary" block onClick={() => this.queryField('search')}>{this.state.dict['header.menu.search.add']}</Button>
              </Panel>
              <Panel header="按钮" key="2">
              {/* 按钮添加 */}
              <Panel header={this.state.dict['header.menu.action']} key="2">
                <div className="search-element">
                  {Source.actionItems.map((item, index) => {
                    return (<SourceElement key={index} content={item}/>)
@@ -1557,7 +1574,7 @@
                </div>
                {configAction.length > 0 ?
                  <div>
                    <p style={{marginTop: '20px', marginBottom: '10px', color: '#1890ff'}}>可配置按钮:</p>
                    <p style={{marginTop: '20px', marginBottom: '10px', color: '#1890ff'}}>{this.state.dict['header.menu.action.configurable']}</p>
                    {configAction.map((item, index) => {
                      return (
                        <div key={index}>
@@ -1573,18 +1590,18 @@
                  </div> : null
                }
              </Panel>
              <Panel header="显示列" key="3">
              <Panel header={this.state.dict['header.menu.column']} key="3">
                <div className="search-element">
                  {Source.columnItems.map((item, index) => {
                    return (<SourceElement key={index} content={item}/>)
                  })}
                </div>
                <Button type="primary" block onClick={() => this.queryField('columns')}>添加显示列</Button>
                <Button type="primary" block onClick={() => this.queryField('columns')}>{this.state.dict['header.menu.column.add']}</Button>
              </Panel>
            </Collapse>
          </div>
          <div className="setting">
            <Card title="页面配置" bordered={false} extra={
            <Card title={this.state.dict['header.menu.page.configurable']} bordered={false} extra={
              <div>
                <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>
@@ -1739,7 +1756,7 @@
          ]}
          destroyOnClose
        >
          菜单配置已修改,是否保存配置信息?
          {this.state.dict['header.menu.config.placeholder']}
        </Modal>
        {this.state.loading && <Spin size="large" />}
      </div>
src/templates/comtableconfig/index.scss
@@ -200,8 +200,6 @@
            color: #1890ff;
            cursor: pointer;
            display: none;
            // border: 1px solid #1890ff;
            // border-radius: 20px;
          }
          .edit.close {
            left: 20px;
src/templates/modalconfig/dragelement/index.jsx
@@ -109,7 +109,7 @@
        </Col>
      ))}
      {cards.length === 0 &&
        <div className="common-drawarea-placeholder">
        <div className="modal-drawarea-placeholder">
          {placeholder}
        </div>
      }
src/templates/modalconfig/dragelement/index.scss
@@ -1,4 +1,4 @@
.common-source-item {
.modal-source-item {
  display: block;
  box-shadow: 0px 0px 2px #bcbcbc;
  padding: 0.5rem 1rem;
@@ -7,7 +7,7 @@
  cursor: move;
  border-radius: 4px;
}
.common-drawarea-placeholder {
.modal-drawarea-placeholder {
  width: 100%;
  line-height: 65px;
  text-align: center;
src/templates/modalconfig/dragelement/source.jsx
@@ -5,7 +5,7 @@
const SourceElement = ({content}) => {
  const [, drag] = useDrag({ item: content })
  return (
    <div ref={drag} className="common-source-item">
    <div ref={drag} className="modal-source-item">
      {content.label}
    </div>
  )
src/templates/modalconfig/groupform/index.jsx
New file
@@ -0,0 +1,66 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, InputNumber } from 'antd'
import TransferForm from '../transferform'
import './index.scss'
class SettingForm extends Component {
  static propTpyes = {
    dict: PropTypes.object, // 字典项
    data: PropTypes.object
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          resolve(values)
        } else {
          reject(err)
        }
      })
    })
  }
  render() {
    const { data } = this.props
    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="ant-advanced-search-form modal-setting-form">
        <Row gutter={24}>
          <Col span={12}>
            <Form.Item label="分组名称">
              {getFieldDecorator('title', {
                initialValue: data.title
              })(<Input placeholder="" autoComplete="off"/>)}
            </Form.Item>
          </Col>
          <Col span={12}>
            <Form.Item label="排序">
              {getFieldDecorator('sort', {
                initialValue: data.sort
              })(<InputNumber min={0} max={100} precision={0} />)}
            </Form.Item>
          </Col>
          <Col span={24}>
            <TransferForm dict={this.props.dict} columns={this.props.columns} ref="column-transfer" selected={this.props.card.sublist}/>
          </Col>
        </Row>
      </Form>
    )
  }
}
export default Form.create()(SettingForm)
src/templates/modalconfig/groupform/index.scss
New file
@@ -0,0 +1,13 @@
.ant-advanced-search-form.modal-setting-form {
  .textarea {
    .ant-form-item-label {
      width: 16.3%;
    }
    .ant-form-item-control-wrapper {
      width: 83.33333333%;
    }
  }
  .ant-input-number {
    width: 100%;
  }
}
src/templates/modalconfig/index.jsx
@@ -4,11 +4,13 @@
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { Button, Card, Modal, Collapse, notification, Select, List, Icon, Empty } from 'antd'
import moment from 'moment'
import DragElement from './dragelement'
import SourceElement from './dragelement/source'
import Api from '@/api'
import ModalForm from './modalform'
import SettingForm from './settingform'
import GroupForm from './groupform'
import EditCard from './editcard'
import MenuForm from './menuform'
import zhCN from '@/locales/zh-CN/comtable.js'
@@ -30,45 +32,49 @@
  }
  state = {
    operaType: '', // 操作类型,新建或编辑
    dict: CommonDict, // 字典
    config: null, // 页面配置
    visible: false, // 搜索条件、按钮、显示列,模态框显示控制
    tableVisible: false, // 数据表字段模态框
    addType: '', // 添加类型-搜索条件或显示列
    tableColumns: [], // 表格显示列
    fields: null, // 搜索条件及显示列,可选字段
    modalformlist: null, // 基本信息表单字段
    formlist: null, // 搜索条件、按钮、显示列表单字段
    card: null, // 编辑元素
    loading: false, // 搜索条件加载中
    menuloading: false, // 菜单保存中
    dict: CommonDict,      // 字典
    config: null,          // 页面配置,包括模板类型、模态框设置、添加表名、表单列表
    visible: false,        // 表单编辑模态框,显示控制
    tableVisible: false,   // 数据表字段列表模态框,显示控制
    tableColumns: [],      // 表格字段名列表
    fields: null,          // 表单,可选字段(去重后)
    modalformlist: null,   // 基本信息表单字段
    formlist: null,        // 表单编辑模态框,可编辑字段
    card: null,            // 编辑元素
    loading: false,        // 表单刷新时使用
    menuloading: false,    // 菜单保存中
    settingVisible: false, // 全局配置模态框
    closeVisible: false, // 关闭模态框
    tables: [], // 可用表名
    selectedTables: [], // 已选表名
    originMenu: null // 原始菜单
    closeVisible: false,   // 关闭模态框
    tables: [],            // 可用表名
    selectedTables: [],    // 已选表名
    originMenu: null,      // 原始菜单
    groupVisible: false,   // 全局配置模态框
  }
  /**
   * @description 数据预处理
   * 1、按钮配置存在时使用按钮配置,不存在时使用默认配置(示例)
   * 2、模态框标题不存在时,使用按钮标题
   * 3、设置已选表
   * 4、设置按钮基本信息
   */
  UNSAFE_componentWillMount () {
    const {menu, editAction} = this.props
    let _config = ''
    let _operaType = 'add'
    if (editAction.pageParam) {
      _config = editAction.pageParam
      _operaType = 'edit'
    } else {
      _config = JSON.parse(JSON.stringify((Source.baseConfig)))
      _config.groups[0].sublist = _config.fields.map(field => field.uuid)
    }
    if (!_config.setting.title) {
      _config.setting.title = editAction.label
    }
    this.setState({
      config: _config,
      operaType: _operaType,
      selectedTables: _config.tables || [],
      modalformlist: [
        {
@@ -91,11 +97,24 @@
    })
  }
  /**
   * @description 获取数据表信息
   * 1、获取系统中全部表名
   * 2、根据已选表名,获取表格字段列表
   */
  componentDidMount () {
    let _text = 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0'
    _text = Utils.formatOptions(_text)
    let param = {
      func: 'sPC_Get_SelectedList',
      LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
      obj_name: 'data',
      arr_field: 'TbName,Remark'
    }
    Api.getSystemConfig({func: 'sPC_Get_SelectedList', LText: _text, obj_name: 'data', arr_field: 'TbName,Remark'}).then(res => {
    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.getSystemConfig(param).then(res => {
      if (res.status) {
        this.setState({
          tables: res.data
@@ -117,6 +136,8 @@
        })
      })
    })
    // 获取字段后数据处理,根据类型分为text、number、datetime、date
    Promise.all(deffers).then(response => {
      let _columns = []
      response.forEach(res => {
@@ -133,16 +154,6 @@
              } else if (/^decimal/.test(_type)) {
                _decimal = _type.split(',')[1]
                _decimal = parseInt(_decimal)
                if (_decimal > 4) {
                  _decimal = 4
                }
                _type = 'number'
              } else if (/^decimal/.test(_type)) {
                _decimal = _type.split(',')[1]
                _decimal = parseInt(_decimal)
                if (_decimal > 4) {
                  _decimal = 4
                }
                _type = 'number'
              } else if (/^datetime/.test(_type)) {
                _type = 'datetime'
@@ -176,11 +187,17 @@
    })
  }
  /**
   * @description 表单变化
   * 1、表单拖拽添加时,检查是否存在示例表单,如存在则去除示例
   * 2、表单移动后,保存移动后的顺序
   */
  handleList = (list) => {
    let _config = JSON.parse(JSON.stringify(this.state.config))
    if (list.length > _config.fields.length) {
      _config.fields = list.filter(item => !item.origin)
      this.setState({
        loading: true,
        config: _config
@@ -195,6 +212,12 @@
    }
  }
  /**
   * @description 表单编辑
   * 1、显示编辑弹窗
   * 2、保存编辑项
   * 3、设置编辑参数项
   */
  handleForm = (card) => {
    this.setState({
      visible: true,
@@ -344,10 +367,16 @@
    })
  }
  /**
   * @description 编辑后提交
   * 1、获取编辑后的表单信息
   * 2、去除可能存在的示例表单
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = JSON.parse(JSON.stringify(this.state.config))
      console.log(res)
      _config.fields = _config.fields.map(item => {
        if (item.uuid === res.uuid) {
          return res
@@ -369,6 +398,9 @@
    })
  }
  /**
   * @description 表单删除并刷新
   */
  closeForm = (card) => {
    let _this = this
@@ -396,10 +428,6 @@
      },
      onCancel() {}
    })
  }
  changeTemplate = () => {
    this.props.handleConfig('template')
  }
  submitConfig = () => {
@@ -449,7 +477,6 @@
        if (response.status) {
          this.setState({
            menuloading: false,
            operaType: 'edit',
            originMenu: {
              ...originMenu,
              LongParam: _config,
@@ -476,57 +503,53 @@
        }
      })
      if (this.state.operaType === 'add') {
      } else {
        let param = {
          func: 'sPC_TrdMenu_Upt',
          ParentID: res.parentId,
          MenuID: menu.MenuID,
          MenuNo: res.menuNo,
          Template: menu.PageParam.Template || '',
          MenuName: res.menuName,
          PageParam: JSON.stringify(_pageParam),
          LongParam: _LongParam
        }
        this.setState({
          menuloading: true
        })
      // let param = {
      //   func: 'sPC_TrdMenu_Upt',
      //   ParentID: res.parentId,
      //   MenuID: menu.MenuID,
      //   MenuNo: res.menuNo,
      //   Template: menu.PageParam.Template || '',
      //   MenuName: res.menuName,
      //   PageParam: JSON.stringify(_pageParam),
      //   LongParam: _LongParam
      // }
      this.setState({
        menuloading: true
      })
        Api.getSystemConfig(param).then(response => {
          if (response.status) {
            notification.success({
              top: 92,
              message: '保存成功',
              duration: 10
            })
            if (this.state.closeVisible) {
              this.props.handleConfig('')
            } else {
              this.setState({
                menuloading: false,
                originMenu: {
                  ...originMenu,
                  LongParam: _config,
                  PageParam: _pageParam,
                  MenuName: res.menuName,
                  MenuNo: res.menuNo,
                  ParentID: res.parentId
                }
              })
            }
      Api.getSystemConfig(param).then(response => {
        if (response.status) {
          notification.success({
            top: 92,
            message: '保存成功',
            duration: 10
          })
          if (this.state.closeVisible) {
            this.props.handleConfig('')
          } else {
            this.setState({
              menuloading: false
            })
            notification.warning({
              top: 92,
              message: response.message,
              duration: 10
              menuloading: false,
              originMenu: {
                ...originMenu,
                LongParam: _config,
                PageParam: _pageParam,
                MenuName: res.menuName,
                MenuNo: res.menuNo,
                ParentID: res.parentId
              }
            })
          }
        })
      }
        } else {
          this.setState({
            menuloading: false
          })
          notification.warning({
            top: 92,
            message: response.message,
            duration: 10
          })
        }
      })
    }, () => {
      notification.warning({
        top: 92,
@@ -541,7 +564,8 @@
    const { config, originMenu } = this.state
    let _this = this
    if (this.state.operaType === 'add') {
    let isOrigin = config.fields.filter(item => item.origin).length > 0
    if (isOrigin) {
      confirm({
        content: '菜单尚未提交,确定放弃保存吗?',
        okText: this.state.dict['header.confirm'],
@@ -579,6 +603,12 @@
    }
  }
  /**
   * @description 通过表字段添加表单
   * 1、检查是否已选表名,为选时警告提示
   * 2、表字段名通过map去重
   * 3、检查表单中的已选字段,并标记已选
   */
  queryField = () => {
    const {selectedTables, tableColumns, config} = this.state
    if (selectedTables.length === 0) {
@@ -599,7 +629,7 @@
    config.fields.forEach(item => {
      if (columns.has(item.field)) {
        columns.set(item.field, {...item, selected: true, type: item.type})
        columns.set(item.field, {...item, selected: true})
      }
    })
@@ -609,6 +639,13 @@
    })
  }
  /**
   * @description 选择字段后提交
   * 1、没有可选字段时,直接关闭
   * 2、获取已选字段
   * 3、与已有字段对比
   * 4、添加新增字段
   */
  addFieldSubmit = () => {
    if (!this.state.fields || this.state.fields.length === 0) {
      this.setState({
@@ -629,15 +666,15 @@
      if (columns.has(item.field)) {
        let cell = columns.get(item.field)
        if (cell.selected && cell.type === item.type) { // 数据未修改
        if (cell.selected && cell.type === item.type) { // 数据选择状态及类型未修改时,直接添加
          items.push(item)
        } else if (cell.selected) { // 数据类型修改
        } else if (cell.selected) {                     // 数据类型修改时,重置类型及初始值
          item.type = cell.type
          item.initval = ''
          items.push(item)
        }
        columns.delete(item.field)
      } else if (!item.origin) {
      } else if (!item.origin) {                        // 过滤示例项
        items.push(item)
      }
    })
@@ -646,7 +683,7 @@
    let indexes = items.map(card => {return card.id})
    let id = Math.max(...indexes, 0) + 1
    _columns.forEach(item => {
    _columns.forEach(item => { // 循环添加新增字段
      if (item.selected) {
        let newcard = {
          id: id,
@@ -684,60 +721,70 @@
    })
  }
  /**
   * @description 添加表名
   * 1、获取表信息
   * 2、检验是否已经添加,已添加时跳过
   * 3、通过表名获取字段集,并设置数据类型
   */
  onTableChange = (value) => {
    const {tables, selectedTables, tableColumns} = this.state
    let _table = tables.filter(item => item.TbName === value)[0]
    let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0]
    if (!isSelected) {
      this.setState({
        selectedTables: [...selectedTables, _table]
      })
      Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
        if (res.status) {
          let tabmsg = {
            tableName: _table.name,
            columns: res.FDName.map(item => {
              let _type = item.FieldType.toLowerCase()
              let _decimal = 0
              if (/^nvarchar/.test(_type)) {
                _type = 'text'
              } else if (/^int/.test(_type)) {
                _type = 'number'
              } else if (/^decimal/.test(_type)) {
                _decimal = _type.split(',')[1]
                _decimal = parseInt(_decimal)
                _type = 'number'
              } else if (/^datetime/.test(_type)) {
                _type = 'datetime'
              } else if (/^date/.test(_type)) {
                _type = 'date'
              } else {
                _type = 'text'
              }
              return {
                field: item.FieldName,
                label: item.FieldDec,
                type: _type,
                decimal: _decimal
              }
            })
          }
          this.setState({
            tableColumns: [...tableColumns, tabmsg]
          })
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
    if (isSelected) return
    this.setState({
      selectedTables: [...selectedTables, _table]
    })
    Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
      if (res.status) {
        let tabmsg = {
          tableName: _table.name,
          columns: res.FDName.map(item => {
            let _type = item.FieldType.toLowerCase()
            let _decimal = 0
            if (/^nvarchar/.test(_type)) {
              _type = 'text'
            } else if (/^int/.test(_type)) {
              _type = 'number'
            } else if (/^decimal/.test(_type)) {
              _decimal = _type.split(',')[1]
              _decimal = parseInt(_decimal)
              _type = 'number'
            } else if (/^datetime/.test(_type)) {
              _type = 'datetime'
            } else if (/^date/.test(_type)) {
              _type = 'date'
            } else {
              _type = 'text'
            }
            return {
              field: item.FieldName,
              label: item.FieldDec,
              type: _type,
              decimal: _decimal
            }
          })
        }
      })
    }
        this.setState({
          tableColumns: [...tableColumns, tabmsg]
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
      }
    })
  }
  /**
   * @description 删除表名,删除对应字段集
   */
  deleteTable = (table) => {
    const {selectedTables, tableColumns} = this.state
@@ -747,12 +794,18 @@
    })
  }
  /**
   * @description 全局设置模态框
   */
  changeSetting = () => {
    this.setState({
      settingVisible: true
    })
  }
  /**
   * @description 保存全局设置
   */
  settingSave = () => {
    const {config} = this.state
    this.settingRef.handleConfirm().then(res => {
@@ -763,6 +816,14 @@
    })
  }
  handleGroup = () => {
  }
  handleGroupSave = () => {
  }
  render () {
    const { config } = this.state
@@ -771,26 +832,23 @@
        <DndProvider backend={HTML5Backend}>
          <div className="tools">
            <Collapse accordion defaultActiveKey="0" bordered={false}>
              <Panel header="基本信息" key="0" id="modal-basedata">
                <MenuForm
                  dict={this.state.dict}
                  formlist={this.state.modalformlist}
                  wrappedComponentRef={(inst) => this.menuformRef = inst}
                />
              <Panel header={this.state.dict['header.menu.basedata']} key="0" id="modal-basedata">
                <MenuForm
                  dict={this.state.dict}
                  formlist={this.state.modalformlist}
                  wrappedComponentRef={(inst) => this.menuformRef = inst}
                />
                <div className="ant-col ant-form-item-label">
                  <label title="添加表名">添加表名</label>
                  <label title={this.state.dict['header.menu.table.add']}>
                    {this.state.dict['header.menu.table.add']}
                  </label>
                </div>
                <Select
                  showSearch
                  className="tables"
                  style={{ width: '100%' }}
                  optionFilterProp="children"
                  value={'请选择表名'}
                  value={this.state.dict['header.menu.table.placeholder']}
                  onChange={this.onTableChange}
                  showArrow={false}
                  getPopupContainer={() => document.getElementById('modal-basedata')}
@@ -813,18 +871,19 @@
                  </List.Item>}
                />}
              </Panel>
              <Panel header="表单" key="1">
              <Panel header={this.state.dict['header.menu.form']} key="1">
                <div className="search-element">
                  {Source.searchItems.map((item, index) => {
                    return (<SourceElement key={index} content={item}/>)
                  })}
                </div>
                <Button type="primary" block onClick={() => this.queryField()}>添加表单</Button>
                <Button type="primary" block onClick={() => this.queryField()}>{this.state.dict['header.menu.form.add']}</Button>
                <Button type="primary" block onClick={() => this.handleGroup()}>{this.state.dict['header.menu.group.add']}</Button>
              </Panel>
            </Collapse>
          </div>
          <div className="setting">
            <Card title="表单配置" bordered={false} extra={
            <Card title={this.state.dict['header.menu.form.configurable']} bordered={false} extra={
              <div>
                <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>
@@ -840,7 +899,24 @@
                </div>
                <div className="ant-modal-body">
                  <div className="modal-form">
                    {!this.state.loading ?
                    {!this.state.loading && config.groups.length > 1 &&
                      config.groups.map(group => {
                        return (
                          <div key={group.uuid}>
                            <p className="group-title">{group.label}</p>
                            <DragElement
                              list={config.fields}
                              setting={config.setting}
                              placeholder={this.state.dict['header.form.modal.placeholder']}
                              handleList={this.handleList}
                              handleForm={this.handleForm}
                              closeForm={this.closeForm}
                            />
                          </div>
                        )
                      })
                    }
                    {!this.state.loading && config.groups.length === 1?
                      <DragElement
                        list={config.fields}
                        setting={config.setting}
@@ -854,8 +930,12 @@
                </div>
                <div className="ant-modal-footer">
                  <div>
                    <button type="button" className="ant-btn"><span>取 消</span></button>
                    <button type="button" className="ant-btn ant-btn-primary"><span>确 定</span></button>
                    <button type="button" className="ant-btn">
                      <span>{this.state.dict['header.cancel']}</span>
                    </button>
                    <button type="button" className="ant-btn ant-btn-primary">
                      <span>{this.state.dict['header.confirm']}</span>
                    </button>
                  </div>
                  <div className="action-mask"></div>
                </div>
@@ -867,11 +947,7 @@
          title={this.state.dict['header.edit']}
          visible={this.state.visible}
          width={700}
          onCancel={() => {
            this.setState({
              visible: false
            })
          }}
          onCancel={() => { this.setState({ visible: false }) }}
          onOk={this.handleSubmit}
          destroyOnClose
        >
@@ -888,11 +964,7 @@
          width={'65vw'}
          style={{minWidth: '900px', maxWidth: '1200px'}}
          onOk={this.addFieldSubmit}
          onCancel={() => {
            this.setState({
              tableVisible: false
            })
          }}
          onCancel={() => { this.setState({ tableVisible: false }) }}
          destroyOnClose
        >
          {this.state.fields && this.state.fields.length > 0 ?
@@ -907,11 +979,7 @@
          visible={this.state.settingVisible}
          width={700}
          onOk={this.settingSave}
          onCancel={() => {
            this.setState({
              settingVisible: false
            })
          }}
          onCancel={() => { this.setState({ settingVisible: false }) }}
          destroyOnClose
        >
          <SettingForm
@@ -932,7 +1000,21 @@
          ]}
          destroyOnClose
        >
          菜单配置已修改,是否保存配置信息?
          {this.state.dict['header.menu.config.placeholder']}
        </Modal>
        <Modal
          title={this.state.dict['header.menu.group.manage']}
          visible={this.state.groupVisible}
          width={700}
          onOk={this.handleGroupSave}
          onCancel={() => { this.setState({ groupVisible: false }) }}
          destroyOnClose
        >
          <GroupForm
            data={config.setting}
            dict={this.state.dict}
            wrappedComponentRef={(inst) => this.settingRef = inst}
          />
        </Modal>
      </div>
    )
src/templates/modalconfig/index.scss
@@ -27,6 +27,8 @@
    .ant-collapse-header {
      padding: 11px 16px 10px 40px;
      border-bottom: 1px solid #d9d9d9;
      background: #1890ff;
      color: #ffffff;
    }
    .ant-collapse-content-box {
      .ant-form-item {
@@ -36,6 +38,9 @@
          height: 25px;
          line-height: 25px;
        }
      }
      .ant-btn {
        margin-bottom: 10px;
      }
    }
    .search-element {
@@ -63,7 +68,6 @@
        text-overflow: ellipsis;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        // white-space: nowrap;
        width: 100%;
        .anticon {
          position: absolute;
@@ -141,12 +145,12 @@
          background: transparent;
        }
        .ant-modal-close {
          opacity: 0.5;
          opacity: 0.3;
        }
        .ant-modal-footer {
          position: relative;
          button {
            opacity: 0.5;
            opacity: 0.3;
          }
        }
        .action-mask {
@@ -160,8 +164,12 @@
      .modal-form {
        min-height: 87px;
        .group-title {
          margin: 10px 0px;
          border-bottom: 1px solid #e8e8e8;
        }
        > .ant-row {
          min-height: 65px;
          min-height: 120px;
        }
        .ant-row .ant-col-6 {
          padding: 0 12px!important;
src/templates/modalconfig/settingform/index.jsx
@@ -3,16 +3,10 @@
import { Form, Row, Col, Input, Radio, InputNumber } from 'antd'
import './index.scss'
// const { TextArea } = Input
class SettingForm extends Component {
  static propTpyes = {
    dict: PropTypes.object, // 字典项
    data: PropTypes.object
  }
  state = {
  }
  handleConfirm = () => {
@@ -31,7 +25,7 @@
  render() {
    const { data } = this.props
    const { getFieldDecorator } = this.props.form
    console.log(data)
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -72,19 +66,6 @@
              })(<InputNumber min={30} max={90} precision={0} />)}
            </Form.Item>
          </Col>
          {/* <Col span={24}>
            <Form.Item label="数据源" className="textarea">
              {getFieldDecorator('dataresource', {
                initialValue: data.dataresource,
                rules: [
                  {
                    required: true,
                    message: dict['form.required.input'] + '数据源!'
                  }
                ]
              })(<TextArea rows={4} />)}
            </Form.Item>
          </Col> */}
        </Row>
      </Form>
    )
src/templates/modalconfig/source.jsx
@@ -13,6 +13,19 @@
      cols: '2'
    },
    tables: [],
    groups: [{
      label: '未分组',
      default: true,
      sort: 101,
      uuid: Utils.getuuid(),
      sublist: []
    }, {
      label: '组1',
      sort: 1,
      default: false,
      uuid: Utils.getuuid(),
      sublist: []
    }],
    fields: [
      {
        origin: true,
src/templates/modalconfig/transferform/index.jsx
New file
@@ -0,0 +1,75 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Transfer } from 'antd'
import './index.scss'
class TransferForm extends Component {
  static propTypes = {
    columns: PropTypes.array,
    selected: PropTypes.array,
    dict: PropTypes.object, // 字典项
  }
  state = {
    data: [],
    targetKeys: [],
    selectedKeys: []
  }
  handleChange = (nextTargetKeys, direction, moveKeys) => {
    this.setState({ targetKeys: nextTargetKeys })
  }
  handleSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {
    this.setState({ selectedKeys: [...sourceSelectedKeys, ...targetSelectedKeys] })
  }
  UNSAFE_componentWillMount() {
    let datas = new Map()
    this.props.columns.forEach(item => {
      if (item.field) {
        datas.set(item.uuid, item)
      }
    })
    let selecteds = []
    this.props.selected.forEach(item => {
      if (datas.has(item)) {
        selecteds.push(item)
        // datas.delete(item)
      }
    })
    this.setState({
      data: [...datas.values()].map(item => {
        return {
          key: item.uuid,
          title: item.label,
          description: ''
        }
      }),
      targetKeys: selecteds
    })
  }
  render() {
    const { targetKeys, selectedKeys } = this.state
    return (
      <div className="common-table-columns-transfer">
        <Transfer
          dataSource={this.state.data}
          titles={[this.props.dict['header.form.column.source'], this.props.dict['header.form.column.target']]}
          targetKeys={targetKeys}
          locale={{itemUnit: this.props.dict['header.form.column.itemUnit'], itemsUnit: this.props.dict['header.form.column.itemsUnit']}}
          selectedKeys={selectedKeys}
          onChange={this.handleChange}
          onSelectChange={this.handleSelectChange}
          render={item => item.title}
        />
      </div>
    )
  }
}
export default TransferForm
src/templates/modalconfig/transferform/index.scss
New file
@@ -0,0 +1,6 @@
.common-table-columns-transfer {
  padding-left: 18px;
  .ant-transfer-list {
    width: 296px;
  }
}
src/utils/utils.js
@@ -1,4 +1,5 @@
import moment from 'moment'
import md5 from 'md5'
const service = window.GLOB.service ? (/\/$/.test(window.GLOB.service) ? window.GLOB.service : window.GLOB.service + '/') : ''
@@ -34,11 +35,22 @@
  }
  /**
   * @description md5加密
   * @return {String}  str         加密串
   * @return {String}  timestamp   时间戳
   */
  static encrypt (str, timestamp) {
    let salt = 'mingke' // 盐值
    return md5(str + salt + timestamp)
  }
  /**
   * @description sql加密
   * @return {String}  value
   */
  static formatOptions (value) {
    // 产生一个新的GUID值
    let salt = 'minKe' // 盐值
    // 关键字转换规则
    let format = [{
      key: 'select',
      value: ' msltk '
@@ -136,18 +148,18 @@
      key: 'ROLLBACK',
      value: ' mrlbkk '
    }]
    // 替换关键字
    format.forEach(item => {
      let reg  =  new RegExp('(^|\\s)' + item.key + '(\\s|$)', 'ig')
      value = value.replace(reg, item.value)
    })
    // 1、替换%符(数据库中解析后sql报错),2、去除收尾多余空格
    value = value.replace(/%/ig, 'mpercent')
    value = value.replace(/(^\s|\s$)/ig, '')
    value = window.btoa(window.encodeURIComponent(value))
    let index = Math.floor(Math.random() * value.length)
    value = value.slice(0, index) + 'minKe' + value.slice(index)
    value = window.btoa(value)
    // value = value.replace(/%/ig, 'mpercent')
    //   .replace(/>/ig, 'greateror')
    // value = value.replace(/>/ig, 'greateror')
    //   .replace(/</ig, 'lessor')
    //   .replace(/!=/ig, 'noequal')
    //   .replace(/=/ig, 'equal')
@@ -160,6 +172,17 @@
    //   .replace(/\*/ig, 'mastrsk')
    //   .replace(/'/ig, 'mqotek')
    //   .replace(/\s/ig, 'mspace')
    // 1、encode编码(中文字符超出base64加密范围),2、base64加密
    value = window.btoa(window.encodeURIComponent(value))
    // 随机插入字符
    let index = Math.floor(Math.random() * value.length)
    value = value.slice(0, index) + salt + value.slice(index)
    // base64加密
    value = window.btoa(value)
    return value
  }