king
2021-07-23 c7414c3cc93649479119d51b230c4b8e36884ca7
2021-07-23
30个文件已修改
2 文件已重命名
2个文件已删除
4 文件已复制
14个文件已添加
4103 ■■■■ 已修改文件
src/components/editor/index.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/normal-menubar/menucomponent/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/navbar/normal-navbar/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/navbar/normal-navbar/menusetting/menuform/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/navbar/normal-navbar/menusetting/menuform/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/topbar/normal-navbar/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/mobshell/card.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/modulesource/option.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/loginform.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/navbar/normal-navbar/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/group/normal-group/index.jsx 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/tabtransfer/index.jsx 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/scriptmanage/index.jsx 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/customSwitch/index.jsx 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/customTextArea/index.jsx 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 1520 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkCheckCard/index.jsx 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkCheckCard/index.scss 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkCheckbox/index.jsx 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkCheckbox/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkColor/index.jsx 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkColor/index.scss 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkDatePicker/index.jsx 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkDatePicker/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkInput/index.jsx 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkInput/index.scss 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkNumberInput/index.jsx 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkNumberInput/index.scss 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkRadio/index.jsx 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkRadio/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkSelect/index.jsx 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkSelect/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkSwitch/index.jsx 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkSwitch/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkTextArea/index.jsx 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkTextArea/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-datamanage.js 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/interface/history/index.jsx 78 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/interface/workspace/index.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/interface/workspace/request/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/interface/workspace/request/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 313 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/rolemanage/index.jsx 211 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/rolemanage/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/editor/index.jsx
@@ -23,8 +23,8 @@
class NormalEditor extends Component {
  static propTpyes = {
    Item: PropTypes.object,     // 表单元素
    onChange: PropTypes.func,   // 表单更新
    config: PropTypes.object,
    onChange: PropTypes.func
  }
  state = {
@@ -33,16 +33,17 @@
  }
  UNSAFE_componentWillMount () {
    const { config, defaultValue } = this.props
    let initVal = null
    let encryption = 'false'
    if (this.props['data-__meta']) {
      initVal = this.props['data-__meta'].initialValue || null
    } else if (this.props.defaultValue) {
      initVal = this.props.defaultValue || null
    if (config && config.initval) {
      initVal = config.initval
    } else if (defaultValue) {
      initVal = defaultValue
    }
    if (this.props.Item && this.props.Item.encryption === 'true') {
    if (config && config.encryption === 'true') {
      encryption = 'true'
      if (initVal) {
        try {
src/mob/components/menubar/normal-menubar/menucomponent/index.jsx
@@ -107,7 +107,6 @@
      window.open(card.setting.linkurl)
    } else {
      MKEmitter.emit('changeEditMenu', {
        fixed: card.setting.type === 'menu',
        MenuID: card.setting.type === 'linkmenu' ? card.setting.linkMenuId : card.uuid,
        copyMenuId: card.setting.type === 'menu' ? card.setting.copyMenuId : '',
        MenuNo: card.setting.MenuNo || '',
src/mob/components/navbar/normal-navbar/index.jsx
@@ -133,7 +133,6 @@
      window.open(menu.link)
    } else {
      MKEmitter.emit('changeEditMenu', {
        fixed: menu.property === 'menu',
        MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID,
        copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '',
        MenuNo: menu.MenuNo,
src/mob/components/navbar/normal-navbar/menusetting/menuform/index.jsx
@@ -88,7 +88,7 @@
    }
    return (
      <Form {...formItemLayout}>
      <Form {...formItemLayout} className="mob-menu-form">
        <Row gutter={24}>
          <Col span={12}>
            <Form.Item label="菜单名称">
@@ -148,8 +148,8 @@
              })(
                <Radio.Group onChange={this.changeProperty} style={{whiteSpace: 'nowrap'}}>
                  <Radio value="menu">菜单</Radio>
                  <Radio value="link">链接</Radio>
                  <Radio value="linkmenu">关联菜单</Radio>
                  <Radio value="link">链接</Radio>
                </Radio.Group>
              )}
            </Form.Item>
@@ -166,8 +166,8 @@
              )}
            </Form.Item>
          </Col>
          {property === 'link' ? <Col span={12}>
            <Form.Item label="链接地址">
          {property === 'link' ? <Col span={24}>
            <Form.Item label="链接地址" className="textarea">
              {getFieldDecorator('link', {
                initialValue: menu.link || '',
                rules: [{
src/mob/components/navbar/normal-navbar/menusetting/menuform/index.scss
@@ -0,0 +1,10 @@
.mob-menu-form {
  .ant-form-item.textarea {
    .ant-form-item-label {
      width: 16%;
    }
    .ant-form-item-control-wrapper {
      width: 84%;
    }
  }
}
src/mob/components/topbar/normal-navbar/index.jsx
@@ -120,7 +120,6 @@
      window.open(menu.link)
    } else {
      MKEmitter.emit('changeEditMenu', {
        fixed: menu.property === 'menu',
        MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID,
        copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '',
        MenuNo: menu.MenuNo,
src/mob/mobshell/card.jsx
@@ -5,7 +5,7 @@
import './index.scss'
const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search'))
// const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search'))
const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie'))
const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard'))
const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter'))
@@ -79,8 +79,8 @@
  const getCardComponent = () => {
    if (card.type === 'bar' || card.type === 'line') {
      return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'search') {
      return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    // } else if (card.type === 'search') {
    //   return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'pie') {
      return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'dashboard') {
src/mob/modulesource/option.jsx
@@ -13,7 +13,7 @@
import SandBox from '@/assets/mobimg/sandbox.png'
import Pie1 from '@/assets/mobimg/ring.png'
import Pie2 from '@/assets/mobimg/nightingale.png'
import Mainsearch from '@/assets/mobimg/mainsearch.png'
// import Mainsearch from '@/assets/mobimg/mainsearch.png'
import Navbar from '@/assets/mobimg/navbar-mob.png'
import Carousel from '@/assets/mobimg/carousel.png'
import Carousel1 from '@/assets/mobimg/carousel1.png'
@@ -30,7 +30,7 @@
  { type: 'menu', url: Navbar, component: 'navbar', subtype: 'tabbar', title: '菜单栏' },
  { type: 'menu', url: MenuBar, component: 'menubar', subtype: 'menubar', title: '菜单' },
  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '标签页', width: 24 },
  { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '搜索条件', width: 24 },
  // { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '搜索条件', width: 24 },
  { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '数据卡', width: 24 },
  { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '属性卡', width: 24 },
  { type: 'menu', url: card2, component: 'balcony', subtype: 'balcony', title: '可浮动卡', width: 24 },
src/pc/components/login/normal-login/loginform.jsx
@@ -61,7 +61,6 @@
    const { wrap, menuId } = this.props
    MKEmitter.emit('changeEditMenu', {
      fixed: false,
      MenuID: wrap.link === 'linkmenu' ? wrap.linkmenu : menuId,
      copyMenuId: '',
      MenuNo: '',
src/pc/components/navbar/normal-navbar/index.jsx
@@ -143,7 +143,6 @@
      return
    }
    MKEmitter.emit('changeEditMenu', {
      fixed: menu.property === 'menu',
      MenuID: menu.property === 'linkmenu' ? menu.linkMenuId : menu.MenuID,
      copyMenuId: menu.property === 'menu' ? menu.copyMenuId : '',
      MenuNo: menu.MenuNo,
@@ -153,10 +152,15 @@
  changeLogoMenu = () => {
    const { card } = this.state
    if (!card.wrap.logolink) return
    MKEmitter.emit('changeEditMenu', {MenuID: card.wrap.logolink})
    if (card.wrap.property === 'linkmenu') {
      MKEmitter.emit('changeEditMenu', {
        MenuID: card.wrap.linkmenu,
        copyMenuId: '',
        MenuNo: '',
        MenuName: ''
      })
    }
  }
  render() {
src/pc/components/navbar/normal-navbar/linksetting/linkform/index.jsx
@@ -112,17 +112,6 @@
              )}
            </Form.Item>
          </Col>
          {property === 'link' ? <Col span={22}>
            <Form.Item label="链接地址">
              {getFieldDecorator('link', {
                initialValue: menu.link || '',
                rules: [{
                  required: true,
                  message: '请输入链接地址!'
                }]
              })(<TextArea rows={2} />)}
            </Form.Item>
          </Col> : null}
          <Col span={22}>
            <Form.Item label="打开方式">
              {getFieldDecorator('open', {
@@ -135,6 +124,17 @@
              )}
            </Form.Item>
          </Col>
          {property === 'link' ? <Col span={22}>
            <Form.Item label="链接地址">
              {getFieldDecorator('link', {
                initialValue: menu.link || '',
                rules: [{
                  required: true,
                  message: '请输入链接地址!'
                }]
              })(<TextArea rows={2} />)}
            </Form.Item>
          </Col> : null}
          {property === 'linkmenu' ? <Col span={22}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="关联当前app中已有的菜单。">
src/pc/components/navbar/normal-navbar/menusetting/menuform/index.jsx
@@ -120,8 +120,8 @@
              })(
                <Radio.Group onChange={this.changeProperty}>
                  <Radio value="menu">菜单</Radio>
                  <Radio value="link">链接</Radio>
                  <Radio value="linkmenu">关联菜单</Radio>
                  <Radio value="link">链接</Radio>
                  {menu.level === 1 || menu.level === 2 ? <Radio value="classify">分类</Radio> : null}
                </Radio.Group>
              )}
@@ -139,17 +139,6 @@
              )}
            </Form.Item>
          </Col>
          {property === 'link' ? <Col span={22}>
            <Form.Item label="链接地址">
              {getFieldDecorator('link', {
                initialValue: menu.link || '',
                rules: [{
                  required: true,
                  message: '请输入链接地址!'
                }]
              })(<TextArea rows={2} />)}
            </Form.Item>
          </Col> : null}
          {property !== 'classify' ? <Col span={22}>
            <Form.Item label="打开方式">
              {getFieldDecorator('open', {
@@ -160,6 +149,17 @@
                  <Radio value="self">当前窗口</Radio>
                </Radio.Group>
              )}
            </Form.Item>
          </Col> : null}
          {property === 'link' ? <Col span={22}>
            <Form.Item label="链接地址">
              {getFieldDecorator('link', {
                initialValue: menu.link || '',
                rules: [{
                  required: true,
                  message: '请输入链接地址!'
                }]
              })(<TextArea rows={2} />)}
            </Form.Item>
          </Col> : null}
          {property === 'linkmenu' ? <Col span={22}>
@@ -192,7 +192,7 @@
              {getFieldDecorator('copyMenuId', {
                initialValue: menu.copyMenuId || ''
              })(
                <Select>
                <Select allowClear>
                  {appMenus.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))}
                </Select>
              )}
src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.jsx
@@ -6,6 +6,7 @@
import './index.scss'
const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent'))
const { TextArea } = Input
class SettingForm extends Component {
  static propTpyes = {
@@ -16,7 +17,8 @@
  }
  state = {
    appMenus: []
    appMenus: [],
    property: ''
  }
  UNSAFE_componentWillMount () {
@@ -31,7 +33,7 @@
      appMenus = []
    }
    this.setState({appMenus})
    this.setState({appMenus, property: this.props.wrap.property || ''})
  }
  handleConfirm = () => {
@@ -58,7 +60,7 @@
  render() {
    const { wrap } = this.props
    const { getFieldDecorator } = this.props.form
    const { appMenus } = this.state
    const { appMenus, property } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -141,22 +143,51 @@
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item label="logo属性">
                {getFieldDecorator('property', {
                  initialValue: wrap.property || ''
                })(
                  <Radio.Group onChange={(e) => this.setState({property: e.target.value})} style={{whiteSpace: 'nowrap'}}>
                    <Radio value="">空</Radio>
                    <Radio value="linkmenu">关联菜单</Radio>
                    <Radio value="link">链接</Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
            {property === 'linkmenu' ? <Col span={12}>
              <Form.Item label="logo链接">
                {getFieldDecorator('logolink', {
                  initialValue: wrap.logolink || ''
                {getFieldDecorator('linkmenu', {
                  initialValue: wrap.linkmenu || '',
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.select'] + '关联菜单!'
                    }
                  ]
                })(
                  <Select
                    showSearch
                    filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  >
                    <Select.Option key="empty" intid={''} value={''}>无</Select.Option>
                    {appMenus.map(option =>
                      <Select.Option key={option.MenuID} value={option.MenuID}>{option.MenuName}</Select.Option>
                    )}
                  </Select>
                )}
              </Form.Item>
            </Col>
            </Col> : null}
            {property === 'link' ? <Col span={24}>
              <Form.Item label="logo链接" className="textarea">
                {getFieldDecorator('link', {
                  initialValue: wrap.link || '',
                  rules: [{
                    required: true,
                    message: '请输入链接地址!'
                  }]
                })(<TextArea rows={2} />)}
              </Form.Item>
            </Col> : null}
            <Col span={12}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="存在登录且取到登录信息时,显示用户头像、用户名及退出。">
src/pc/components/navbar/normal-navbar/wrapsetting/settingform/index.scss
@@ -8,4 +8,12 @@
  .ant-input-number {
    width: 100%;
  }
  .ant-form-item.textarea {
    .ant-form-item-label {
      width: 16%;
    }
    .ant-form-item-control-wrapper {
      width: 84%;
    }
  }
}
src/tabviews/custom/components/group/normal-group/index.jsx
@@ -3,12 +3,13 @@
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { Col, Empty, notification, Button, Row } from 'antd'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import options from '@/store/options.js'
import asyncComponent from '@/utils/asyncComponent'
import {
  getStructuredParams,
  getStructDefaultParam
} from '@/utils/utils-datamanage.js'
import Utils from '@/utils/utils.js'
import './index.scss'
@@ -73,7 +74,7 @@
          item.setting.sync = 'false'
          item.setting.onload = 'false'
        } else {
          params.push(this.getDefaultParam(item, searchlist))
          params.push(getStructDefaultParam(item, searchlist))
        }
      } else {
        item.setting.sync = 'false'
@@ -94,130 +95,10 @@
  }
  /**
   * @description 获取系统存储过程 sPC_Get_TableData 的参数
   */
  getDefaultParam = (component, searchlist) => {
    const { columns, setting, dataName, format } = component
    let arr_field = columns.map(col => col.field)
    let _dataresource = setting.dataresource
    let _customScript = setting.customScript
    if (setting.queryType === 'statistics' || _customScript) {
      let allSearch = Utils.getAllSearchOptions(searchlist)
      let regoptions = allSearch.map(item => {
        return {
          reg: new RegExp('@' + item.key + '@', 'ig'),
          value: `'${item.value}'`
        }
      })
      regoptions.forEach(item => {
        if (_dataresource && setting.queryType === 'statistics') {
          _dataresource = _dataresource.replace(item.reg, item.value)
        }
        if (_customScript) {
          _customScript = _customScript.replace(item.reg, item.value)
        }
      })
    }
    _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
    _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
    _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
    _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
    _customScript = _customScript.replace(/\$sum@/ig, '/*')
    _customScript = _customScript.replace(/@sum\$/ig, '*/')
    let _search = ''
    if (setting.queryType !== 'statistics' && _dataresource) {
      _search = Utils.joinMainSearchkey(searchlist)
      _search = _search ? 'where ' + _search : ''
    }
    if (setting.order && _dataresource) {
      _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
    } else if (_dataresource) {
      _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} ${_search} `
    }
    // 测试系统打印查询语句
    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
      _customScript &&  console.info(`${_dataresource ? '' : '/*不执行默认sql*/\n'}${_customScript}`)
      _dataresource &&  console.info(_dataresource)
    }
    return {
      name: dataName,
      columns: columns,
      par_tablename: '',
      type: format === 'array' ? format : '',
      primaryKey: setting.primaryKey || '',
      foreign_key: '',
      sql: _dataresource,
      script: _customScript
    }
  }
  /**
   * @description 主表数据加载
   */ 
  loadmaindata = (params) => {
    const { config } = this.props
    let LText_field = []
    let diffUser = false
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let city = sessionStorage.getItem('city') || ''
    if (sessionStorage.getItem('isEditState') === 'true') {
      userName = sessionStorage.getItem('CloudUserName') || ''
      fullName = sessionStorage.getItem('CloudFullName') || ''
    }
    let _LText = params.map((item, index) => {
      let _script = item.script
      if (index === 0) {
        _script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50)
          select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @login_city='${city}'
          ${_script}
        `
      }
      if (!diffUser && (/@userid@/ig.test(item.sql) || /@userid@/ig.test(_script))) {
        diffUser = true
      }
      item.columns.forEach(cell => {
        LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`)
      })
      return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
    })
    let param = {
      func: 'sPC_Get_structured_data',
      LText: _LText.join(' union all '),
      LText_field: LText_field.join(' union all ')
    }
    let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText)
    param.LText1 = LText1
    param.LText = LText
    param.LText2 = LText2
    param.LText_field = Utils.formatOptions(param.LText_field)
    if (config.cacheUseful === 'true') {
      param.time_type = config.timeUnit
      param.time_limit = config.cacheTime
      if (diffUser) {
        param.userid = sessionStorage.getItem('UserID')
      }
      param.data_md5 = md5(JSON.stringify(param))
    }
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    let param = getStructuredParams(params, this.props.config)
    Api.getLocalConfig(param).then(result => {
      if (result.status) {
src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -3,12 +3,13 @@
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { Row, Col, Empty, notification } from 'antd'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import options from '@/store/options.js'
import asyncComponent from '@/utils/asyncComponent'
import {
  getStructuredParams,
  getStructDefaultParam
} from '@/utils/utils-datamanage.js'
import Utils from '@/utils/utils.js'
import './index.scss'
@@ -87,7 +88,7 @@
          item.setting.sync = 'false'
          item.setting.onload = 'false'
        } else {
          params.push(this.getDefaultParam(item, searchlist))
          params.push(getStructDefaultParam(item, searchlist))
        }
      } else {
        item.setting.sync = 'false'
@@ -110,130 +111,10 @@
  }
  /**
   * @description 获取系统存储过程 sPC_Get_TableData 的参数
   */
  getDefaultParam = (component, searchlist) => {
    const { columns, setting, dataName, format } = component
    let arr_field = columns.map(col => col.field)
    let _dataresource = setting.dataresource
    let _customScript = setting.customScript
    if (setting.queryType === 'statistics' || _customScript) {
      let allSearch = Utils.getAllSearchOptions(searchlist)
      let regoptions = allSearch.map(item => {
        return {
          reg: new RegExp('@' + item.key + '@', 'ig'),
          value: `'${item.value}'`
        }
      })
      regoptions.forEach(item => {
        if (_dataresource && setting.queryType === 'statistics') {
          _dataresource = _dataresource.replace(item.reg, item.value)
        }
        if (_customScript) {
          _customScript = _customScript.replace(item.reg, item.value)
        }
      })
    }
    _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
    _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
    _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
    _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
    _customScript = _customScript.replace(/\$sum@/ig, '/*')
    _customScript = _customScript.replace(/@sum\$/ig, '*/')
    let _search = ''
    if (setting.queryType !== 'statistics' && _dataresource) {
      _search = Utils.joinMainSearchkey(searchlist)
      _search = _search ? 'where ' + _search : ''
    }
    if (setting.order && _dataresource) {
      _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
    } else if (_dataresource) {
      _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} ${_search} `
    }
    // 测试系统打印查询语句
    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
      _customScript &&  console.info(`${_dataresource ? '' : '/*不执行默认sql*/\n'}${_customScript}`)
      _dataresource &&  console.info(_dataresource)
    }
    return {
      name: dataName,
      columns: columns,
      par_tablename: '',
      type: format === 'array' ? format : '',
      primaryKey: setting.primaryKey || '',
      foreign_key: '',
      sql: _dataresource,
      script: _customScript
    }
  }
  /**
   * @description 主表数据加载
   */ 
  loadmaindata = (params) => {
    const { config } = this.props
    let LText_field = []
    let diffUser = false
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let city = sessionStorage.getItem('city') || ''
    if (sessionStorage.getItem('isEditState') === 'true') {
      userName = sessionStorage.getItem('CloudUserName') || ''
      fullName = sessionStorage.getItem('CloudFullName') || ''
    }
    let _LText = params.map((item, index) => {
      let _script = item.script
      if (index === 0) {
        _script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50)
          select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @login_city='${city}'
          ${_script}
        `
      }
      if (!diffUser && (/@userid@/ig.test(item.sql) || /@userid@/ig.test(_script))) {
        diffUser = true
      }
      item.columns.forEach(cell => {
        LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`)
      })
      return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
    })
    let param = {
      func: 'sPC_Get_structured_data',
      LText: _LText.join(' union all '),
      LText_field: LText_field.join(' union all ')
    }
    let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText)
    param.LText1 = LText1
    param.LText = LText
    param.LText2 = LText2
    param.LText_field = Utils.formatOptions(param.LText_field)
    if (config.cacheUseful === 'true') {
      param.time_type = config.timeUnit
      param.time_limit = config.cacheTime
      if (diffUser) {
        param.userid = sessionStorage.getItem('UserID')
      }
      param.data_md5 = md5(JSON.stringify(param))
    }
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    let param = getStructuredParams(params, this.props.config)
    Api.getLocalConfig(param).then(result => {
      if (result.status) {
src/tabviews/custom/index.jsx
@@ -3,15 +3,13 @@
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Row, Col } from 'antd'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import options from '@/store/options.js'
import zhCN from '@/locales/zh-CN/main.js'
import enUS from '@/locales/en-US/main.js'
import Utils from '@/utils/utils.js'
import UtilsDM from '@/utils/utils-datamanage.js'
import UtilsDM, { getStructuredParams, getStructDefaultParam } from '@/utils/utils-datamanage.js'
import asyncComponent from '@/utils/asyncComponent'
import MKEmitter from '@/utils/events.js'
import NotFount from '@/components/404'
@@ -828,7 +826,7 @@
          component.setting.sync = 'false'
          component.setting.onload = 'false'
        } else {
          params.push(this.getDefaultParam(component, searchlist))
          params.push(getStructDefaultParam(component, searchlist))
        }
      } else if (component.floor === 1) {
        component.setting.sync = 'false'
@@ -839,131 +837,10 @@
  }
  /**
   * @description 获取系统存储过程 sPC_Get_TableData 的参数
   */
  getDefaultParam = (component, searchlist) => {
    const { columns, setting, dataName, format } = component
    let arr_field = columns.map(col => col.field)
    let _dataresource = setting.dataresource
    let _customScript = setting.customScript
    if (setting.queryType === 'statistics' || _customScript) {
      let allSearch = Utils.getAllSearchOptions(searchlist)
      let regoptions = allSearch.map(item => {
        return {
          reg: new RegExp('@' + item.key + '@', 'ig'),
          value: `'${item.value}'`
        }
      })
      regoptions.forEach(item => {
        if (_dataresource && setting.queryType === 'statistics') {
          _dataresource = _dataresource.replace(item.reg, item.value)
        }
        _customScript = _customScript.replace(item.reg, item.value)
      })
    }
    _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
    _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
    _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
    _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
    _customScript = _customScript.replace(/\$sum@/ig, '/*')
    _customScript = _customScript.replace(/@sum\$/ig, '*/')
    let _search = ''
    if (setting.queryType !== 'statistics' && _dataresource) {
      _search = Utils.joinMainSearchkey(searchlist)
      _search = _search ? 'where ' + _search : ''
    }
    if (setting.order && _dataresource) {
      _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
    } else if (_dataresource) {
      _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} ${_search} `
    }
    // 测试系统打印查询语句
    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
      _customScript &&  console.info(`${setting.$name ? `/*组件-${setting.$name} 自定义脚本*/\n` : ''}${_dataresource ? '' : '/*不执行默认sql*/\n'}${_customScript}`)
      _dataresource &&  console.info(`${setting.$name ? `/*组件-${setting.$name} 数据源*/\n` : ''}` + _dataresource)
    }
    return {
      name: dataName,
      columns: columns,
      par_tablename: '',
      type: format === 'array' ? format : '',
      primaryKey: setting.primaryKey || '',
      foreign_key: '',
      sql: _dataresource,
      script: _customScript
    }
  }
  /**
   * @description 主表数据加载
   */ 
  loadmaindata = (params) => {
    const { config } = this.state
    let LText_field = []
    let diffUser = false
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let city = sessionStorage.getItem('city') || ''
    if (sessionStorage.getItem('isEditState') === 'true') {
      userName = sessionStorage.getItem('CloudUserName') || ''
      fullName = sessionStorage.getItem('CloudFullName') || ''
    }
    let _LText = params.map((item, index) => {
      let _script = item.script
      if (index === 0) {
        _script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50)
          select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @login_city='${city}'
          ${_script}
        `
      }
      if (!diffUser && (/@userid@/ig.test(item.sql) || /@userid@/ig.test(_script))) {
        diffUser = true
      }
      item.columns.forEach(cell => {
        LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`)
      })
      return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
    })
    // 把大接口sPC_Get_structured_data的ltext拆成三份,第一段:@LText1,第二段@LText,第三段@LText2
    let param = {
      func: 'sPC_Get_structured_data',
      LText: _LText.join(' union all '),
      LText_field: LText_field.join(' union all '),
      BID: this.state.BID || ''
    }
    let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText)
    param.LText1 = LText1
    param.LText = LText
    param.LText2 = LText2
    param.LText_field = Utils.formatOptions(param.LText_field)
    if (config.cacheUseful === 'true') {
      param.time_type = config.timeUnit
      param.time_limit = config.cacheTime
      if (diffUser) {
        param.userid = sessionStorage.getItem('UserID')
      }
      param.data_md5 = md5(JSON.stringify(param))
    }
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    let param = getStructuredParams(params, this.state.config, this.state.BID)
    this.setState({loading: true, loadingview: false})
src/tabviews/scriptmanage/index.jsx
@@ -135,7 +135,6 @@
    if (result.status) {
      this.setState({
        data: result.data.map((item, index) => {
          // item.LongParam = this.UnformatOptions(item.LongParam)
          item.key = index
          item.$$uuid = item[setting.primaryKey] || ''
          return item
@@ -154,75 +153,6 @@
      })
    }
  }
  // UnformatOptions = (value) => {
  //   if (!value) return ''
  //   let salt = 'minKe' // 盐值
  //   let _value = ''
  //   const formatKeys = [
  //     { key: 'select', value: ' msltk ' },
  //     { key: 'from', value: ' mfrmk ' },
  //     { key: 'where', value: ' mwhrk ' },
  //     { key: 'order by', value: ' modbk ' },
  //     { key: 'asc', value: ' modack ' },
  //     { key: 'desc', value: ' moddesk ' },
  //     { key: 'top', value: ' mtpk ' },
  //     { key: 'like', value: ' mlkk ' },
  //     { key: 'not like', value: ' mnlkk ' },
  //     { key: 'between', value: ' mbtnk ' },
  //     { key: 'and', value: ' madk ' },
  //     { key: 'insert', value: ' mistk ' },
  //     { key: 'into', value: ' mitk ' },
  //     { key: 'update', value: ' muptk ' },
  //     { key: 'delete', value: ' mdelk ' },
  //     { key: 'begin', value: ' mbgink ' },
  //     { key: 'end', value: ' medk ' },
  //     { key: 'if', value: ' mefk ' },
  //     { key: 'while', value: ' mwilk ' },
  //     { key: 'create', value: ' mcrtk ' },
  //     { key: 'alter', value: ' matek ' },
  //     { key: 'len', value: ' mlnk ' },
  //     { key: 'left', value: ' mlftk ' },
  //     { key: 'right', value: ' mritk ' },
  //     { key: 'union', value: ' munok ' },
  //     { key: 'varchar', value: ' mvcrk ' },
  //     { key: 'getdate', value: ' mgtdtk ' },
  //     { key: 'TRY', value: ' mtryonek ' },
  //     { key: 'TRAN', value: ' mtrnk ' },
  //     { key: 'goto', value: ' mgtk ' },
  //     { key: 'set', value: ' mstk ' },
  //     { key: 'ROLLBACK', value: ' mrlbkk ' }
  //   ]
  //   try {
  //     try {
  //       _value = JSON.parse(window.decodeURIComponent(window.atob(value)))
  //     } catch {
  //       _value = ''
  //     }
  //     if (!_value) {
  //       _value = window.atob(value)
  //       _value = _value.replace(salt, '')
  //       _value = window.decodeURIComponent(window.atob(_value))
  //       _value = _value.replace(/\smpercent\s/g, '%')
  //       formatKeys.forEach(item => {
  //         let reg = new RegExp(item.value, 'g')
  //         _value = _value.replace(reg, ' ' + item.key + ' ')
  //       })
  //       _value = _value.replace(/\s\n\s/ig, '\n')
  //       _value = _value.replace(/(^\s+|\s+$)/ig, '')
  //     }
  //   } catch {
  //     console.warn('UnFormat Failure')
  //     _value = ''
  //   }
  //   return _value
  // }
  /**
   * @description 获取系统存储过程 sPC_Get_TableData 的参数
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -1728,7 +1728,7 @@
            BData={this.props.BData}
            wrappedComponentRef={(inst) => this.formRef = inst}
          />
          <div style={{ position: 'absolute', right: 0, bottom: 0, width: '100%', borderTop: '1px solid #e9e9e9', padding: '10px 16px', background: '#fff', textAlign: 'right'}}>
          <div style={{ position: 'absolute', zIndex: 1, right: 0, bottom: 0, width: '100%', borderTop: '1px solid #e9e9e9', padding: '10px 16px', background: '#fff', textAlign: 'right'}}>
            <Button onClick={this.handleCancel} style={{ marginRight: 8 }}>
              取消
            </Button>
src/tabviews/zshare/mutilform/customSwitch/index.jsx
File was deleted
src/tabviews/zshare/mutilform/customTextArea/index.jsx
File was deleted
src/tabviews/zshare/mutilform/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Input, InputNumber, Select, DatePicker, notification, Checkbox, Radio, Tooltip, Icon } from 'antd'
import { Form, Row, Col, notification, Tooltip, Icon } from 'antd'
import moment from 'moment'
import Api from '@/api'
@@ -9,17 +9,21 @@
import { formRule } from '@/utils/option.js'
import Utils from '@/utils/utils.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncSpinComponent from '@/utils/asyncSpinComponent'
import MKEmitter from '@/utils/events.js'
import MKInput from './mkInput'
import MKNumberInput from './mkNumberInput'
import MKSelect from './mkSelect'
import './index.scss'
const { MonthPicker } = DatePicker
const CheckCard = asyncComponent(() => import('./checkCard'))
const CustomSwitch = asyncComponent(() => import('./customSwitch'))
const CustomTextArea = asyncComponent(() => import('./customTextArea'))
const FileUpload = asyncComponent(() => import('../fileupload'))
const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
const Editor = asyncSpinComponent(() => import('@/components/editor'))
const MKCheckCard = asyncComponent(() => import('./mkCheckCard'))
const MKSwitch = asyncComponent(() => import('./mkSwitch'))
const MKCheckbox = asyncComponent(() => import('./mkCheckbox'))
const MKRadio = asyncComponent(() => import('./mkRadio'))
const MKDatePicker = asyncComponent(() => import('./mkDatePicker'))
const MKTextArea = asyncComponent(() => import('./mkTextArea'))
const MKFileUpload = asyncComponent(() => import('../fileupload'))
const MKColor = asyncComponent(() => import('./mkColor'))
const MKEditor = asyncComponent(() => import('@/components/editor'))
class MainSearch extends Component {
  static propTpyes = {
@@ -34,134 +38,23 @@
  state = {
    formlist: [],    // 表单项
    record: {}       // 记录下拉表单关联字段,用于数据写入
  }
  record = {}
  componentDidMount () {
    const { data, BData, action } = this.props
    let _inputfields = []
    let linkFields = {} // 关联菜单
    let supItemVal = {} // 上级菜单初始值
    let controlFields = {} // 控制表单
    let deForms = []    // 需要动态获取下拉菜单的表单
    let record = {}
    let formlist = fromJS(action.fields).toJS()
    let fieldMap = new Map()
    formlist.forEach(item => {
      if (item.type === 'text' || item.type === 'number') {
        _inputfields.push(item.field)
      } else if (item.type === 'textarea') {
        _inputfields.push(item.field)
      } else if (item.type === 'link') {
        linkFields[item.linkField] = linkFields[item.linkField] || []
        linkFields[item.linkField].push(item.field)
      }
    })
    formlist = formlist.map(item => {
      if (item.labelwidth) {
        item.labelCol = {style: {width: item.labelwidth + '%'}}
        item.wrapperCol = {style: {width: (100 - item.labelwidth) + '%'}}
      }
      if (item.type === 'split' || item.type === 'hint') return item
      // 数据自动填充
      item.readin = item.readin !== 'false'
      if (item.type === 'linkMain' || item.type === 'funcvar') {
        item.readin = false
      }
      item.readonly = item.readonly === 'true'
      item.writein = item.writein !== 'false'
      item.fieldlength = item.fieldlength || 50
      if (item.type === 'number') {
        item.fieldlength = item.decimal ? item.decimal : 0
        item.initval = item.initval || 0
      }
      if (item.setAll === 'true' && (item.type === 'select' || item.type === 'link' || item.type === 'radio')) { // 添加空值
        item.options.unshift({
          key: Utils.getuuid(),
          Value: '',
          Text: item.emptyText || '空',
          ParentID: ''
        })
      }
      item.oriOptions = item.options ? fromJS(item.options).toJS() : null // 保存初始列表,用于联动菜单控制
      // 下级表单控制-字段写入
      if ((['select', 'radio'].includes(item.type) || (item.type === 'checkcard' && item.multiple !== 'true')) && item.linkSubField && item.linkSubField.length > 0) {
        item.linkSubField = item.linkSubField.filter(_item => _inputfields.includes(_item))
        if (item.linkSubField.length === 0) {
          item.linkSubField = null
        }
      } else {
        item.linkSubField = null
      }
      let newval = ''
      if (item.type === 'linkMain') {
        newval = BData && BData[item.field] ? BData[item.field] : ''
      } else if (item.readin && !/^date/.test(item.type) && data && data.hasOwnProperty(item.field)) {
        newval = data[item.field]
      } else if (item.type === 'date') { // 时间搜索
        if (item.readin && data && data.hasOwnProperty(item.field)) {
          newval = data[item.field]
        }
        if (newval) {
          newval = moment(newval, 'YYYY-MM-DD')
          newval = newval.format('YYYY-MM-DD') === 'Invalid date' ? '' : newval
        }
        if (!newval && item.initval) {
          newval = moment().subtract(item.initval, 'days')
        } else if (!newval) {
          newval = null
        }
      } else if (item.type === 'datemonth') {
        if (item.readin && data && data.hasOwnProperty(item.field)) {
          newval = data[item.field]
        }
        if (newval) {
          newval = moment(newval, 'YYYY-MM')
          newval = newval.format('YYYY-MM') === 'Invalid date' ? '' : newval
        }
        if (!newval && item.initval) {
          newval = moment().subtract(item.initval, 'month')
        } else if (!newval) {
          newval = null
        }
      } else if (item.type === 'datetime') {
        if (item.readin && data && data.hasOwnProperty(item.field)) {
          newval = data[item.field]
        }
        if (newval) {
          newval = moment(newval, 'YYYY-MM-DD HH:mm:ss')
          newval = newval.format('YYYY-MM-DD HH:mm:ss') === 'Invalid date' ? '' : newval
        }
        if (!newval && item.initval) {
          newval = moment(moment().subtract(item.initval, 'days').format('YYYY-MM-DD') + ' 00:00:00', 'YYYY-MM-DD HH:mm:ss')
        } else if (!newval) {
          newval = null
        }
      }
      if (item.type === 'switch' && newval !== '') { // 开关只接收固定值
        if (newval !== item.closeVal && newval !== item.openVal) {
          newval = ''
        } else if (newval === item.openVal) {
          newval = true
        } else {
          newval = false
        }
      }
      // 读取表格数据或设有时间的初始值
      item.initval = newval !== '' ? newval : item.initval
      // 下拉表单,存在上级菜单时,生成显示值列表,优先以数字判断
      if (item.supvalue) {
    formlist = formlist.filter(item => {
      if (item.supField && item.supvalue) { // 多层表单控制
        let supvals = []
        item.supvalue.split(',').forEach(val => {
          supvals.push(val)
@@ -169,82 +62,306 @@
            supvals.push(+val)
          }
        })
        item.supvalue = supvals
        controlFields[item.supField] = controlFields[item.supField] || []
        controlFields[item.supField].push({field: item.field, values: supvals})
      }
      if (item.type === 'link') {
        linkFields[item.linkField] = linkFields[item.linkField] || []
        linkFields[item.linkField].push({field: item.field, uuid: item.uuid})
      }
      if (item.type === 'split' || item.type === 'hint') return true
      if (!item.field || !['text', 'number', 'switch', 'select', 'link', 'linkMain', 'funcvar', 'date', 'datemonth', 'datetime', 'radio', 'checkbox', 'checkcard', 'fileupload', 'textarea', 'multiselect', 'brafteditor', 'color'].includes(item.type)) return false
      // 数据自动填充
      item.readin = item.readin !== 'false'
      item.readonly = item.readonly === 'true'
      item.writein = item.writein !== 'false'
      item.hidden = item.hidden === 'true'
      item.fieldlength = item.fieldlength || 50
      if (item.type === 'funcvar') {
        item.readin = false
        item.hidden = true
      } else if (item.type === 'number') {
        item.decimal = item.decimal || 0
        item.fieldlength = item.decimal
        item.initval = item.initval || 0
      }
      if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type)) {
        item.options = item.options || []
        item.options = item.options.map(cell => {
          cell.value = cell.Value
          cell.label = cell.Text
          return cell
        })
        if (item.setAll === 'true' && ['select', 'link', 'radio'].includes(item.type)) { // 添加空值
          item.options.unshift({
            key: Utils.getuuid(),
            value: '',
            label: item.emptyText || '空',
            ParentID: ''
          })
        }
        item.oriOptions = fromJS(item.options).toJS()
      }
      let newval = '$empty'
      if (item.readin && data && data.hasOwnProperty(item.field)) {
        newval = data[item.field]
      }
      if (item.type === 'linkMain') {
        newval = BData && BData[item.field] ? BData[item.field] : '$empty'
      } else if (item.type === 'date') { // 时间搜索
        if (newval !== '$empty') {
          newval = moment(newval, 'YYYY-MM-DD').format('YYYY-MM-DD')
          newval = newval === 'Invalid date' ? '$empty' : newval
        }
        if (newval === '$empty' && item.initval) {
          newval = moment().subtract(item.initval, 'days').format('YYYY-MM-DD')
        }
      } else if (item.type === 'datemonth') {
        if (newval !== '$empty') {
          newval = moment(newval, 'YYYY-MM').format('YYYY-MM')
          newval = newval === 'Invalid date' ? '$empty' : newval
        }
        if (newval === '$empty' && item.initval) {
          newval = moment().subtract(item.initval, 'month').format('YYYY-MM')
        }
      } else if (item.type === 'datetime') {
        if (newval !== '$empty') {
          newval = moment(newval, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss')
          newval = newval === 'Invalid date' ? '$empty' : newval
        }
        if (newval === '$empty' && item.initval) {
          newval = moment().subtract(item.initval, 'days').format('YYYY-MM-DD') + ' 00:00:00'
        }
      } else if (item.type === 'switch') { // 开关只接收固定值
        if (newval !== '$empty' && (newval === item.closeVal || newval === item.openVal)) {
        } else if (item.initval === true) {
          newval = item.openVal
        } else {
          newval = item.closeVal
        }
      }
      if (newval !== '$empty') {
        item.initval = newval
      } else if (item.initval === undefined) {
        item.initval = ''
      }
      if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type) && item.resourceType === '1') {
        deForms.push(item)
      }
      if (item.type === 'text') {
        let _rules = [{
          pattern: /^[^']*$/ig,
          message: formRule.input.quotemsg
        }, {
          required: item.required === 'true',
          message: item.label + '不可为空!'
        }, {
          max: item.fieldlength,
          message: formRule.input.formMessage.replace('@max', item.fieldlength)
        }]
        if (item.regular) {
          if (item.regular === 'number') {
            _rules.push({
              pattern: /^[0-9.-]*$/ig,
              message: formRule.input.numbermsg
            })
          } else if (item.regular === 'letter') {
            _rules.push({
              pattern: /^[a-zA-Z]*$/ig,
              message: formRule.input.lettermsg
            })
          } else if (item.regular === 'letter&number') {
            _rules.push({
              pattern: /^[a-zA-Z0-9]*$/ig,
              message: formRule.input.letternummsg
            })
          } else if (item.regular === 'funcname') {
            _rules.push({
              pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
              message: formRule.input.funcname
            })
          }
        }
        item.rules = _rules
      } else if (item.type === 'number') {
        item.rules = [{
          required: true,
          message: item.label + '不可为空!'
        }, {
          validator: (rule, value, callback) => this.handleConfirmPassword(rule, value, callback, item)
        }]
      } else if (item.type === 'textarea') {
        let _rules = [
          {
            required: item.required === 'true',
            message: item.label + '不可为空!'
          },
          {
            max: item.fieldlength,
            message: formRule.input.formMessage.replace('@max', item.fieldlength)
          }
        ]
        if (item.encryption !== 'true') {
          _rules.push({
            pattern: /^[^']*$/ig,
            message: formRule.input.quotemsg
          })
        }
        item.rules = _rules
      } else if (item.type === 'brafteditor') {
        item.rules = [
          {
            required: item.required === 'true',
            message: item.label + '不可为空!'
          },
          {
            max: item.fieldlength,
            message: formRule.input.formMessage.replace('@max', item.fieldlength)
          }
        ]
      } else if (item.type === 'linkMain') {
        item.rules = [
          {
            required: item.required === 'true',
            message: item.label + '不可为空!'
          }
        ]
      } else {
        item.rules = [
          {
            required: item.required === 'true',
            message: '请选择' + item.label + '!'
          }
        ]
      }
      fieldMap.set(item.field, item)
      return true
    })
    Object.keys(controlFields).forEach(key => {
      if (!fieldMap.has(key)) return
      let supItem = fieldMap.get(key)
      let fields = []
      controlFields[key].forEach(item => {
        if (!fieldMap.has(item.field)) return
        let cell = fieldMap.get(item.field)
        if (cell.hidden) return
        if (supItem.hidden || !item.values.includes(supItem.initval)) {
          cell.hidden = true
          fieldMap.set(item.field, cell)
        }
        fields.push(item)
      })
      supItem.controlFields = fields
      fieldMap.set(key, supItem)
    })
    formlist = formlist.map(cell => {
      if (cell.labelwidth) {
        cell.labelCol = {style: {width: cell.labelwidth + '%'}}
        cell.wrapperCol = {style: {width: (100 - cell.labelwidth) + '%'}}
      }
      if (!cell.field || !fieldMap.has(cell.field)) return cell
      let item = fieldMap.get(cell.field)
      if (item.type === 'link') {
        item.supInitVal = ''
        if (fieldMap.has(item.linkField)) {
          item.supInitVal = fieldMap.get(item.linkField).initval || ''
        } else if (data && data.hasOwnProperty(item.linkField)) {
          item.supInitVal = data[item.linkField]
        }
        item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.value === '')
      }
      if (['select', 'link', 'radio'].includes(item.type) && item.resourceType !== '1') { // 选中第一项
        if (typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) {
          item.initval = item.options[0] ? item.options[0].value : ''
        }
      }
      if (typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) {
        record[item.field] = ''
      } else {
        record[item.field] = item.initval
      }
      if (linkFields[item.field]) {
        item.linkFields = linkFields[item.field]
      }
      supItemVal[item.field] = item.initval
      if (['select', 'link', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type) && item.resourceType === '1') {
        deForms.push(item)
      } else if (['select', 'link', 'radio'].includes(item.type) && item.resourceType !== '1') { // 选中第一项
        if (typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) {
          item.initval = item.options[0] ? item.options[0].Value : ''
      // 下级表单控制-字段写入
      if ((['select', 'radio'].includes(item.type) || (item.type === 'checkcard' && item.multiple !== 'true')) && item.linkSubField) {
        item.subFields = []
        item.linkSubField.forEach(m => {
          let n = fieldMap.get(m)
          if (n && ['text', 'number', 'textarea'].includes(n.type)) {
            item.subFields.push({
              uuid: n.uuid,
              field: m
            })
          }
        })
        if (item.subFields.length === 0) {
          item.subFields = null
        }
        item.linkSubField = null
      }
      if (item.enter === 'tab' || item.enter === 'sub') {
        if (fieldMap.has(item.tabField)) {
          item.tabUuid = fieldMap.get(item.tabField).uuid
        } else {
          item.tabUuid = item.uuid
        }
      }
      return item
    })
    formlist = formlist.map(item => {
      if (item.type === 'link') {
        item.supInitVal = ''
    this.record = record
        if (supItemVal[item.linkField]) {
          item.supInitVal = supItemVal[item.linkField]
        } else if (data && data.hasOwnProperty(item.linkField)) {
          item.supInitVal = data[item.linkField]
        }
        item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.Value === '')
      }
      return item
    })
    this.setState({
      formlist
    }, () => {
      if (action.setting && action.setting.focus) {
    this.setState({ formlist }, () => {
      if (action.setting && action.setting.focus && fieldMap.has(action.setting.focus)) {
        setTimeout(() => {
          this.selectInput(action.setting.focus)
          MKEmitter.emit('mkFC', 'focus', fieldMap.get(action.setting.focus).uuid)
        }, 500)
      }
      // 用来更新state,防止受控表单初始时不显示
      this.setState({
        loaded: true
      })
      this.improveActionForm(deForms)
    })
  }
  selectInput = (selectId) => {
    try {
      let _form = document.getElementById('main-form-box')
      let _inputs = _form.getElementsByTagName('input')
      _inputs = [..._inputs]
      _inputs.forEach(input => {
        if (!input || input.id !== selectId) return
        if (input.className === 'ant-select-search__field') {
          let div = input.parentNode
          while (div && div.parentNode) {
            div = div.parentNode
            if (div.id === selectId) {
              div && div.click && div.click()
              div = null
            }
          }
        } else if (input.select) {
          input.select()
        } else if (input.focus) {
          input.focus()
      if (deForms.length > 0) {
        if (this.props.menuType !== 'HS' && options.sysType === 'local' && window.GLOB.systemType !== 'production') {
          this.improveSimpleActionForm(deForms)
        } else {
          this.improveActionForm(deForms)
        }
      })
    } catch {
      console.warn('focus error!')
    }
      }
    })
  }
  /**
@@ -252,14 +369,6 @@
   */
  improveActionForm = (deForms) => {
    const { BID, menuType } = this.props
    const { formlist } = this.state
    if (deForms.length === 0) {
      return
    } else if (menuType !== 'HS' && options.sysType === 'local' && window.GLOB.systemType !== 'production') {
      this.improveSimpleActionForm(deForms)
      return
    }
    let deffers = []
    let mainItems = []  // 云端或单点数据
@@ -273,7 +382,7 @@
      }
    })
    
    if (menuType !== 'HS' && window.GLOB.systemType !== 'production') {
    if (menuType !== 'HS' && options.sysType !== 'local') {
      localItems = [...localItems, ...mainItems]
      mainItems = []
    }
@@ -284,11 +393,8 @@
      LText: localItems.join(' union all '),
      obj_name: '',
      arr_field: '',
      table_type: 'Y'
    }
    if (BID) {
      param.BID = BID
      table_type: 'Y',
      BID: BID || ''
    }
    if (param.LText) {
@@ -322,11 +428,8 @@
      LText: mainItems.join(' union all '),
      obj_name: '',
      arr_field: '',
      table_type: 'Y'
    }
    if (BID) {
      mainparam.BID = BID
      table_type: 'Y',
      BID: BID || ''
    }
    if (mainparam.LText) {
@@ -369,62 +472,7 @@
      delete result.message
      delete result.status
      let _formlist = formlist.map(item => {
        if (['select', 'link', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type) && result[item.field] && result[item.field].length > 0) {
          let options = []
          result[item.field].forEach(cell => {
            let _cell = { key: Utils.getuuid() }
            if (item.type !== 'checkcard') {
              _cell.Value = cell[item.valueField]
              _cell.Text = cell[item.valueText]
              if ((!_cell.Value && _cell.Value !== 0) || (!_cell.Text && _cell.Text !== 0)) return
            } else {
              _cell.$value = cell[item.cardValField]
              _cell = {..._cell, ...cell}
              if (!_cell.$value && _cell.$value !== 0) return
            }
            if (item.type === 'link') {
              _cell.ParentID = cell[item.linkField] === undefined ? '' : cell[item.linkField]
            } else if (item.linkSubField) {
              item.linkSubField.forEach(_field => {
                _cell[_field] = (cell[_field] || cell[_field] === 0) ? cell[_field] : ''
              })
            }
            options.push(_cell)
          })
          item.oriOptions = [...item.oriOptions, ...options]
        }
        return item
      })
      let values = []
      this.setState({
        formlist: _formlist.map(item => {
          if (item.type === 'link') {
            item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.Value === '')
          } else if (['select', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type)) {
            item.options = item.oriOptions
          }
          if (['select', 'link', 'radio'].includes(item.type) && typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) { // 选中第一项
            item.initval = item.options[0] ? item.options[0].Value : ''
            values.push({field: item.field, value: item.initval})
          }
          return item
        })
      }, () => {
        if (values.length === 0) return
        let fieldsvalue = {}
        values.forEach(item => {
          if (this.props.form.getFieldValue(item.field) !== undefined) {
            fieldsvalue[item.field] = item.value
          }
        })
        this.props.form.setFieldsValue(fieldsvalue)
      })
      this.resetFormList(result)
    })
  }
@@ -432,18 +480,13 @@
   * @description 测试系统获取下拉表单选项信息
   */
  improveSimpleActionForm = (deForms) => {
    const { formlist } = this.state
    let deffers = deForms.map(form => {
      let param = {
        func: 'sPC_Get_SelectedList',
        LText: form.data_sql,
        obj_name: form.field,
        arr_field: form.arr_field
      }
      if (this.props.BID) {
        param.BID = this.props.BID
        arr_field: form.arr_field,
        BID: this.props.BID || ''
      }
  
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -476,152 +519,56 @@
      delete result.message
      delete result.status
      let _formlist = formlist.map(item => {
        if (['select', 'link', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type) && result[item.field] && result[item.field].length > 0) {
          let options = []
          result[item.field].forEach(cell => {
            let _cell = { key: Utils.getuuid() }
            if (item.type !== 'checkcard') {
              _cell.Value = cell[item.valueField]
              _cell.Text = cell[item.valueText]
              if ((!_cell.Value && _cell.Value !== 0) || (!_cell.Text && _cell.Text !== 0)) return
            } else {
              _cell.$value = cell[item.valueField]
              _cell = {..._cell, ...cell}
              if (!_cell.$value && _cell.$value !== 0) return
            }
            if (item.type === 'link') {
              _cell.ParentID = cell[item.linkField] === undefined ? '' : cell[item.linkField]
            } else if (item.linkSubField) {
              item.linkSubField.forEach(_field => {
                _cell[_field] = (cell[_field] || cell[_field] === 0) ? cell[_field] : ''
              })
            }
            options.push(_cell)
          })
          item.oriOptions = [...item.oriOptions, ...options]
        }
        return item
      })
      let values = []
      this.setState({
        formlist: _formlist.map(item => {
          if (item.type === 'link') {
            item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.Value === '')
          } else if (['select', 'multiselect', 'radio', 'checkbox', 'checkcard'].includes(item.type)) {
            item.options = item.oriOptions
          }
          if (['select', 'link', 'radio'].includes(item.type) && typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) { // 选中第一项
            item.initval = item.options[0] ? item.options[0].Value : ''
            values.push({field: item.field, value: item.initval})
          }
          return item
        })
      }, () => {
        if (values.length === 0) return
        let fieldsvalue = {}
        values.forEach(item => {
          if (this.props.form.getFieldValue(item.field) !== undefined) {
            fieldsvalue[item.field] = item.value
          }
        })
        this.props.form.setFieldsValue(fieldsvalue)
      })
      this.resetFormList(result)
    })
  }
  resetform = (formlist, supfields, index, fieldsvalue) => {
    index++
    let subfields = []
  resetFormList = (result) => {
    let _formlist = this.state.formlist.map(item => {
      if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type) && result[item.field] && result[item.field].length > 0) {
        let options = []
        result[item.field].forEach(cell => {
          let _cell = { key: Utils.getuuid() }
    supfields.forEach(supfield => {
      formlist = formlist.map(item => {
        if (item.type === 'link' && item.linkField === supfield.field) {
          item.options = item.oriOptions.filter(option => option.ParentID === supfield.initval || option.Value === '')
          item.initval = item.options[0] ? item.options[0].Value : ''
          if (this.props.form.getFieldValue(item.field) !== undefined) {
            fieldsvalue[item.field] = item.initval
          if (item.type !== 'checkcard') {
            _cell.value = cell[item.valueField]
            _cell.label = cell[item.valueText]
            if (!_cell.label && _cell.label !== 0) return
          } else {
            _cell.$value = cell[item.cardValField]
            _cell = {..._cell, ...cell}
          }
  
          subfields.push(item)
          if (item.type === 'link') {
            _cell.ParentID = cell[item.linkField] === undefined ? '' : cell[item.linkField]
          } else if (item.subFields) {
            item.subFields.forEach(m => {
              _cell[m.field] = (cell[m.field] || cell[m.field] === 0) ? cell[m.field] : ''
            })
          }
          options.push(_cell)
        })
        item.oriOptions = [...item.oriOptions, ...options]
        if (item.type === 'link') {
          item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.value === '')
        } else if (['select', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type)) {
          item.options = item.oriOptions
        }
        return item
      })
    })
    if (subfields.length === 0 || index > 6) {
      return {formlist: formlist, fieldsvalue: fieldsvalue}
    } else {
      return this.resetform(formlist, subfields, index, fieldsvalue)
    }
  }
  selectChange = (_field, value) => {
    const { record } = this.state
    let formlist = fromJS(this.state.formlist).toJS()
    let subfields = []
    let fieldsvalue = {}
    let _record = {}
    formlist = formlist.map(item => {
      if (item.type === 'link' && item.linkField === _field.field) {
        item.options = item.oriOptions.filter(option => option.ParentID === value || option.Value === '')
        item.initval = item.options[0] ? item.options[0].Value : ''
        if (this.props.form.getFieldValue(item.field) !== undefined) {
          fieldsvalue[item.field] = item.initval
        }
        subfields.push(item)
      }
      if (['select', 'link', 'radio'].includes(item.type) && typeof(item.initval) === 'string' && item.initval.indexOf('$first') > -1) { // 选中第一项
        item.initval = item.options[0] ? item.options[0].value : ''
        this.record[item.field] = item.initval
      }
      return item
    })
    // 表单切换时,更新关联字段
    if (_field.linkSubField) {
      let _data = _field.options.filter(op => op.Value === value)[0]
      if (_data) {
        _field.linkSubField.forEach(subfield => {
          if (this.props.form.getFieldValue(subfield) !== undefined) {
            fieldsvalue[subfield] = (_data[subfield] || _data[subfield] === 0) ? _data[subfield] : ''
          } else {
            _record[subfield] = (_data[subfield] || _data[subfield] === 0) ? _data[subfield] : ''
          }
        })
      }
    }
    if (subfields.length === 0) {
      this.props.form.setFieldsValue(fieldsvalue)
      this.setState({
        record: {...record, ..._record}
      })
    } else {
      let result = this.resetform(formlist, subfields, 0, fieldsvalue)
      this.props.form.setFieldsValue(fieldsvalue)
      this.setState({
        formlist: result.formlist,
        record: {...record, ..._record}
      })
    }
    this.setState({}, () => {
      if (!_field.enter || _field.enter === 'false') return
      if (_field.enter === 'tab') {
        this.selectInput(_field.tabField)
      } else if (_field.enter === 'sub') {
        this.handleSubmit()
      }
    this.setState({
      formlist: _formlist
    })
  }
@@ -638,26 +585,45 @@
    callback()
  }
  handleChange = (e, item) => {
    let val = e.target.value
  recordChange = (values, item) => {
    this.record = {...this.record, ...values}
    if (item.enter === 'false') return
    if (!val || !/\n/ig.test(val)) return
    if (item.enter === 'tab') {
      this.selectInput(item.tabField)
    } else {
      this.handleSubmit(e)
      this.selectInput(item.tabField || item.field)
    }
  }
    if (item && item.controlFields) {
      let map = new Map()
      this.state.formlist.forEach(cell => {
        if (!cell.field) return
        map.set(cell.field, cell)
      })
  handleInputSubmit = (e, item) => {
    if (item.enter === 'false') return
    if (item.enter === 'tab') {
      this.selectInput(item.tabField)
    } else {
      this.handleSubmit(e)
      this.selectInput(item.tabField || item.field)
      let reset = (current) => {
        let val = this.record[current.field]
        current.controlFields.forEach(cell => {
          let m = map.get(cell.field)
          m.hidden = current.hidden || !cell.values.includes(val)
          if (m.hidden) {
            m.initval = this.record[m.field]
          }
          map.set(cell.field, m)
          if (m.controlFields) {
            reset(m)
          }
        })
      }
      reset(item)
      this.setState({
        formlist: this.state.formlist.map(cell => {
          if (cell.field) {
            return map.get(cell.field)
          }
          return cell
        })
      })
    }
  }
@@ -666,24 +632,9 @@
    const { formlist } = this.state
    const fields = []
    let filtration = {}
    formlist.forEach((item, index) => {
      if ((!item.field && item.type !== 'split' && item.type !== 'hint') || item.hidden === 'true' || item.type === 'funcvar') return
      if (item.supField) { // 多层表单控制
        let _supVal = this.props.form.getFieldValue(item.supField)
        if (_supVal === undefined && filtration[item.supField]) {
          _supVal = filtration[item.supField]
        }
        if (item.supvalue.includes(_supVal)) {
          let _subVal = this.props.form.getFieldValue(item.field)
          filtration[item.field] = _subVal === undefined ? item.initval : _subVal
        } else {
          return
        }
      }
      if (item.hidden) return
      if (item.type === 'split') {
        fields.push(
@@ -694,540 +645,59 @@
      } else if (item.type === 'hint') {
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              colon={!!item.label}
              label={item.label}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              className="hint"
            >
            <Form.Item className="hint" colon={!!item.label} label={item.label} labelCol={item.labelCol} wrapperCol={item.wrapperCol}>
              <div className="message">{item.message}</div>
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'text') {
        let _max = item.fieldlength
        let _rules = [{
          pattern: /^[^']*$/ig,
          message: formRule.input.quotemsg
        }]
        if (item.regular) {
          if (item.regular === 'number') {
            _rules = [{
              pattern: /^[0-9.-]*$/ig,
              message: formRule.input.numbermsg
            }]
          } else if (item.regular === 'letter') {
            _rules = [{
              pattern: /^[a-zA-Z]*$/ig,
              message: formRule.input.lettermsg
            }]
          } else if (item.regular === 'letter&number') {
            _rules = [{
              pattern: /^[a-zA-Z0-9]*$/ig,
              message: formRule.input.letternummsg
            }]
          } else if (item.regular === 'funcname') {
            _rules = [{
              pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
              message: formRule.input.funcname
            }]
          }
      } else {
        let content = null
        let className = ''
        let label = item.tooltip ? <Tooltip placement="topLeft" title={item.tooltip}><Icon type="question-circle" />{item.label}</Tooltip> : item.label
        if (item.type === 'text' || item.type === 'linkMain') {
          content = (<MKInput config={item} onChange={(val) => this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
        } else if (item.type === 'number') {
          content = (<MKNumberInput config={item} onChange={(val) => this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
        } else if (item.type === 'select' || item.type === 'link' || item.type === 'multiselect') {
          content = (<MKSelect config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)} onSubmit={this.props.inputSubmit} />)
        } else if (item.type === 'color') {
          content = (<MKColor config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>)
        } else if (item.type === 'checkcard') {
          className = "checkcard"
          content = (<MKCheckCard config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>)
        } else if (item.type === 'switch') {
          content = (<MKSwitch config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>)
        } else if (item.type === 'checkbox') {
          content = (<MKCheckbox config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>)
        } else if (item.type === 'radio') {
          content = (<MKRadio config={item} onChange={(val) => this.recordChange({[item.field]: val}, item)}/>)
        } else if (item.type === 'date' || item.type === 'datemonth' || item.type === 'datetime') {
          content = (<MKDatePicker config={item} onChange={(val) => this.recordChange({[item.field]: val})} />)
        } else if (item.type === 'fileupload') {
          content = (<MKFileUpload config={item} onChange={(val) => this.recordChange({[item.field]: val})} />)
        } else if (item.type === 'textarea') {
          content = (<MKTextArea config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>)
        } else if (item.type === 'brafteditor') {
          content = (<MKEditor config={item} onChange={(val) => this.recordChange({[item.field]: val})}/>)
          label = item.hidelabel !== 'true' ? label : ''
        }
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval + '',
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  },
                  {
                    max: _max,
                    message: formRule.input.formMessage.replace('@max', _max)
                  },
                  ..._rules
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onChange={(e) => this.handleChange(e, item)} onPressEnter={(e) => this.handleInputSubmit(e, item)} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'number') { // 数字
        let precision = (item.decimal || item.decimal === 0) ? item.decimal : null
        if (!content) return
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              label={label}
              className={className}
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  },
                  {
                    validator: (rule, value, callback) => this.handleConfirmPassword(rule, value, callback, item)
                  }
                ]
              })(
                precision === null ?
                <InputNumber disabled={item.readonly} onPressEnter={(e) => this.handleInputSubmit(e, item)} /> :
                <InputNumber precision={precision} disabled={item.readonly} onPressEnter={(e) => this.handleInputSubmit(e, item)} />
                )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'color') { // 颜色选择
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval || 'transparent',
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <ColorSketch />
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'checkcard') { // 多选框
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              className="checkcard"
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(<CheckCard card={item} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'switch') { // 多选框
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(<CustomSwitch Item={item} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'checkbox') { // 多选框
        let _initval = item.initval ? item.initval.split(',').filter(Boolean) : []
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: _initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Checkbox.Group disabled={item.readonly}>
                  {item.options.map(option => <Checkbox key={option.key} title={option.Text} value={option.Value}>{option.Text}</Checkbox>)}
                </Checkbox.Group>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'radio') { // 单选框
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Radio.Group disabled={item.readonly} onChange={(e) => {this.selectChange(item, e.target.value)}}>
                  {item.options.map(option => <Radio key={option.key} value={option.Value}>{option.Text}</Radio>)}
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select' || item.type === 'link') { // 下拉搜索
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Select
                  showSearch
                  allowClear={true}
                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 || option.props.value.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  onSelect={(value) => {this.selectChange(item, value)}}
                  disabled={item.readonly}
                >
                  {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 === 'multiselect') { // 多选
        let _initval = item.initval ? item.initval.split(',').filter(Boolean) : []
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: _initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Select
                  showSearch
                  mode="multiple"
                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 || option.props.value.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  disabled={item.readonly}
                >
                  {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') { // 时间搜索
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <DatePicker disabled={item.readonly} />
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'datemonth') {
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <MonthPicker disabled={item.readonly} />
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'datetime') {
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <DatePicker showTime disabled={item.readonly} />
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'fileupload') {
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval || '',
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <FileUpload config={item}/>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'linkMain') {
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'funcvar') {
        // 函数变量字段,默认不显示
      } else if (item.type === 'textarea') {
        let _max = item.fieldlength
        let _rules = []
        if (item.encryption !== 'true') {
          _rules = [{
            pattern: /^[^']*$/ig,
            message: formRule.input.quotemsg
          }]
        }
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : item.label
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval,
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  },
                  {
                    max: _max,
                    message: formRule.input.formMessage.replace('@max', _max)
                  },
                  ..._rules
                ]
              })(<CustomTextArea Item={item} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'brafteditor') {
        let _max = item.fieldlength
        fields.push(
          <Col span={item.span || 24} key={index}>
            <Form.Item
              extra={item.extra || null}
              labelCol={item.labelCol}
              wrapperCol={item.wrapperCol}
              label={item.hidelabel !== 'true' && item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <Icon type="question-circle" />
                  {item.label}
                </Tooltip> : (item.hidelabel !== 'true' ? item.label : '')
              }
            >
              {getFieldDecorator(item.field, {
                initialValue: item.initval || '',
                rules: [
                  {
                    required: item.required === 'true',
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  },
                  {
                    max: _max,
                    message: formRule.input.formMessage.replace('@max', _max)
                  }
                ]
              })(<Editor Item={item}/>)}
                rules: item.rules
              })(content)}
            </Form.Item>
          </Col>
        )
@@ -1238,111 +708,57 @@
  }
  handleConfirm = () => {
    const { record, formlist } = this.state
    let _format = {
      date: 'YYYY-MM-DD',
      datemonth: 'YYYY-MM',
      datetime: 'YYYY-MM-DD HH:mm:ss'
    }
    const { formlist } = this.state
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let search = []
          formlist.forEach(item => {
            if (!item.field) return
            let _item = {
              type: item.type,
              readonly: item.readonly,
              readin: item.readin,
              writein: item.writein,
              fieldlen: item.fieldlength,
              key: item.field
            }
            if (item.type === 'funcvar') {
              _item.value = ''
            } else if (item.hidden === 'true' || (item.supField && !item.supvalue.includes(this.props.form.getFieldValue(item.supField)))) {
              let _val = item.initval
              if (record.hasOwnProperty(item.field)) {
                _val = record[item.field]
              }
              _item.value = _val
              if (['date', 'datemonth', 'datetime'].includes(item.type)) {
                if (!_item.value) {
                  _item.value = ''
                } else if (_item.value.format) {
                  _item.value = _item.value.format(_format[item.type])
                }
                if (item.declareType === 'nvarchar(50)') {
                  _item.type = 'text'
                }
              } else if (item.type === 'text' && _item.value && typeof(_item.value) === 'string') { // 特殊字段替换
                _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey)
                _item.value = _item.value.replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || ''))
                _item.value = _item.value.replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || ''))
              }
            } else if (typeof(values[item.field]) !== 'undefined') {
              let _value = values[item.field]
              if (item.type === 'datetime') {
                _value = _value ? moment(_value).format('YYYY-MM-DD HH:mm:ss') : ''
                if (item.declareType === 'nvarchar(50)') {
                  _item.type = 'text'
                }
              } else if (item.type === 'datemonth') {
                _value = _value ? moment(_value).format('YYYY-MM') : ''
                if (item.declareType === 'nvarchar(50)') {
                  _item.type = 'text'
                }
              } else if (item.type === 'date') {
                _value = _value ? moment(_value).format('YYYY-MM-DD') : ''
                if (item.declareType === 'nvarchar(50)') {
                  _item.type = 'text'
                }
              } else if (item.type === 'multiselect' || item.type === 'checkbox') {
                _value = _value ? _value.join(',') : ''
              } else if (item.type === 'text' || item.type === 'textarea') {
                _value = _value.replace(/\t*|\v*/g, '')       // 去除制表符
                if (item.interception === 'true') {           // 去除首尾空格
                  _value = _value.replace(/(^\s*|\s*$)/g, '')
                }
                if (item.type === 'text' && _value) { // 特殊字段替换
                  _value = _value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey)
                  _value = _value.replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || ''))
                  _value = _value.replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || ''))
                }
              }
              _item.value = _value
            } else {
              _item.value = ''
            }
            if (_item.value === undefined) {
              _item.value = ''
            }
            search.push(_item)
          })
          resolve(search)
        } else {
        if (err) {
          reject(err)
          return
        }
        let search = []
        let record = {...this.record, ...values}
        formlist.forEach(item => {
          if (!item.field) return
          let _item = {
            type: item.type,
            readonly: item.readonly,
            readin: item.readin,
            writein: item.writein,
            fieldlen: item.fieldlength,
            key: item.field
          }
          _item.value = record[item.field] !== undefined ? record[item.field] : ''
          if (item.type === 'funcvar') {
            _item.value = ''
          } else if (_item.value && (item.type === 'text' || item.type === 'textarea' || item.type === 'linkMain')) {
            _item.value = _item.value.replace(/\t*|\v*/g, '')       // 去除制表符
            if (item.interception === 'true') {           // 去除首尾空格
              _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
            }
            if (item.type === 'text' && typeof(_item.value) === 'string') { // 特殊字段替换
              _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey)
              _item.value = _item.value.replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || ''))
              _item.value = _item.value.replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || ''))
            }
          } else if (item.type.indexOf('date') > -1) {
            if (item.declareType === 'nvarchar(50)') {
              _item.type = 'text'
            }
          }
          search.push(_item)
        })
        resolve(search)
      })
    })
  }
  handleSubmit = (e) => {
    e && e.preventDefault()
    this.props.inputSubmit()
  }
  render() {
src/tabviews/zshare/mutilform/mkCheckCard/index.jsx
New file
@@ -0,0 +1,140 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Col, Row } from 'antd'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class MKCheckCard extends Component {
  static propTpyes = {
    config: PropTypes.object,
    onChange: PropTypes.func
  }
  state = {
    selectKeys: null
  }
  UNSAFE_componentWillMount() {
    const { config } = this.props
    if (config.multiple === 'true') {
      this.setState({
        selectKeys: config.initval ? config.initval.split(',') : []
      })
    } else {
      this.setState({
        selectKeys: config.initval
      })
    }
  }
  changeCard = (item) => {
    const { config } = this.props
    const { selectKeys } = this.state
    if (config.readonly) return
    if (config.multiple === 'true') {
      let keys = []
      if (selectKeys.includes(item.$value)) {
        keys = selectKeys.filter(key => key !== item.$value)
      } else {
        keys = [...selectKeys, item.$value]
      }
      this.setState({
        selectKeys: keys
      }, () => {
        this.props.onChange(keys.join(','))
      })
    } else if (selectKeys !== item.$value) {
      let other = {}
      config.subFields && config.subFields.forEach((n, i) => {
        other[n.field] = item[n.field]
        setTimeout(() => {
          MKEmitter.emit('mkFC', 'input', n.uuid, item[n.field])
        }, i * 5)
      })
      config.linkFields && config.linkFields.forEach((m, i) => {
        setTimeout(() => {
          MKEmitter.emit('mkFP', m.uuid, item.$value, 0)
        }, (i + 1) * 100)
      })
      this.setState({
        selectKeys: item.$value
      }, () => {
        this.props.onChange(item.$value, other)
      })
    }
  }
  getCards = () => {
    const { display, width, options, fields, ratio, multiple, backgroundColor, borderColor } = this.props.config
    const { selectKeys } = this.state
    let paddingTop = '100%'
    if (ratio === '4:3') {
      paddingTop = '75%'
    } else if (ratio === '3:2') {
      paddingTop = '66.7%'
    } else if (ratio === '16:9') {
      paddingTop = '56.25%'
    }
    let style = borderColor ? {borderColor} : {}
    let _style = backgroundColor ? {backgroundColor} : null
    if (!options || options.length === 0) {
      return null
    } else if (display !== 'picture') {
      if (!fields || fields.length === 0) {
        return null
      }
      return options.map(item => {
        let _active = false
        if (multiple === 'true' && selectKeys.includes(item.$value)) {
          _active = true
        } else if (multiple !== 'true' && selectKeys === item.$value) {
          _active = true
        }
        return <Col span={width} key={item.key}>
          <div className={'card-cell' + (_active ? ' active' : '') + (_style ? ' bg-control' : '')} style={style} onClick={() => this.changeCard(item)}>
            <div className="bg-mask" style={_style}></div>
            {fields.map(col => {
              return <span key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span>
            })}
          </div>
        </Col>
      })
    } else {
      return options.map(item => {
        let _active = false
        if (multiple === 'true' && selectKeys.includes(item.$value)) {
          _active = true
        } else if (multiple !== 'true' && selectKeys === item.$value) {
          _active = true
        }
        return <Col span={width} key={item.key}>
          <div className={'card-pic-cell ' + (_active ? 'active' : '')} onClick={() => this.changeCard(item)} style={{...style, paddingTop, backgroundImage: `url(${item.$url})`}}>
          </div>
        </Col>
      })
    }
  }
  render() {
    const { config } = this.props
    return (
      <div className={'check-card-form-box' + (config.readonly ? ' readonly' : '')}>
        <Row gutter={12}>{this.getCards()}</Row>
      </div>
    )
  }
}
export default MKCheckCard
src/tabviews/zshare/mutilform/mkCheckCard/index.scss
New file
@@ -0,0 +1,98 @@
.check-card-form-box {
  margin-top: 10px;
  margin-bottom: -10px;
  .card-cell {
    position: relative;
    border: 1px solid #bcbcbc;
    border-radius: 4px;
    padding: 6px;
    margin-bottom: 12px;
    line-height: 1.5;
    transition: all 0.3s;
    cursor: pointer;
    span {
      display: block;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      position: relative;
      z-index: 1;
    }
    .bg-mask {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      opacity: 0.5;
      border-radius: 4px;
      background-color: transparent;
      transition: opacity 0.3s;
    }
  }
  .card-cell:not(.bg-control).active {
    border-color: #1890ff;
    background: #1890ff;
    span {
      color: #ffffff!important;
    }
  }
  .card-cell.bg-control.active {
    .bg-mask {
      opacity: 1;
    }
  }
  .card-pic-cell {
    position: relative;
    border: 1px solid #bcbcbc;
    border-radius: 4px;
    background-size: cover;
    background-position: center;
    margin-bottom: 12px;
    line-height: 1.5;
    cursor: pointer;
    transition: all 0.3s;
  }
  .card-pic-cell.active {
    border-color: #1890ff;
    box-shadow: 0px 0px 4px #1890ff;
  }
  .card-cell:not(.bg-control).active::after {
    content: ' ';
    position: absolute;
    display: table;
    border: 2px solid #ffffff;
    border-top: 0;
    border-left: 0;
    bottom: 0;
    right: 10px;
    width: 6px;
    height: 12px;
    transform: rotate(45deg) scale(1) translate(-50%, -50%);
  }
}
.check-card-form-box:not(.readonly) {
  .card-cell:not(.bg-control):hover {
    border-color: #1890ff;
    background: #1890ff;
    span {
      color: #ffffff!important;
    }
  }
  .card-cell.bg-control:not(.active):hover {
    .bg-mask {
      opacity: 0.7;
    }
  }
  .card-pic-cell:hover {
    border-color: #1890ff;
    box-shadow: 0px 0px 4px #1890ff;
  }
}
.check-card-form-box.readonly {
  .card-cell, .card-pic-cell {
    cursor: not-allowed;
  }
}
src/tabviews/zshare/mutilform/mkCheckbox/index.jsx
New file
@@ -0,0 +1,39 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Checkbox } from 'antd'
import './index.scss'
class MKCheckbox extends Component {
  static propTpyes = {
    config: PropTypes.object,
    onChange: PropTypes.func
  }
  state = {
    defaultValue: this.props.config.initval ? this.props.config.initval.split(',').filter(Boolean) : []
  }
  onChange = (values) => {
    this.props.onChange(values.join(','))
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  render() {
    const { config } = this.props
    const { defaultValue } = this.state
    return (
      <Checkbox.Group defaultValue={defaultValue} disabled={config.readonly} onChange={this.onChange}>
        {config.options.map(option => <Checkbox key={option.key} title={option.label} value={option.value}>{option.label}</Checkbox>)}
      </Checkbox.Group>
    )
  }
}
export default MKCheckbox
src/tabviews/zshare/mutilform/mkCheckbox/index.scss
copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/mutilform/mkCheckbox/index.scss
src/tabviews/zshare/mutilform/mkColor/index.jsx
New file
@@ -0,0 +1,60 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { SketchPicker } from 'react-color'
import { Popover } from 'antd'
import './index.scss'
const presetColors = [
  '#f5222d', '#fa541c', '#fa8c16', '#faad14', '#fadb14', '#a0d911', '#52c41a', '#13c2c2', '#1890ff', '#2f54eb', '#722ed1',
  '#eb2f96', '#595959', '#ffa39e', '#ffbb96', '#ffd591', '#ffe58f', '#fffb8f', '#eaff8f', '#b7eb8f', '#87e8de', '#91d5ff',
  '#adc6ff', '#d3adf7', '#ffadd2', '#d9d9d9', '#434343', '#000000', '#ffffff', 'transparent'
]
class MkColor extends Component {
  static propTpyes = {
    config: PropTypes.object,
    onChange: PropTypes.func
  }
  state = {
    color: '',
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    this.setState({color: config.initval})
  }
  handleChange = (color) => {
    let _color = `rgba(${ color.rgb.r }, ${ color.rgb.g }, ${ color.rgb.b }, ${ color.rgb.a })`
    this.setState({ color: _color }, () => {
      this.props.onChange(_color)
    })
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  render() {
    const { color } = this.state
    return (
      <div className="color-sketch-block">
        <Popover content={
          <SketchPicker color={ color } presetColors={presetColors} onChange={ this.handleChange } />
        } overlayClassName="color-sketch-popover" placement="bottomRight" title="" trigger="click">
          <div className="color-sketch-block-box">
            <div className="color-sketch-block-inner" style={ {background: color} }></div>
          </div>
        </Popover>
        <div className="color-sketch-value">{color}</div>
      </div>
    )
  }
}
export default MkColor
src/tabviews/zshare/mutilform/mkColor/index.scss
New file
@@ -0,0 +1,41 @@
.color-sketch-block {
  height: 25px;
  width: 100%;
  .color-sketch-block-box {
    display: inline-block;
    width: calc(100% - 160px);
    height: 100%;
    border-radius: 4px;
    background: #ffffff url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==') left center;
  }
  .color-sketch-block-inner {
    display: inline-block;
    cursor: pointer;
    border-radius: 4px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .1);
    width: 100%;
    height: 100%;
  }
  .color-sketch-value {
    display: inline-block;
    font-size: 13px;
    width: 160px;
    padding-left: 10px;
    height: 25px;
    line-height: 25px;
    vertical-align: top;
    white-space: nowrap;
    overflow: visible;
  }
}
.color-sketch-popover {
  z-index: 1090!important;
  .ant-popover-inner-content {
    padding: 0;
    .sketch-picker {
      width: 250px!important;
    }
  }
}
src/tabviews/zshare/mutilform/mkDatePicker/index.jsx
New file
@@ -0,0 +1,71 @@
import React, { Component } from 'react'
import { is, fromJS } from 'immutable'
import { DatePicker } from 'antd'
import moment from 'moment'
import './index.scss'
const { MonthPicker } = DatePicker
/**
 * @description 自定义时间选择器
 */
class MkDatePicker extends Component {
  constructor(props) {
    super(props)
    const config = props.config
    let mode = 'date'
    let format = 'YYYY-MM-DD'
    if (config.type === 'datemonth') {
      mode = 'month'
      format = 'YYYY-MM'
    } else if (config.type === 'datetime') {
      mode = 'datetime'
      format = 'YYYY-MM-DD HH:mm:ss'
    }
    let value = config.initval || null
    if (value) {
      value = moment(value, format)
    }
    this.state = {
      value,
      mode,
      format
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  onChange = (val) => {
    const { format } = this.state
    this.props.onChange(val ? moment(val).format(format) : '')
  }
  render() {
    const { config } = this.props
    const { value, mode } = this.state
    if (mode === 'date') {
      return <DatePicker defaultValue={value} disabled={config.readonly} onChange={this.onChange}/>
    } else if (mode === 'month') {
      return <MonthPicker defaultValue={value} disabled={config.readonly} onChange={this.onChange}/>
    } else if (mode === 'datetime') {
      return <DatePicker defaultValue={value} showTime disabled={config.readonly} onChange={this.onChange}/>
    }
  }
}
export default MkDatePicker
src/tabviews/zshare/mutilform/mkDatePicker/index.scss
copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/mutilform/mkDatePicker/index.scss
src/tabviews/zshare/mutilform/mkInput/index.jsx
New file
@@ -0,0 +1,84 @@
import React, { Component } from 'react'
import { is, fromJS } from 'immutable'
import { Input } from 'antd'
import MKEmitter from '@/utils/events.js'
import './index.scss'
/**
 * @description 自定义文本输入
 */
class MKInput extends Component {
  constructor(props) {
    super(props)
    const config = props.config
    this.state = {
      value: config.initval
    }
  }
  inputRef = React.createRef()
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentDidMount () {
    MKEmitter.addListener('mkFC', this.mkFormHandle)
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('mkFC', this.mkFormHandle)
  }
  mkFormHandle = (type, uuid, value) => {
    if (uuid !== this.props.config.uuid) return
    if (type === 'focus') {
      this.inputRef.current.select()
    } else if (type === 'input') {
      this.setState({value})
    }
  }
  handleChange = (e) => {
    let val = e.target.value
    if (!/\n/ig.test(val)) {
      this.props.onChange(val)
      this.setState({value: val})
    } else {
      val = val.replace(/\n/ig, '')
      this.props.onChange(val)
      this.setState({value: val}, () => {
        this.handleInputSubmit()
      })
    }
  }
  handleInputSubmit = () => {
    const { config } = this.props
    if (config.enter === 'false') return
    if (config.enter === 'tab') {
      MKEmitter.emit('mkFC', 'focus', config.tabUuid)
    } else {
      this.props.onSubmit()
    }
  }
  render() {
    const { config } = this.props
    const { value } = this.state
    return <Input ref={this.inputRef} placeholder="" value={value} autoComplete="off" disabled={config.readonly} onChange={this.handleChange} onPressEnter={this.handleInputSubmit} />
  }
}
export default MKInput
src/tabviews/zshare/mutilform/mkInput/index.scss
New file
@@ -0,0 +1,27 @@
.am-list-item.am-input-item {
  .am-input-control {
    height: 100%;
    input {
      height: 100%;
    }
  }
  .am-input-label {
    width: 28%;
    max-width: 120px;
    text-overflow: ellipsis;
  }
  .am-input-extra {
    max-height: 40px;
    .anticon-scan {
      font-size: 22px;
      padding: 8px 5px;
    }
  }
}
.am-input-item.right {
  .am-input-control {
    input {
      text-align: right;
    }
  }
}
src/tabviews/zshare/mutilform/mkNumberInput/index.jsx
New file
@@ -0,0 +1,67 @@
import React, { Component } from 'react'
import { is, fromJS } from 'immutable'
import { InputNumber } from 'antd'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class MKNumberInput extends Component {
  constructor(props) {
    super(props)
    const config = props.config
    let precision = (config.decimal || config.decimal === 0) ? config.decimal : null
    this.state = {
      precision,
      value: config.initval
    }
  }
  inputNumberRef = React.createRef()
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentDidMount () {
    MKEmitter.addListener('mkFC', this.mkFormHandle)
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('mkFC', this.mkFormHandle)
  }
  mkFormHandle = (type, uuid, value) => {
    if (uuid !== this.props.config.uuid) return
    if (type === 'focus') {
      this.inputNumberRef.current.focus()
    } else if (type === 'input') {
      this.setState({value})
    }
  }
  handleChange = (val) => {
    this.props.onChange(val)
    this.setState({value: val})
  }
  render() {
    const { config, onSubmit } = this.props
    const { value, precision } = this.state
    if (precision === null) {
      return (<InputNumber ref={this.inputNumberRef} value={value} disabled={config.readonly} onChange={this.handleChange} onPressEnter={onSubmit}/>)
    } else {
      return (<InputNumber ref={this.inputNumberRef} value={value} precision={precision} disabled={config.readonly} onChange={this.handleChange} onPressEnter={onSubmit} />)
    }
  }
}
export default MKNumberInput
src/tabviews/zshare/mutilform/mkNumberInput/index.scss
New file
@@ -0,0 +1,27 @@
.am-list-item.am-input-item {
  .am-input-control {
    height: 100%;
    input {
      height: 100%;
    }
  }
  .am-input-label {
    width: 28%;
    max-width: 120px;
    text-overflow: ellipsis;
  }
  .am-input-extra {
    max-height: 40px;
    .anticon-scan {
      font-size: 22px;
      padding: 8px 5px;
    }
  }
}
.am-input-item.right {
  .am-input-control {
    input {
      text-align: right;
    }
  }
}
src/tabviews/zshare/mutilform/mkRadio/index.jsx
New file
@@ -0,0 +1,40 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Radio } from 'antd'
import './index.scss'
class MKRadio extends Component {
  static propTpyes = {
    config: PropTypes.object,
    onChange: PropTypes.func
  }
  state = {
    defaultValue: this.props.config.initval
  }
  onChange = (e) => {
    let value = e.target.value
    this.props.onChange(value)
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  render() {
    const { config } = this.props
    const { defaultValue } = this.state
    return (
      <Radio.Group defaultValue={defaultValue} disabled={config.readonly} onChange={this.onChange}>
        {config.options.map(option => <Radio key={option.key} value={option.value}>{option.label}</Radio>)}
      </Radio.Group>
    )
  }
}
export default MKRadio
src/tabviews/zshare/mutilform/mkRadio/index.scss
copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/mutilform/mkRadio/index.scss
src/tabviews/zshare/mutilform/mkSelect/index.jsx
New file
@@ -0,0 +1,179 @@
import React, {Component} from 'react'
import { is, fromJS } from 'immutable'
import { Select } from 'antd'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class MKSelect extends Component {
  constructor(props) {
    super(props)
    const config = props.config
    let value = config.initval
    if (config.type === 'multiselect') {
      if (value) {
        value = value.split(',')
      } else {
        value = []
      }
    }
    this.state = {
      config: fromJS(config).toJS(),
      options: fromJS(config.options).toJS(),
      value,
    }
  }
  componentDidMount () {
    const { config } = this.state
    if (config.type !== 'multiselect') {
      MKEmitter.addListener('mkFP', this.mkFormHandle)
    }
    MKEmitter.addListener('mkFC', this.mkFormFocus)
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    const { config } = this.state
    if (!is(fromJS(config.oriOptions), fromJS(nextProps.config.oriOptions))) {
      this.setState({
        config: fromJS(nextProps.config).toJS(),
        options: fromJS(nextProps.config.options).toJS()
      })
      if (typeof(config.initval) === 'string' && config.initval.indexOf('$first') > -1) {
        this.setState({
          value: nextProps.config.initval,
        })
      }
    }
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('mkFP', this.mkFormHandle)
    MKEmitter.removeListener('mkFC', this.mkFormFocus)
  }
  mkFormFocus = (type, uuid) => {
    if (uuid !== this.props.config.uuid) return
    if (type !== 'focus') return
    let _div = document.getElementById(uuid)
    _div && _div.click && _div.click()
  }
  mkFormHandle = (uuid, parentId, level) => {
    if (uuid !== this.state.config.uuid) return
    const { config } = this.state
    let options = config.oriOptions.filter(option => option.ParentID === parentId || option.value === '')
    let val = options[0] ? options[0].value : ''
    this.setState({
      options,
      value: val
    })
    this.props.onChange(val)
    if (level < 7 && config.linkFields) {
      config.linkFields.forEach((m, i) => {
        setTimeout(() => {
          MKEmitter.emit('mkFP', m.uuid, val, level + 1)
        }, (i + 1) * 70)
      })
    }
  }
  selectChange = (val) => {
    const { config } = this.state
    let other = {}
    if (config.subFields) {
      let option = this.state.options.filter(m => m.value === val)[0]
      option && config.subFields.forEach((n, i) => {
        other[n.field] = option[n.field]
        setTimeout(() => {
          MKEmitter.emit('mkFC', 'input', n.uuid, option[n.field])
        }, i * 5)
      })
    }
    if (config.linkFields) {
      config.linkFields.forEach((m, i) => {
        setTimeout(() => {
          MKEmitter.emit('mkFP', m.uuid, val, 0)
        }, (i + 1) * 100)
      })
    }
    this.props.onChange(val, other)
    this.setState({value: val}, () => {
      if (config.enter === 'tab') {
        MKEmitter.emit('mkFC', 'focus', config.tabUuid)
      } else if (config.enter === 'sub') {
        if (config.linkFields || config.subFields || config.controlFields) {
          setTimeout(() => {
            this.props.onSubmit()
          }, 1000)
        } else {
          this.props.onSubmit()
        }
      }
    })
  }
  mutilselectChange = (val) => {
    this.props.onChange(val.join(','))
  }
  render() {
    const { value, config, options } = this.state
    if (config.type !== 'multiselect') {
      return (
        <Select
          showSearch
          allowClear
          id={config.uuid}
          value={value}
          filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
          onSelect={this.selectChange}
          onClear={() => this.selectChange('')}
          disabled={config.readonly}
        >
          {options.map(option =>
            <Select.Option id={option.key} title={option.label} key={option.key} value={option.value}>{option.label}</Select.Option>
          )}
        </Select>
      )
    } else {
      return (<Select
        showSearch
        id={config.uuid}
        mode="multiple"
        defaultValue={value}
        filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
        onChange={this.mutilselectChange}
        disabled={config.readonly}
      >
        {options.map(option =>
          <Select.Option id={option.key} title={option.label} key={option.key} value={option.value}>{option.label}</Select.Option>
        )}
      </Select>)
    }
  }
}
export default MKSelect
src/tabviews/zshare/mutilform/mkSelect/index.scss
copy from src/tabviews/zshare/mutilform/customSwitch/index.scss copy to src/tabviews/zshare/mutilform/mkSelect/index.scss
src/tabviews/zshare/mutilform/mkSwitch/index.jsx
New file
@@ -0,0 +1,43 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Switch } from 'antd'
import './index.scss'
class MKSwitch extends Component {
  static propTpyes = {
    config: PropTypes.object,
    onChange: PropTypes.func
  }
  state = {
    defaultChecked: this.props.config.initval === this.props.config.openVal
  }
  onChange = (val) => {
    const { config } = this.props
    if (val) {
      this.props.onChange(config.openVal)
    } else {
      this.props.onChange(config.closeVal)
    }
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  render() {
    const { config } = this.props
    const { defaultChecked } = this.state
    return (
      <Switch checkedChildren={config.openText || ''} unCheckedChildren={config.closeText || ''} defaultChecked={defaultChecked} onChange={this.onChange}/>
    )
  }
}
export default MKSwitch
src/tabviews/zshare/mutilform/mkSwitch/index.scss
src/tabviews/zshare/mutilform/mkTextArea/index.jsx
New file
@@ -0,0 +1,92 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Input } from 'antd'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const { TextArea } = Input
class MkTextArea extends Component {
  static propTpyes = {
    config: PropTypes.bool,
    onChange: PropTypes.func
  }
  inputRef = React.createRef()
  state = {
    value: '',
    encryption: 'false'
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    let _value = config.initval
    let encryption = 'false'
    if (config.encryption === 'true') {
      encryption = 'true'
      if (_value) {
        try {
          _value = window.decodeURIComponent(window.atob(_value))
        } catch {
          _value = config.initval
        }
      }
    }
    this.setState({
      value: _value,
      encryption
    })
  }
  componentDidMount () {
    MKEmitter.addListener('mkFC', this.mkFormHandle)
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('mkFC', this.mkFormHandle)
  }
  mkFormHandle = (type, uuid, value) => {
    if (uuid !== this.props.config.uuid) return
    if (type === 'focus') {
      this.inputRef.current.focus()
    } else if (type === 'input') {
      this.setState({value})
    }
  }
  onChange = (e) => {
    const { encryption } = this.state
    let val = e.target.value
    this.setState({ value: val })
    let _val = val
    if (encryption === 'true') {
      try {
        _val = window.btoa(window.encodeURIComponent(_val))
      } catch {
        _val = val
      }
    }
    this.props.onChange(_val)
  }
  render() {
    const { config } = this.props
    const { value } = this.state
    return (
      <TextArea ref={this.inputRef} value={value} autoSize={{ minRows: 2, maxRows: config.maxRows || 6 }} onChange={this.onChange} disabled={config.readonly} />
    )
  }
}
export default MkTextArea
src/tabviews/zshare/mutilform/mkTextArea/index.scss
src/utils/utils-datamanage.js
@@ -1,3 +1,4 @@
import md5 from 'md5'
import moment from 'moment'
import options from '@/store/options.js'
import Utils from './utils.js'
@@ -575,4 +576,132 @@
    return [...lineMap.values()]
  }
}
/**
 * @description 生成单个组件sPC_Get_structured_data请求参数
 */
export function getStructDefaultParam (component, searchlist) {
  const { columns, setting, dataName, format } = component
  let arr_field = columns.map(col => col.field)
  let _dataresource = setting.dataresource
  let _customScript = setting.customScript
  if (setting.queryType === 'statistics' || _customScript) {
    let allSearch = Utils.getAllSearchOptions(searchlist)
    let regoptions = allSearch.map(item => {
      return {
        reg: new RegExp('@' + item.key + '@', 'ig'),
        value: `'${item.value}'`
      }
    })
    regoptions.forEach(item => {
      if (_dataresource && setting.queryType === 'statistics') {
        _dataresource = _dataresource.replace(item.reg, item.value)
      }
      _customScript = _customScript.replace(item.reg, item.value)
    })
  }
  _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
  _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
  _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
  _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
  _customScript = _customScript.replace(/\$sum@/ig, '/*')
  _customScript = _customScript.replace(/@sum\$/ig, '*/')
  let _search = ''
  if (setting.queryType !== 'statistics' && _dataresource) {
    _search = Utils.joinMainSearchkey(searchlist)
    _search = _search ? 'where ' + _search : ''
  }
  if (setting.order && _dataresource) {
    _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
  } else if (_dataresource) {
    _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} ${_search} `
  }
  // 测试系统打印查询语句
  if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
    _customScript &&  console.info(`${setting.$name ? `/*组件-${setting.$name} 自定义脚本*/\n` : ''}${_dataresource ? '' : '/*不执行默认sql*/\n'}${_customScript}`)
    _dataresource &&  console.info(`${setting.$name ? `/*组件-${setting.$name} 数据源*/\n` : ''}` + _dataresource)
  }
  return {
    name: dataName,
    columns: columns,
    par_tablename: '',
    type: format === 'array' ? format : '',
    primaryKey: setting.primaryKey || '',
    foreign_key: '',
    sql: _dataresource,
    script: _customScript
  }
}
/**
 * @description 生成sPC_Get_structured_data请求参数
 * 1、把大接口sPC_Get_structured_data的ltext拆成三份,第一段:@LText1,第二段@LText,第三段@LText2
 */
export function getStructuredParams (params, config, BID = '') {
  let LText_field = []
  let diffUser = false
  let userName = sessionStorage.getItem('User_Name') || ''
  let fullName = sessionStorage.getItem('Full_Name') || ''
  let city = sessionStorage.getItem('city') || ''
  if (sessionStorage.getItem('isEditState') === 'true') {
    userName = sessionStorage.getItem('CloudUserName') || ''
    fullName = sessionStorage.getItem('CloudFullName') || ''
  }
  let _LText = params.map((item, index) => {
    let _script = item.script
    if (index === 0) {
      _script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@login_city nvarchar(50)
        select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @login_city='${city}'
        ${_script}
      `
    }
    if (!diffUser && (/@userid@/ig.test(item.sql) || /@userid@/ig.test(_script))) {
      diffUser = true
    }
    item.columns.forEach(cell => {
      LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`)
    })
    return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
  })
  let param = {
    func: 'sPC_Get_structured_data',
    LText: _LText.join(' union all '),
    LText_field: LText_field.join(' union all '),
    BID: BID
  }
  let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText)
  param.LText1 = LText1
  param.LText = LText
  param.LText2 = LText2
  param.LText_field = Utils.formatOptions(param.LText_field)
  if (config.cacheUseful === 'true') {
    param.time_type = config.timeUnit
    param.time_limit = config.cacheTime
    if (diffUser) {
      param.userid = sessionStorage.getItem('UserID')
    }
    param.data_md5 = md5(JSON.stringify(param))
  }
  param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
  param.secretkey = Utils.encrypt(param.LText, param.timestamp)
  return param
}
src/utils/utils.js
@@ -1805,7 +1805,6 @@
      }
    }
  }
}
/**
src/views/interface/history/index.jsx
@@ -1,6 +1,6 @@
import React, {Component} from 'react'
import { fromJS } from 'immutable'
import { Input, Modal, Empty, Icon } from 'antd'
import { Input, Modal, Icon } from 'antd'
import moment from 'moment'
import Api from '@/views/interface/api'
@@ -193,6 +193,36 @@
    MKEmitter.emit('useInterface', fromJS(m).toJS())
  }
  uselogon = () => {
    let m = {
      active: 'raw',
      createDate: '',
      formData: [],
      headers: [],
      interface: 'dologon / logon',
      method: 'POST',
      params: [],
      raw: "{\n \"UserName\":\"******\",\n \"Password\":\"******\",\n \"systemType\":\"local\",\n \"Type\":\"公钥\",\n \"privatekey\":\"私钥\",\n \"timestamp\":\"YYYY-MM-DD HH:mm:ss\",\n \"appkey\":\"******\"\n}",
      uuid: 'dologon'
    }
    MKEmitter.emit('useInterface', m)
  }
  usedostars = () => {
    let m = {
      active: 'raw',
      createDate: '',
      formData: [],
      headers: [],
      interface: 'dostars',
      method: 'POST',
      params: [],
      raw: "{\n \"LoginUID\":\"******\",\n \"UserID\":\"******\",\n \"func\":\"******\"\n}",
      uuid: 'dologon'
    }
    MKEmitter.emit('useInterface', m)
  }
  changeSearch = (value) => {
    const { list } = this.state
@@ -219,24 +249,38 @@
          <span onClick={this.clear}>Clear all</span>
        </div>
        <div className="list-view">
          {historys.length === 0 ?
            <Empty /> :
            historys.map((item, index) => (
              <div className="list-line" key={index}>
                <div className="line-title">{item.date}</div>
                {item.sublist.map(m => (
                  <div className="line-item" key={m.uuid}>
                    <div className="method">POST</div>
                    <div className="inter">{m.interface}</div>
                    <div className="action">
                      <Icon type="delete" onClick={() => this.delete(m)} />
                      <Icon type="right" onClick={() => this.use(m)} />
                    </div>
          {historys.map((item, index) => (
            <div className="list-line" key={index}>
              <div className="line-title">{item.date}</div>
              {item.sublist.map(m => (
                <div className="line-item" key={m.uuid}>
                  <div className="method">POST</div>
                  <div className="inter">{m.interface}</div>
                  <div className="action">
                    <Icon type="delete" onClick={() => this.delete(m)} />
                    <Icon type="right" onClick={() => this.use(m)} />
                  </div>
                ))}
                </div>
              ))}
            </div>
          ))}
          <div className="list-line" key="example">
            <div className="line-title">示例</div>
              <div className="line-item" key="dologon">
                <div className="method">POST</div>
                <div className="inter" style={{lineHeight: '40px'}}>dologon / logon</div>
                <div className="action" style={{paddingLeft: '40px'}}>
                  <Icon type="right" onClick={this.uselogon} />
                </div>
              </div>
            ))
          }
              <div className="line-item" key="dostars">
                <div className="method">POST</div>
                <div className="inter" style={{lineHeight: '40px'}}>dostars</div>
                <div className="action" style={{paddingLeft: '40px'}}>
                  <Icon type="right" onClick={this.usedostars} />
                </div>
              </div>
          </div>
        </div>
      </aside>
    )
src/views/interface/workspace/index.jsx
@@ -39,7 +39,11 @@
  useInterface = (item) => {
    item.uuid = Utils.getuuid()
    this.setState({tabviews: [...this.state.tabviews, item]})
    this.setState({tabviews: [...this.state.tabviews, item]}, () => {
      let div = document.getElementById(item.uuid)
      div && div.click && div.click()
    })
  }
  handleTabview = (view) => {
@@ -66,7 +70,7 @@
  }
  handleAdd = () => {
    this.setState({tabviews: [...this.state.tabviews, {
    let item = {
      uuid: Utils.getuuid(),
      createDate: '',
      method: 'POST',
@@ -76,7 +80,11 @@
      active: 'raw',
      raw: '',
      formData: []
    }]})
    }
    this.setState({tabviews: [...this.state.tabviews, item]}, () => {
      let div = document.getElementById(item.uuid)
      div && div.click && div.click()
    })
  }
  render () {
@@ -90,7 +98,7 @@
            return (
              <Tabs.TabPane
                tab={
                  <span className="control">
                  <span className="control" id={view.uuid || ''}>
                    <span className="method">
                      {view.method || 'POST'}
                    </span>
src/views/interface/workspace/request/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import { fromJS } from 'immutable'
import md5 from 'md5'
import { Input, Select, Button, Tabs, Radio, Modal } from 'antd'
import { Input, Select, Button, Tabs, Radio, Modal, Spin } from 'antd'
import Api from '@/views/interface/api'
import Utils from '@/utils/utils.js'
@@ -18,7 +18,8 @@
    active: 'raw',
    body: null,
    response: null,
    status: ''
    status: '',
    loading: false
  }
  UNSAFE_componentWillMount() {
@@ -145,6 +146,8 @@
      n = JSON.stringify(n)
    }
    this.setState({loading: true})
    if (/logon/ig.test(url)) {
      Api.dologon(url, config.method, header, n).then(res => {
        this.handleResponse(res)
@@ -193,7 +196,7 @@
      body = `请求异常${status === 'Network Error' ? ',可能原因:1、网络异常;2、接口跨域。' : '!'}`
    }
    this.setState({response: res, body, status})
    this.setState({response: res, body, status, loading: false})
  }
  encryptParam (param) {
@@ -237,7 +240,7 @@
  }
  render () {
    const { active, config, response, body, status } = this.state
    const { active, config, response, body, status, loading } = this.state
    let hasParam = config.params.filter(item => item.selected && item.key).length > 0
    let hasHeader = config.headers.filter(item => item.selected && item.key).length
@@ -297,6 +300,7 @@
            <span className="empty">Hit the Send button to get a response.</span>
          </div>}
          <div style={{paddingLeft: '3px', paddingTop: '3px'}} dangerouslySetInnerHTML={{__html: body}}></div>
          {loading ? <div className="pending"><Spin size="large"/></div> : null}
        </div>
      </div>
    )
src/views/interface/workspace/request/index.scss
@@ -107,6 +107,7 @@
    border-radius: 0;
  }
  .response {
    position: relative;
    min-height: 400px;
    border-left: 1px solid #e8e8e8;
    border-right: 1px solid #e8e8e8;
@@ -137,6 +138,11 @@
        }
      }
    }
    .pending {
      position: absolute;
      left: 50%;
      top: 160px;
    }
  }
}
src/views/mobdesign/index.jsx
@@ -63,7 +63,6 @@
    menuloading: false,
    oriConfig: null,
    config: null,
    visible: false,
    customComponents: [],
    direction: 'vertical',
    settingshow: true,
@@ -276,13 +275,11 @@
            })
          } else {
            sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
            sessionStorage.setItem('appHomeId', homeId)
            this.props.history.replace('/mobdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'}))))
          }
        })
      } else {
        sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
        sessionStorage.setItem('appHomeId', homeId)
        this.props.history.replace('/mobdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'}))))
      }
    })
@@ -851,6 +848,9 @@
      }
      let parMenuId = sessionStorage.getItem('kei_no') + 'pc' + sessionStorage.getItem('lang')
      let roleParam = {type: 'view', key: config.uuid, title: config.MenuName, children: []}
      roleParam.children = this.getMenuMessage()
      let param = {
        func: 'sPC_TrdMenu_AddUpt',
        FstID: parMenuId,
@@ -865,16 +865,13 @@
        MenuName: config.MenuName || '',
        PageParam: JSON.stringify({Template: 'webPage'}),
        open_edition: config.open_edition,
        menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roleParam))),
        LText: '',
        LTexttb: ''
      }
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      param.secretkey = Utils.encrypt('', param.timestamp)
      let roleParam = {key: config.uuid, title: config.MenuName, children: []}
      roleParam.children = this.getMenuMessage()
      console.log(roleParam)
      new Promise(resolve => {
        let _config = fromJS(config).toJS()
@@ -905,6 +902,20 @@
                return
              }
              let roles = {
                type: 'navbar',
                key: item.uuid,
                title: item.name,
                children: []
              }
              roles.children = item.menus.map(menu => {
                return {
                  key: menu.MenuID,
                  title: menu.name
                }
              })
              let _param = {
                func: 'sPC_TrdMenu_AddUpt',
                FstID: parMenuId,
@@ -919,6 +930,7 @@
                MenuName: item.name || '',
                PageParam: JSON.stringify({Template: item.type}),
                open_edition: item.open_edition || '',
                menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roles))),
                LText: '',
                LTexttb: ''
              }
@@ -926,20 +938,6 @@
              _param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(item)))
              _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
              _param.secretkey = Utils.encrypt('', _param.timestamp)
              let roles = {
                key: item.uuid,
                title: item.name,
                children: []
              }
              roles.children = item.menus.map(menu => {
                return {
                  key: menu.MenuID,
                  title: menu.name
                }
              })
              console.log(roles)
              
              Api.getSystemConfig(_param).then(res => {
                if (!res.status) {
@@ -1251,7 +1249,6 @@
              duration: 5
            })
          } else {
            sessionStorage.setItem('appHomeId', config.MenuID)
            sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
          }
        })
src/views/pcdesign/index.jsx
@@ -24,6 +24,7 @@
const MenuForm = asyncComponent(() => import('./menuform'))
const Transfer = asyncComponent(() => import('@/pc/transfer'))
// const PopviewController = asyncComponent(() => import('@/menu/popview'))
const MenuShell = asyncComponent(() => import('@/pc/menushell'))
const SourceWrap = asyncComponent(() => import('@/pc/modulesource'))
const CreateView = asyncComponent(() => import('@/pc/createview'))
@@ -175,7 +176,10 @@
    param = window.btoa(window.encodeURIComponent(JSON.stringify(param)))
    if (param === this.props.match.params.param) return
    if (param === this.props.match.params.param) {
      window.location.reload()
      return
    }
    this.props.history.push('/pcdesign/' + param)
  }
@@ -240,13 +244,11 @@
            })
          } else {
            sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
            sessionStorage.setItem('appHomeId', homeId)
            this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'}))))
          }
        })
      } else {
        sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
        sessionStorage.setItem('appHomeId', homeId)
        this.props.history.replace('/pcdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: homeId, type: 'view'}))))
      }
    })
@@ -366,6 +368,14 @@
      }
      this.setState({customComponents: coms})
      this.getRoleFields()
    })
  }
  handleBack = () => {
    this.setState({popBtn: null, delButtons: [], copyButtons: [], thawButtons: []}, () => {
      sessionStorage.setItem('editMenuType', 'menu')
      window.GLOB.customMenu = this.state.config
      this.setState({visible: false})
    })
  }
@@ -500,7 +510,7 @@
            }
          }
        }
        config.uuid = MenuId
        config.MenuID = MenuId
        config.open_edition = result.open_edition || ''
@@ -718,35 +728,68 @@
  getMenuMessage = () => {
    const { config } = this.state
    let buttons = []
    let _sort = 1
    let nodes = {type: 'view', key: config.uuid, title: config.MenuName, children: []}
    let popviews = []
    let traversal = (components) => {
      components.forEach(item => {
      let list = components.map(item => {
        let m = {
          key: item.uuid,
          title: item.name,
          children: []
        }
        if (item.type === 'tabs') {
          let tabs = []
          item.subtabs.forEach(tab => {
            traversal(tab.components)
            let s = traversal(tab.components)
            if (s.length === 0) return
            tabs.push({
              key: tab.uuid,
              title: tab.label,
              children: s
            })
          })
          if (tabs.length > 0) {
            m.children = tabs
          }
        } else if (item.type === 'group') {
          traversal(item.components)
          m.children = traversal(item.components)
        } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) {
          item.action && item.action.forEach(btn => {
            this.checkBtn(btn)
            buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
            m.children.push({
              key: btn.uuid,
              title: btn.label,
            })
            if (btn.OpenType === 'popview') {
              popviews.push(btn.uuid)
            }
          })
          item.subcards.forEach(card => {
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
              this.checkBtn(cell)
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
              _sort++
              m.children.push({
                key: cell.uuid,
                title: cell.label,
              })
              if (cell.OpenType === 'popview') {
                popviews.push(cell.uuid)
              }
            })
            card.backElements && card.backElements.forEach(cell => {
              if (cell.eleType !== 'button') return
              this.checkBtn(cell)
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
              _sort++
              m.children.push({
                key: cell.uuid,
                title: cell.label,
              })
              if (cell.OpenType === 'popview') {
                popviews.push(cell.uuid)
              }
            })
          })
        } else if (item.type === 'carousel') {
@@ -754,44 +797,80 @@
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
              this.checkBtn(cell)
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
              _sort++
              m.children.push({
                key: cell.uuid,
                title: cell.label,
              })
              if (cell.OpenType === 'popview') {
                popviews.push(cell.uuid)
              }
            })
          })
        } else if (item.type === 'balcony') {
          item.elements && item.elements.forEach(cell => {
            if (cell.eleType !== 'button') return
            this.checkBtn(cell)
            buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
            m.children.push({
              key: cell.uuid,
              title: cell.label,
            })
            if (cell.OpenType === 'popview') {
              popviews.push(cell.uuid)
            }
          })
        } else if (item.type === 'line' || item.type === 'bar') {
          item.action && item.action.forEach(btn => {
            this.checkBtn(btn)
            buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
        } else if (item.type === 'menubar') {
          if (item.wrap.title) {
            m.title = item.wrap.title
          }
          m.children = item.subMenus.map(menu => {
            return {
              key: menu.uuid,
              title: menu.setting.name
            }
          })
        } else if (item.type === 'table' && item.subtype === 'normaltable') {
          item.action && item.action.forEach(btn => {
            this.checkBtn(btn)
            buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
            m.children.push({
              key: btn.uuid,
              title: btn.label,
            })
            if (btn.OpenType === 'popview') {
              popviews.push(btn.uuid)
            }
          })
          item.cols && item.cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements.forEach(btn => {
              this.checkBtn(btn)
              buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`)
              _sort++
              m.children.push({
                key: btn.uuid,
                title: btn.label,
              })
              if (btn.OpenType === 'popview') {
                popviews.push(btn.uuid)
              }
            })
          })
        }
        if (m.children.length === 0) return null
        return m
      })
      list = list.filter(Boolean)
      return list
    }
    traversal(config.components)
    let trees = traversal(config.components)
    return buttons
    nodes.children = trees
    nodes.popviews = popviews
    return nodes
  }
  checkBtn = (btn) => {
@@ -861,6 +940,8 @@
      }
      let parMenuId = sessionStorage.getItem('kei_no') + 'pc' + sessionStorage.getItem('lang')
      let roleParam = this.getMenuMessage()
      let param = {
        func: 'sPC_TrdMenu_AddUpt',
        FstID: parMenuId,
@@ -874,6 +955,7 @@
        Typename: 'pc',
        MenuName: config.MenuName || '',
        PageParam: JSON.stringify({Template: 'webPage'}),
        menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roleParam))),
        open_edition: config.open_edition,
        LText: '',
        LTexttb: ''
@@ -881,26 +963,6 @@
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      param.secretkey = Utils.encrypt('', param.timestamp)
      let btnParam = {             // 添加菜单按钮
        func: 'sPC_Button_AddUpt',
        Type: 40,                  // 添加菜单下的按钮type为40,按钮下的按钮type为60
        ParentID: config.uuid,
        MenuNo: config.MenuNo,
        Template: 'webPage',
        PageParam: '',
        LongParam: '',
        LText: []
      }
      btnParam.LText = this.getMenuMessage()
      btnParam.LText = btnParam.LText.join(' union all ')
      let btnIds = btnParam.LText // 用于复制按钮的过滤
      btnParam.LText = Utils.formatOptions(btnParam.LText)
      btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
      new Promise(resolve => {
        let _config = fromJS(config).toJS()
@@ -931,6 +993,37 @@
                return
              }
              let roles = {
                type: 'navbar',
                key: item.uuid,
                title: item.name,
                children: []
              }
              roles.children = item.menus.map(fst => {
                if (fst.property === 'classify' && fst.sublist.length > 0) {
                  return {
                    key: fst.MenuID,
                    title: fst.name,
                    children: fst.sublist.map(scd => {
                      if (scd.property === 'classify' && scd.sublist.length > 0) {
                        return {
                          key: scd.MenuID,
                          title: scd.name,
                          children: scd.sublist.map(thd => {
                            return { key: thd.MenuID, title: thd.name }
                          })
                        }
                      } else {
                        return { key: scd.MenuID, title: scd.name }
                      }
                    })
                  }
                } else {
                  return { key: fst.MenuID, title: fst.name }
                }
              })
              let _param = {
                func: 'sPC_TrdMenu_AddUpt',
                FstID: parMenuId,
@@ -944,6 +1037,7 @@
                Typename: 'pc',
                MenuName: item.name || '',
                PageParam: JSON.stringify({Template: item.type}),
                menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roles))),
                open_edition: item.open_edition || '',
                LText: '',
                LTexttb: ''
@@ -953,87 +1047,20 @@
              _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
              _param.secretkey = Utils.encrypt('', _param.timestamp)
              // let appMenuParam = null
              // if (item.type === 'navbar') {
              //   appMenuParam = {
              //     func: 's_appmenus_addupt',
              //     exec_type: 'y'
              //   }
              //   appMenuParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
              //   appMenuParam.secretkey = Utils.encrypt('', _param.timestamp)
              Api.getSystemConfig(_param).then(res => {
                if (!res.status) {
                  notification.warning({
                    top: 92,
                    message: res.message,
                    duration: 5
                  })
                  this.setState({ menuloading: false })
                  return
                }
              //   let LText = []
              //   let app_param = []
              //   let kei_no = sessionStorage.getItem('kei_no')
              //   let userid = sessionStorage.getItem('CloudUserID') || ''
              //   item.menus.forEach((fst, findex) => {
              //     // LText.push(`select '${fst.MenuID}','${fst.name}','','0','${sessionStorage.getItem('appId')}','0','${(findex + 1) * 10}','10','','${userid}','${window.GLOB.appkey}','${fst.MenuNo || ''}','${kei_no}','pc'`)
              //     LText.push(`select '${fst.MenuID}','${fst.name}','','0','0','0','${(findex + 1) * 10}','10','','${userid}','${window.GLOB.appkey}','${fst.MenuNo || ''}','${kei_no}','pc'`)
              //     app_param.push(`select '${window.GLOB.appkey}','${fst.MenuID}','${userid}','${(findex + 1) * 10}','','${fst.name}','${fst.MenuNo || ''}','0','10','${kei_no}','pc'`)
              //     if (fst.property === 'classify' && fst.sublist.length > 0) {
              //       fst.sublist.forEach(scd => {
              //         LText.push(`select '${scd.MenuID}','${scd.name}','','0','${fst.MenuID}','0','${(findex + 1) * 10}','20','','${userid}','${window.GLOB.appkey}','${scd.MenuNo || ''}','${kei_no}','pc'`)
              //         app_param.push(`select '${window.GLOB.appkey}','${scd.MenuID}','${userid}','${(findex + 1) * 10}','','${scd.name}','${scd.MenuNo || ''}','${fst.MenuID}','20','${kei_no}','pc'`)
              //         if (scd.property === 'classify' && scd.sublist.length > 0) {
              //           scd.sublist.forEach(thd => {
              //             LText.push(`select '${thd.MenuID}','${thd.name}','','0','${scd.MenuID}','0','${(findex + 1) * 10}','20','','${userid}','${window.GLOB.appkey}','${thd.MenuNo || ''}','${kei_no}','pc'`)
              //             app_param.push(`select '${window.GLOB.appkey}','${thd.MenuID}','${userid}','${(findex + 1) * 10}','','${thd.name}','${thd.MenuNo || ''}','${scd.MenuID}','20','${kei_no}','pc'`)
              //           })
              //         }
              //       })
              //     }
              //   })
              //   appMenuParam.LText = Utils.formatOptions(LText.join(' union '))
              //   appMenuParam.LText1 = Utils.formatOptions(app_param.join(' union '))
              // }
              // if (appMenuParam) {
              //   Api.getSystemConfig(appMenuParam).then(_res => {
              //     if (!_res.status) {
              //       notification.warning({
              //         top: 92,
              //         message: _res.message,
              //         duration: 5
              //       })
              //       this.setState({ menuloading: false })
              //       return
              //     }
              //     Api.getSystemConfig(_param).then(res => {
              //       if (!res.status) {
              //         notification.warning({
              //           top: 92,
              //           message: res.message,
              //           duration: 5
              //         })
              //         this.setState({ menuloading: false })
              //         return
              //       }
              //       new_open_edition[item.uuid] = res.open_edition || ''
              //       resolve()
              //     })
              //   })
              // } else {
                Api.getSystemConfig(_param).then(res => {
                  if (!res.status) {
                    notification.warning({
                      top: 92,
                      message: res.message,
                      duration: 5
                    })
                    this.setState({ menuloading: false })
                    return
                  }
                  new_open_edition[item.uuid] = res.open_edition || ''
                  resolve()
                })
              // }
                new_open_edition[item.uuid] = res.open_edition || ''
                resolve()
              })
            })
          })
          Promise.all(deffers).then(() => {
@@ -1107,10 +1134,9 @@
        if (delButtons.length === 0) {
          return { status: true, nonexec: true }
        } else {
          let appHomeId = sessionStorage.getItem('appHomeId')
          let _param = {
            func: 'sPC_MainMenu_Del',
            MenuID: delButtons.filter(id => id !== appHomeId).join(',')
            MenuID: delButtons.join(',')
          }
          return Api.getSystemConfig(_param)
        }
@@ -1127,13 +1153,12 @@
          this.getAppMenus()
        }
        let ids = thawButtons.filter(item => btnIds.indexOf(item) !== -1)
        if (ids.length === 0) {
        if (thawButtons.length === 0) {
          return { status: true }
        } else {
          return Api.getSystemConfig({
            func: 'sPC_MainMenu_ReDel',
            MenuID: ids.join(',')
            MenuID: thawButtons.join(',')
          })
        }
      }).then(res => { // 页面保存
@@ -1160,12 +1185,8 @@
            oriConfig: fromJS(config).toJS(),
          })
          if (btnParam.LText) {
            return Api.getSystemConfig(btnParam)
          } else {
            return {
              status: true
            }
          return {
            status: true
          }
        } else {
          notification.warning({
@@ -1194,7 +1215,7 @@
          return new Promise(resolve => {
            let deffers = copyButtons.map(item => {
              return new Promise(resolve => {
                if (btnIds.indexOf(item.uuid) === -1) { // 复制的按钮已删除
                if (delButtons.includes(item.uuid)) { // 复制的按钮已删除
                  resolve({
                    status: true
                  })
@@ -1496,7 +1517,6 @@
              duration: 5
            })
          } else {
            sessionStorage.setItem('appHomeId', config.MenuID)
            sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
          }
        })
@@ -1506,13 +1526,13 @@
  }
  render () {
    const { localedict, loading, comloading, activeKey, settingshow, controlshow, dict, MenuId, config, menuloading, customComponents } = this.state
    const { localedict, loading, visible, popBtn, comloading, activeKey, settingshow, controlshow, dict, MenuId, config, menuloading, customComponents } = this.state
    return (
      <ConfigProvider locale={localedict}>
        <div className={'mk-pc-view '} id="mk-pc-design-view">
          {loading ? <Spin className="view-spin" size="large" /> : null}
          <DndProvider backend={HTML5Backend}>
          {!popBtn && !visible ? <DndProvider backend={HTML5Backend}>
            <div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}>
              <div className="draw">
                {settingshow ? <Icon onClick={() => {sessionStorage.setItem('settingshow', 'false'); this.setState({settingshow: false})}} type="double-left" /> : null}
@@ -1568,7 +1588,8 @@
            <div className={'menu-body menu-view' + (menuloading ? 'saving' : '')}>
              {config && !comloading ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
            </div>
          </DndProvider>
          </DndProvider> : null}
          {/* {popBtn && visible ? <PopviewController btn={popBtn} handleBack={this.handleBack}/> : null} */}
          <StyleController />
          <StyleCombController />
          <ModalController />
src/views/rolemanage/index.jsx
@@ -1,6 +1,6 @@
import React, {Component} from 'react'
// import { fromJS } from 'immutable'
import { Spin, notification, Button, Table, Modal, ConfigProvider, Tree } from 'antd'
import { fromJS } from 'immutable'
import { Spin, notification, Button, Table, Modal, ConfigProvider, Tree, Input, Empty } from 'antd'
import moment from 'moment'
// import md5 from 'md5'
import enUS from 'antd/es/locale/en_US'
@@ -14,7 +14,7 @@
const { confirm } = Modal
const { TreeNode } = Tree
// const { Paragraph } = Typography
// const { Search } = Input
const { Search } = Input
const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
const Header = asyncComponent(() => import('./header'))
@@ -47,109 +47,14 @@
    confirmLoading: false,
    targetKeys: [],
    trees: [],
    expandedKeys: []
    expandedKeys: [],
    searchkey: ''
  }
  UNSAFE_componentWillMount() {
    let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
    let expandedKeys = []
    const data = [
      {
        key: Utils.getuuid(),
        title: '导航栏',
        children: [
          {
            key: Utils.getuuid(),
            title: '采购',
            children: [
              {
                key: Utils.getuuid(),
                title: '采购业务',
                children: [
                  {
                    key: Utils.getuuid(),
                    title: '采购单管理'
                  },
                  {
                    key: Utils.getuuid(),
                    title: '委外采购'
                  }
                ]
              },
              {
                key: Utils.getuuid(),
                title: '主数据'
              }
            ]
          },
          {
            key: Utils.getuuid(),
            title: '库存',
            children: [
              {
                key: Utils.getuuid(),
                title: '库存管理',
                children: [
                  {
                    key: Utils.getuuid(),
                    title: '收货管理'
                  },
                  {
                    key: Utils.getuuid(),
                    title: '销退收货'
                  },
                  {
                    key: Utils.getuuid(),
                    title: '发货通知单'
                  }
                ]
              }
            ]
          },
          {
            key: Utils.getuuid(),
            title: '报表',
            children: [
              {
                key: Utils.getuuid(),
                title: '报表查询',
                children: [
                  {
                    key: Utils.getuuid(),
                    title: '采购查询'
                  },
                  {
                    key: Utils.getuuid(),
                    title: '库存查询'
                  },
                  {
                    key: Utils.getuuid(),
                    title: '出库查询'
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        key: Utils.getuuid(),
        title: '首页001'
      },
      {
        key: Utils.getuuid(),
        title: '供应商'
      }
    ]
    if (data[0]) {
      expandedKeys.push(data[0].key)
      if (data[0].children && data[0].children[0]) {
        expandedKeys.push(data[0].children[0].key)
      }
    }
    this.setState({app: param, trees: data, expandedKeys}, () => {
    this.setState({app: param}, () => {
      this.getMenuList()
      this.getThawMenulist()
    })
@@ -185,7 +90,25 @@
      if (result.status) {
        this.setState({
          loading: false,
          menulist: result.menus
          menulist: result.menus.map(item => {
            item.nodes = ''
            item.type = 'view'
            if (item.menus_rolelist) {
              try {
                let pageParam = JSON.parse(window.decodeURIComponent(window.atob(item.menus_rolelist)))
                item.nodes = pageParam
                if (pageParam.type === 'navbar') {
                  item.type = 'navbar'
                }
              } catch {
                item.nodes = ''
              }
            }
            return item
          })
        }, () => {
          this.initMenutree()
        })
      } else {
        this.setState({
@@ -197,6 +120,63 @@
          duration: 5
        })
      }
    })
  }
  initMenutree = () => {
    const { menulist } = this.state
    let navbars = []
    let map = new Map()
    fromJS(menulist).toJS().forEach(menu => {
      if (!menu.nodes) return
      if (menu.type === 'navbar') {
        navbars.push(menu.nodes)
      } else {
        map.set(menu.MenuID, menu.nodes)
      }
    })
    let data = []
    if (navbars.length === 0) {
      data = [...map.values()]
    } else {
      let reset = (m) => {
        return m.map(n => {
          if (n.children && n.children.length > 0) {
            n.children = reset(n.children)
          } else if (map.has(n.key)) {
            let p = map.get(n.key)
            if (p.children && p.children.length > 0) {
              n.children = reset(p.children)
            }
            map.delete(n.key)
          }
          return n
        })
      }
      data = reset(navbars)
      data = [...data, ...map.values()]
    }
    let expandedKeys = []
    if (data[0]) {
      expandedKeys.push(data[0].key)
      if (data[0].children && data[0].children[0]) {
        expandedKeys.push(data[0].children[0].key)
        if (data[0].children[0].children && data[0].children[0].children[0]) {
          expandedKeys.push(data[0].children[0].children[0].key)
        }
      }
    }
    this.setState({trees: [], expandedKeys: []}, () => {
      this.setState({trees: data, expandedKeys})
    })
  }
@@ -318,13 +298,6 @@
    })
  }
  onDragEnter = info => {
    // expandedKeys 需要受控时设置
    // this.setState({
    //   expandedKeys: info.expandedKeys,
    // });
  }
  onDrop = info => {
    const dropKey = info.node.props.eventKey;
    const dragKey = info.dragNode.props.eventKey;
@@ -396,10 +369,11 @@
  }
  initTree = () => {
    const _this = this
    confirm({
      content: '初始化会根据菜单重置权限树,确定执行吗?',
      onOk() {
        _this.initMenutree()
      },
      onCancel() {}
    })
@@ -426,7 +400,12 @@
  }
  render () {
    const { app, loading, columns, menulist, trees } = this.state
    const { app, loading, columns, menulist, trees, searchkey } = this.state
    let _menulist = menulist
    if (searchkey) {
      _menulist = _menulist.filter(item => item.MenuName.toLowerCase().indexOf(searchkey.toLowerCase()) > -1)
    }
    return (
      <div className="mk-role-manage">
@@ -442,11 +421,12 @@
              <div className="app-table">
                <div className="app-action">
                  <Button className="mk-green" onClick={() => this.setState({ visible: true, targetKeys: [] })}>解冻菜单</Button>
                  <Search placeholder="综合搜索" onSearch={value => this.setState({ searchkey: value })} enterButton />
                </div>
                <Table
                  rowKey="MenuID"
                  columns={columns}
                  dataSource={menulist}
                  dataSource={_menulist}
                  pagination={false}
                />
              </div>
@@ -457,17 +437,18 @@
                <Button className="mk-purple" onClick={this.syncTree}>同步</Button>
                <Button className="mk-green save" onClick={this.saveTree}>保存</Button>
              </div>
              <Tree
              {trees.length ? <Tree
                className="draggable-tree"
                defaultExpandedKeys={this.state.expandedKeys}
                // showLine
                draggable
                blockNode
                onDragEnter={this.onDragEnter}
                onDrop={this.onDrop}
              >
                {this.renderNode(trees)}
              </Tree>
              </Tree> : <div className="empty">
                <Empty />
              </div>}
            </div>
          </div>
          <Modal
src/views/rolemanage/index.scss
@@ -53,6 +53,12 @@
          text-overflow: ellipsis;
        }
      }
      .empty {
        border: 1px solid #e8e8e8;
        padding: 100px 10px 30px;
        min-height: 400px;
        border-radius: 4px;
      }
    }
  }
  .ant-table-wrapper {
@@ -72,6 +78,10 @@
      margin-bottom: 10px;
      margin-right: 15px;
    }
    .ant-input-search {
      width: 250px;
      float: right;
    }
    .save {
      float: right;
      margin-right: 0px;