king
2024-12-05 ea06034e06a30d3e97838c7885ae7694273a8ca1
Merge branch 'develop'
31个文件已修改
2610 ■■■■ 已修改文件
public/manifest.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/formconfig.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/markcomponent/index.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/options.jsx 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.jsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/debug/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/interfaces/interItem/index.jsx 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/resetAttach/addAttach/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/resetAttach/documents/index.jsx 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/resetAttach/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.jsx 203 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.scss 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/base-table/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.jsx 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/tree/antd-tree/index.jsx 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/popview/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/popupbutton/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/printbutton/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/billcodeform/index.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/callbackcustomscript/index.jsx 143 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customform/index.jsx 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customscript/index.jsx 239 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 1463 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-custom.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/manifest.json
@@ -6,5 +6,5 @@
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "mk_version": "20241106"
  "mk_version": "20241202"
}
src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -241,7 +241,7 @@
    _style_ = {float: 'right'}
  }
  let mark = ['text', 'number', 'slider', 'sequence', 'formula'].includes(card.eleType)
  let mark = ['text', 'number', 'slider', 'sequence', 'formula', 'icon'].includes(card.eleType)
  if (parent.setting && parent.setting.cardRole === 'header') {
    mark = false
  } else if (card.eleType === 'formula' && card.eval === 'func') {
src/menu/components/share/actioncomponent/formconfig.jsx
@@ -842,6 +842,10 @@
        value: 'never',
        text: '不刷新'
      }, {
        value: 'line',
        text: '刷新行',
        $disabled: !['table_normaltable', 'table_editable', 'table_basetable', 'card_datacard', 'card_dualdatacard'].includes(alltype)
      }, {
        value: 'grid',
        text: '刷新当前组件'
      }, {
@@ -2315,6 +2319,9 @@
        value: 'never',
        text: '不刷新'
      }, {
        value: 'line',
        text: '刷新行'
      }, {
        value: 'grid',
        text: '刷新当前组件'
      }, {
src/menu/components/share/markcomponent/index.jsx
@@ -112,7 +112,7 @@
        options: [],
        render: text => {
          let sign = {
            'font': '文字',
            'font': '字体颜色',
            'background': '背景',
            'underline': '下划线',
            'line-through': '中划线',
@@ -267,7 +267,7 @@
    let signs = [
      {
        value: 'font',
        label: '文字'
        label: '字体颜色'
      },
      {
        value: 'background',
@@ -324,6 +324,11 @@
      signs.pop()
      signs.pop()
      signs.pop()
    } else if (type === 'icon') {
      signs = [{
        value: 'font',
        label: '字体颜色'
      }]
    } else if (type === 'slider') {
      markColumns = markColumns.filter(col => {
        col.width = '20%'
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -673,6 +673,21 @@
    },
    {
      type: 'radio',
      key: 'showValue',
      label: '显示值',
      initVal: card.showValue || 'label',
      tooltip: '单元格不可编辑时显示的信息。',
      required: false,
      options: [{
        value: 'value',
        text: '值·字段'
      }, {
        value: 'label',
        text: '文本·字段'
      }]
    },
    {
      type: 'radio',
      key: 'dropdown',
      label: '下拉宽度',
      initVal: card.dropdown || 'flex',
src/menu/components/table/edit-table/columns/editColumn/index.jsx
@@ -83,7 +83,7 @@
        } else if (this.record.editType === 'popSelect') {
          _options.push('required', 'enter', 'linkSubField', 'columns', 'dataSource', 'primaryKey', 'order', 'showField', 'controlField', 'searchKey', 'popWidth', 'laypage', 'cache', 'onload')
        } else if (this.record.editType === 'select') {
          _options.push('required', 'enter', 'resourceType', 'linkSubField', 'dropdown')
          _options.push('required', 'enter', 'resourceType', 'linkSubField', 'dropdown', 'showValue')
          if (this.record.resourceType === '0') {
            _options.push('options')
src/menu/components/table/normal-table/options.jsx
@@ -389,6 +389,67 @@
      forbid: !!appType || isprint
    },
    {
      type: 'radio',
      field: 'tree',
      label: '结构树',
      initval: wrap.tree || 'false',
      tooltip: '使用结构树时,显示列首列请使用文本类型。',
      required: false,
      options: [
        {value: 'true', label: '启用'},
        {value: 'false', label: '禁用'},
      ],
      controlFields: [
        {field: 'valueField', values: ['true']},
        {field: 'parentField', values: ['true']},
        {field: 'mark', values: ['true']},
        {field: 'defOpen', values: ['true']},
      ],
      forbid: appType === 'mob' || isprint
    },
    {
      type: 'select',
      field: 'valueField',
      label: '值字段',
      initval: wrap.valueField || '',
      tooltip: '数据值字段,结构树中节点ID值,与上级字段配合组织数据的上下级关系。',
      required: true,
      options: columns,
      forbid: appType === 'mob' || isprint
    },
    {
      type: 'select',
      field: 'parentField',
      label: '上级字段',
      initval: wrap.parentField || '',
      tooltip: '上级字段,用于组织数据的上下级关系。',
      required: true,
      options: columns,
      forbid: appType === 'mob' || isprint
    },
    {
      type: 'text',
      field: 'mark',
      label: '顶级标识',
      initval: wrap.mark || '',
      tooltip: '上级字段值与顶级标识相同时,视为顶级节点。',
      required: false,
      forbid: appType === 'mob' || isprint
    },
    {
      type: 'radio',
      field: 'defOpen',
      label: '默认展开',
      initval: wrap.defOpen || '',
      required: false,
      options: [
        {value: '', label: '无'},
        {value: 'topline', label: '首行'},
        {value: 'all', label: '全部'},
      ],
      forbid: appType === 'mob' || isprint
    },
    {
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
src/menu/datasource/verifycard/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Tabs, Popconfirm, notification, Modal, Typography, Spin, message, Button, Input } from 'antd'
import { Form, Tabs, Popconfirm, notification, Modal, Typography, Spin, message, Button, Input, Switch } from 'antd'
import { StopOutlined, CheckCircleOutlined, TableOutlined, EditOutlined, SwapOutlined, DeleteOutlined, CopyOutlined, BorderOutlined, SnippetsOutlined } from '@ant-design/icons'
import moment from 'moment'
@@ -40,6 +40,7 @@
    subColumns: [],
    activeKey: 'setting',
    loading: false,
    skip: false,
    colLoading: false,
    searchKey: '',
    usefulfields: '',
@@ -832,7 +833,7 @@
  }
  triggerConfirm = () => {
    const { script, scriptValue, scripts } = this.state
    const { script, scriptValue, scripts, skip } = this.state
    let _scripts = fromJS(scripts).toJS()
    if (!scriptValue) {
@@ -865,9 +866,13 @@
      _scripts.push(_script)
    }
    this.setState({loading: true, editLineId})
    if (skip) {
      this.setState({scripts: _scripts, script: null, scriptValue: '', editLineId})
    } else {
      this.setState({loading: true, editLineId})
    this.sqlverify(() => {this.setState({scripts: _scripts, script: null, scriptValue: '', loading: false})}, () => {this.setState({loading: false})}, 'script', _scripts)
      this.sqlverify(() => {this.setState({scripts: _scripts, script: null, scriptValue: '', loading: false})}, () => {this.setState({loading: false})}, 'script', _scripts)
    }
  }
  updatefields = (columns) => {
@@ -1228,7 +1233,7 @@
  render() {
    const { config } = this.props
    const { columns, subColumns, median, setting, scripts, colColumns, scriptsColumns, activeKey, loading, searches, defaultsql, visible, pvisible, reload, script, scriptValue, searchKey, editLineId } = this.state
    const { columns, subColumns, median, skip, setting, scripts, colColumns, scriptsColumns, activeKey, loading, searches, defaultsql, visible, pvisible, reload, script, scriptValue, searchKey, editLineId } = this.state
    return (
      <div className="model-data-source-wrap">
@@ -1313,7 +1318,7 @@
                })
                return
              }
              this.setState({visible: true, script: null, scriptValue: '', editLineId: ''})
              this.setState({visible: true, skip: false, script: null, scriptValue: '', editLineId: ''})
            }}/> : null}
            <CustomScriptsForm
              type={config.type}
@@ -1321,7 +1326,6 @@
              setting={setting}
              searches={searches}
              defaultsql={defaultsql}
              customScripts={scripts}
              systemScripts={this.state.systemScripts}
              scriptsChange={this.scriptsChange}
              scriptSubmit={this.scriptSubmit}
@@ -1405,6 +1409,10 @@
            <Button onClick={() => {this.setState({script: null, scriptValue: ''})}} style={{marginBottom: 15, marginLeft: 10}}>
              取消
            </Button>
            <span style={{paddingLeft: '20px', fontSize: '12px'}}>
              强制保存:
              <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
            </span>
          </div>
          <CodeMirror value={scriptValue} onChange={(val) => {this.setState({scriptValue: val})}}></CodeMirror>
        </Modal>
src/menu/debug/index.jsx
@@ -637,7 +637,7 @@
    if (!_prev) return _back
    let tbs = []
    _prev.replace(/\n|\r/g, ' ').split(/\sdeclare\s/ig).forEach(line => {
    _prev.replace(/\/\*[^/*]+\*\//g, '').replace(/\n|\r/g, ' ').split(/\sdeclare\s/ig).forEach(line => {
      if (!/^\s*(@|#)[a-zA-Z0-9_]+\s+table\s+\(/ig.test(line)) return
      let tb = line.match(/(@|#)[a-zA-Z0-9_]+\s+table\s+\(.+(\)|date|datetime)\s*\)/ig)
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -224,9 +224,17 @@
    //   })
    //   return
    // }
    if (/^http.+(.txt|.doc|.docx|.pdf|.xlsx|.xls|.zip|.rar|.ppt)$/i.test(url)) {
      let name = url.replace(/.+\//g, '').replace(/\.{1}[^.]*$/g, '')
    if (/^http.+(.txt|.doc|.docx|.pdf|.xlsx|.xls|.zip|.rar|.ppt)$/i.test(url) || card.linkType === 'download') {
      let name = ''
      if (card.datatype === 'static') {
        name = card.value || ''
      } else if (data.hasOwnProperty(card.field)) {
        name = data[card.field] + ''
      }
      name = name.replace(/\.{1}[^.]*$/g, '')
      name = name ? name + url.replace(/.+\./g, '.') : ''
      let d = document.createElement('a')
      d.href = url
      d.setAttribute('download', name)
@@ -649,10 +657,21 @@
          }
        }
        let _style = {...card.style}
        if (card.marks) {
          let _s = {}
          getMark(card.marks, data, _s)
          if (_s.color) {
            _style.color = _s.color
          }
        }
        if (card.tipType === 'text') {
          contents.push(
            <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
              <div style={card.style}>
              <div style={_style}>
                {val ? <Tooltip title={val}>
                  <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight}}>{icon}</div>
                </Tooltip> : <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight}}>{icon}</div>}
@@ -662,7 +681,7 @@
        } else {
          contents.push(
            <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
              <div style={card.style}>
              <div style={_style}>
                {val ? <Tooltip title={val}>
                  <MkIcon className="ant-mk-icon" style={{height: card.innerHeight}} type={icon}/>
                </Tooltip> : <MkIcon className="ant-mk-icon" style={{height: card.innerHeight}} type={icon}/>}
@@ -968,6 +987,8 @@
            if (key === 'children') return
            if (/^1949-10-01/.test(data[key])) {
              _data[key.toLowerCase()] = ''
            } else if (/\d{4}-\d{2}-\d{2}\s00:00:00/.test(data[key])) {
              _data[key.toLowerCase()] = data[key].replace(/\s00:00:00/g, '')
            } else {
              _data[key.toLowerCase()] = data[key]
            }
@@ -1031,7 +1052,7 @@
        if (val !== '') {
          if (val && typeof(val) === 'string') {
            if (!card.evalchars || card.evalchars.includes('enter')) {
              val = val.replace(/\n/ig, '<br/>')
              val = val.replace(/\\n|\n/ig, '<br/>')
            }
            if ((!card.evalchars || card.evalchars.includes('space')) && !/<(span|div|p|a|img)\s/g.test(val)) {
              val = val.replace(/\s/ig, '&nbsp;')
src/tabviews/custom/components/interfaces/interItem/index.jsx
@@ -1,4 +1,4 @@
import {Component} from 'react'
import { Component } from 'react'
import PropTypes from 'prop-types'
import Api from '@/api'
@@ -15,6 +15,7 @@
  }
  loading = false
  loadTimer = null
  
  state = {
    BID: ''
@@ -39,9 +40,7 @@
    }
    if (config.setting.onload !== 'false') {
      setTimeout(() => {
        this.loadData()
      }, config.setting.delay)
      this.loadData()
    } else {
      MKEmitter.addListener('initFinish', this.initFinish)
    }
@@ -84,9 +83,7 @@
    if (config.MenuID !== MenuID) return
    if (config.setting.onload === 'false') {
      setTimeout(() => {
        this.loadData()
      }, config.setting.delay)
      this.loadData()
    }
  }
@@ -107,7 +104,17 @@
    this.loadData()
  }
  async loadData () {
  loadData = () => {
    const { config } = this.props
    this.loadTimer && clearTimeout(this.loadTimer)
    this.loadTimer = setTimeout(() => {
      this.execLoadData()
    }, config.setting.delay)
  }
  async execLoadData () {
    const { config } = this.props
    const { BID } = this.state
src/tabviews/custom/components/module/voucher/resetAttach/addAttach/index.jsx
@@ -131,8 +131,8 @@
                  message: '请输入文件名!'
                },
                {
                  max: 50,
                  message: '最大长度为50位!'
                  max: 100,
                  message: '最大长度为100位!'
                }
              ]
            })(<Input />)}
src/tabviews/custom/components/module/voucher/resetAttach/documents/index.jsx
@@ -1,4 +1,5 @@
import React, {Component} from 'react'
import { fromJS } from 'immutable'
class Documents extends Component {
  state = {
@@ -7,9 +8,16 @@
  }
  UNSAFE_componentWillMount() {
    const { documents } = this.props
    const { documents, list } = this.props
    let actFolder = documents[0] || null
    let actFolder = null
    if (documents[0]) {
      actFolder = fromJS(documents[0]).toJS()
      let ids = list.map(item => item.id)
      actFolder.attachments = actFolder.attachments.filter(doc => !ids.includes(doc.id))
    }
    this.setState({selectKey: [], actFolder: actFolder})
  }
@@ -31,15 +39,17 @@
  }
  checkfolder = (id) => {
    const { documents } = this.props
    const { documents, list } = this.props
    const { actFolder } = this.state
    if (!actFolder || actFolder.id === id) return
    let _actFolder = null
    let ids = list.map(item => item.id)
    documents.forEach(item => {
      if (item.id === id) {
        _actFolder = item
        _actFolder = fromJS(item).toJS()
        _actFolder.attachments = _actFolder.attachments.filter(doc => !ids.includes(doc.id))
      }
    })
src/tabviews/custom/components/module/voucher/resetAttach/index.jsx
@@ -202,7 +202,6 @@
  docSubmit = () => {
    const { selectDocs, list } = this.state
    if (selectDocs.length > 0 && list.length > 0) {
      let _list = fromJS(list).toJS()
      let err = ''
@@ -241,7 +240,7 @@
          title="添加附件"
          wrapClassName="voucher-attach-wrap"
          visible={visible}
          width={700}
          width={'62vw'}
          maskClosable={false}
          onOk={this.submit}
          onCancel={() => { this.setState({ visible: false })}}
@@ -270,7 +269,7 @@
          title="添加附件"
          wrapClassName="voucher-attach-add-wrap"
          visible={upVisible}
          width={700}
          width={'62vw'}
          maskClosable={false}
          onOk={this.upSubmit}
          onCancel={() => { this.setState({ upVisible: false })}}
@@ -282,13 +281,13 @@
          title="电子档案"
          wrapClassName="voucher-attach-document-wrap"
          visible={docVisible}
          width={700}
          width={'62vw'}
          maskClosable={false}
          onOk={this.docSubmit}
          onCancel={() => { this.setState({ docVisible: false, selectDocs: [] })}}
          destroyOnClose
        >
          {docVisible ? <Documents documents={documents} onChange={(vals) => this.setState({selectDocs: vals})}/> : null}
          {docVisible ? <Documents documents={documents} list={list} onChange={(vals) => this.setState({selectDocs: vals})}/> : null}
        </Modal>
      </>
    )
src/tabviews/custom/components/share/normalTable/index.jsx
@@ -2,7 +2,8 @@
import PropTypes from 'prop-types'
import md5 from 'md5'
import { is, fromJS } from 'immutable'
import { Table, Typography, Col, Switch, message } from 'antd'
import { Table, Typography, Col, Switch, message, Pagination } from 'antd'
import { CaretRightOutlined, CaretDownOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import { getMark } from '@/utils/utils.js'
@@ -152,7 +153,7 @@
  }
  render() {
    let { col, config, record, className, style, ...resProps } = this.props
    let { col, config, record, className, style, openChange, ...resProps } = this.props
    if (!col) return (<td {...resProps} className={className} style={style}/>)
@@ -209,6 +210,21 @@
      if (col.rowspan === 'true') {
        resProps.rowSpan = record['$$' + col.field]
      }
      if (col.$tree && record.$mk_floor) {
        className += ' mk-tree-td'
        if (record.$open) {
          content = <>
            <span className="mk-tree-node" style={{width: `calc(var(--tree-node-width) * ${record.$mk_floor})`}}><CaretRightOutlined onClick={(e) => openChange(e, record.$key)} /><CaretDownOutlined onClick={(e) => openChange(e, record.$key)}/></span>
            {content}
          </>
        } else {
          content = <>
            <span className="mk-tree-node" style={{width: `calc(var(--tree-node-width) * ${record.$mk_floor})`}}></span>
            {content}
          </>
        }
      }
      
      resProps.children = content
@@ -539,11 +555,12 @@
    orderfields: {},      // 排序id与field转换
    pageOptions: [],
    allColumns: null,
    reseting: false
    reseting: false,
    openkeys: []
  }
  UNSAFE_componentWillMount () {
    const { setting, columns, fields, colsCtrls } = this.props
    const { setting, columns, fields, colsCtrls, data } = this.props
    let radio = 5          // 虚化比例
    let _format = false    // 是否虚化处理
    let rowspans = []
@@ -594,6 +611,7 @@
                record,
                col: item,
                config: item.type === 'custom' ? {setting, columns: fields} : null,
                openChange: item.$tree ? this.openChange : null,
              })
            }
          }
@@ -653,6 +671,10 @@
      _columns = this.getCurColumns(_columns, this.props.allSearch)
    }
    if (setting.$tree) {
      this.resetOpenKeys(data)
    }
    this.setState({
      pageSize: setting.pageSize || 10,
      pageOptions,
@@ -669,7 +691,7 @@
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    const { allSearch, parCtrl } = this.props
    const { allSearch, parCtrl, setting, data } = this.props
    const { allColumns } = this.state
    if (allSearch && !is(fromJS(allSearch), fromJS(nextProps.allSearch))) {
@@ -698,6 +720,7 @@
                record,
                col: item,
                config: item.type === 'custom' ? {setting: this.props.setting, columns: this.props.fields} : null,
                openChange: item.$tree ? this.openChange : null,
              })
            }
          }
@@ -709,6 +732,10 @@
      this.setState({
        columns: getColumns(nextProps.columns)
      })
    }
    if (setting.$tree && !is(fromJS(data), fromJS(nextProps.data))) {
      this.resetOpenKeys(nextProps.data)
    }
  }
@@ -738,6 +765,83 @@
    MKEmitter.removeListener('autoQueryData', this.autoQueryData)
    MKEmitter.removeListener('autoSelectData', this.autoSelectData)
    MKEmitter.removeListener('mkCheckTopLine', this.mkCheckTopLine)
  }
  resetOpenKeys = (data) => {
    const { setting } = this.props
    if (!data || data.length === 0 || !setting.defOpen) {
      this.setState({openkeys: []})
    } else if (setting.defOpen === 'topline') {
      let keys = []
      if (data[0].$open) {
        keys = [data[0].$key]
        data.forEach(item => {
          if (item.$pkeys && item.$pkeys.length > 1 && item.$pkeys.includes(data[0].$key)) {
            keys.push(...item.$pkeys)
          }
        })
        keys = Array.from(new Set(keys))
      }
      this.setState({openkeys: keys})
    } else {
      this.setState({openkeys: data.filter(item => !!item.$open).map(item => item.$key)})
    }
  }
  openChange = (e, key) => {
    const { setting, MenuID, data } = this.props
    const { openkeys, selectedRowKeys } = this.state
    e.stopPropagation()
    let _openkeys = []
    if (openkeys.includes(key)) {
      _openkeys = openkeys.filter(k => k !== key)
    } else {
      _openkeys = [...openkeys, key]
    }
    if (!setting.tableType || _openkeys.length > openkeys.length) {
      this.setState({openkeys: _openkeys})
      return
    }
    let newkeys = fromJS(selectedRowKeys).toJS()
    newkeys = newkeys.filter(k => {
      if (!data[k]) return false
      if (!data[k].$pkeys) return true
      return data[k].$pkeys.every(key => _openkeys.includes(key))
    })
    if (newkeys.length === selectedRowKeys.length) {
      this.setState({openkeys: _openkeys})
      return
    }
    let _index = ''
    if (newkeys.length > 0) {
      _index = newkeys.slice(-1)[0]
    }
    this.changedata(_index)
    this.setState({ openkeys: _openkeys, selectedRowKeys: newkeys, activeIndex: _index !== '' ? _index : null })
    let selects = data.filter((item, _index) => newkeys.includes(_index))
    this.props.chgSelectData(selects)
    if (setting.$hasSyncModule) {
      MKEmitter.emit('syncBalconyData', MenuID, selects, false)
    }
  }
  getCurColumns = (columns, allSearch) => {
@@ -974,21 +1078,44 @@
  }
  changeTable = (pagination, filters, sorter) => {
    const { orderfields } = this.state
    this.setState({
      pageIndex: pagination.current,
      pageSize: pagination.pageSize,
      selectedRowKeys: [],
      activeIndex: null,
      pickup: false
    })
    const { setting } = this.props
    const { orderfields, pageSize } = this.state
    if (orderfields) {
      sorter.field = orderfields[sorter.field] || ''
    }
    this.props.refreshdata(pagination, filters, sorter)
    if (setting.$tree) {
      this.setState({
        pageIndex: 1,
        selectedRowKeys: [],
        activeIndex: null,
        pickup: false
      })
      this.props.refreshdata({current: 1, pageSize: pageSize}, sorter)
    } else {
      this.setState({
        pageIndex: pagination.current,
        pageSize: pagination.pageSize,
        selectedRowKeys: [],
        activeIndex: null,
        pickup: false
      })
      this.props.refreshdata(pagination, sorter)
    }
  }
  onPaginationChange = (current, pageSize) => {
    this.setState({
      pageIndex: current,
      pageSize: pageSize,
      selectedRowKeys: [],
      activeIndex: null
    })
    this.props.refreshdata({current: current, pageSize: pageSize, fixed: true}, {})
  }
  changedata = (index) => {
@@ -1125,7 +1252,7 @@
  render() {
    const { setting, statFValue, lineMarks, data } = this.props
    const { selectedRowKeys, activeIndex, pickup, pageOptions, columns, reseting } = this.state
    const { selectedRowKeys, activeIndex, pickup, pageOptions, columns, reseting, openkeys } = this.state
    if (reseting) return null
@@ -1152,14 +1279,16 @@
    // 数据收起时,过滤已选数据
    let _data = data || []
    if (pickup) {
      _data = _data.filter((item, index) => selectedRowKeys.includes(index))
    if (!setting.$tree) {
      if (pickup) {
        _data = _data.filter((item, index) => selectedRowKeys.includes(index))
      }
      _data = this.handleRowspan(_data)
    }
    _data = this.handleRowspan(_data)
    
    let _pagination = false
    if (setting.laypage !== 'false' && setting.laypage !== false) {
    if (setting.laypage && !setting.$tree) {
      _pagination = {
        current: this.state.pageIndex,
        pageSize: this.state.pageSize,
@@ -1210,7 +1339,7 @@
    return (
      <div className={`normal-custom-table ${setting.tableHeader || ''} ${setting.parity === 'true' ? 'mk-parity' : ''} ${height ? 'fixed-table-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || 'middle'} table-col-${columns.length} ${fixed} ${setting.empSign === 'hidden' ? 'mk-empty-hide' : ''}`} style={style}>
        {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && data && data.length > 0 ?
        {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && data && data.length > 0 && !setting.$tree ?
          <Switch title="收起" className="main-pickup" checkedChildren={window.GLOB.dict['open'] || '开'} unCheckedChildren={window.GLOB.dict['shut'] || '关'} checked={pickup} onChange={this.pickupChange} /> : null
        }
        <Table
@@ -1223,11 +1352,26 @@
          loading={loading}
          scroll={{ x: '100%', y: height }}
          onRow={(record, index) => {
            let className = ''
            if (index === activeIndex) {
              className = ' mk-row-active '
            }
            if (setting.$tree) {
              if (record.$open && openkeys.includes(record.$key)) {
                className += ' mk-tree-open '
              }
              if (record.$pkeys && !record.$pkeys.every(key => openkeys.includes(key))) {
                className += ' mk-tree-hide '
              }
            }
            return {
              lineMarks: setting.tableMode !== 'fast' ? lineMarks : null,
              lineMarks: lineMarks,
              data: record,
              title: setting.tipField ? record[setting.tipField] : '',
              className: index === activeIndex ? ' mk-row-active ' : '',
              className: className,
              onClick: () => {this.changeRow(record, index)},
              onDoubleClick: () => {this.doubleClickLine(record)}
            }
@@ -1235,6 +1379,17 @@
          onChange={this.changeTable}
          pagination={_pagination}
        />
        {setting.laypage && setting.$tree ? <Pagination
          showSizeChanger
          className="mk-tree-pagination"
          onChange={this.onPaginationChange}
          onShowSizeChange={this.onPaginationChange}
          current={this.state.pageIndex}
          pageSize={this.state.pageSize}
          pageSizeOptions={pageOptions}
          total={this.props.total || 0}
          showTotal={(total, range) => `${range[0]}-${range[1]} ${window.GLOB.dict['of'] || '共'} ${total} ${window.GLOB.dict['items'] || '条'}`}
        /> : null}
        {_footer ? <div className={'normal-table-footer ' + (_pagination ? 'pagination' : '')}>{_footer}</div> : null}
      </div>
    )
src/tabviews/custom/components/share/normalTable/index.scss
@@ -170,6 +170,14 @@
  }
  .ant-table-small.ant-table-bordered {
    border-right: 1px solid #e8e8e8;
    .ant-table-content {
      border-radius: inherit;
      .ant-table-scroll {
        border-radius: inherit;
      }
    }
  }
  table, tr, th, td, .ant-table-small {
@@ -192,6 +200,43 @@
  table tbody tr {
    color: var(--mk-table-color);
  }
  .mk-tree-node {
    display: inline-block;
    text-align: right;
    --tree-node-width: 18px;
    .anticon-caret-right, .anticon-caret-down {
      cursor: pointer;
      padding-right: 3px;
    }
    .anticon-caret-down {
      display: none;
    }
  }
  .mk-tree-open {
    .mk-tree-node {
      .anticon-caret-right {
        display: none;
      }
      .anticon-caret-down {
        display: inline-block;
      }
    }
  }
  .mk-tree-hide {
    display: none;
  }
  .mk-tree-td {
    overflow: hidden;
    word-break: break-word;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .mk-tree-pagination {
    float: right;
    margin: 16px 0;
  }
}
.normal-custom-table.mk-parity {
  .ant-table-tbody tr:nth-child(even) {
src/tabviews/custom/components/table/base-table/index.jsx
@@ -73,6 +73,10 @@
      _config.setting.onload = 'false'
    }
    if (setting.tableMode === 'fast') {
      _config.lineMarks = null
    }
    _config.style = _config.style || {}
    this.setState({
@@ -454,7 +458,7 @@
  /**
   * @description 表格条件改变时重置数据(分页或排序)
   */
  refreshbytable = (pagination, filters, sorter) => {
  refreshbytable = (pagination, sorter) => {
    if (!sorter) { // 无人值守
      this.setState({
        pageIndex: pagination.pageIndex
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -20,7 +20,6 @@
class MkSwitch extends Component {
  static propTpyes = {
    autoFocus: PropTypes.bool,
    defaultValue: PropTypes.any,
    config: PropTypes.object,
    onChange: PropTypes.func
@@ -78,12 +77,10 @@
    if (config.$ctrl) {
      MKEmitter.emit('colBlur' + config.tableId, lineId, config.uuid)
    }
    this.props.onBlur && this.props.onBlur()
  }
  render() {
    const { config, autoFocus } = this.props
    const { config } = this.props
    const { status } = this.state
    return (
@@ -91,7 +88,6 @@
        ref={ref => this.node = ref}
        checkedChildren={config.openText}
        checked={status}
        autoFocus={autoFocus}
        onFocus={this.onFocus}
        onBlur={this.onBlur}
        unCheckedChildren={config.closeText}
@@ -763,7 +759,7 @@
        content = `${record[col.field]}`
      }
      if (col.editType === 'select' && col.options.length > 0) {
      if (col.editType === 'select' && col.showValue !== 'value' && col.options.length > 0) {
        content = col.map.get(content) || content
      } else if (col.editType === 'switch') {
        if (content === col.openVal) {
@@ -820,16 +816,17 @@
      }
      if (col.editable === 'true' && !disabled) {
        if (editing) {
        if (col.editType === 'switch') {
          let _value = record[col.field] !== undefined ? record[col.field] : ''
          return (<td onClick={(e) => e.stopPropagation()} className="editing_table_cell">
            <MkSwitch config={col} lineId={record.$$uuid} defaultValue={_value} onChange={this.onColChange}/>
          </td>)
        } else if (editing) {
          let _value = record[col.field] !== undefined ? record[col.field] : ''
          if (!col.editType || col.editType === 'text') {
            return (<td onClick={(e) => e.stopPropagation()} className="editing_table_cell">
              <MkInput config={col} lineId={record.$$uuid} defaultValue={_value} autoFocus={true} onChange={this.onColChange} onBlur={() => this.setState({editing: false})}/>
            </td>)
          } else if (col.editType === 'switch') {
            return (<td onClick={(e) => e.stopPropagation()} className="editing_table_cell">
              <MkSwitch config={col} lineId={record.$$uuid} defaultValue={_value} autoFocus={true} onChange={this.onColChange} onBlur={() => this.setState({editing: false})}/>
            </td>)
          } else if (col.editType === 'date') {
            return (<td onClick={(e) => e.stopPropagation()} className="editing_table_cell">
@@ -1099,7 +1096,7 @@
          )
        } else if (col.editType === 'switch') {
          children = (
            <MkSwitch config={col} lineId={record.$$uuid} defaultValue={_value} autoFocus={false} onChange={this.onColChange}/>
            <MkSwitch config={col} lineId={record.$$uuid} defaultValue={_value} onChange={this.onColChange}/>
          )
        } else if (col.editType === 'date') {
          children = (
@@ -1125,7 +1122,7 @@
          content = `${record[col.field]}`
        }
        if (col.editType === 'select' && col.options.length > 0) {
        if (col.editType === 'select' && col.showValue !== 'value' && col.options.length > 0) {
          content = col.map.get(content) || content
        } else if (col.editType === 'switch') {
          if (content === col.openVal) {
@@ -2140,6 +2137,12 @@
      delete result.message
      delete result.status
      this.props.columns.forEach(item => {
        if (item.arr_field && result[item.field]) {
          result[item.uuid] = result[item.field]
        }
      })
      this.resetFormList(result)
    })
  }
src/tabviews/custom/components/table/edit-table/normalTable/index.scss
@@ -232,6 +232,14 @@
  }
  .ant-table-small.ant-table-bordered {
    border-right: 1px solid #e8e8e8;
    .ant-table-content {
      border-radius: inherit;
      .ant-table-scroll {
        border-radius: inherit;
      }
    }
  }
  table, tr, th, td, .ant-table-small {
    border-color: var(--mk-table-border-color)!important;
src/tabviews/custom/components/table/normal-table/index.jsx
@@ -153,6 +153,10 @@
      _config.colsCtrls = null
    }
    if (setting.$tree && _config.cols[0]) {
      _config.cols[0].$tree = true
    }
    let columns = _config.cols
    if (_config.hasExtend) {
      columns = this.getCols(_config.cols, BData, _config.setting.extendTime)
@@ -610,6 +614,10 @@
        return item
      })
      if (setting.$tree && data.length) {
        data = this.getTree(data)
      }
      let total = result.total || 0
      if (config.setting.custompage && data.length) {
        total = data[data.length - 1].mk_total || 0
@@ -665,6 +673,90 @@
      
      UtilsDM.queryFail(result)
    }
  }
  getTree = (data) => {
    const { setting } = this.state
    let options = []
    let pnodes = []
    let _data = []
    data.forEach(item => {
      let pval = item[setting.parentField] + ''
      let val = item[setting.valueField] + ''
      if (pval === setting.mark) {
        pnodes.push({
          ...item,
          $mk_floor: 1,
          $key: val,
          $pid: ''
        })
      } else if (pval) {
        options.push({
          ...item,
          $mk_floor: 0,
          $key: val,
          $pid: pval
        })
      }
    })
    let get_tree = (parents) => {
      parents.forEach(parent => {
        parent.children = []
        options = options.filter(option => {
          if (option.$pid === parent.$key) {
            option.$mk_floor = parent.$mk_floor + 1
            option.$pkeys = parent.$pkeys ? [...parent.$pkeys, parent.$key] : [parent.$key]
            parent.children.push(option)
            return false
          }
          return true
        })
        if (parent.children.length === 0) {
          parent.children = null
        } else {
          parent.$open = true
          parent.children = get_tree(parent.children)
        }
      })
      return parents
    }
    let tree = get_tree(pnodes)
    let get_data = (parents) => {
      parents.forEach(parent => {
        let children = parent.children
        delete parent.children
        _data.push(parent)
        if (children) {
          get_data(children)
        }
      })
    }
    get_data(tree)
    if (options.length) {
      _data.push(...options)
    }
    _data = _data.map((item, index) => {
      item.key = index
      return item
    })
    return _data
  }
  /**
@@ -825,7 +917,7 @@
  /**
   * @description 表格条件改变时重置数据(分页或排序)
   */
  refreshbytable = (pagination, filters, sorter) => {
  refreshbytable = (pagination, sorter) => {
    if (sorter.order) {
      let _chg = {
        ascend: 'asc',
@@ -837,7 +929,7 @@
    this.setState({
      pageIndex: pagination.current,
      pageSize: pagination.pageSize,
      orderBy: (sorter.field && sorter.order) ? `${sorter.field} ${sorter.order}` : ''
      orderBy: (sorter.field && sorter.order) ? `${sorter.field} ${sorter.order}` : (pagination.fixed ? this.state.orderBy : '')
    }, () => {
      this.loadData()
    })
src/tabviews/custom/components/tree/antd-tree/index.jsx
@@ -36,6 +36,7 @@
  }
  loaded = false
  options = null
  UNSAFE_componentWillMount () {
    const { config } = this.props
@@ -364,11 +365,12 @@
      return
    }
    let parentNodes = []
    let _options = []
    let logMap = new Map()
    let selectKey = selectedKeys[0] || ''
    let selectData = ''
    let hasSelectKey = false
    this.options = []
    data.forEach(item => {
      let pval = item[config.wrap.parentField] + ''
@@ -399,7 +401,7 @@
          $parentId: ''
        })
      } else if (pval) {
        _options.push({
        this.options.push({
          ...item,
          $$uuid: uuid,
          $title: item[config.wrap.labelField] || '',
@@ -408,7 +410,17 @@
        })
      }
    })
    let _treedata = this.getTree(parentNodes, _options)
    let _treedata = this.getTree(parentNodes)
    if (this.options.length) {
      this.options.forEach(item => {
        _treedata.push({
          ...item,
          mk_floor: 1,
          $$title: <span style={{color: '#f5222d'}}>{item.$title}</span>
        })
      })
    }
    let _treeNodes = []
@@ -485,11 +497,11 @@
  /**
   * @description 获取结构树信息
   */
  getTree = (parents, options) => {
  getTree = (parents) => {
    parents.forEach(parent => {
      parent.children = []
      // 添加菜单的子元素
      options = options.filter(option => {
      this.options = this.options.filter(option => {
        if (option.$parentId === parent.$key) {
          option.mk_floor = parent.mk_floor + 1
          parent.children.push(option)
@@ -501,7 +513,7 @@
      if (parent.children.length === 0) {
        parent.children = null
      } else {
        parent.children = this.getTree(parent.children, options)
        parent.children = this.getTree(parent.children)
      }
    })
    return parents
@@ -519,7 +531,7 @@
          </TreeNode>
        )
      }
      return <TreeNode icon={<FileOutlined />} key={item.$key} title={item.$title} dataRef={item} isLeaf />
      return <TreeNode icon={<FileOutlined />} key={item.$key} title={item.$$title || item.$title} dataRef={item} isLeaf />
    })
  }
@@ -528,7 +540,7 @@
      let title = null
      if (actShow === 'line') {
        title = <>
          {item.$title}
          {item.$$title || item.$title}
          <MainAction
            BID={this.state.BID}
            BData={this.state.BData}
@@ -540,7 +552,7 @@
        </>
      } else {
        title = <>
          {item.$title}
          {item.$$title || item.$title}
          <Dropdown overlay={
            <div className="mk-tree-dropdown-wrap" onClick={(e) => e.stopPropagation()}>
              <MainAction
@@ -661,6 +673,7 @@
          </Tree>
        </div> : null}
        {treeNodes && treeNodes.length === 0 ? <Empty description={false}/> : null}
        {!treeNodes ? <div style={{height: '100px'}}></div> : null}
      </div>
    )
  }
src/tabviews/custom/index.jsx
@@ -702,6 +702,12 @@
          item.colsCtrls = null
        }
        if (item.wrap.tree === 'true') {
          item.setting.sync = 'false'
          item.$cache = false
          item.setting.$tree = true
        }
        if (item.subtype === 'editable') {
          item.submit.logLabel = item.$menuname + '-提交'
          item.submit.$menuId = item.uuid
@@ -922,6 +928,10 @@
          item.setting.custompage = /@pageSize@|@orderBy@|@mk_total/i.test(item.setting.dataresource + item.setting.customScript)
          if (item.setting.$tree) {
            item.setting.custompage = true
          }
          if (!item.setting.execute || item.setting.custompage) {
            item.forbidLine = true
          }
src/tabviews/custom/popview/index.jsx
@@ -420,6 +420,12 @@
          item.colsCtrls = null
        }
        if (item.wrap.tree === 'true') {
          item.setting.sync = 'false'
          item.$cache = false
          item.setting.$tree = true
        }
        if (item.subtype === 'editable') {
          item.submit.logLabel = item.$menuname + '-提交'
          item.submit.$menuId = item.uuid
@@ -618,6 +624,10 @@
          item.setting.custompage = /@pageSize@|@orderBy@|@mk_total/i.test(item.setting.dataresource + item.setting.customScript)
          if (item.setting.$tree) {
            item.setting.custompage = true
          }
          if (!item.setting.execute || item.setting.custompage) {
            item.forbidLine = true
          }
src/tabviews/zshare/actionList/popupbutton/index.jsx
@@ -131,11 +131,11 @@
    if (btn.$view === 'popview') {
      if (btn.popClose !== 'never') {
        MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.popClose, btn)
        MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.popClose, btn, '', this.state.popData ? [this.state.popData] : null)
      }
    } else {
      let position = btn.popClose !== 'never' ? btn.popClose : 'grid'
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, position, btn)
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, position, btn, '', this.state.popData ? [this.state.popData] : null)
    }
  }
@@ -207,7 +207,7 @@
    })
    if (btn.popClose !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.popClose, btn)
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.popClose, btn, '', this.state.popData ? [this.state.popData] : null)
    }
    if (btn.syncComponentId) {
src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -180,6 +180,7 @@
      let modal = this.state.btnconfig
      if (!modal && btn.modal) {
        modal = this.handleModelConfig(btn.modal)
        modal.uuid = btn.uuid
      }
      this.setState({
@@ -2129,6 +2130,7 @@
        } else {
          _LongParam = updateForm(_LongParam)
          _LongParam = this.handleModelConfig(_LongParam)
          _LongParam.uuid = btn.uuid
          this.setState({
            btnconfig: _LongParam
src/templates/zshare/verifycard/billcodeform/index.jsx
@@ -8,13 +8,13 @@
class BillCodeForm extends Component {
  static propTpyes = {
    btn: PropTypes.object,          // 按钮信息
    fields: PropTypes.array,        // 表单
    billcodes: PropTypes.array,     // 表单
    columns: PropTypes.array,       // 表单
    modular: PropTypes.array,       // 表单
    modularDetail: PropTypes.array, // 表单
    orderChange: PropTypes.func     // 表单
    btn: PropTypes.object,
    fields: PropTypes.array,
    billcodes: PropTypes.array,
    columns: PropTypes.array,
    modular: PropTypes.array,
    modularDetail: PropTypes.array,
    orderChange: PropTypes.func
  }
  state = {
src/templates/zshare/verifycard/callbackcustomscript/index.jsx
@@ -1,22 +1,19 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Button, Modal, Tooltip, Radio, Select, Switch, notification } from 'antd'
import { Form, Row, Col, Button, Tooltip, Radio, Select, Switch, notification } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import Api from '@/api'
import { checkSQL } from '@/utils/utils-custom.js'
import CodeMirror from '@/templates/zshare/codemirror'
import './index.scss'
class CustomForm extends Component {
  static propTpyes = {
    btn: PropTypes.object,          // 按钮信息
    initsql: PropTypes.string,      // 初始化脚本
    btn: PropTypes.object,
    formfields: PropTypes.string,
    colfields: PropTypes.string,
    systemScripts: PropTypes.array, // 系统脚本
    customScripts: PropTypes.array, // 自定义脚本
    scriptsChange: PropTypes.func   // 表单
    systemScripts: PropTypes.array,
    cbScriptsChange: PropTypes.func
  }
  state = {
@@ -47,7 +44,9 @@
    const { editItem, skip } = this.state
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (type === 'fullscreen' && err) {
      if (err) return
      if (!values.sql || /^[\s\n]+$/.test(values.sql)) {
        notification.warning({
          top: 92,
          message: '请输入sql!',
@@ -56,110 +55,40 @@
        return
      }
      if (!err) {
        if (/^[\s\n]+$/.test(values.sql)) {
          notification.warning({
            top: 92,
            message: '请输入sql!',
            duration: 5
          })
          return
        }
      values.uuid = editItem ? editItem.uuid : ''
      values.position = values.position || (editItem ? editItem.position : 'front')
        values.uuid = editItem ? editItem.uuid : ''
        values.position = values.position || (editItem ? editItem.position : 'front')
      if (type === 'fullscreen' && editItem) {
        values.status = editItem.status || 'true'
      }
        if (type === 'fullscreen' && editItem) {
          values.status = editItem.status || 'true'
        }
      let pass = checkSQL(values.sql, 'customscript')
        let pass = checkSQL(values.sql, 'customscript')
      if (!pass && !skip) return
        if (!pass && !skip) return
        let tail = `
          aaa:
        `
        let _prevCustomScript = '' // 默认sql前执行脚本
        let _backCustomScript = '' // 默认sql后执行脚本
        this.props.customScripts.forEach(item => {
          if (item.status === 'false') return
          if (item.position === 'front') {
            _prevCustomScript += `
            /* 默认sql前脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          } else {
            _backCustomScript += `
            /* 默认sql后脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          }
      if (skip) {
        this.setState({
          skip: false,
          editItem: null
        })
        this.props.form.setFieldsValue({
          sql: ''
        })
        this.props.cbScriptsChange(values)
      } else {
        this.setState({loading: true})
        if (!values.uuid) {
          if (values.position === 'front') {
            _prevCustomScript += `
            /* 默认sql前脚本 */
            ${values.sql}
            `
          } else {
            _backCustomScript += `
            /* 默认sql后脚本 */
            ${values.sql}
            `
          }
        }
        let sql = this.props.initsql +  _prevCustomScript + _backCustomScript + tail
        // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
        //   window.GLOB.funcs.forEach(item => {
        //     let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
        //     sql = sql.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
        //   })
        // }
        // 数据权限
        sql = sql.replace(/@\$|\$@/ig, '').replace(/\$check@|@check\$/ig, '')
        sql = sql.replace(/@datam@/ig, `''`)
        sql = sql.replace(/@typename@/ig, `'debug'`)
        if (skip) {
        this.props.cbScriptsChange(values, () => {
          this.setState({
            skip: false,
            loading: false,
            editItem: null
          }, () => {
            this.props.scriptsChange(values)
          })
          this.props.form.setFieldsValue({
            sql: ' '
            sql: ''
          })
        } else {
          this.setState({loading: true})
          Api.sDebug(sql).then(res => {
            if (res.status || res.ErrCode === '-2') {
              this.setState({
                loading: false,
                editItem: null
              }, () => {
                this.props.scriptsChange(values)
              })
              this.props.form.setFieldsValue({
                sql: ' '
              })
            } else {
              this.setState({loading: false})
              Modal.error({
                title: res.message
              })
            }
          })
        }
        }, () => {
          this.setState({loading: false})
        })
      }
    })
  }
@@ -170,7 +99,7 @@
    })
    this.props.form.setFieldsValue({
      sql: ' '
      sql: ''
    })
  }
@@ -280,15 +209,9 @@
            <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
          </Col>
          <Col span={24} className="sql">
            <Form.Item label="sql">
            <Form.Item label="sql" required>
              {getFieldDecorator('sql', {
                initialValue: '',
                rules: [
                  {
                    required: true,
                    message: '请输入sql!'
                  }
                ]
                initialValue: ''
              })(<CodeMirror />)}
            </Form.Item>
          </Col>
src/templates/zshare/verifycard/customform/index.jsx
@@ -1,24 +1,23 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Select, Button, notification, Modal, Tooltip } from 'antd'
import { Form, Row, Col, Input, Select, Button, notification, Tooltip, Switch } from 'antd'
import Api from '@/api'
import { checkSQL } from '@/utils/utils-custom.js'
import CodeMirror from '@/templates/zshare/codemirror'
// import './index.scss'
class CustomForm extends Component {
  static propTpyes = {
    btn: PropTypes.object,          // 按钮
    btn: PropTypes.object,
    formfields: PropTypes.string,
    colfields: PropTypes.string,
    initsql: PropTypes.string,      // 可用字段
    customChange: PropTypes.func    // 表单
    customChange: PropTypes.func
  }
  state = {
    editItem: null,
    loading: false
    loading: false,
    skip: false
  }
  edit = (record) => {
@@ -40,16 +39,17 @@
    })
    this.props.form.setFieldsValue({
      sql: ' ',
      sql: '',
      errmsg: ''
    })
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    const { skip, editItem } = this.state
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        if (/^[\s\n]+$/.test(values.sql)) {
        if (!values.sql || /^[\s\n]+$/.test(values.sql)) {
          notification.warning({
            top: 92,
            message: '请输入sql!',
@@ -58,55 +58,41 @@
          return
        }
        
        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
        values.uuid = editItem ? editItem.uuid : ''
        values.resultName = values.result === 'false' ? '不存在' : '存在'
        let pass = checkSQL(values.sql, 'customscript')
        if (!pass) return
        if (!pass && !skip) return
        let sql = `${this.props.initsql}
          /* 自定义验证 */
          select @tbid='', @ErrorCode='',@retmsg=''
          select top 1 @tbid='X' from (${values.sql}) a
          If @tbid = ''
          Begin
            select @ErrorCode='${values.errorCode}',@retmsg='${values.errmsg}'
            goto aaa
          end
          aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
        if (skip) {
          this.setState({
            skip: false,
            editItem: null
          })
          this.props.form.setFieldsValue({
            sql: '',
            errmsg: ''
          })
          this.props.customChange(values)
        } else {
          this.setState({loading: true})
        // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
        //   window.GLOB.funcs.forEach(item => {
        //     let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
        //     sql = sql.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
        //   })
        // }
        // 数据权限
        sql = sql.replace(/@\$|\$@/ig, '')
        this.setState({loading: true})
        Api.sDebug(sql).then(res => {
          if (res.status || res.ErrCode === '-2') {
          this.props.customChange(values, () => {
            this.setState({
              loading: false,
              editItem: null
            }, () => {
              this.props.customChange(values)
            })
            this.props.form.setFieldsValue({
              sql: ' ',
              sql: '',
              errmsg: ''
            })
          } else {
            this.setState({loading: false})
            Modal.error({
              title: res.message
          }, () => {
            this.setState({
              loading: false
            })
          }
        })
          })
        }
      }
    })
  }
@@ -114,6 +100,7 @@
  render() {
    const { formfields, colfields, btn } = this.props
    const { getFieldDecorator } = this.props.form
    const { skip } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -138,15 +125,9 @@
            </Form.Item>
          </Col>
          <Col span={21} className="sql">
            <Form.Item label="sql">
            <Form.Item label="sql" required>
              {getFieldDecorator('sql', {
                initialValue: '',
                rules: [
                  {
                    required: true,
                    message: '请输入sql!'
                  }
                ]
                initialValue: ''
              })(<CodeMirror />)}
            </Form.Item>
          </Col>
@@ -161,9 +142,13 @@
            {btn.sql ? <div style={{marginTop: '31px'}}>
              表名:  <div style={{wordBreak: 'break-all'}}>{btn.sql}</div>
            </div> : null}
            <div style={{paddingTop: '20px', fontSize: '12px'}}>
              强制保存:
              <Switch checked={skip} size="small" onChange={() => this.setState({skip: !skip})}/>
            </div>
          </Col>
          <Col span={7}>
            <Form.Item label={'结果处理'}>
            <Form.Item label="结果处理">
              {getFieldDecorator('result', {
                initialValue: 'true',
                rules: [
@@ -198,7 +183,7 @@
            </Form.Item>
          </Col>
          <Col span={7}>
            <Form.Item label={'报错编码'}>
            <Form.Item label="报错编码">
              {getFieldDecorator('errorCode', {
                initialValue: 'E',
                rules: [
@@ -219,7 +204,6 @@
              )}
            </Form.Item>
          </Col>
        </Row>
      </Form>
    )
src/templates/zshare/verifycard/customscript/index.jsx
@@ -1,9 +1,8 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select, Switch } from 'antd'
import { Form, Row, Col, Button, notification, Tooltip, Radio, Select, Switch } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import Api from '@/api'
import { checkSQL } from '@/utils/utils-custom.js'
import CodeMirror from '@/templates/zshare/codemirror'
import './index.scss'
@@ -14,11 +13,8 @@
    btn: PropTypes.object,
    formfields: PropTypes.string,
    colfields: PropTypes.string,
    initsql: PropTypes.string,
    defaultsql: PropTypes.string,
    useDefaultSql: PropTypes.any,
    getSysDefSql: PropTypes.func,
    systemScripts: PropTypes.array,
    customScripts: PropTypes.array,
    scriptsChange: PropTypes.func
  }
@@ -46,11 +42,13 @@
  }
  handleConfirm = () => {
    const { type, workFlow, flowType, flowSql, flowRemark, useDefaultSql, defaultsql } = this.props
    const { type } = this.props
    const { editItem, skip } = this.state
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (type === 'fullscreen' && err) {
      if (err) return
      if (!values.sql || /^[\s\n]+$/.test(values.sql)) {
        notification.warning({
          top: 92,
          message: '请输入sql!',
@@ -58,199 +56,43 @@
        })
        return
      }
      if (!err) {
        if (/^[\s\n]+$/.test(values.sql)) {
          notification.warning({
            top: 92,
            message: '请输入sql!',
            duration: 5
          })
          return
        }
        values.uuid = editItem ? editItem.uuid : ''
        values.position = values.position || (editItem ? editItem.position : 'front')
        if (type === 'fullscreen' && editItem) {
          values.status = editItem.status || 'true'
        }
      values.uuid = editItem ? editItem.uuid : ''
      values.position = values.position || (editItem ? editItem.position : 'front')
        let pass = checkSQL(values.sql, 'customscript')
      if (type === 'fullscreen' && editItem) {
        values.status = editItem.status || 'true'
      }
        if (!pass && !skip) return
      let pass = checkSQL(values.sql, 'customscript')
        let tail = `
          aaa:
        `
        let _initCustomScript = '' // 初始化脚本
        let _prevCustomScript = '' // 默认sql前执行脚本
        let _backCustomScript = '' // 默认sql后执行脚本
        this.props.customScripts.forEach(item => {
          let _item = values.uuid === item.uuid ? values : item
          if (_item.status === 'false') return
          if (_item.position === 'init') {
            _initCustomScript += `
            /* 初始化脚本 */
            ${_item.sql}
            `
          } else if (_item.position === 'front') {
            _prevCustomScript += `
            /* 默认sql前脚本 */
            ${_item.sql}
            `
          } else {
            _backCustomScript += `
            /* 默认sql后脚本 */
            ${_item.sql}
            `
          }
      if (!pass && !skip) return
      if (skip) {
        this.setState({
          skip: false,
          editItem: null
        })
        this.props.form.setFieldsValue({
          sql: ''
        })
        this.props.scriptsChange(values)
      } else {
        this.setState({loading: true})
        if (!values.uuid) {
          if (values.position === 'init') {
            _initCustomScript += `
            /* 初始化脚本 */
            ${values.sql}
            `
          } else if (values.position === 'front') {
            _prevCustomScript += `
            /* 默认sql前脚本 */
            ${values.sql}
            `
          } else {
            _backCustomScript += `
            /* 默认sql后脚本 */
            ${values.sql}
            `
          }
        }
        let sql = this.props.initsql + _initCustomScript + _prevCustomScript
        if (useDefaultSql) {
          sql += `\n/* 默认sql */
            ${defaultsql}
          `
        }
        if (window.GLOB.process && workFlow === 'true' && flowSql === 'true') {
          if (flowType === 'start') {
            sql += `
              /* 工作流默认sql */
              insert into s_my_works_flow (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,work_group,works_flow_detail_id,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
              select @ID@,@works_flow_code@,@works_flow_name@,@works_flow_param@,@status@,@statusname@,@work_group@,@works_flow_detail_id@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
              insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
              select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
              insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
              select @ID@,@works_flow_code@,@works_flow_detail_id@,@userid@,@start_type@,@userid@,@UserName,@FullName,@time_id@
              insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid,typecharone)
              select @ID@,@works_flow_code@,@userid@,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@,'begin'
            `
          } else {
            sql += `
              /* 工作流默认sql */
              update s_my_works_flow set status=@status@,statusname=@statusname@,works_flow_param=@works_flow_param@,works_flow_detail_id=@works_flow_detail_id@,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname${flowRemark ? ',remark=@' + flowRemark : ''}
              where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
              insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid${flowRemark ? ',remark' : ''})
              select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@${flowRemark ? ',@' + flowRemark : ''}
              update s_my_works_flow_role set deleted=10,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
              where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
              if @check_userids@ != ''
              begin
                    insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid)
                    select @ID@,@works_flow_code@,ID,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@check_userids@)
                    insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
                    select @ID@,@works_flow_code@,@works_flow_detail_id@,ID,@check_type@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@check_userids@)
              end
              if @notice_userids@ != ''
              begin
                    update n
                    set deleted=10,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
                    from (select * from s_my_works_flow_notice where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0) n
                    inner join (select ID from dbo.SplitComma(@notice_userids@)) s
                    on n.userid = s.id
                    insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
                    select @ID@,@works_flow_code@,@works_flow_detail_id@,ID,@notice_type@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@notice_userids@)
              end
            `
          }
        }
        sql += _backCustomScript + tail
        // if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
        //   window.GLOB.funcs.forEach(item => {
        //     let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
        //     sql = sql.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
        //   })
        // }
        // 数据权限
        sql = sql.replace(/@\$|\$@/ig, '').replace(/\$check@|@check\$/ig, '')
        sql = sql.replace(/@datam@/ig, `''`)
        sql = sql.replace(/@typename@/ig, `'debug'`)
        if (window.GLOB.process && workFlow === 'true') {
          sql = sql.replace(/@works_flow_code@/ig, `'works_flow_code'`)
          sql = sql.replace(/@works_flow_name@/ig, `'works_flow_name'`)
          sql = sql.replace(/@works_flow_param@/ig, `'works_flow_param'`)
          sql = sql.replace(/@works_flow_detail_id@/ig, `'works_flow_detail_id'`)
          sql = sql.replace(/@status@/ig, `0`)
          sql = sql.replace(/@statusname@/ig, `'开始'`)
          sql = sql.replace(/@work_group@/ig, `'work_group'`)
          sql = sql.replace(/@work_grade@/ig, '0')
          if (flowType === 'start') {
            sql = sql.replace(/@start_type@/ig, `'开始'`)
          } else {
            sql = sql.replace(/@check_type@/ig, `'审核'`)
            sql = sql.replace(/@notice_type@/ig, `'抄送'`)
            sql = sql.replace(/@check_userids@/ig, `''`)
            sql = sql.replace(/@notice_userids@/ig, `''`)
            sql = sql.replace(/@works_flow_sign@/ig, `''`)
          }
        }
        if (skip) {
        this.props.scriptsChange(values, () => {
          this.setState({
            skip: false,
            loading: false,
            editItem: null
          }, () => {
            this.props.scriptsChange(values)
          })
          this.props.form.setFieldsValue({
            sql: ' '
            sql: ''
          })
        } else {
          this.setState({loading: true})
          Api.sDebug(sql).then(res => {
            if (res.status || res.ErrCode === '-2') {
              this.setState({
                loading: false,
                editItem: null
              }, () => {
                this.props.scriptsChange(values)
              })
              this.props.form.setFieldsValue({
                sql: ' '
              })
            } else {
              this.setState({loading: false})
              Modal.error({
                title: res.message
              })
            }
        }, () => {
          this.setState({
            loading: false
          })
        }
        })
      }
    })
  }
@@ -261,12 +103,12 @@
    })
    this.props.form.setFieldsValue({
      sql: ' '
      sql: ''
    })
  }
  selectScript = (value, option) => {
    const { flowType, flowRemark } = this.props
    const { flowType, flowRemark, getSysDefSql } = this.props
    if (!value || !option) return
@@ -364,6 +206,11 @@
      }
      value = value.replace(/\n\s{8}/g, '\n')
    } else if (value === 'defaultsql') {
      value = ''
      if (getSysDefSql) {
        value = getSysDefSql()
      }
    }
    _sql = _sql.replace(/\s{6}$/, '')
@@ -443,7 +290,7 @@
                onSelect={this.selectScript}
                getPopupContainer={() => document.getElementById('verify-custom-scripts' + _type)}
              >
                <Select.Option key="default" value={this.props.defaultsql}>默认sql</Select.Option>
                <Select.Option key="default" value="defaultsql">默认sql</Select.Option>
                {window.GLOB.process && workFlow === 'true' ? <Select.Option key="flow" value="flowSql">默认sql(工作流)</Select.Option> : null}
                <Select.Option key="debugger" value={`z_debug: select @ErrorCode='E',@retmsg='测试断点' goto aaa`}>
                  测试断点
@@ -472,15 +319,9 @@
                <QuestionCircleOutlined className="mk-form-tip" />
                sql
              </Tooltip>
            }>
            } required>
              {getFieldDecorator('sql', {
                initialValue: '',
                rules: [
                  {
                    required: true,
                    message: '请输入sql!'
                  }
                ]
              })(<CodeMirror />)}
            </Form.Item>
          </Col>
src/templates/zshare/verifycard/index.jsx
@@ -36,7 +36,6 @@
  }
  state = {
    initsql: '',            // sql验证时变量声明及赋值
    verifyInter: 'system',  // 接口类型
    activeKey: 'base',
    appType: sessionStorage.getItem('appType'),
@@ -46,7 +45,6 @@
    fields: [],
    formfields: '',
    colfields: '',
    defaultsql: '',         // 默认Sql
    orderModular: [],
    orderModularDetail: [],
    voucher: [],
@@ -54,7 +52,6 @@
    systemScripts: [],
    columnsFields: [],
    unionFields: [],
    uniqueFields: [],  // 唯一性验证,表单字段
    uniqueColumns: [
      {
        title: '名称',
@@ -613,7 +610,15 @@
      _verify.limitInvalid = true
      _verify.limitText = '静态数据源,不可使用失效验证'
      _invalid = 'false'
    } else if (config.setting && config.setting.maxScript && config.setting.maxScript >= 300) {
    } else if (!config.setting || config.setting.interType !== 'system') {
      _verify.limitInvalid = true
      _verify.limitText = '数据源未使用系统接口,不能使用失效验证!'
      _invalid = 'false'
    } else if (config.setting.execute !== 'true' || !config.setting.dataresource) {
      _verify.limitInvalid = true
      _verify.limitText = '尚未添加数据源,不能使用失效验证!'
      _invalid = 'false'
    } else if (config.setting.maxScript && config.setting.maxScript >= 300) {
      _verify.limitInvalid = true
      _verify.limitText = '数据源中自定义脚本过于复杂,不能使用失效验证!'
      _invalid = 'false'
@@ -714,99 +719,93 @@
    let _fields = []
    if (card.OpenType === 'form') {
      _fields.push({
      let item = {
        field: card.field,
        label: card.label,
        type: 'text'
      })
    } else if (card.modal && (card.OpenType === 'pop' || !card.OpenType)) {
      _fields = card.modal.fields || []
    }
        type: 'text',
        writein: true,
        fieldlen: 50
      }
      if (card.formType === 'counter') {
        item.type = 'number'
        item.fieldlen = 0
      } else if (card.formType === 'switch' || card.formType === 'radio') {
        if (typeof(card.openVal) === 'number') {
          item.type = 'number'
          item.fieldlen = 0
        }
      }
    let sysfields = ['UserName', 'FullName', 'RoleID', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'ModularDetailCode', 'tbid', 'mk_deleted', 'bid', 'mk_submit_type']
    let _declare = ['@UserName nvarchar(50)', '@FullName nvarchar(50)', '@RoleID nvarchar(512)', '@mk_departmentcode nvarchar(512)', '@mk_organization nvarchar(512)', '@mk_user_type nvarchar(20)', '@mk_nation nvarchar(50)', '@mk_province nvarchar(50)', '@mk_city nvarchar(50)', '@mk_district nvarchar(50)', '@mk_address nvarchar(100)', '@ErrorCode nvarchar(50)', '@retmsg nvarchar(4000)', '@BillCode nvarchar(50)', '@BVoucher nvarchar(50)', '@FIBVoucherDate nvarchar(50)', '@FiYear nvarchar(50)', '@ModularDetailCode nvarchar(50)', '@bid nvarchar(50)', '@tbid nvarchar(50)', '@mk_deleted int', '@mk_submit_type nvarchar(50)']
    let _select = ['@UserName=\'\'', '@FullName=\'\'', '@RoleID=\'\'', '@mk_departmentcode=\'\'', '@mk_organization=\'\'', '@mk_user_type=\'\'', '@mk_nation=\'\'', '@mk_province=\'\'', '@mk_city=\'\'', '@mk_district=\'\'', '@mk_address=\'\'', '@ErrorCode=\'\'', '@retmsg=\'\'', '@BillCode=\'\'', '@BVoucher=\'\'', '@FIBVoucherDate=\'\'', '@FiYear=\'\'', '@ModularDetailCode=\'\'', '@bid=\'\'', '@mk_deleted=1', '@mk_submit_type=\'\'']
    let fieldArr = sysfields.map(_f => _f.toLowerCase())
    let hasBid = false
      _fields.push(item)
    } else if (card.modal && (card.OpenType === 'pop' || !card.OpenType)) {
      _fields = fromJS(card.modal.fields || []).toJS()
      _fields = _fields.filter(_f => {
        if (!_f.field) return false
        _f.writein = _f.writein !== 'false'
        _f.fieldlen = _f.fieldlength || 50
        if (_f.type === 'datemonth') {
          _f.type = 'text'
        } else if (_f.type === 'number' || _f.type === 'rate') {
          _f.fieldlen = _f.decimal || 0
        } else if (_f.type === 'date') {
          _f.type = _f.declareType === 'nvarchar(50)' ? 'text' : 'date'
        } else if (_f.type === 'datetime') {
          _f.type = 'date'
        } else if (_f.declare === 'decimal') {
          _f.type = 'number'
          _f.fieldlen = _f.decimal || 0
        }
        return true
      })
    }
    let verIndex = _fields.findIndex(item => item.type === 'vercode')
    if (verIndex > -1) {
      _fields = fromJS(_fields).toJS()
      _fields.splice(verIndex, 0, {
        type: 'text',
        fieldlength: 50,
        writein: 'false',
        fieldlen: 50,
        writein: false,
        field: 'mk_timestamp'
      }, {
        type: 'text',
        fieldlength: 50,
        writein: 'false',
        fieldlen: 50,
        writein: false,
        field: 'mk_send_type'
      }, {
        type: 'text',
        fieldlength: 50,
        writein: 'false',
        fieldlen: 50,
        writein: false,
        field: 'mk_n_id'
      })
    }
    let sysfields = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'mk_deleted', 'bid', 'mk_submit_type']
    let hasBid = false
    let formfields = []
    _fields = _fields.filter(_f => _f.field)
    _fields.forEach(_f => {
      let key = _f.field.toLowerCase()
      if (key === 'bid') {
        hasBid = true
      }
      if (fieldArr.includes(key)) return
      fieldArr.push(key)
      if (sysfields.includes(key)) return
      formfields.push(_f.field)
      let _fieldlen = _f.fieldlength || 50
      if (_f.type === 'number') {
        _fieldlen = _f.decimal ? _f.decimal : 0
      }
      if (_fieldlen > 4000) {
        _fieldlen = 'max'
      }
      let _type = `nvarchar(${_fieldlen})`
      if (_f.type.match(/date/ig)) {
        _type = 'datetime'
        _select.push(`@${_f.field}='1949-10-01'`)
      } else if (_f.type === 'number') {
        _type = `decimal(18,${_fieldlen})`
        _select.push(`@${_f.field}=1`)
      } else if (_f.declare === 'decimal') {
        _type = `decimal(18,${_f.decimal || 0})`
        _select.push(`@${_f.field}=1`)
      } else if (_f.type === 'rate') {
        _type = `decimal(18,2)`
        _select.push(`@${_f.field}=1`)
      } else {
        _select.push(`@${_f.field}=''`)
      }
      if (['appkey'].includes(key)) return
      _declare.push(`@${_f.field} ${_type}`)
    })
    let uniqueFields = fromJS(_fields).toJS()
    if (!hasBid) { // 唯一性验证添加BID
      uniqueFields.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
      _fields.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text' })
    if (!hasBid) {
      _fields.unshift({ uuid: 'BID', field: 'BID', label: 'BID', type: 'text', writein: false, fieldlen: 50 })
    }
    let unionFields = fromJS(_fields).toJS()
    let formArr = _fields.map(_f => _f.field.toLowerCase())
    let fieldArr = [...sysfields, ...formArr]
    let colfields = []
    if (card.Ot !== 'notRequired' && columns) {
@@ -815,215 +814,14 @@
        let key = _f.field.toLowerCase()
        if (!formArr.includes(key)) {
          formArr.push(key)
          unionFields.push(_f)
        }
        if (formArr.includes(key)) return
        unionFields.push(_f)
        if (fieldArr.includes(key)) return
        fieldArr.push(key)
        colfields.push(_f.field)
        if (_f.datatype) { // 自定义字段
          if (/decimal|int/ig.test(_f.datatype)) {
            _select.push(`@${_f.field}=1`)
          } else if (/date/ig.test(_f.datatype)) {
            _select.push(`@${_f.field}='1949-10-01'`)
          } else {
            _select.push(`@${_f.field}=''`)
          }
          if (['appkey'].includes(key)) return
          _declare.push(`@${_f.field} ${_f.datatype}`)
        } else {
          let _fieldlen = _f.fieldlength || 50
          if (_fieldlen > 4000) {
            _fieldlen = 'max'
          }
          let _type = `nvarchar(${_fieldlen})`
          if (_f.type === 'number') {
            _type = `decimal(18,${_f.decimal ? _f.decimal : 0})`
          } else if (_f.type === 'picture' || _f.type === 'textarea') {
            _type = `nvarchar(${_fieldlen})`
          }
          if (_f.type === 'number') {
            _select.push(`@${_f.field}=1`)
          } else {
            _select.push(`@${_f.field}=''`)
          }
          if (['appkey'].includes(key)) return
          _declare.push(`@${_f.field} ${_type}`)
        }
      })
    }
    let _sql = `Declare ${_declare.join(', ')}
      Select ${_select.join(', ')}
    `
    // 默认sql
    let _defaultsql = ''
    let _insertsql = ''
    let _updatesql = ''
    let _primaryKey = config.setting.primaryKey || 'id'
    if (this.props.side === 'sub') {
      _primaryKey = config.setting.subKey || 'id'
    }
    if (card.sqlType === 'insert' || card.sqlType === 'insertOrUpdate') {
      let keys = []
      let values = []
      _fields.forEach(item => {
        if (!item.field || item.writein === 'false') return
        keys.push(item.field.toLowerCase())
        if (item.field.toLowerCase() === 'bid' && item.uuid === 'BID') {
          values.push('@BID@')
        } else {
          values.push('@' + item.field)
        }
      })
      if (!keys.includes(_primaryKey.toLowerCase())) {
        keys.push(_primaryKey.toLowerCase())
        values.push('@ID@')
      }
      if (!keys.includes('createuserid')) {
        keys.push('createuserid')
        values.push('@userid@')
      }
      if (!keys.includes('createuser')) {
        keys.push('createuser')
        values.push('@username')
      }
      if (!keys.includes('createstaff')) {
        keys.push('createstaff')
        values.push('@fullname')
      }
      if (!keys.includes('bid')) {
        keys.push('bid')
        values.push('@BID@')
      }
      if (!keys.includes('typename')) {
        keys.push('typename')
        values.push('@typename@')
      }
      keys = keys.join(', ')
      values = values.join(', ')
      _insertsql = `insert into ${card.sql} (${keys}) select ${values};`
    }
    if (card.sqlType === 'update' || card.sqlType === 'audit' || card.sqlType === 'insertOrUpdate') {
      let _form = []
      let _arr = []
      _fields.forEach(item => {
        if (!item.field || item.writein === 'false' || item.uuid === 'BID') return
        _arr.push(item.field.toLowerCase())
        if (item.field.toLowerCase() === 'bid') {
          _form.push(item.field + '=@BID@')
        } else {
          _form.push(item.field + '=@' + item.field)
        }
      })
      if (this.props.card.sqlType === 'audit') {
        if (!_arr.includes('submitdate')) {
          _form.push('submitdate=getdate()')
        }
        if (!_arr.includes('submituser')) {
          _form.push('submituser=@username')
        }
        if (!_arr.includes('submitstaff')) {
          _form.push('submitstaff=@fullname')
        }
        if (!_arr.includes('submituserid')) {
          _form.push('submituserid=@userid@')
        }
        if (!_arr.includes('typename')) {
          _form.push(`typename=@typename@`)
        }
      } else {
        if (!_arr.includes('modifydate')) {
          _form.push('modifydate=getdate()')
        }
        if (!_arr.includes('modifyuser')) {
          _form.push('modifyuser=@username')
        }
        if (!_arr.includes('modifystaff')) {
          _form.push('modifystaff=@fullname')
        }
        if (!_arr.includes('modifyuserid')) {
          _form.push('modifyuserid=@userid@')
        }
        if (!_arr.includes('typename')) {
          _form.push(`typename=@typename@`)
        }
      }
      if (_verify.voucher && _verify.voucher.enabled) {
        if (!_arr.includes('bvoucher')) {
          _form.push('BVoucher=@BVoucher')
        }
        if (!_arr.includes('fibvoucherdate')) {
          _form.push('FIBVoucherDate=@FIBVoucherDate')
        }
        if (!_arr.includes('fiyear')) {
          _form.push('FiYear=@FiYear')
        }
      }
      _form = _form.join(', ')
      _updatesql = `update ${card.sql} set ${_form} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
    }
    if (card.sqlType === 'insert') {
      _defaultsql = _insertsql
    } else if (card.sqlType === 'update' || card.sqlType === 'audit') {
      _defaultsql = _updatesql
    } else if (card.sqlType === 'insertOrUpdate') {
      _defaultsql += `select @tbid=''
        select @tbid='X' from ${card.sql} where ${_primaryKey}=@ID@
        if @tbid=''
          begin
          ${_insertsql}
          end
        else
          begin
          ${_updatesql}
          end
      `
    } else if (card.sqlType === 'LogicDelete' || card.sqlType === 'custom') {
      let _voucher = ''
      if (_verify.voucher && _verify.voucher.enabled) {
        _voucher = ',BVoucher=@BVoucher,FIBVoucherDate=@FIBVoucherDate,FiYear=@FiYear'
      }
      _defaultsql = `update ${card.sql} set deleted=@mk_deleted,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@${_voucher} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
    } else if (card.sqlType === 'delete') {
      let _msg = ''
      if (columns && columns.length > 0 && card.Ot !== 'notRequired') {
        let _index = 0
        columns.forEach(col => {
          if (!col.field || col.Hide === 'true' || _index >= 4) return
          _msg += col.label + '=\'\','
          _index++
        })
      }
      _defaultsql += `insert into snote (remark,createuserid,CreateUser,CreateStaff,typename) select left('删除表:${card.sql} 数据: ${_msg}${_primaryKey}='+@ID@,200),@userid@,@username,@fullname,@typename@ delete ${card.sql} where ${_primaryKey}${card.Ot !== 'requiredOnce' ? '=@ID@' : ' in (select ID  from dbo.SplitComma(@ID@))'};`
    }
    let _columns = []
@@ -1046,13 +844,11 @@
    this.setState({
      fields: _fields,
      columnsFields: _columns,
      initsql: _sql,
      defaultsql: _defaultsql,
      formfields: formfields.join(', '),
      colfields: colfields.join(', '),
      uniqueColumns: this.state.uniqueColumns.map(col => {
        if (col.dataIndex === 'field') {
          col.options = uniqueFields
          col.options = _fields
        }
        return col
      }),
@@ -1062,8 +858,7 @@
        }
        return col
      }),
      unionFields,
      uniqueFields
      unionFields
    })
  }
@@ -1172,6 +967,1011 @@
    })
  }
  getSysExecSql = (verify, retmsg) => {
    const { columns, config, card } = this.props
    const { fields } = this.state
    let btn = card
    let primaryId = Utils.getuuid()
    let BID = Utils.getuuid()
    let _actionType = null
    let setting = config.setting || {}
    if (verify.uniques && verify.uniques.length > 0 && btn.Ot === 'requiredOnce') {
      if (config.wrap && (config.wrap.datatype === 'static' || config.wrap.datatype === 'public')) {
        verify.uniques = []
      }
    }
    if (verify.default !== 'false') { // 判断是否使用默认sql
      _actionType = btn.sqlType
    }
    let _initCustomScript = '' // 初始化脚本
    let _prevCustomScript = '' // 默认sql前执行脚本
    let _backCustomScript = '' // 默认sql后执行脚本
    verify.scripts && verify.scripts.forEach(item => {
      if (item.status === 'false') return
      if (item.position === 'init') {
        _initCustomScript += `
        /* 自定义脚本 */
        ${item.sql}
        `
      } else if (item.position === 'front') {
        _prevCustomScript += `
        /* 自定义脚本 */
        ${item.sql}
        `
      } else {
        _backCustomScript += `
        /* 自定义脚本 */
        ${item.sql}
        `
      }
    })
    // 需要声明的变量集
    let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'mk_deleted', 'bid', 'mk_submit_type']
    // 主键字段
    let primaryKey = setting.primaryKey || 'id'
    if (this.props.side === 'sub') {
      primaryKey = setting.subKey || 'id'
    }
    // sql语句
    let _sql = ''
    let _initvars = [] // 已赋值字段集
    let _initFormfields = []
    let _initColfields = []
    let _declarefields = []
    let formdata = fields.filter(item => item.uuid !== 'BID')
    formdata = formdata.length ? formdata : null
    // 获取字段键值对
    formdata && formdata.forEach(form => {
      let _key = form.field.toLowerCase()
      if (!_initvars.includes(_key)) {
        _initvars.push(_key)
        if (form.type === 'number' || form.type === 'rate') {
          _initFormfields.push(`@${form.field}=1`)
        } else if (form.type === 'date') {
          _initFormfields.push(`@${form.field}='1949-10-01'`)
        } else if (form.type === 'select' || form.type === 'link' || form.type === 'radio') {
          _initFormfields.push(`@${form.field}='1'`)
        } else {
          _initFormfields.push(`@${form.field}='mk'`)
        }
      }
      if (!_vars.includes(_key)) {
        _vars.push(_key)
        if (form.fieldlen && form.fieldlen > 4000) {
          form.fieldlen = 'max'
        }
        let _type = `nvarchar(${form.fieldlen})`
        if (form.type.match(/date/ig)) {
          _type = 'datetime'
        } else if (form.type === 'number') {
          _type = `decimal(18,${form.fieldlen})`
        } else if (form.type === 'rate') {
          _type = `decimal(18,2)`
        }
        if (['appkey'].includes(_key)) return
        _declarefields.push(`@${form.field} ${_type}`)
      }
    })
    // 添加数据中字段,表单值优先(按钮不选行或多行拼接时跳过)
    if (btn.Ot !== 'notRequired' && columns.length > 0) {
      columns.forEach(col => {
        if (!col.field) return
        let _key = col.field.toLowerCase()
        if (!_initvars.includes(_key)) {
          _initvars.push(_key)
          if (col.datatype && /^date/ig.test(col.datatype)) {
            _initColfields.push(`@${col.field}='1949-10-01'`)
          } else if (col.type === 'number') {
            _initColfields.push(`@${col.field}=1`)
          } else {
            _initColfields.push(`@${col.field}='mk'`)
          }
        }
        if (!_vars.includes(_key) && !['appkey'].includes(_key)) {
          _vars.push(_key)
          _declarefields.push(`@${col.field} ${col.datatype || 'nvarchar(50)'}`)
        }
      })
    }
    // 变量声明
    _declarefields = _declarefields.join(',')
    if (_declarefields) {
      _declarefields = ',' + _declarefields
    }
    _sql = `Declare @tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50),@ModularDetailCode nvarchar(50), @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@mk_deleted int,@bid nvarchar(50),@mk_submit_type nvarchar(50)${_declarefields}
      `
    let userName = 'User_Name'
    let fullName = 'Full_Name'
    let RoleID = 'role_id'
    let departmentcode = 'departmentcode'
    let organization = 'organization'
    let mk_user_type = 'mk_user_type'
    let nation = 'nation'
    let province = 'province'
    let city = 'city'
    let district = 'district'
    let address = 'address'
    // 初始化凭证及用户信息字段
    _sql += `
        /* 凭证及用户信息初始化赋值 */
        select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @mk_deleted=1, @bid='${BID}', @mk_submit_type='', @BillCode='', @ModularDetailCode=''
        `
    // 表单变量赋值
    if (_initFormfields.length > 0) {
      _sql += `
        /* 表单变量赋值 */
        select ${_initFormfields.join(',')}
        `
    }
    // 显示列变量赋值
    if (_initColfields.length > 0) {
      _sql += `
        /* 显示列变量赋值 */
        select ${_initColfields.join(',')}
        `
    }
    if (retmsg) {
      return _sql
    }
    // 去除禁用的验证
    if (verify.contrasts) {
      verify.contrasts = verify.contrasts.filter(item => item.status !== 'false')
    }
    if (verify.uniques) {
      verify.uniques = verify.uniques.filter(item => item.status !== 'false')
    }
    if (verify.customverifys) {
      verify.customverifys = verify.customverifys.filter(item => item.status !== 'false')
    }
    if (verify.billcodes) {
      verify.billcodes = verify.billcodes.filter(item => item.status !== 'false')
    }
    if (_initCustomScript) {
      _sql += _initCustomScript
    }
    // 启用账期验证
    if (verify.accountdate === 'true') {
      let orgcode = `''`
      let date = `''`
      if (verify.accountfield && _initvars.includes(verify.accountfield.toLowerCase())) {
        orgcode = '@' + verify.accountfield
      }
      if (verify.voucherdate && _initvars.includes(verify.voucherdate.toLowerCase())) {
        date = '@' + verify.voucherdate
      }
      _sql += `
        /* 账期验证 */
        exec s_FIBVoucherDateCheck @OrgCode=${orgcode},@FIBVoucherDate=${date},@ErrorCode=@ErrorCode OUTPUT,@retmsg=@retmsg OUTPUT
        if @ErrorCode!=''
          GOTO aaa
        `
    }
    // 失效验证,添加数据时不用
    if (verify.invalid === 'true') {
      let datasource = setting.dataresource
      let customScript = ''
      config.scripts && config.scripts.forEach(script => {
        if (script.status === 'false' || script.position === 'back') return
        customScript += `
        ${script.sql}
        `
      })
      if (/\s/.test(datasource)) {
        datasource = '(' + datasource + ') tb'
      }
      let regoptions = [{
        reg: new RegExp('@userName@', 'ig'),
        value: `'${userName}'`
      }, {
        reg: new RegExp('@fullName@', 'ig'),
        value: `'${fullName}'`
      }, {
        reg: new RegExp('@orderBy@', 'ig'),
        value: setting.order || primaryKey
      }, {
        reg: new RegExp('@pageSize@', 'ig'),
        value: 1
      }, {
        reg: new RegExp('@pageIndex@', 'ig'),
        value: 1
      }]
      regoptions.forEach(item => {
        datasource = datasource.replace(item.reg, item.value)
        customScript = customScript.replace(item.reg, item.value)
      })
      if (customScript) {
        _sql += `
        /* 数据源自定义脚本,请注意变量定义是否重复 */
        ${customScript}
        `
      }
      if (btn.Ot === 'requiredOnce') {
        _sql += `
        /* 失效验证 */
        select @tbid='', @ErrorCode='',@retmsg=''
        select @tbid='X' from ${datasource} right join (select ID from  dbo.SplitComma(@ID@)) sp
        on tb.${primaryKey} =sp.id where tb.${primaryKey} is null
        If @tbid!=''
        Begin
          select @ErrorCode='E',@retmsg='数据已失效'
          goto aaa
        end
        `
      } else {
        _sql += `
        /* 失效验证 */
        select @tbid='', @ErrorCode='',@retmsg=''
        select @tbid=${primaryKey} from ${datasource} where ${primaryKey}=@ID@
        If @tbid=''
        Begin
          select @ErrorCode='E',@retmsg='数据已失效'
          goto aaa
        end
        `
      }
    }
    // 比较验证
    if (verify.contrasts && verify.contrasts.length > 0) {
      verify.contrasts.forEach(item => {
        _sql += `
        /* 比较验证 */
        If ${item.frontfield} ${item.operator} ${item.backfield}
        Begin
          select @ErrorCode='${item.errorCode}',@retmsg='${item.errmsg}'
            goto aaa
        end
        `
      })
    }
    // 自定义验证
    verify.customverifys && verify.customverifys.forEach(item => {
      _sql += `
        /* 自定义验证 */
        select @tbid='', @ErrorCode='',@retmsg=''
        select top 1 @tbid='X' from (${item.sql}) a
        If @tbid ${item.result === 'true' ? '!=' : '='}''
        Begin
          select @ErrorCode='${item.errorCode}',@retmsg='${item.errmsg}'
          goto aaa
        end
        `
    })
    // 单号生成,使用上级id(BID)或列表数据,声明变量(检验)
    let _billcodesSql  = ''
    if (formdata && verify.billcodes && verify.billcodes.length > 0) {
      let keys = formdata.map(item => item.field.toLowerCase()) // 表单字段
      verify.billcodes.forEach(item => {
        let _key = item.field.toLowerCase()
        let _linkKey = item.linkField ? item.linkField.toLowerCase() : ''
        if (!keys.includes(_key)) return // 表单中不含单号生成字段
        let _lpline = ''
        if (item.TypeCharOne === 'Lp') {
          if (_linkKey === 'bid' && BID) { // 替换bid
            _lpline = `set @ModularDetailCode= 'Lp'+ right('${item.mark || btn.uuid}'+@BID@,48)`
          } else {
            _lpline = `set @ModularDetailCode= 'Lp'+ right('${item.mark || btn.uuid}'+@${_linkKey},48)`
          }
        } else if (item.TypeCharOne === 'BN') {
          if (_linkKey === 'bid' && BID) { // 替换bid
            _lpline = `set @ModularDetailCode= 'BN'+ right(@BID@,48)`
          } else {
            _lpline = `set @ModularDetailCode= 'BN'+ right(@${_linkKey},48)`
          }
        } else {
          _lpline = `set @ModularDetailCode= right('${item.ModularDetailCode}',50)`
        }
        _billcodesSql += `
        /* 单号生成 */
        select @BillCode='', @${_key}='', @ModularDetailCode=''
        ${_lpline}
        exec s_get_BillCode
          @ModularDetailCode=@ModularDetailCode,
          @Type=${item.Type},
          @TypeCharOne='${item.TypeCharOne}',
          @TypeCharTwo ='${item.TypeCharTwo}',
          @BillCode =@BillCode output,
          @ErrorCode =@ErrorCode output,
          @retmsg=@retmsg output
        if @ErrorCode!=''
          goto aaa
        set @${_key}=@BillCode
        `
      })
      if (_actionType !== 'insertOrUpdate') {
        _sql += _billcodesSql
      }
    }
    // 唯一性验证,必须存在表单(表单存在时,主键均为单值),必须填写数据源,多行拼接时不可用
    if (formdata && verify.uniques && verify.uniques.length > 0 && btn.Ot !== 'requiredOnce') {
      let dateForms = []
      let numForms = []
      formdata.forEach(form => {
        let _key = form.field.toLowerCase()
        if (form.type === 'date') {
          dateForms.push(_key)
        } else if (form.type === 'number' || form.type === 'rate') {
          numForms.push(_key)
        }
      })
      verify.uniques.forEach(item => {
        let _fieldValue = []                     // 表单键值对field=value
        let _value = []                          // 表单值,用于错误提示
        let _labels = item.fieldlabel.split(',') // 表单提示文字
        let arr = [] // 验证主键
        item.field.split(',').forEach((_field, index) => {
          let _key = _field.toLowerCase()
          let _val = ''
          arr.push(_key)
          if (_key === 'bid') { // 表单中没有bid则使用系统bid变量
            _val = BID
          } else if (numForms.includes(_key)) {
            _val = '1'
          } else if (dateForms.includes(_key)) {
            _val = '1949-10-01'
          }
          _fieldValue.push(`${_key}='${_val}'`)
          _value.push(`${_labels[index] || ''}:${_val || ''}`)
        })
        if (!arr.includes(primaryKey.toLowerCase())) {
          _fieldValue.push(`${primaryKey} !='${primaryId}'`)
        }
        _sql += `
        /* 唯一性验证 */
        select @tbid='', @ErrorCode='',@retmsg=''
        select @tbid='X' from ${btn.sql} where ${_fieldValue.join(' and ')}${item.verifyType === 'logic' ? ' and deleted=0' : ''}
        If @tbid!=''
        Begin
          select @ErrorCode='${item.errorCode}',@retmsg='${_value.join(', ')} 已存在'
          goto aaa
        end
        `
      })
    } else if (verify.uniques && verify.uniques.length > 0 && btn.Ot === 'requiredOnce' && setting.dataresource) {
      let datasource = setting.dataresource
      if (/\s/.test(datasource)) { // 拼接别名
        if (!/tb$/.test(datasource)) {
          datasource = '(' + datasource + ') tb'
        }
      } else {
        datasource = datasource + ' tb'
      }
      if (setting.customScript) {
        _sql += `
        /* 数据源自定义脚本,请注意变量定义是否重复 */
        ${setting.customScript}
        `
      }
      verify.uniques.forEach(item => {
        _sql += `
        /* 同类数据验证 */
        Set @tbid=''
        Select top 1 @tbid='X' from (select distinct ${item.field},1 as n from ${datasource} inner join (select ID from  dbo.SplitComma(@ID@)) sp on tb.${primaryKey}=sp.ID ) a having sum(n)>1
        If @tbid!=''
        Begin
          Set @ErrorCode='E' Set @retmsg='${item.fieldlabel} 值不唯一'
          goto aaa
        end
        `
      })
    }
    let hasvoucher = false
    // 凭证-显示列中选取,必须选行
    if (verify.voucher && verify.voucher.enabled && btn.Ot !== 'requiredOnce') {
      let _voucher = verify.voucher
      hasvoucher = true
      _sql += `
        /* 创建凭证 */
        exec s_BVoucher_Create
          @Bill ='0',
          @BVoucherType ='${_voucher.BVoucherType}',
          @VoucherTypeOne ='${_voucher.VoucherTypeOne}',
          @VoucherTypeTwo ='${_voucher.VoucherTypeTwo}',
          @Type =${_voucher.Type},
          @UserID=@UserID@,
          @Username=@Username,
          @FullName=@FullName,
          @BVoucher =@BVoucher OUTPUT ,
          @FIBVoucherDate =@FIBVoucherDate OUTPUT ,
          @FiYear =@FiYear OUTPUT ,
          @ErrorCode =@ErrorCode OUTPUT,
          @retmsg=@retmsg OUTPUT
        if @ErrorCode!=''
          GOTO aaa
        `
    }
    let _insertsql = ''
    if (_actionType === 'insert' || _actionType === 'insertOrUpdate') { // 添加语句
      let keys = []
      let values = []
      formdata.forEach(item => {
        if (item.writein === false) return
        let _key = item.field.toLowerCase()
        keys.push(_key)
        values.push('@' + _key)
      })
      if (!keys.includes(primaryKey.toLowerCase())) {
        keys.push(primaryKey.toLowerCase())
        values.push('\'' + primaryId + '\'')
      }
      if (!keys.includes('createuserid')) {
        keys.push('createuserid')
        values.push('@userid@')
      }
      if (!keys.includes('createuser')) {
        keys.push('createuser')
        values.push('@username')
      }
      if (!keys.includes('createstaff')) {
        keys.push('createstaff')
        values.push('@fullname')
      }
      if (!keys.includes('bid')) {
        keys.push('bid')
        values.push('@BID@')
      }
      if (!keys.includes('typename')) {
        keys.push('typename')
        values.push('@typename@')
      }
      keys = keys.join(',')
      values = values.join(',')
      _insertsql = `insert into ${btn.sql} (${keys}) select ${values};`
    }
    let _updatesql = ''
    if (_actionType === 'update' || _actionType === 'audit' || _actionType === 'insertOrUpdate') { // 修改语句
      let _form = []
      let _arr = []
      formdata.forEach(item => {
        if (item.writein === false) return
        let _key = item.field.toLowerCase()
        _arr.push(_key)
        _form.push(_key + '=@' + _key)
      })
      if (_actionType === 'audit') {
        if (!_arr.includes('submitdate')) {
          _form.push('submitdate=getdate()')
        }
        if (!_arr.includes('submituser')) {
          _form.push('submituser=@username')
        }
        if (!_arr.includes('submitstaff')) {
          _form.push('submitstaff=@fullname')
        }
        if (!_arr.includes('submituserid')) {
          _form.push('submituserid=@userid@')
        }
      } else {
        if (!_arr.includes('modifydate')) {
          _form.push('modifydate=getdate()')
        }
        if (!_arr.includes('modifyuser')) {
          _form.push('modifyuser=@username')
        }
        if (!_arr.includes('modifystaff')) {
          _form.push('modifystaff=@fullname')
        }
        if (!_arr.includes('modifyuserid')) {
          _form.push('modifyuserid=@userid@')
        }
      }
      if (hasvoucher) {
        if (!_arr.includes('bvoucher')) {
          _form.push('BVoucher=@BVoucher')
        }
        if (!_arr.includes('fibvoucherdate')) {
          _form.push('FIBVoucherDate=@FIBVoucherDate')
        }
        if (!_arr.includes('fiyear')) {
          _form.push('FiYear=@FiYear')
        }
      }
      if (!_arr.includes('typename')) {
        _form.push('typename=@typename@')
      }
      _form = _form.join(',')
      let _ID = '=@ID@'
      if (btn.Ot === 'requiredOnce') {
        _ID = ' in (select ID from  dbo.SplitComma(@ID@))'
      }
      _updatesql = `update ${btn.sql} set ${_form} where ${primaryKey}${_ID};`
    }
    if (_prevCustomScript) {
      _sql += _prevCustomScript
    }
    // 添加、修改、逻辑删除、物理删除
    if (_actionType === 'insert') {
      _sql += `
        /* 默认sql */
        ${_insertsql}`
    } else if (_actionType === 'update' || _actionType === 'audit') {
      _sql += `
        /* 默认sql */
        ${_updatesql}`
    } else if (_actionType === 'LogicDelete') { // 逻辑删除
      let _ID = '=@ID@'
      if (btn.Ot === 'requiredOnce') {
        _ID = ' in (select ID from  dbo.SplitComma(@ID@))'
      }
      _sql += `
        /* 默认sql */
        update ${btn.sql} set deleted=@mk_deleted,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@ where ${primaryKey}${_ID};`
    } else if (_actionType === 'delete') {      // 物理删除
      let _msg = ''
      if (columns && columns.length > 0 && btn.Ot !== 'notRequired') {
        let _index = 0
        columns.forEach(col => {
          if (!col.field || col.Hide === 'true' || _index >= 4 || col.field === primaryKey) return
          _msg += col.label + '=0,'
          _index++
        })
      }
      let _ID = '=@ID@'
      if (btn.Ot === 'requiredOnce') {
        _ID = ' in (select ID from  dbo.SplitComma(@ID@))'
      }
      _sql += `
        /* 默认sql */
        insert into snote (remark,createuserid,CreateUser,CreateStaff,typename) select left('删除表:${btn.sql} 数据: ${_msg}${primaryKey}='+@ID@,200),@userid@,@username,@fullname,@typename@
        delete ${btn.sql} where ${primaryKey}${_ID};`
    } else if (_actionType === 'insertOrUpdate') {
      _sql += `
        /* 默认sql */
        select @tbid=''
        select @tbid='X' from ${btn.sql} where ${primaryKey}=@ID@
        if @tbid=''
          begin
          ${_billcodesSql}
          ${_insertsql}
          end
        else
          begin
          ${_updatesql}
          end
      `
    }
    if (verify.workFlow === 'true' && window.GLOB.process) {
      let status = 888
      let statusName = '结束'
      let detailId = '0'
      if (verify.flowSql === 'true') {
        if (verify.flowType === 'start') {
          _sql += `
            /* 工作流默认sql */
            insert into s_my_works_flow (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,work_group,works_flow_detail_id,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
            select @ID@,@works_flow_code@,@works_flow_name@,@works_flow_param@,@status@,@statusname@,@work_group@,@works_flow_detail_id@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
            insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
            select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
            insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
            select @ID@,@works_flow_code@,@works_flow_detail_id@,@userid@,@start_type@,@userid@,@UserName,@FullName,@time_id@
            insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid,typecharone)
            select @ID@,@works_flow_code@,@userid@,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@,'begin'
          `
        } else {
          _sql += `
            /* 工作流默认sql */
            update s_my_works_flow set status=@status@,statusname=@statusname@,works_flow_param=@works_flow_param@,works_flow_detail_id=@works_flow_detail_id@,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname${verify.flowRemark ? ',remark=@' + verify.flowRemark : ''}
            where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
            insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid${verify.flowRemark ? ',remark' : ''})
            select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@${verify.flowRemark ? ',@' + verify.flowRemark : ''}
            update s_my_works_flow_role set deleted=10,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
            where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
            if @check_userids@ != ''
            begin
                  insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid)
                  select @ID@,@works_flow_code@,ID,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@check_userids@)
                  insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
                  select @ID@,@works_flow_code@,@works_flow_detail_id@,ID,@check_type@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@check_userids@)
            end
            if @notice_userids@ != ''
            begin
                  update n
                  set deleted=10,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
                  from (select * from s_my_works_flow_notice where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0) n
                  inner join (select ID from dbo.SplitComma(@notice_userids@)) s
                  on n.userid = s.id
                  insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
                  select @ID@,@works_flow_code@,@works_flow_detail_id@,ID,@notice_type@,@userid@,@UserName,@FullName,@time_id@ from dbo.SplitComma(@notice_userids@)
            end
          `
        }
      }
      if (_backCustomScript) {
        _sql += _backCustomScript
      }
      _sql = _sql.replace(/@works_flow_code@/ig, `'mk'`)
      _sql = _sql.replace(/@works_flow_name@/ig, `'mk'`)
      _sql = _sql.replace(/@works_flow_param@/ig, `''`)
      _sql = _sql.replace(/@works_flow_detail_id@/ig, `'${detailId}'`)
      _sql = _sql.replace(/@status@/ig, `'${status}'`)
      _sql = _sql.replace(/@statusname@/ig, `'${statusName}'`)
      _sql = _sql.replace(/@work_group@/ig, `'mk'`)
      _sql = _sql.replace(/@work_grade@/ig, `'0'`)
      if (verify.flowType === 'start') {
        _sql = _sql.replace(/@start_type@/ig, `'开始'`)
      } else {
        _sql = _sql.replace(/@check_type@/ig, `'审核'`)
        _sql = _sql.replace(/@notice_type@/ig, `'抄送'`)
        _sql = _sql.replace(/@check_userids@/ig, `''`)
        _sql = _sql.replace(/@notice_userids@/ig, `''`)
        _sql = _sql.replace(/@works_flow_sign@/ig, `''`)
      }
    } else if (_backCustomScript) {
      _sql += _backCustomScript
    }
    if (btn.procMode === 'system') {
      _sql += `
        aaa: if @ErrorCode!=''
        insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@`
    } else if (btn.output) {
      _sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${btn.output} as mk_b_id`
    } else {
      _sql += `
        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    }
    _sql = _sql.replace(/@ID@/ig, `'${primaryId || ''}'`)
    _sql = _sql.replace(/@BID@/ig, `'${BID}'`)
    _sql = _sql.replace(/@typename@/ig, `'typename'`)
    _sql = _sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
    return _sql
  }
  getSysBackSql = (scripts, cbTable) => {
    let _prev = ''
    let _back = ''
    scripts.forEach(script => {
      if (script.status === 'false') return
      if (script.position === 'front') {
        _prev += `
      /* 自定义脚本 */
      ${script.sql}
      `
      } else {
        _back += `
      /* 自定义脚本 */
      ${script.sql}
      `
      }
    })
    if (!_prev) return _back
    let tbs = []
    _prev.replace(/\/\*[^/*]+\*\//g, '').replace(/\n|\r/g, ' ').split(/\sdeclare\s/ig).forEach(line => {
      if (!/^\s*(@|#)[a-zA-Z0-9_]+\s+table\s+\(/ig.test(line)) return
      let tb = line.match(/(@|#)[a-zA-Z0-9_]+\s+table\s+\(.+(\)|date|datetime)\s*\)/ig)
      if (tb && tb.length === 1) {
        tbs.push(tb[0])
      }
    })
    tbs.forEach(tb => {
      let tbName = tb.match(/(@|#)[a-zA-Z0-9_]+/ig)[0]
      if (!tbName) return
      let content = tb.replace(/(@|#)[a-zA-Z0-9_]+\s+table\s+\(\s*/, '').replace(/\s*\)$/, '')
      content = content.replace(/decimal\(\s*\d+\s*,\s*\d+\s*\)/ig, 'decimal')
      let keys = []
      let vals = []
      let error = false
      let istop = new RegExp(cbTable + '$', 'ig').test(tbName)
      let id = tbName.replace(/@|#/, '')
      content.split(/\s*,\s*/).forEach(m => {
        let ms = m.split(/\s+/)
        if (ms.length > 1) {
          keys.push(ms[0])
          if (/^mk_level$/i.test(ms[0])) {
            vals.push(istop ? `'1'` : `'2'`)
          } else if (/^mk_id$/i.test(ms[0])) {
            vals.push(istop ? `'${cbTable}'` : `'${id}'`)
          } else if (/^mk_bid$/i.test(ms[0])) {
            vals.push(istop ? `''` : `'${cbTable}'`)
          } else if (/nvarchar/i.test(ms[1])) {
            vals.push(`'mk'`)
          } else if (/date/i.test(ms[1])) {
            vals.push(`'1949-10-01'`)
          } else if (/int|decimal/i.test(ms[1])) {
            vals.push('0')
          } else {
            error = true
          }
        } else {
          error = true
        }
      })
      if (error || vals.length === 0) return
      _prev += `
      Insert into ${tbName} (${keys.join(',')})
      Select ${vals.join(',')}
      `
    })
    return _prev + _back
  }
  getSysDefSql = () => {
    const { columns, config, card } = this.props
    const { fields, verify } = this.state
    let btn = card
    let _actionType = btn.sqlType
    let setting = config.setting || {}
    // 主键字段
    let primaryKey = setting.primaryKey || 'id'
    if (this.props.side === 'sub') {
      primaryKey = setting.subKey || 'id'
    }
    let _sql = ''
    let _insertsql = ''
    if (_actionType === 'insert' || _actionType === 'insertOrUpdate') { // 添加语句
      let keys = []
      let values = []
      fields.forEach(item => {
        if (item.writein === false) return
        let _key = item.field.toLowerCase()
        keys.push(_key)
        values.push('@' + _key)
      })
      if (!keys.includes(primaryKey.toLowerCase())) {
        keys.push(primaryKey.toLowerCase())
        values.push('@ID@')
      }
      if (!keys.includes('createuserid')) {
        keys.push('createuserid')
        values.push('@userid@')
      }
      if (!keys.includes('createuser')) {
        keys.push('createuser')
        values.push('@username')
      }
      if (!keys.includes('createstaff')) {
        keys.push('createstaff')
        values.push('@fullname')
      }
      if (!keys.includes('bid')) {
        keys.push('bid')
        values.push('@BID@')
      }
      if (!keys.includes('typename')) {
        keys.push('typename')
        values.push('@typename@')
      }
      keys = keys.join(', ')
      values = values.join(', ')
      _insertsql = `insert into ${btn.sql} (${keys}) select ${values};`
    }
    let _updatesql = ''
    if (_actionType === 'update' || _actionType === 'audit' || _actionType === 'insertOrUpdate') { // 修改语句
      let _form = []
      let _arr = []
      fields.forEach(item => {
        if (item.writein === false) return
        let _key = item.field.toLowerCase()
        _arr.push(_key)
        _form.push(_key + '=@' + _key)
      })
      if (_actionType === 'audit') {
        if (!_arr.includes('submitdate')) {
          _form.push('submitdate=getdate()')
        }
        if (!_arr.includes('submituser')) {
          _form.push('submituser=@username')
        }
        if (!_arr.includes('submitstaff')) {
          _form.push('submitstaff=@fullname')
        }
        if (!_arr.includes('submituserid')) {
          _form.push('submituserid=@userid@')
        }
      } else {
        if (!_arr.includes('modifydate')) {
          _form.push('modifydate=getdate()')
        }
        if (!_arr.includes('modifyuser')) {
          _form.push('modifyuser=@username')
        }
        if (!_arr.includes('modifystaff')) {
          _form.push('modifystaff=@fullname')
        }
        if (!_arr.includes('modifyuserid')) {
          _form.push('modifyuserid=@userid@')
        }
      }
      let hasvoucher = false
      // 凭证-显示列中选取,必须选行
      if (verify.voucher && verify.voucher.enabled && btn.Ot !== 'requiredOnce') {
        hasvoucher = true
      }
      if (hasvoucher) {
        if (!_arr.includes('bvoucher')) {
          _form.push('BVoucher=@BVoucher')
        }
        if (!_arr.includes('fibvoucherdate')) {
          _form.push('FIBVoucherDate=@FIBVoucherDate')
        }
        if (!_arr.includes('fiyear')) {
          _form.push('FiYear=@FiYear')
        }
      }
      if (!_arr.includes('typename')) {
        _form.push('typename=@typename@')
      }
      _form = _form.join(', ')
      let _ID = '=@ID@'
      if (btn.Ot === 'requiredOnce') {
        _ID = ' in (select ID from  dbo.SplitComma(@ID@))'
      }
      _updatesql = `update ${btn.sql} set ${_form} where ${primaryKey}${_ID};`
    }
    // 添加、修改、逻辑删除、物理删除
    if (_actionType === 'insert') {
      _sql = _insertsql
    } else if (_actionType === 'update' || _actionType === 'audit') {
      _sql = _updatesql
    } else if (_actionType === 'LogicDelete' || _actionType === 'custom') { // 逻辑删除
      let _ID = '=@ID@'
      if (btn.Ot === 'requiredOnce') {
        _ID = ' in (select ID from  dbo.SplitComma(@ID@))'
      }
      _sql = `update ${btn.sql} set deleted=@mk_deleted,modifydate=getdate(),modifyuser=@username,modifystaff=@fullname,modifyuserid=@userid@ where ${primaryKey}${_ID};`
    } else if (_actionType === 'delete') {      // 物理删除
      let _msg = ''
      if (columns && columns.length > 0 && btn.Ot !== 'notRequired') {
        let _index = 0
        columns.forEach(col => {
          if (!col.field || col.Hide === 'true' || _index >= 4 || col.field === primaryKey) return
          _msg += col.label + '=0,'
          _index++
        })
      }
      let _ID = '=@ID@'
      if (btn.Ot === 'requiredOnce') {
        _ID = ' in (select ID from  dbo.SplitComma(@ID@))'
      }
      _sql = `insert into snote (remark,createuserid,CreateUser,CreateStaff,typename) select left('删除表:${btn.sql} 数据: ${_msg}${primaryKey}='+@ID@,200),@userid@,@username,@fullname,@typename@
        delete ${btn.sql} where ${primaryKey}${_ID};`
    } else if (_actionType === 'insertOrUpdate') {
      _sql = `
        /* 默认sql */
        select @tbid=''
        select @tbid='X' from ${btn.sql} where ${primaryKey}=@ID@
        if @tbid=''
          begin
          ${_insertsql}
          end
        else
          begin
          ${_updatesql}
          end
      `
    }
    return _sql
  }
  orderSql = (record) => {
    let _lpline = ''
    if (record.TypeCharOne === 'Lp') {
@@ -1242,7 +2042,7 @@
    this.setState({ verify })
  }
  customChange = (values) => {
  customChange = (values, resolve, reject) => {
    let verify = fromJS(this.state.verify).toJS()
    if (values.uuid) {
@@ -1258,10 +2058,28 @@
      verify.customverifys.push(values)
    }
    this.setState({ verify })
    if (resolve) {
      let sql = this.getSysExecSql(verify, false)
      Api.sDebug(sql).then(res => {
        if (res.status || res.ErrCode === '-2') {
          resolve()
          this.setState({ verify })
        } else {
          reject()
          Modal.error({
            title: res.message
          })
        }
      })
    } else {
      this.setState({ verify })
    }
  }
  scriptsChange = (values) => {
  scriptsChange = (values, resolve, reject) => {
    const { columns, card } = this.props
    let verify = fromJS(this.state.verify).toJS()
@@ -1308,12 +2126,32 @@
      }
    }
    MKEmitter.emit('editLineId', values.uuid)
    if (resolve) {
      let sql = this.getSysExecSql(verify, false)
      Api.sDebug(sql).then(res => {
        if (res.status || res.ErrCode === '-2') {
          resolve()
          values && MKEmitter.emit('editLineId', values.uuid)
    this.setState({ verify })
          this.setState({ verify })
        } else {
          reject()
          Modal.error({
            title: res.message
          })
        }
      })
    } else {
      MKEmitter.emit('editLineId', values.uuid)
      this.setState({ verify })
    }
  }
  cbScriptsChange = (values) => {
  cbScriptsChange = (values, resolve, reject) => {
    const { card } = this.props
    let verify = fromJS(this.state.verify).toJS()
    if (values.uuid) {
@@ -1329,9 +2167,52 @@
      verify.cbScripts.push(values)
    }
    MKEmitter.emit('editLineId', values.uuid)
    if (resolve) {
      let sql = this.getSysBackSql(verify.cbScripts, card.cbTable)
      if (sql) {
        let defSql = this.getSysExecSql(verify, true)
    this.setState({ verify })
        sql = `${defSql}
          ${sql}
        `
        if (card.output) {
          sql += `
            aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg,${card.output} as mk_b_id`
        } else {
          sql += `
            aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
        }
        sql = sql.replace(/@typename@/ig, `'typename'`)
        sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
        Api.sDebug(sql).then(res => {
          if (res.status || res.ErrCode === '-2') {
            resolve()
            MKEmitter.emit('editLineId', values.uuid)
            this.setState({ verify })
          } else {
            reject()
            Modal.error({
              title: res.message
            })
          }
        })
      } else {
        MKEmitter.emit('editLineId', values.uuid)
        this.setState({ verify })
      }
    } else {
      MKEmitter.emit('editLineId', values.uuid)
      this.setState({ verify })
    }
  }
  orderChange = (values) => {
@@ -1682,7 +2563,7 @@
  render() {
    const { card, columns } = this.props
    const { activeKey, verifyInter, verify, fields, uniqueFields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, cbScriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes, emailCodes, appType, formfields, colfields } = this.state
    const { activeKey, verifyInter, verify, fields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, cbScriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes, emailCodes, appType, formfields, colfields } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -1723,7 +2604,6 @@
          } key="customverifys" id="mk-custom-script">
            <CustomForm
              btn={this.props.card}
              initsql={this.state.initsql}
              formfields={formfields}
              colfields={colfields}
              customChange={this.customChange}
@@ -1757,7 +2637,7 @@
          } key="uniques">
            <UniqueForm
              btn={card}
              fields={card.Ot !== 'requiredOnce' ? uniqueFields : columnsFields}
              fields={card.Ot !== 'requiredOnce' ? fields : columnsFields}
              uniqueChange={this.uniqueChange}
            />
            <EditTable actions={['edit', 'move', 'del', 'status', 'sql']} data={verify.uniques} columns={card.Ot !== 'requiredOnce' ? uniqueColumns : onceUniqueColumns} onChange={this.changeUniques}/>
@@ -1793,14 +2673,10 @@
              <CustomScript
                type="fullscreen"
                btn={this.props.card}
                initsql={this.state.initsql}
                workFlow={verify.workFlow}
                flowRemark={verify.flowRemark}
                flowType={verify.flowType}
                flowSql={verify.flowSql}
                customScripts={verify.scripts}
                useDefaultSql={verify.default !== 'false'}
                defaultsql={this.state.defaultsql}
                formfields={formfields}
                colfields={colfields}
                systemScripts={this.state.systemScripts}
@@ -1810,14 +2686,11 @@
            </FullScripts>
            <CustomScript
              btn={this.props.card}
              initsql={this.state.initsql}
              workFlow={verify.workFlow}
              flowRemark={verify.flowRemark}
              flowType={verify.flowType}
              flowSql={verify.flowSql}
              customScripts={verify.scripts}
              useDefaultSql={verify.default !== 'false'}
              defaultsql={this.state.defaultsql}
              getSysDefSql={this.getSysDefSql}
              formfields={formfields}
              colfields={colfields}
              systemScripts={this.state.systemScripts}
@@ -1842,23 +2715,19 @@
              <CallBackCustomScript
                type="fullscreen"
                btn={this.props.card}
                initsql={this.state.initsql}
                customScripts={verify.cbScripts}
                formfields={formfields}
                colfields={colfields}
                systemScripts={this.state.systemScripts}
                scriptsChange={this.cbScriptsChange}
                cbScriptsChange={this.cbScriptsChange}
                wrappedComponentRef={(inst) => this.cbscriptsFullForm = inst}
              />
            </FullScripts>
            <CallBackCustomScript
              btn={this.props.card}
              initsql={this.state.initsql}
              customScripts={verify.cbScripts}
              formfields={formfields}
              colfields={colfields}
              systemScripts={this.state.systemScripts}
              scriptsChange={this.cbScriptsChange}
              cbScriptsChange={this.cbScriptsChange}
              wrappedComponentRef={(inst) => this.cbscriptsForm = inst}
            />
            <EditTable actions={['move']} data={verify.cbScripts} columns={cbScriptsColumns} onChange={(cbScripts) => {this.setState({verify: {...verify, cbScripts}})}}/>
src/utils/utils-custom.js
@@ -4890,7 +4890,7 @@
    let DateCount = ''
    if (_dataresource) {
      /*system_query*/
      if (/@pageSize@|@orderBy@|@mk_total/i.test(testSql)) {
      if (/@pageSize@|@orderBy@|@mk_total/i.test(testSql) || (item.wrap && item.wrap.tree === 'true')) {
        LText = `select ${arr_field} from ${_dataresource} ${_search} `
      } else if (item.setting.laypage === 'true' && item.setting.order) {
        LText = `select top @pageSize@ ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by @orderBy@) as rows from ${_dataresource} ${_search}) tmptable where rows > @pageSize@ * (@pageIndex@ - 1) order by tmptable.rows `