king
2023-10-18 81d0d7721bb14a34b1eef99fd9506c3eda4bda99
2023-10-18
22个文件已修改
2个文件已添加
2个文件已删除
1973 ■■■■■ 已修改文件
src/assets/css/main.scss 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/simple-form/index.jsx 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/index.jsx 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/tab-form/index.jsx 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.jsx 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/index.jsx 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/index.scss 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/modalconfig/index.jsx 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/printbutton/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkPopSelect/index.jsx 372 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkPopSelect/index.scss 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/card.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.jsx 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/settingform/index.jsx 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/settingform/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searchform/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/editTable/index.jsx 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/editTable/index.scss 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 324 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/fieldtable/index.jsx 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/fieldtable/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 197 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss
@@ -321,6 +321,25 @@
  .ant-modal {
    max-width: 95vw;
    top: 70px;
    .ant-modal-title {
      height: 22px;
      .mk-modal-icon-def {
        margin-right: 10px;
        background: transparent!important;
      }
      .mk-modal-icon-circle {
        display: inline-block;
        border-radius: 30px;
        margin-right: 10px;
        margin-top: -5px;
        color: #ffffff!important;
        width: 30px;
        height: 30px;
        text-align: center;
        line-height: 30px;
      }
    }
  }
  .ant-modal-body {
    max-height: calc(100vh - 205px);
src/menu/components/form/simple-form/index.jsx
@@ -1,10 +1,9 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Modal, Button, Switch, notification, message } from 'antd'
import { Popover, Modal, Button, Switch, message } from 'antd'
import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import Api from '@/api'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { getModalForm } from '@/templates/zshare/formconfig'
@@ -399,68 +398,33 @@
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = fromJS(this.state.card).toJS()
      let fieldrepet = false // 字段重复
    let _config = fromJS(this.state.card).toJS()
    this.formRef.handleConfirm(_config.subcards[0].fields).then(res => {
      _config.subcards[0].fields = _config.subcards[0].fields.map(item => {
        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
          fieldrepet = true
        }
        delete item.focus
        if (item.uuid === res.uuid) {
          if (item.style) {
            res.style = item.style
          }
          return res
        if (item.uuid === res.values.uuid) {
          return res.values
        } else {
          return item
        }
      })
      if (fieldrepet) {
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 10
        })
        return
      }
      window.GLOB.formId = res.uuid
      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
      if (res.loading) {
        this.setState({
          sqlVerifing: true
        })
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
        let rduri = ''
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          rduri = window.GLOB.mainSystemApi
        }
        Api.sDebug(sql, rduri).then(result => {
          if (result.status || result.ErrCode === '-2') {
            this.setState({
              sqlVerifing: false,
              editform: null,
              visible: false
            })
            this.updateComponent(_config)
          } else {
            this.setState({sqlVerifing: false})
            Modal.error({
              title: result.message
            })
          }
        res.promise().then(() => {
          this.setState({
            sqlVerifing: false,
            editform: null,
            visible: false
          })
          this.updateComponent(_config)
        }, () => {
          this.setState({sqlVerifing: false})
        })
      } else {
        this.setState({
src/menu/components/form/step-form/index.jsx
@@ -4,7 +4,6 @@
import { Popover, Modal, Button, Switch, notification, message } from 'antd'
import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import Api from '@/api'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { getModalForm } from '@/templates/zshare/formconfig'
@@ -501,68 +500,33 @@
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = fromJS(this.state.group).toJS()
      let fieldrepet = false // 字段重复
    let _config = fromJS(this.state.group).toJS()
    this.formRef.handleConfirm(_config.fields).then(res => {
      _config.fields = _config.fields.map(item => {
        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
          fieldrepet = true
        }
        delete item.focus
        if (item.uuid === res.uuid) {
          if (item.style) {
            res.style = item.style
          }
          return res
        if (item.uuid === res.values.uuid) {
          return res.values
        } else {
          return item
        }
      })
      if (fieldrepet) {
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 10
        })
        return
      }
      window.GLOB.formId = res.uuid
      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
      if (res.loading) {
        this.setState({
          sqlVerifing: true
        })
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
        let rduri = ''
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          rduri = window.GLOB.mainSystemApi
        }
        Api.sDebug(sql, rduri).then(result => {
          if (result.status || result.ErrCode === '-2') {
            this.setState({
              sqlVerifing: false,
              editform: null,
              visible: false
            })
            this.updateGroup(_config)
          } else {
            this.setState({sqlVerifing: false})
            Modal.error({
              title: result.message
            })
          }
        res.promise().then(() => {
          this.setState({
            sqlVerifing: false,
            editform: null,
            visible: false
          })
          this.updateGroup(_config)
        }, () => {
          this.setState({sqlVerifing: false})
        })
      } else {
        this.setState({
src/menu/components/form/tab-form/index.jsx
@@ -4,7 +4,6 @@
import { Popover, Modal, Button, Switch, notification, message } from 'antd'
import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import Api from '@/api'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { getModalForm } from '@/templates/zshare/formconfig'
@@ -506,68 +505,33 @@
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = fromJS(this.state.group).toJS()
      let fieldrepet = false // 字段重复
    let _config = fromJS(this.state.group).toJS()
    this.formRef.handleConfirm(_config.fields).then(res => {
      _config.fields = _config.fields.map(item => {
        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
          fieldrepet = true
        }
        delete item.focus
        if (item.uuid === res.uuid) {
          if (item.style) {
            res.style = item.style
          }
          return res
        if (item.uuid === res.values.uuid) {
          return res.values
        } else {
          return item
        }
      })
      if (fieldrepet) {
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 10
        })
        return
      }
      window.GLOB.formId = res.uuid
      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
      if (res.loading) {
        this.setState({
          sqlVerifing: true
        })
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
        let rduri = ''
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          rduri = window.GLOB.mainSystemApi
        }
        Api.sDebug(sql, rduri).then(result => {
          if (result.status || result.ErrCode === '-2') {
            this.setState({
              sqlVerifing: false,
              editform: null,
              visible: false
            })
            this.updateGroup(_config)
          } else {
            this.setState({sqlVerifing: false})
            Modal.error({
              title: result.message
            })
          }
        res.promise().then(() => {
          this.setState({
            sqlVerifing: false,
            editform: null,
            visible: false
          })
          this.updateGroup(_config)
        }, () => {
          this.setState({sqlVerifing: false})
        })
      } else {
        this.setState({
src/menu/datasource/verifycard/index.jsx
@@ -678,6 +678,55 @@
            resolve()
          })
        } else {
          if (/列名\s*'[a-zA-Z0-9_-]+'\s*无效/.test(result.message)) {
            let tail = ''
            let type = ''
            searches.forEach(item => {
              if (item.forbid) return
              item.key.split(',').forEach(field => {
                if (new RegExp(`'${field}'`).test(result.message)) {
                  tail = field
                  type = '搜索条件'
                }
              })
            })
            if (!tail) {
              let keys = setting.order.replace(/\s+(asc|desc)/ig, '').replace(/\s+/g, '')
              keys.split(',').forEach(field => {
                if (new RegExp(`'${field}'`).test(result.message)) {
                  tail = field
                  type = '排序'
                }
              })
            }
            if (!tail) {
              columns.forEach(item => {
                if (new RegExp(`'${item.field}'`).test(result.message)) {
                  tail = item.field
                  if (config.subtype === 'basetable') {
                    type = '显示列'
                  } else {
                    type = '字段集'
                  }
                }
              })
              if (!tail && config.subtype === 'dualdatacard') {
                subColumns.forEach(item => {
                  if (new RegExp(`'${item.field}'`).test(result.message)) {
                    tail = item.field
                    type = '子表字段集'
                  }
                })
              }
            }
            if (tail) {
              result.message = result.message.replace(/ROLLBACK TRANSACTION 请求没有对应的 BEGIN TRANSACTION。/, '')
              result.message = <>{result.message}<span style={{color: 'red'}}>注:{type}中存在字段{tail}</span></>
            }
          }
          if (type === 'submit') {
            Modal.confirm({
              title: result.message,
@@ -1078,8 +1127,8 @@
            <span>
              自定义脚本
              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
              {config.type !== 'interface' && activeKey === 'setting' ? <CopyOutlined title="复制数据源" className="mk-copy-datasource" onClick={(e) => {e.stopPropagation();this.copyDatasource()}}/> : null}
              {config.type !== 'interface' && activeKey === 'setting' ? <SnippetsOutlined title="导入数据源" className="mk-paste-datasource" onClick={(e) => {e.stopPropagation();this.setState({pvisible: true})}}/> : null}
              {activeKey === 'setting' ? <CopyOutlined title="复制数据源" className="mk-copy-datasource" onClick={(e) => {e.stopPropagation();this.copyDatasource()}}/> : null}
              {activeKey === 'setting' ? <SnippetsOutlined title="导入数据源" className="mk-paste-datasource" onClick={(e) => {e.stopPropagation();this.setState({pvisible: true})}}/> : null}
              {activeKey === 'columns' ? <CopyOutlined title="以逗号拼接形式复制字段" className="mk-copy-fields" onClick={(e) => {e.stopPropagation();this.copyColumns()}}/> : null}
              {activeKey === 'subcolumns' ? <CopyOutlined title="以逗号拼接形式复制字段" className="mk-copy-fields" onClick={(e) => {e.stopPropagation();this.copySubColumns()}}/> : null}
              {activeKey === 'subcolumns' || activeKey === 'columns' ? <span onClick={(e) => {e.stopPropagation()}}><Search className="mk-search-fields" defaultValue={searchKey} allowClear onSearch={(val, e) => {e.stopPropagation();this.setState({searchKey: val})}} /></span> : null}
src/menu/modalconfig/index.jsx
@@ -3,12 +3,10 @@
import { is, fromJS } from 'immutable'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { Button, Card, Modal, Collapse, notification, Switch, message } from 'antd'
import { Button, Card, Modal, Collapse, Switch, message } from 'antd'
import { SettingOutlined, CopyOutlined } from '@ant-design/icons'
import Api from '@/api'
import { getModalForm } from '@/templates/zshare/formconfig'
import SourceElement from '@/templates/modalconfig/dragelement/source'
import SettingForm from '@/templates/modalconfig/settingform'
import asyncComponent from '@/utils/asyncComponent'
@@ -18,6 +16,8 @@
const { Panel } = Collapse
const { confirm } = Modal
const MkIcon = asyncComponent(() => import('@/components/mk-icon'))
const TableComponent = asyncComponent(() => import('./tablecomponent'))
const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform'))
const PasteForms = asyncComponent(() => import('@/menu/components/share/pasteforms'))
@@ -225,68 +225,33 @@
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = fromJS(this.state.config).toJS()
      let fieldrepet = false // 字段重复
    let _config = fromJS(this.state.config).toJS()
    this.formRef.handleConfirm(_config.fields).then(res => {
      _config.fields = _config.fields.map(item => {
        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
          fieldrepet = true
        }
        delete item.focus
        if (item.uuid === res.uuid) {
          if (item.style) {
            res.style = item.style
          }
          return res
        if (item.uuid === res.values.uuid) {
          return res.values
        } else {
          return item
        }
      })
      if (fieldrepet) {
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 10
        })
        return
      }
      window.GLOB.formId = res.uuid
      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
      if (res.loading) {
        this.setState({
          sqlVerifing: true
        })
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
        let rduri = ''
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          rduri = window.GLOB.mainSystemApi
        }
        Api.sDebug(sql, rduri).then(result => {
          if (result.status || result.ErrCode === '-2') {
            this.setState({
              sqlVerifing: false,
              config: _config,
              card: null,
              visible: false
            })
          } else {
            this.setState({sqlVerifing: false})
            Modal.error({
              title: result.message
            })
          }
        res.promise().then(() => {
          this.setState({
            sqlVerifing: false,
            config: _config,
            card: null,
            visible: false
          })
        }, () => {
          this.setState({sqlVerifing: false})
        })
      } else {
        this.setState({
@@ -538,7 +503,7 @@
              <SettingOutlined onClick={this.changeSetting} />
              <div className="ant-modal-content" style={{width: config.setting.width > 100 ? config.setting.width : config.setting.width + '%'}}>
                <div className="ant-modal-header">
                  <div className="ant-modal-title">{btn.label}</div>
                  <div className="ant-modal-title">{config.setting.icon ? <span className={'mk-modal-icon-' + config.setting.iconType} style={{background: config.setting.iconColor || 'unset', color: config.setting.iconColor || 'inherit'}}><MkIcon type={config.setting.icon}/></span> : null}{btn.label}</div>
                  <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1列</Button>
                  <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2列</Button>
                  <Button className="mk-cols-change" onClick={() => this.changecols(3)}>3列</Button>
src/menu/modalconfig/index.scss
@@ -120,6 +120,21 @@
          padding-right: 80px;
          .ant-modal-title {
            display: inline-block;
            height: 22px;
            .mk-modal-icon-def {
              margin-right: 10px;
              background: transparent!important;
            }
            .mk-modal-icon-circle {
              display: inline-block;
              border-radius: 30px;
              margin-right: 10px;
              color: #ffffff!important;
              width: 30px;
              height: 30px;
              text-align: center;
              line-height: 30px;
            }
          }
          .anticon-copy {
            position: absolute;
src/menu/sysinterface/index.jsx
@@ -176,7 +176,7 @@
    let trimreg = /(from|update|insert\s+into)\s+(@db@)?/ig
    if (record.setting.interType === 'system') {
      if (record.setting.execute !== 'false') {
      if (record.setting.execute !== 'false' && record.setting.dataresource) {
        let tbs = record.setting.dataresource.match(cutreg)
        tbs && cuts.push(...tbs)
      }
@@ -185,7 +185,7 @@
        let tbs = script.sql.match(cutreg)
        tbs && cuts.push(...tbs)
      })
    } else {
    } else if (record.setting.tableName) {
      let tb = record.setting.tableName.replace(/@db@|\s+/ig, '')
      if (/[a-z_]+/ig.test(tb)) {
        tables.push(tb)
@@ -211,6 +211,8 @@
    record.name = record.setting.name
    record.$tables = this.getTables(record)
    delete record.subColumns
    let interfaces = this.state.interfaces.map(item => {
      if (item.uuid !== record.uuid) {
        return item
src/mob/modalconfig/index.jsx
@@ -3,12 +3,10 @@
import { is, fromJS } from 'immutable'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { Button, Modal, Collapse, notification, Switch, message } from 'antd'
import { Button, Modal, Collapse, Switch, message } from 'antd'
import { LeftOutlined } from '@ant-design/icons'
import Api from '@/api'
import { getModalForm } from '@/templates/zshare/formconfig'
import SourceElement from '@/templates/modalconfig/dragelement/source'
import SettingForm from '@/templates/modalconfig/settingform'
import asyncComponent from '@/utils/asyncComponent'
@@ -222,68 +220,33 @@
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = fromJS(this.state.config).toJS()
      let fieldrepet = false // 字段重复
    let _config = fromJS(this.state.config).toJS()
    this.formRef.handleConfirm(_config.fields).then(res => {
      _config.fields = _config.fields.map(item => {
        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
          fieldrepet = true
        }
        delete item.focus
        if (item.uuid === res.uuid) {
          if (item.style) {
            res.style = item.style
          }
          return res
        if (item.uuid === res.values.uuid) {
          return res.values
        } else {
          return item
        }
      })
      if (fieldrepet) {
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 10
        })
        return
      }
      window.GLOB.formId = res.uuid
      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
      if (res.loading) {
        this.setState({
          sqlVerifing: true
        })
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
        let rduri = ''
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          rduri = window.GLOB.mainSystemApi
        }
        Api.sDebug(sql, rduri).then(result => {
          if (result.status || result.ErrCode === '-2') {
            this.setState({
              sqlVerifing: false,
              config: _config,
              card: null,
              visible: false
            })
          } else {
            this.setState({sqlVerifing: false})
            Modal.error({
              title: result.message
            })
          }
        res.promise().then(() => {
          this.setState({
            sqlVerifing: false,
            config: _config,
            card: null,
            visible: false
          })
        }, () => {
          this.setState({sqlVerifing: false})
        })
      } else {
        this.setState({
src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
@@ -171,6 +171,13 @@
      }
    }
  }
  .ant-transfer-operation {
    margin: 0 15px;
    .ant-btn:first-child {
      margin-bottom: 10px;
    }
  }
}
.member-modal {
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -3008,6 +3008,13 @@
        container = () => document.getElementById(btn.ContainerId)
      }
      if (btnconfig.setting.icon) {
        title = <>
          <span className={'mk-modal-icon-' + btnconfig.setting.iconType} style={{background: btnconfig.setting.iconColor || 'unset', color: btnconfig.setting.iconColor || 'inherit'}}><MkIcon type={btnconfig.setting.icon}/></span>
          {title}
        </>
      }
      return (
        <Modal
          title={title}
src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -2238,6 +2238,13 @@
      clickouter = true
    }
    if (btnconfig.setting.icon) {
      title = <>
        <span className={'mk-modal-icon-' + btnconfig.setting.iconType} style={{background: btnconfig.setting.iconColor || 'unset', color: btnconfig.setting.iconColor || 'inherit'}}><MkIcon type={btnconfig.setting.icon}/></span>
        {title}
      </>
    }
    return (
      <Modal
        title={title}
src/tabviews/zshare/mutilform/index.jsx
@@ -28,6 +28,7 @@
const MkFormula = asyncComponent(() => import('./mkFormula'))
const MkCascader = asyncComponent(() => import('./mkCascader'))
const MkVercode = asyncComponent(() => import('./mkVercode'))
const MKPopSelect = asyncComponent(() => import('./mkPopSelect'))
const MKEditor = asyncComponent(() => import('@/components/editor'))
class MutilFormComponent extends Component {
@@ -125,7 +126,7 @@
        item.precision = 'second'
      }
      if (!item.field || !['text', 'number', 'switch', 'check', 'rate', 'select', 'link', 'cascader', 'linkMain', 'funcvar', 'date', 'datemonth', 'radio', 'checkbox', 'checkcard', 'fileupload', 'textarea', 'multiselect', 'brafteditor', 'color', 'vercode'].includes(item.type)) return false
      if (!item.field || !['text', 'number', 'switch', 'check', 'rate', 'select', 'popSelect', 'link', 'cascader', 'linkMain', 'funcvar', 'date', 'datemonth', 'radio', 'checkbox', 'checkcard', 'fileupload', 'textarea', 'multiselect', 'brafteditor', 'color', 'vercode'].includes(item.type)) return false
      if (/^\s+$/.test(item.label)) {
        item.style = item.style || {}
@@ -292,26 +293,31 @@
        }
      }
      item.rules = []
      if (item.type === 'text') {
        item.initval = item.initval + ''
        let _rules = [{
          pattern: /^[^']*$/ig,
          message: '不可使用英文状态的单引号!'
        }, {
        if (item.required === 'true') {
          item.rules.push({
            required: true,
            message: item.label + '不可为空!'
          })
        }
        item.rules.push({
          validator: (rule, value, callback) => {
            if (/--/ig.test(value)) {
            if (/'/.test(value)) {
              callback('不可使用英文状态的单引号!')
            } else if (/--/.test(value)) {
              callback('不可使用 -- !')
            } else {
              callback()
            }
          }
        }, {
          required: item.required === 'true',
          message: item.label + '不可为空!'
        }]
        })
        if (!item.lenControl || item.lenControl === 'limit') {
          _rules.push({
          item.rules.push({
            max: item.fieldlength,
            message: formRule.input.formMessage.replace('@max', item.fieldlength)
          })
@@ -323,7 +329,7 @@
            if (item.regularExtra) {
              reg = new RegExp('^[0-9.-' + item.regularExtra.replace(/\.|-/g, '') + ']*$')
            }
            _rules.push({
            item.rules.push({
              pattern: reg,
              message: item.regularText || formRule.input.numbermsg
            })
@@ -332,7 +338,7 @@
            if (item.regularExtra) {
              reg = new RegExp('^[a-zA-Z' + item.regularExtra + ']*$')
            }
            _rules.push({
            item.rules.push({
              pattern: reg,
              message: item.regularText || formRule.input.lettermsg
            })
@@ -341,7 +347,7 @@
            if (item.regularExtra) {
              reg = new RegExp('^[a-zA-Z0-9' + item.regularExtra + ']*$')
            }
            _rules.push({
            item.rules.push({
              pattern: reg,
              message: item.regularText || '请输入数字或字母'
            })
@@ -350,80 +356,113 @@
            if (item.regularExtra) {
              reg = new RegExp('^[a-zA-Z0-9@_.' + item.regularExtra.replace(/\.|_|@/g, '') + ']*$')
            }
            _rules.push({
            item.rules.push({
              pattern: reg,
              message: item.regularText || '请输入数字、字母以及@_.'
            })
          } else if (item.regular === 'phone') {
            _rules.push({
            item.rules.push({
              pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
              message: item.regularText || '请正确输入手机号'
            })
          } else if (item.regular === 'email') {
            _rules.push({
            item.rules.push({
              pattern: /^([a-zA-Z0-9._-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/,
              message: item.regularText || '请正确输入邮箱地址'
            })
          }
        }
        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)
          },
          {
            pattern: /^[^']*$/ig,
            message: '不可使用英文状态的单引号!'
          }, {
        if (typeof(item.min) === 'number' || typeof(item.max) === 'number') {
          item.rules.push({
            validator: (rule, value, callback) => {
              if (/--/ig.test(value)) {
                callback('不可使用 -- !')
              if (isNaN(value)) {
                callback()
              } else if (typeof(item.min) === 'number' && value < item.min) {
                if (item.min < 1e-6) {
                  if (item.min === 1e-6) {
                    callback(item.label + '最小值为 0.000001')
                  } else if (item.min === 1e-7) {
                    callback(item.label + '最小值为 0.0000001')
                  } else if (item.min === 1e-8) {
                    callback(item.label + '最小值为 0.00000001')
                  } else if (item.min === 1e-9) {
                    callback(item.label + '最小值为 0.000000001')
                  } else if (item.min === 1e-10) {
                    callback(item.label + '最小值为 0.0000000001')
                  } else if (item.min === 1e-11) {
                    callback(item.label + '最小值为 0.00000000001')
                  } else {
                    callback(item.label + '最小值为 ' + item.min)
                  }
                } else {
                  callback(item.label + '最小值为 ' + item.min)
                }
              } else if (typeof(item.max) === 'number' && value > item.max) {
                callback(item.label + '最大值为 ' + item.max)
              } else {
                callback()
              }
            }
          })
        }
      } else if (item.type === 'textarea') {
        if (item.required === 'true') {
          item.rules.push({
            required: true,
            message: item.label + '不可为空!'
          })
        }
        item.rules.push({
          validator: (rule, value, callback) => {
            if (/'/.test(value)) {
              callback('不可使用英文状态的单引号!')
            } else if (/--/.test(value)) {
              callback('不可使用 -- !')
            } else {
              callback()
            }
          }
        ]
        item.rules = _rules
        }, {
          max: item.fieldlength,
          message: formRule.input.formMessage.replace('@max', item.fieldlength)
        })
      } else if (item.type === 'brafteditor') {
        item.rules = [
          {
            required: item.required === 'true',
        if (item.required === 'true') {
          item.rules.push({
            required: true,
            message: item.label + '不可为空!'
          },
          {
            max: item.fieldlength,
            message: formRule.input.formMessage.replace('@max', item.fieldlength)
          }
        ]
          })
        }
        item.rules.push({
          max: item.fieldlength,
          message: formRule.input.formMessage.replace('@max', item.fieldlength)
        })
      } else if (item.type === 'linkMain' || item.type === 'vercode') {
        item.rules = [
          {
            required: item.required === 'true',
        if (item.required === 'true') {
          item.rules.push({
            required: true,
            message: item.label + '不可为空!'
          }
        ]
          })
        }
      } else {
        item.rules = [
          {
            required: item.required === 'true',
        if (item.required === 'true') {
          item.rules.push({
            required: true,
            message: '请选择' + item.label + '!'
          }
        ]
          })
        }
      }
      if (item.rules.length === 0) {
        item.rules = null
      }
      fieldMap.set(item.field, item)
@@ -530,6 +569,18 @@
            reFieldsVal[n.field] = val || ''
          })
        } else if (item.type === 'fileupload') {
          item.options = []
          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
              })
            }
          })
        } else if (item.type === 'popSelect') {
          item.options = []
          item.subFields = []
          item.linkSubField.forEach(m => {
@@ -1002,22 +1053,6 @@
    })
  }
  handleConfirmPassword = (rule, value, callback, item) => {
    let val = parseFloat(value)
    if (!isNaN(val)) {
      if (typeof(item.min) === 'number' && val < item.min) {
        callback(item.label + '最小值为 ' + item.min)
      } else if (typeof(item.max) === 'number' && val > item.max) {
        callback(item.label + '最大值为 ' + item.max)
      } else {
        callback()
      }
    } else {
      callback()
    }
  }
  recordChange = (values, item) => {
    this.record = {...this.record, ...values}
@@ -1124,6 +1159,8 @@
          content = (<MKNumberInput config={item} onChange={(val, defer) => !defer && 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 === 'popSelect') {
          content = (<MKPopSelect config={item} BID={this.props.BID} ID={this.state.ID} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)} onSubmit={this.props.inputSubmit} />)
        } else if (item.type === 'cascader') {
          content = (<MkCascader config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>)
        } else if (item.type === 'color') {
src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
New file
@@ -0,0 +1,372 @@
import React, {Component} from 'react'
import { is, fromJS } from 'immutable'
import { Select } from 'antd'
import { notification, Modal, Table, Input } from 'antd'
import moment from 'moment'
import { TableOutlined } from '@ant-design/icons'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const { Search } = Input
class MKPopSelect extends Component {
  constructor(props) {
    super(props)
    let config = fromJS(props.config).toJS()
    let value = config.initval
    let arrfield = config.columns.map(f => f.field)
    if (config.subFields && config.subFields.length > 0) {
      config.subFields.forEach(n => {
        if (!arrfield.includes(n.field)) {
          arrfield.push(n.field)
        }
      })
    }
    if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
      config.dataSource = config.dataSource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
    } else {
      config.dataSource = config.dataSource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
    }
    config.dataSource = config.dataSource.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
    config.dataSource = config.dataSource.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
    config.dataSource = config.dataSource.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
    config.dataSource = config.dataSource.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
    if (/\s/.test(config.dataSource)) { // 拼接别名
      config.dataSource = '(' + config.dataSource + ') tb'
    }
    let columns = []
    let labels = {}
    config.columns.forEach(col => {
      labels[col.field] = col.label
      if (col.Hide === 'true') return
      columns.push({
        dataIndex: col.field,
        title: col.label,
        sorter: col.IsSort === 'true',
        width: 120
      })
    })
    let placeholder = ''
    if (!config.searchKey) {
      config.onload = 'true'
    } else {
      placeholder = []
      config.searchKey.split(',').forEach(key => {
        if (!labels[key]) {
          placeholder = ''
        } else if (placeholder) {
          placeholder.push(labels[key])
        }
      })
      placeholder = placeholder ? placeholder.join('、') : ''
    }
    this.state = {
      config: config,
      options: [],
      columns,
      value,
      placeholder,
      arr_field: arrfield.join(','),
      searchKey: '',
      pageIndex: 1,
      pageSize: 10,
      orderBy: '',
      visible: false,
      loading: false
    }
    this.timer = null
  }
  componentDidMount () {
    const { config } = this.state
    if (config.onload === 'true') {
      this.loadData()
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  loadData () {
    const { BID, ID } = this.props
    const { config, pageIndex, pageSize, arr_field, searchKey, orderBy } = this.state
    this.setState({
      loading: true
    })
    let param = {
      func: 'sPC_Get_TableData',
      obj_name: 'data',
      exec_type: 'y',
      arr_field: arr_field,
      default_sql: 'true',
      custom_script: '',
      menuname: config.label
    }
    let sql = ''
    let DateCount = ''
    let _search = ''
    let _orderBy = orderBy || config.order || ''
    let _datasource = config.dataSource
    if (config.searchKey && searchKey) {
      let fields = config.searchKey.split(',').map(field => field + ` like '%${searchKey}%'`)
      _search = 'where ' + fields.join(' OR ')
    }
    _datasource = _datasource.replace(/@BID@/ig, `'${BID || ''}'`)
    _datasource = _datasource.replace(/@ID@/ig, `'${ID || ''}'`)
    if (config.laypage === 'true') {
      sql = `/*system_query*/select top ${pageSize} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
      DateCount = `/*system_query*/select count(1) as total from ${_datasource} ${_search}`
    } else if (_orderBy) {
      sql = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable order by tmptable.rows `
    } else {
      sql = `/*system_query*/select ${arr_field} from ${_datasource} ${_search}  `
    }
    let departmentcode = sessionStorage.getItem('departmentcode') || ''
    let organization = sessionStorage.getItem('organization') || ''
    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
    sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
      Select @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}'
      ${sql}`
    // 测试系统打印查询语句
    if (window.GLOB.debugger === true) {
      console.info(`/*${config.label} 数据源*/\n` + sql.replace(/\n\s{6}/ig, '\n'))
      DateCount && console.info(`/*${config.label} 总数查询*/\n` + DateCount.replace(/\n\s{6}/ig, '\n'))
    }
    param.LText = Utils.formatOptions(sql)
    param.DateCount = Utils.formatOptions(DateCount)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt('', param.timestamp)
    param.username = sessionStorage.getItem('User_Name') || ''
    param.fullname = sessionStorage.getItem('Full_Name') || ''
    Api.genericInterface(param).then(result => {
      if (result.status) {
        let options = result.data.map((item, index) => {
          item.key = index
          item.$$uuid = item[config.primaryKey] || ''
          item.$label = item[config.showField]
          if (config.controlField && item[config.controlField] === 'true') {
            item.$disabled = true
          }
          return item
        })
        this.setState({
          options: options,
          total: result.total || 0,
          loading: false
        })
        if (result.message) {
          if (result.ErrCode === 'Y') {
            Modal.success({
              title: result.message
            })
          } else if (result.ErrCode === 'S') {
            notification.success({
              top: 92,
              message: result.message,
              duration: 2
            })
          }
        }
      } else {
        this.setState({
          loading: false
        })
        if (!result.message) return
        if (result.ErrCode === 'N') {
          Modal.error({
            title: result.message,
          })
        } else if (result.ErrCode !== '-2') {
          notification.error({
            top: 92,
            message: result.message,
            duration: 10
          })
        }
      }
    })
  }
  searchOption = (val) => {
    this.setState({searchKey: val})
    if (this.timer) {
      clearTimeout(this.timer)
    }
    this.timer = setTimeout(() => {
      this.loadData()
    }, 500)
  }
  selectChange = (val, record) => {
    const { config } = this.state
    let other = {}
    if (config.subFields) {
      let option = record || null
      if (!option) {
        option = this.state.options.filter(m => m.$$uuid === 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)
      })
    }
    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.subFields) {
          setTimeout(() => {
            this.props.onSubmit()
          }, 1000)
        } else {
          this.props.onSubmit()
        }
      }
    })
  }
  trigger = (e) => {
    e.stopPropagation()
    this.setState({visible: true})
  }
  changeRow = (record) => {
    if (record.$disabled) return
    this.selectChange(record.$$uuid, record)
    this.setState({visible: false})
  }
  changeTable = (pagination, filters, sorter) => {
    let orderBy = ''
    if (sorter.field && sorter.order) {
      if (sorter.order === 'ascend') {
        orderBy = `${sorter.field} asc`
      } else {
        orderBy = `${sorter.field} desc`
      }
    }
    this.setState({
      pageIndex: pagination.current,
      pageSize: pagination.pageSize,
      orderBy: orderBy,
    }, () => {
      this.loadData()
    })
  }
  render() {
    const { value, config, options, visible, loading, total, pageIndex, pageSize, columns, placeholder } = this.state
    return <>
      <Select
        className="mk-pop-select"
        showSearch={!!config.searchKey}
        allowClear
        value={value}
        onSearch={(val) => val && this.searchOption(val)}
        filterOption={false}
        onChange={(val) => this.selectChange(val === undefined ? '' : val)}
        disabled={config.readonly}
        suffixIcon={<TableOutlined onClick={this.trigger}/>}
      >
        {options.map(option =>
          <Select.Option disabled={option.$disabled} key={option.key} value={option.$$uuid}>{option.$label}</Select.Option>
        )}
      </Select>
      <Modal
        wrapClassName='mk-pop-select-modal'
        title={config.label}
        visible={visible}
        closable={true}
        centered={true}
        maskClosable={false}
        cancelText="关闭"
        width={config.popWidth < 100 ? config.popWidth + 'vw' : config.popWidth}
        onCancel={() => this.setState({visible: false})}
        destroyOnClose
      >
        {config.searchKey ? <Search placeholder={placeholder} onSearch={this.searchOption} enterButton /> : null}
        <Table
          rowKey="$$uuid"
          bordered={true}
          rowSelection={null}
          columns={columns}
          dataSource={options}
          loading={loading}
          onRow={(record) => {
            return {
              className: value === record.$$uuid ? ' ant-table-row-selected ' : '',
              onClick: () => {this.changeRow(record)},
            }
          }}
          onChange={this.changeTable}
          pagination={config.laypage === 'true' ? {
            current: pageIndex,
            pageSize: pageSize,
            showSizeChanger: true,
            total: total || 0,
            showTotal: (total, range) => `${range[0]}-${range[1]} 共 ${total} 条`
          } : false}
        />
      </Modal>
    </>
  }
}
export default MKPopSelect
src/tabviews/zshare/mutilform/mkPopSelect/index.scss
New file
@@ -0,0 +1,64 @@
.mk-pop-select {
  .ant-select-selection__rendered {
    margin-right: 30px;
  }
  .ant-select-selection__clear {
    right: 35px;
  }
  .ant-select-arrow {
    transform: translate(8px, -9px);
    .ant-select-arrow-icon {
      padding: 7px;
      color: rgba(0, 0, 0, 0.25);
      transition: color 0.2s;
      font-size: 14px;
      svg {
        transition: none!important;
        transform: none!important;
      }
    }
    .ant-select-arrow-icon:hover {
      color: var(--mk-sys-color);
    }
  }
}
.mk-pop-select-modal {
  .ant-modal-body {
    min-height: 200px;
    max-height: calc(100vh - 210px);
    overflow-y: auto;
    .ant-input-search {
      max-width: 300px;
      margin-bottom: 20px;
    }
    table {
      tr:not(.ant-table-row-selected):hover > td {
        background-color: var(--mk-sys-color1);
      }
      tr.ant-table-row-selected td {
        background-color: var(--mk-sys-color3);
      }
    }
  }
  .ant-modal-body::-webkit-scrollbar {
    width: 7px;
  }
  .ant-modal-body::-webkit-scrollbar-thumb {
    border-radius: 5px;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
    background: rgba(0, 0, 0, 0.13);
  }
  .ant-modal-body::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
    border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(0, 0, 0, 0);
  }
  .ant-modal-footer {
    .ant-btn-primary {
      display: none;
    }
  }
}
src/templates/modalconfig/dragelement/card.jsx
@@ -1,7 +1,7 @@
import React from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { Select, DatePicker, Input, InputNumber, Button, Popover, Switch, Radio, Checkbox, Form, Rate } from 'antd'
import { QuestionCircleOutlined, UploadOutlined, EditOutlined, CopyOutlined, CloseOutlined, StarFilled, FontColorsOutlined } from '@ant-design/icons'
import { QuestionCircleOutlined, UploadOutlined, EditOutlined, CopyOutlined, CloseOutlined, StarFilled, SearchOutlined, FontColorsOutlined } from '@ant-design/icons'
import moment from 'moment'
import asyncComponent from '@/utils/asyncComponent'
@@ -80,6 +80,8 @@
    formItem = (<InputNumber value={card.initval} precision={card.decimal} />)
  } else if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link' || card.type === 'cascader') {
    formItem = (<Select value={selectval}></Select>)
  } else if (card.type === 'popSelect') {
    formItem = (<Select value={card.initval} suffixIcon={<SearchOutlined />}></Select>)
  } else if (card.type === 'color') {
    formItem = (<ColorSketch value={card.initval || 'transparent'}/>)
  } else if (card.type === 'date') {
src/templates/modalconfig/index.jsx
@@ -8,7 +8,6 @@
import Api from '@/api'
import { getModalForm } from '@/templates/zshare/formconfig'
import SourceElement from './dragelement/source'
import SettingForm from './settingform'
import MenuForm from './menuform'
@@ -348,73 +347,35 @@
  /**
   * @description 编辑后提交
   * 1、获取编辑后的表单信息
   * 2、去除可能存在的示例表单
   * 3、通过loading刷新
   */
  handleSubmit = () => {
    this.formRef.handleConfirm().then(res => {
      let _config = fromJS(this.state.config).toJS()
      let fieldrepet = false // 字段重复
    let _config = fromJS(this.state.config).toJS()
    this.formRef.handleConfirm(_config.fields).then(res => {
      _config.fields = _config.fields.map(item => {
        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
          fieldrepet = true
        }
        if (item.uuid === res.uuid) {
          if (item.style) {
            res.style = item.style
          }
          return res
        if (item.uuid === res.values.uuid) {
          return res.values
        } else {
          return item
        }
      })
      if (fieldrepet) {
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 10
        })
        return
      }
      _config.fields = _config.fields.filter(item => !item.origin)
      window.GLOB.formId = res.uuid
      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
      if (res.loading) {
        this.setState({
          sqlVerifing: true
        })
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
        let rduri = ''
        if (window.GLOB.mainSystemApi && res.database === 'sso') {
          rduri = window.GLOB.mainSystemApi
        }
        Api.sDebug(sql, rduri).then(result => {
          if (result.status || result.ErrCode === '-2') {
            this.setState({
              sqlVerifing: false,
              config: _config,
              card: null,
              visible: false
            })
          } else {
            this.setState({sqlVerifing: false})
            Modal.error({
              title: result.message
            })
          }
        res.promise().then(() => {
          this.setState({
            sqlVerifing: false,
            config: _config,
            card: null,
            visible: false
          })
        }, () => {
          this.setState({sqlVerifing: false})
        })
      } else {
        this.setState({
src/templates/modalconfig/settingform/index.jsx
@@ -5,7 +5,11 @@
// import { formRule } from '@/utils/option.js'
import StyleInput from '@/menu/stylecontroller/styleInput'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
class SettingForm extends Component {
  static propTpyes = {
@@ -18,6 +22,7 @@
    fields: null,
    display: this.props.config.setting.display || 'modal',
    placement: this.props.config.setting.placement || 'right',
    icon: this.props.config.setting.icon || '',
    appType: sessionStorage.getItem('appType'),
    viewType: sessionStorage.getItem('editMenuType') || '',
    dialogInput: false
@@ -80,7 +85,7 @@
  render() {
    const { config } = this.props
    const { fields, appType, display, placement } = this.state
    const { fields, appType, display, placement, icon } = this.state
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
@@ -197,6 +202,32 @@
              )}
            </Form.Item>
          </Col> : null}
          {appType !== 'mob' && display === 'modal' ? <Col span={12}>
            <Form.Item label="图标">
              {getFieldDecorator('icon', {
                initialValue: icon
              })(<MkEditIcon onChange={(value) => this.setState({icon: value})} allowClear={true}/>)}
            </Form.Item>
          </Col> : null}
          {appType !== 'mob' && display === 'modal' && icon ? <Col span={12}>
            <Form.Item label="图标样式">
              {getFieldDecorator('iconType', {
                initialValue: config.setting.iconType || 'def'
              })(
                <Radio.Group>
                  <Radio value="def">默认</Radio>
                  <Radio value="circle">圆形</Radio>
                </Radio.Group>
              )}
            </Form.Item>
          </Col> : null}
          {appType !== 'mob' && display === 'modal' && icon ? <Col span={12}>
            <Form.Item label="图标颜色">
              {getFieldDecorator('iconColor', {
                initialValue: config.setting.iconColor || ''
              })(<ColorSketch allowClear={true}/>)}
            </Form.Item>
          </Col> : null}
          {appType === 'mob' && display === 'drawer' ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="表单元素与左侧边界的距离。">
src/templates/modalconfig/settingform/index.scss
@@ -5,4 +5,8 @@
      width: 16.5%;
    }
  }
  .color-sketch-block {
    position: relative;
    top: 9px;
  }
}
src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -11,8 +11,8 @@
import './index.scss'
const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
const FieldsTable = asyncComponent(() => import('@/templates/zshare/modalform/fieldtable'))
const EditTable = asyncComponent(() => import('@/templates/zshare/modalform/modaleditable'))
const FieldsTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const groupOptions = [
  {
@@ -623,7 +623,7 @@
          { required: item.required, message: '请添加' + item.label + '!' }
        ]
        content = <FieldsTable onChange={this.changeField}/>
        content = <FieldsTable indexShow={false} actions={['edit', 'move', 'del', 'add']} columns={item.columns} data={this.record.fields || []} onChange={this.changeField}/>
      } else if (item.type === 'checkbox') {
        rules = [
          { required: item.required, message: '请选择' + item.label + '!' }
src/templates/zshare/editTable/index.jsx
@@ -3,7 +3,7 @@
import { is, fromJS } from 'immutable'
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
import { Table, Input, InputNumber, Popconfirm, Form, Select, Radio, Cascader, notification, message, Modal, Typography } from 'antd'
import { CopyOutlined, EditOutlined, DeleteOutlined, SwapOutlined } from '@ant-design/icons'
import { CopyOutlined, EditOutlined, DeleteOutlined, SwapOutlined, PlusOutlined } from '@ant-design/icons'
import Utils from '@/utils/utils.js'
import ColorSketch from '@/mob/colorsketch'
@@ -258,6 +258,7 @@
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.state.data), fromJS(nextProps.data))) {
      this.setState({data: nextProps.data, editingKey: ''})
    } else if (!is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
@@ -518,6 +519,26 @@
      return
    }
    let forbid = false
    columns.forEach(col => {
      if (!col.forbids || forbid) return
      let key = record[col.dataIndex].toLowerCase()
      if (col.forbids.includes(key)) {
        forbid = col.title + '不可使用' + record[col.dataIndex]
      }
    })
    if (forbid) {
      notification.warning({
        top: 92,
        message: forbid,
        duration: 5
      })
      return
    }
    let unique = true
    columns.forEach(col => {
      if (col.unique !== true || !unique) return
@@ -582,6 +603,26 @@
        row = {...newData[index], ...row}
      } else {
        row.uuid = uuid
      }
      let forbid = false
      columns.forEach(col => {
        if (!col.forbids || forbid) return
        let key = row[col.dataIndex].toLowerCase()
        if (col.forbids.includes(key)) {
          forbid = col.title + '不可使用' + row[col.dataIndex]
        }
      })
      if (forbid) {
        notification.warning({
          top: 92,
          message: forbid,
          duration: 5
        })
        return
      }
      let unique = true
@@ -652,6 +693,37 @@
    })
  }
  handleAdd = () => {
    const { columns } = this.props
    const { data } = this.state
    let _index = data.length + 1
    let item = {
      uuid: Utils.getuuid()
    }
    columns.forEach(col => {
      if (!col.dataIndex) return
      item[col.dataIndex] = col.initval || ''
      if (col.unique) {
        while (data.filter(cell => cell[col.dataIndex] === item[col.dataIndex]).length > 0) {
          _index++
          item[col.dataIndex] = col.initval + _index
        }
      }
    })
    let _data = [...data, item]
    this.setState({
      data: _data
    }, () => {
      this.props.onChange(_data)
    })
  }
  render() {
    const { actions, indexShow, searchKey } = this.props
    const { editLineId } = this.state
@@ -714,6 +786,7 @@
    return (
      <EditableContext.Provider value={this.props.form}>
        <div className="modal-edit-table">
          {actions.includes('add') ? <PlusOutlined className="add-row" onClick={this.handleAdd} /> : null}
          <DndProvider>
            <Table
              bordered
src/templates/zshare/editTable/index.scss
@@ -4,6 +4,7 @@
      position: absolute;
      font-size: 12px;
      margin-top: -4px;
      white-space: nowrap;
    }
    .color-sketch-block {
      width: 200px;
@@ -112,5 +113,17 @@
      color: #ff4d4f;
    }
  }
  .ant-typography {
    margin: 3px 0px;
  }
  .add-row {
    position: absolute;
    z-index: 1;
    right: 10px;
    top: -30px;
    padding: 5px;
    font-size: 18px;
    color: #26C281;
  }
}
src/templates/zshare/formconfig.jsx
@@ -1,3 +1,4 @@
import React from 'react'
import { formRule, btnClasses } from '@/utils/option.js'
/**
@@ -549,19 +550,80 @@
      }]
    },
    {
      type: 'fields',
      key: 'fields',
      label: '字段集',
      initVal: card.fields || [],
      required: true
    },
    {
      type: 'codemirror',
      key: 'dataSource',
      label: '数据源',
      initVal: card.dataSource || '',
      tooltip: '数据权限替换符 $@ -> /* 或 \'\'、 @$ -> */ 或 \'\'',
      required: true
    },
    {
      type: 'fields',
      key: 'fields',
      label: '字段集',
      initVal: card.fields || [],
      required: true,
      columns: [
        {
          title: '字段名',
          dataIndex: 'field',
          inputType: 'input',
          editable: true,
          unique: true,
          strict: true,
          forbids: ['value', 'parentid', 'pid'],
          initval: 'field',
          rules: [{
            pattern: /^[\u4E00-\u9FA50-9a-zA-Z_-]*$/ig,
            message: '请使用数字、字母、汉字以及_-'
          }],
          width: '20%'
        },
        {
          title: '字体颜色',
          dataIndex: 'color',
          inputType: 'color',
          editable: true,
          initval: 'rgba(0, 0, 0, 0.85)',
          width: '20%',
          render: (text, record) => {
            return <span style={{color: text}}>示例</span>
          }
        },
        {
          title: '字体大小',
          dataIndex: 'fontSize',
          inputType: 'number',
          min: 12,
          max: 50,
          editable: true,
          initval: 14,
          width: '20%',
        },
        {
          title: '对齐方式',
          dataIndex: 'align',
          inputType: 'select',
          editable: true,
          width: '20%',
          initval: 'left',
          options: [
            {value: 'left', text: '居左'},
            {value: 'center', text: '居中'},
            {value: 'right', text: '居右'},
            // {value: 'justify', text: 'justify'}
          ],
          render: (text, record) => {
            if (text === 'center') {
              return '居中'
            } else if (text === 'right') {
              return '居右'
            } else {
              return '居左'
            }
          }
        }
      ]
    },
    {
      type: 'options',
@@ -645,7 +707,7 @@
      required: false
    },
    {
      type: 'select',
      type: 'radio',
      key: 'orderType',
      label: '排序方式',
      initVal: card.orderType || 'asc',
@@ -2568,6 +2630,9 @@
    value: 'link',
    text: '联动菜单'
  }, {
    value: 'popSelect',
    text: '选择器'
  }, {
    value: 'switch',
    text: '开关'
  }, {
@@ -2905,12 +2970,210 @@
    //   }]
    // },
    {
      type: 'codemirror',
      key: 'dataSource',
      label: '数据源',
      initVal: card.dataSource || '',
      tooltip: '数据权限替换符 $@ -> /* 或 \'\'、 @$ -> */ 或 \'\'',
      placeholder: '系统变量:mk_departmentcode、mk_organization、mk_user_type。公共值:@ID@、@BID@。',
      required: true,
      readonly: false
    },
    {
      type: 'fields',
      key: 'fields',
      label: '字段集',
      initVal: card.fields || [],
      required: true,
      readonly: false
      readonly: false,
      columns: [
        {
          title: '字段名',
          dataIndex: 'field',
          inputType: 'input',
          editable: true,
          unique: true,
          strict: true,
          forbids: ['value', 'parentid', 'pid'],
          initval: 'field',
          rules: [{
            pattern: /^[\u4E00-\u9FA50-9a-zA-Z_-]*$/ig,
            message: '请使用数字、字母、汉字以及_-'
          }],
          width: '20%'
        },
        {
          title: '字体颜色',
          dataIndex: 'color',
          inputType: 'color',
          editable: true,
          initval: 'rgba(0, 0, 0, 0.85)',
          width: '20%',
          render: (text, record) => {
            return <span style={{color: text}}>示例</span>
          }
        },
        {
          title: '字体大小',
          dataIndex: 'fontSize',
          inputType: 'number',
          min: 12,
          max: 50,
          editable: true,
          initval: 14,
          width: '20%',
        },
        {
          title: '对齐方式',
          dataIndex: 'align',
          inputType: 'select',
          editable: true,
          width: '20%',
          initval: 'left',
          options: [
            {value: 'left', text: '居左'},
            {value: 'center', text: '居中'},
            {value: 'right', text: '居右'},
            // {value: 'justify', text: 'justify'}
          ],
          render: (text, record) => {
            if (text === 'center') {
              return '居中'
            } else if (text === 'right') {
              return '居右'
            } else {
              return '居左'
            }
          }
        }
      ]
    },
    {
      type: 'fields',
      key: 'columns',
      label: '字段集',
      initVal: card.columns || [],
      required: true,
      readonly: false,
      columns: [
        {
          title: '名称',
          dataIndex: 'label',
          inputType: 'input',
          editable: true,
          initval: 'label',
          width: '20%'
        },
        {
          title: '字段',
          dataIndex: 'field',
          inputType: 'input',
          editable: true,
          unique: true,
          strict: true,
          copy: true,
          initval: 'field',
          rules: [{
            pattern: /^[\u4E00-\u9FA50-9a-zA-Z_-]*$/ig,
            message: '请使用数字、字母、汉字以及_-'
          }],
          width: '20%'
        },
        {
          title: '隐藏',
          dataIndex: 'Hide',
          inputType: 'radio',
          editable: true,
          width: '20%',
          initval: 'false',
          options: [
            {value: 'true', text: '是'},
            {value: 'false', text: '否'},
          ],
          render: (text, record) => {
            if (text === 'true') {
              return '是'
            } else {
              return '否'
            }
          }
        },
        {
          title: '排序',
          dataIndex: 'IsSort',
          inputType: 'radio',
          editable: true,
          width: '20%',
          initval: 'false',
          options: [
            {value: 'true', text: '是'},
            {value: 'false', text: '否'},
          ],
          render: (text, record) => {
            if (text === 'true') {
              return '是'
            } else {
              return '否'
            }
          }
        }
      ]
    },
    {
      type: 'select',
      key: 'primaryKey',
      label: '主键',
      initVal: card.primaryKey || '',
      required: true,
      readonly: false,
      options: 'columns'
    },
    {
      type: 'text',
      key: 'order',
      label: '默认排序',
      initVal: card.order || '',
      placeholder: 'ID asc',
      required: true
    },
    {
      type: 'select',
      key: 'showField',
      label: '显示字段',
      initVal: card.showField || '',
      tooltip: '用于控制选择框中的显示内容。',
      required: true,
      options: 'columns'
    },
    {
      type: 'select',
      key: 'controlField',
      label: '禁用字段',
      initVal: card.controlField || '',
      tooltip: '用于控制行数据是否可选择。字段值为true时,选项不可选。',
      required: false,
      allowClear: true,
      options: 'columns'
    },
    {
      type: 'text',
      key: 'searchKey',
      label: '搜索字段',
      initVal: card.searchKey || '',
      tooltip: '多个值请用逗号分隔。',
      required: false,
      rules: [{
        pattern: /^[0-9a-zA-Z,_-]*$/ig,
        message: '字段名只允许包含数字、字母以及_-',
      }]
    },
    {
      type: 'number',
      key: 'popWidth',
      label: '弹窗宽度',
      initVal: card.popWidth || 60,
      tooltip: '小于100时为百分率,大于100时为绝对值。',
      required: true
    },
    {
      type: 'options',
@@ -2921,14 +3184,33 @@
      readonly: false
    },
    {
      type: 'codemirror',
      key: 'dataSource',
      label: '数据源',
      initVal: card.dataSource || '',
      tooltip: '数据权限替换符 $@ -> /* 或 \'\'、 @$ -> */ 或 \'\'',
      placeholder: '系统变量:mk_departmentcode、mk_organization、mk_user_type。公共值:@ID@、@BID@。',
      required: true,
      readonly: false
      type: 'radio',
      key: 'laypage',
      label: '分页',
      initVal: card.laypage || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'radio',
      key: 'onload',
      label: '初始化',
      initVal: card.onload || 'true',
      tooltip: '当没有设置搜索字段时,初始化加载数据。',
      required: false,
      options: [{
        value: 'true',
        text: '加载'
      }, {
        value: 'false',
        text: '不加载'
      }]
    },
    {
      type: 'radio',
@@ -2987,7 +3269,7 @@
      readonly: false
    },
    {
      type: 'select',
      type: 'radio',
      key: 'orderType',
      label: '排序方式',
      initVal: card.orderType || 'asc',
@@ -4018,7 +4300,11 @@
      initVal: card.regularExtra || '',
      tooltip: '正则验证时允许添加的自定义字符,包括~!@#$%^&*()_+:;{}<>,.-',
      required: false,
      readonly: false
      readonly: false,
      rules: [{
        pattern: /^[~!@#$%^&*()_+:;{}<>,.-]*$/,
        message: '扩展符包括~!@#$%^&*()_+:;{}<>,.-'
      }]
    },
    {
      type: 'text',
src/templates/zshare/modalform/fieldtable/index.jsx
File was deleted
src/templates/zshare/modalform/fieldtable/index.scss
File was deleted
src/templates/zshare/modalform/index.jsx
@@ -1,9 +1,10 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Input, Select, Radio, notification, InputNumber, Tooltip, Checkbox, AutoComplete } from 'antd'
import { Form, Row, Col, Input, Select, Radio, notification, InputNumber, Tooltip, Checkbox, AutoComplete, Modal } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import Api from '@/api'
import { formRule } from '@/utils/option.js'
import { dateOptions } from '@/utils/option.js'
import Utils from '@/utils/utils.js'
@@ -14,18 +15,18 @@
const { TextArea } = Input
const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
const FieldsTable = asyncComponent(() => import('./fieldtable'))
const FieldsTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
const modalTypeOptions = {
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType', 'constant'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'setAll', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'setAll', 'emptyText', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
  checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'span', 'labelwidth', 'display', 'tooltip', 'extra', 'place', 'width', 'multiple', 'splitline', 'marginTop', 'marginBottom'],
  multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'marginTop', 'marginBottom', 'dropdown'],
  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'setAll', 'linkField', 'linkSubField', 'span', 'place', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkField', 'linkSubField', 'span', 'place', 'labelwidth', 'tooltip', 'extra', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
  fileupload: ['readonly', 'required', 'hidden', 'readin', 'fieldlength', 'maxfile', 'fileType', 'span', 'labelwidth', 'linkSubField', 'tooltip', 'extra', 'compress', 'miniSet', 'splitline', 'marginTop', 'marginBottom', 'maxSize'],
  switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'linkSubField', 'tooltip', 'extra', 'splitline', 'marginTop', 'marginBottom'],
  check: ['initval', 'openVal', 'closeVal', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'marginTop', 'marginBottom', 'checkTip'],
@@ -42,6 +43,7 @@
  brafteditor: ['required', 'hidelabel', 'hidden', 'readin', 'fieldlength', 'readonly', 'span', 'labelwidth', 'tooltip', 'extra', 'encryption', 'marginTop', 'marginBottom'],
  funcvar: ['span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
  linkMain: ['readonly', 'required', 'hidden','declare', 'span', 'labelwidth', 'tooltip', 'interception', 'extra', 'place', 'marginTop', 'marginBottom'],
  popSelect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'enter', 'dataSource', 'columns', 'primaryKey', 'order', 'controlField', 'laypage', 'onload', 'searchKey', 'showField', 'popWidth'],
  vercode: ['label', 'field', 'type', 'blacklist', 'supField', 'readonly', 'required', 'hidden', 'span', 'labelwidth', 'tooltip', 'marginTop', 'marginBottom', 'placeholder', 'enter', 'smsId', 'phoneField', 'sendType']
}
@@ -428,28 +430,32 @@
        this.record.readonly = 'false'
      }
      if (this.record.options.length > 0) {
        if (value === 'checkcard') {
      if (value === 'checkcard') {
        if (this.record.options.length > 0) {
          this.record.options = this.record.options.map(cell => {
            cell.$value = cell.Value || ''
            delete cell.Value
            return cell
          })
        }
  
          if (this.record.options[0].Text) {
            let key = Utils.getuuid()
            this.record.fields = [{
              $index: 1,
              align: 'left',
              color: 'rgba(0, 0, 0, 0.85)',
              field: 'Text',
              fontSize: 14,
              key: key,
              uuid: key
            }]
          }
        } else if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(value)) {
        if (this.record.options[0] && this.record.options[0].Text) {
          let key = Utils.getuuid()
          this.record.fields = [{
            $index: 1,
            align: 'left',
            color: 'rgba(0, 0, 0, 0.85)',
            field: 'Text',
            fontSize: 14,
            key: key,
            uuid: key
          }]
        } else {
          this.record.fields = []
        }
      } else if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(value)) {
        if (this.record.options.length > 0) {
          if (!this.record.options[0].Text && this.record.fields.length > 0) {
            let field = this.record.fields[0].field
    
@@ -513,12 +519,8 @@
    this.record[key] = value
  }
  changeField = (data) => {
    this.record.fields = data || []
  }
  changeOptions = (data) => {
    this.record.options = data || []
  changeOptions = (data, key) => {
    this.record[key] = data || []
  }
  changeVal = (val, type) => {
@@ -635,18 +637,15 @@
            message: '不可使用英文状态的单引号!'
          }
        ]
        if (item.key === 'field') {
        if (item.rules) {
          rules.push(...item.rules)
        } else if (item.key === 'field') {
          rules.push({
            pattern: formRule.field.pattern,
            message: formRule.field.message
          }, {
            max: formRule.field.max,
            message: formRule.field.maxMessage
          })
        } else if (item.key === 'regularExtra') {
          rules.push({
            pattern: /^[~!@#$%^&*()_+:;{}<>,.-]*$/,
            message: '扩展符包括~!@#$%^&*()_+:;{}<>,.-'
          })
        } else if (item.max) {
          rules.push({
@@ -672,7 +671,7 @@
            <Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />
          </AutoComplete>
        } else {
          content = <Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />
          content = <Input placeholder={item.placeholder || ''} autoComplete="off" onPressEnter={this.handleSubmit} />
        }
      } else if (item.type === 'number') {
        rules = [
@@ -689,6 +688,12 @@
        rules = [
          { required: item.required, message: '请选择' + item.label + '!' }
        ]
        let options = item.options
        if (typeof(item.options) === 'string') {
          options = this.record[item.options] || []
        }
        content = <Select
          showSearch
          allowClear={item.allowClear === true}
@@ -696,7 +701,7 @@
          onChange={(value) => {this.optionChange(item.key, value)}}
          getPopupContainer={() => document.getElementById('modal-fields-form-box')}
        >
          {item.options.map((option, i) =>
          {options.map((option, i) =>
            <Select.Option key={`${i}`} value={option.value || option.field || ''}>
              {option.text || option.label}
            </Select.Option>
@@ -791,7 +796,7 @@
            columns.push({ title: transfield[field] || field, key: field })
          })
          content = <EditTable columns={columns} module="form" onChange={this.changeOptions}/>
          content = <EditTable columns={columns} module="form" onChange={(data) => this.changeOptions(data, item.key)}/>
        } else {
          if (this.record.multiple === 'true') {
            linkSubFields = []
@@ -826,7 +831,7 @@
            columns.push({ title: transfield[m] || m, key: m })
          })
          content = <EditTable columns={columns} onChange={this.changeOptions}/>
          content = <EditTable columns={columns} onChange={(data) => this.changeOptions(data, item.key)}/>
        }
      } else if (item.type === 'fields') {
        span = 24
@@ -835,7 +840,7 @@
          { required: item.required, message: '请添加' + item.label + '!' }
        ]
        content = <FieldsTable onChange={this.changeField}/>
        content = <FieldsTable indexShow={false} actions={['edit', 'move', 'del', 'add']} columns={item.columns} data={this.record[item.key] || []} onChange={(data) => this.changeOptions(data, item.key)}/>
      } else if (item.type === 'color') {
        className = 'color-form-item'
        rules = [
@@ -917,12 +922,36 @@
    }
  }
  handleConfirm = () => {
  handleConfirm = (fields) => {
    const { card } = this.props
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          values.uuid = this.props.card.uuid
          values.uuid = card.uuid
          if (card.style) {
            values.style = card.style
          }
          let fieldrepet = false // 字段重复
          fields.forEach(item => {
            if (item.uuid === card.uuid || !values.field || !item.field) return
            if (item.field.toLowerCase() === values.field.toLowerCase()) {
              fieldrepet = true
            }
          })
          if (fieldrepet) {
            notification.warning({
              top: 92,
              message: '字段已存在!',
              duration: 10
            })
            return
          }
          // 下拉菜单或联动菜单
          if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(values.type)) {
            if (values.resourceType === '0') {
@@ -1060,7 +1089,93 @@
            return
          }
          resolve(values)
          window.GLOB.formId = card.uuid
          if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(values.type) && values.resourceType === '1' && values.dataSource) {
            let _option = Utils.getSelectQueryOptions(values)
            let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
            ${_option.sql}`
            // LoginUID|SessionUid|UserID|Appkey 已替换
            sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|time_id)@/ig, `'1949-10-01 15:00:00'`)
            let rduri = ''
            if (window.GLOB.mainSystemApi && values.database === 'sso') {
              rduri = window.GLOB.mainSystemApi
            }
            resolve({values, loading: true, promise: () => new Promise((resolve, reject) => {
              Api.sDebug(sql, rduri).then(result => {
                if (result.status || result.ErrCode === '-2') {
                  resolve()
                } else {
                  Modal.error({
                    title: result.message
                  })
                  reject()
                }
              })
            })})
          } else if (values.type === 'popSelect') {
            let arrfield = values.columns.map(f => f.field)
            if (values.linkSubField && values.linkSubField.length > 0) {
              values.linkSubField.forEach(n => {
                if (!arrfield.includes(n)) {
                  arrfield.push(n)
                }
              })
            }
            let _datasource = values.dataSource
            let sql = ''
            if (/\s/.test(_datasource)) { // 拼接别名
              _datasource = '(' + _datasource + ') tb'
            }
            arrfield = arrfield.join(',')
            let _search = ''
            if (values.searchKey) {
              let fields = values.searchKey.split(',').map(field => field + ' like \'%mk%\'')
              _search = 'where ' + fields.join(' OR ')
            }
            if (values.laypage === 'true') {
              sql = `/*system_query*/select top 10 ${arrfield} from (select ${arrfield} ,ROW_NUMBER() over(order by ${values.order}) as rows from ${_datasource} ${_search}) tmptable where rows > 0 order by tmptable.rows `
            } else if (values.order) {
              sql = `/*system_query*/select ${arrfield} from (select ${arrfield} ,ROW_NUMBER() over(order by ${values.order}) as rows from ${_datasource} ${_search}) tmptable order by tmptable.rows `
            } else {
              sql = `/*system_query*/select ${arrfield} from ${_datasource} ${_search}  `
            }
            sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
              ${sql}`
            sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
            sql = sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
            sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
            sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
            sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
            resolve({values, loading: true, promise: () => new Promise((resolve, reject) => {
              Api.sDebug(sql).then(result => {
                if (result.status || result.ErrCode === '-2') {
                  resolve()
                } else {
                  Modal.error({
                    title: result.message
                  })
                  reject()
                }
              })
            })})
          } else {
            resolve({values})
          }
        } else {
          reject(err)
        }