king
2024-05-21 8a6ce370f1aa1c061b76fa3e9d2d4d1df53ca4c5
Merge branch 'master' into positec
1 文件已重命名
138个文件已修改
1个文件已添加
1个文件已删除
4460 ■■■■■ 已修改文件
public/manifest.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/normalform/modalform/index.jsx 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/options.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/elementform/index.jsx 98 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/formconfig.jsx 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/options.jsx 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardsimplecomponent/options.jsx 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/options.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/doublecardcomponent/options.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/chart-custom/index.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/formaction/actionform/index.jsx 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/formaction/formconfig.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/simple-form/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/options.jsx 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/tab-form/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/account/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/account/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/index.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/options.jsx 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/verifycard/baseform/index.jsx 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/verifycard/customscript/index.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/invoice/verifycard/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/search/main-search/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/actionform/index.jsx 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/formconfig.jsx 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/searchcomponent/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/editColumn/formconfig.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/editColumn/index.jsx 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx 120 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/editColumn/index.jsx 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/tableIn/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/editColumn/index.jsx 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.jsx 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/debug/index.jsx 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modalconfig/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/stylecontroller/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/searchconfig/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/basetable/index.jsx 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/calendar/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/balcony/index.jsx 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardItem/index.jsx 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/data-card/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/double-data-card/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/prop-card/index.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/table-card/index.jsx 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/carousel/cardItem/index.jsx 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/carousel/data-card/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/carousel/prop-card/index.jsx 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-G6/index.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-X6/index.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-scatter/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/custom-chart/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/simple-form/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/step-form/index.jsx 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/step-form/index.scss 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/tab-form/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/account/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/invoice/index.jsx 633 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/invoice/index.scss 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx 98 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/invoice/subTable/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.jsx 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/base-table/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/index.jsx 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.jsx 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/timeline/normal-timeline/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/tree/antd-tree/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/popview/index.jsx 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/changeuserbutton/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/editLine/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/excelInbutton/index.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/exceloutbutton/index.jsx 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/exportPdf/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/funcMegvii/index.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/funcbutton/index.jsx 344 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/funcbutton/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/funczip/index.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/index.jsx 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/newpagebutton/index.jsx 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/popupbutton/index.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/printbutton/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/shareLink/index.jsx 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/tabbutton/index.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.jsx 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/topSearch/index.jsx 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/updatetable/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/checkCard/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/formconfig.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/fieldscomponent/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searchform/index.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searchform/index.scss 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/treepageconfig/updatetable/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/baseform/index.jsx 86 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/baseform/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customscript/index.jsx 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 233 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basedesign/updateFormTab/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/thdmenuform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/loginform.jsx 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/popview/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/popview/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/printTemplate/index.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tabledesign/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tabledesign/popview/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/manifest.json
@@ -6,5 +6,5 @@
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "mk_version": "20240401"
  "mk_version": "20240501"
}
src/api/index.js
@@ -1096,6 +1096,21 @@
    })
  }
  /**
   * @description 微信支付退款
   */
  setRefund (orderId) {
    let _param = new FormData()
    _param.append('out_biz_no', orderId)
    return axios({
      url: '/wxpay/wxRefund',
      headers: { 'Content-Type': 'multipart/form-data' },
      method: 'post',
      data: _param
    })
  }
  postekPrint (data) {
    return axios({
      url: 'http://127.0.0.1:888/postek/print',
src/components/normalform/modalform/index.jsx
@@ -280,7 +280,14 @@
      if (item.hidden || item.forbid) return
      let content = null
      let label = item.tooltip ? <Tooltip placement="topLeft" title={item.tooltip}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip> : item.label
      let label = item.label
      if (item.tooltip) {
        if (item.toolWidth) {
          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        } else {
          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        }
      }
    
      if (item.type === 'text') {
        content = (<MKEInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val}, item)} onSubmit={this.props.inputSubmit} />)
src/menu/components/card/balcony/index.jsx
@@ -283,7 +283,7 @@
          <div className="mk-popover-control">
            <PlusOutlined className="plus" title="添加元素" onClick={this.addElement} />
            <PlusSquareOutlined className="plus" title="添加按钮" onClick={this.addButton} />
            <NormalForm title="浮动卡设置" width={850} update={this.updateWrap} getForms={this.getWrapForms}>
            <NormalForm title="浮动卡设置" width={900} update={this.updateWrap} getForms={this.getWrapForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <CopyComponent type="balcony" card={card}/>
src/menu/components/card/balcony/options.jsx
@@ -113,6 +113,7 @@
        <div>2、同步类型中公式、按钮以及全选元素比较特殊,操作数据为其同步组件的数据。</div>
        <div>3、上级类型需添加当前组件的上级组件,并可设置当前组件为始终显示,还是只有在上级组件选行后才显示。</div>
      </div>,
      toolWidth: 400,
      required: false,
      options: [
        {value: 'static', label: '独立'},
src/menu/components/card/cardcellcomponent/elementform/index.jsx
@@ -194,14 +194,14 @@
      if (['text', 'picture'].includes(this.record.eleType) && this.record.link) {
        _options.push('linkType')
        if (this.record.linkType === 'linkmenu') {
          _options.push('open', 'joint')
          _options.push('open')
          if (this.record.link === 'static') {
            _options.push('linkmenu')
          } else {
            _options.push('linkurl')
          }
        } else if (this.record.linkType === 'other') {
          _options.push('linkurl', 'joint', 'open')
          _options.push('linkurl', 'open')
        } else {
          _options.push('linkurl')
        }
@@ -400,11 +400,21 @@
    this.state.formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      let label = item.label
      if (item.tooltip) {
        if (item.toolWidth) {
          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        } else {
          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        }
      }
      if (item.type === 'text') {
        let rules = item.rules || []
        if (item.options && item.options.length > 0) {
          fields.push(
            <Col span={12} key={index}>
              <Form.Item label={item.label}>
              <Form.Item label={label}>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal || '',
                  rules: [
@@ -437,12 +447,7 @@
        } else {
          fields.push(
            <Col span={12} key={index}>
              <Form.Item label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  {item.label}
                </Tooltip> : item.label
              }>
              <Form.Item label={label}>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal || '',
                  rules: [
@@ -453,7 +458,8 @@
                    {
                      max: formRule.input.max,
                      message: formRule.input.message
                    }
                    },
                    ...rules
                  ]
                })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
              </Form.Item>
@@ -463,12 +469,7 @@
      } else if (item.type === 'textarea') {
        fields.push(
          <Col span={24} className="textarea" key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
@@ -485,12 +486,7 @@
        if (item.help) {
          fields.push(
            <Col span={12} key={index}>
              <Form.Item help={item.help} label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  {item.label}
                </Tooltip> : item.label
              }>
              <Form.Item help={item.help} label={label}>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal,
                  rules: [{
@@ -504,12 +500,7 @@
        } else {
          fields.push(
            <Col span={12} key={index}>
              <Form.Item label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  {item.label}
                </Tooltip> : item.label
              }>
              <Form.Item label={label}>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal,
                  rules: [{
@@ -524,12 +515,7 @@
      } else if (item.type === 'select') { // 下拉搜索
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [{
@@ -557,12 +543,7 @@
      } else if (item.type === 'icon') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [{
@@ -578,12 +559,7 @@
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [{
@@ -605,7 +581,7 @@
      } else if (item.type === 'color') {
        fields.push(
          <Col span={12} key={index} className="color-form">
            <Form.Item label={item.label}>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -628,12 +604,7 @@
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -651,12 +622,7 @@
      } else if (item.type === 'cascader') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || [],
                rules: [
@@ -674,12 +640,7 @@
      } else if (item.type === 'table') {
        fields.push(
          <Col span={24} key={index} className="textarea">
            <Form.Item label={
              item.tooltip ? <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
@@ -697,12 +658,7 @@
      } else if (item.type === 'codemirror') {
        fields.push(
          <Col span={24} key={index} className="textarea">
            <Form.Item label={
              <Tooltip placement="topLeft" overlayStyle={{width: 500, maxWidth: 500}} title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip>
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -128,14 +128,13 @@
  }
  let fields = []
  if (cards.subtype === 'propcard' && cards.wrap.datatype === 'static') {
  let isStatic = (cards.subtype === 'propcard' || cards.type === 'balcony') && cards.wrap.datatype === 'static'
  if (isStatic) {
    if (cards.wrap.supModule && cards.wrap.supModule.length) {
      let cell = MenuUtils.getComponent(cards.wrap.supModule[cards.wrap.supModule.length - 1])
      if (cell && cell.columns) {
        fields = cell.columns.map(col => ({ value: col.field }))
      }
    } else {
      fields = cards.columns.map(col => ({ value: col.field }))
    }
  }
@@ -172,12 +171,17 @@
      ]
    },
    {
      type: cards.subtype === 'propcard' && cards.wrap.datatype === 'static' ? 'text' : 'select',
      type: isStatic ? 'text' : 'select',
      key: 'field',
      label: '字段',
      initVal: card.field || '',
      tooltip: isStatic ? '可绑定上级组件字段,不存在上级组件时可绑定url参数字段。' : '',
      required: true,
      options: fields
      options: fields,
      rules: [{
        pattern: /^[\u4E00-\u9FA50-9a-zA-Z_-]*$/ig,
        message: '字段名只允许包含数字、字母、汉字以及_-'
      }]
    },
    {
      type: 'icon',
@@ -256,7 +260,7 @@
      required: true
    },
    {
      type: cards.subtype === 'propcard' && cards.wrap.datatype === 'static' ? 'text' : 'select',
      type: isStatic ? 'text' : 'select',
      key: 'posterField',
      label: '预览地址',
      initVal: card.posterField || '',
@@ -475,7 +479,7 @@
      required: false
    },
    {
      type: cards.subtype === 'propcard' && cards.wrap.datatype === 'static' ? 'text' : 'select',
      type: isStatic ? 'text' : 'select',
      key: 'bgImage',
      label: '动态背景',
      initVal: card.bgImage || '',
@@ -641,6 +645,7 @@
      key: 'linkmenu',
      label: '关联菜单',
      initVal: card.linkmenu || '',
      tooltip: '行信息(字段集中前40个长度不超过256的字段)将传递至此菜单,可在url变量、表单(关联主表)、静态属性卡、浮动卡中使用。',
      required: true,
      options: appMenus || [],
      forbid: !['pc', 'mob'].includes(appType)
@@ -650,17 +655,19 @@
      key: 'linkmenu',
      label: '关联菜单',
      initVal: card.linkmenu || [],
      tooltip: '行信息将传递至此菜单,可在url变量、表单(关联主表)、静态属性卡、浮动卡中使用。',
      required: true,
      options: menulist,
      forbid: ['pc', 'mob'].includes(appType)
    },
    {
      type: cards.subtype === 'propcard' && cards.wrap.datatype === 'static' ? 'text' : 'select',
      defType: cards.subtype === 'propcard' && cards.wrap.datatype === 'static' ? 'text' : 'select',
      type: isStatic ? 'text' : 'select',
      defType: isStatic ? 'text' : 'select',
      key: 'linkurl',
      label: '链接地址',
      initVal: card.linkurl || '',
      tooltip: ['pc', 'mob'].includes(appType) ? '当链接类型为“其他”,且链接地址以@menuid@开头时,其后内容将被视为菜单ID。' : '',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。' + (['pc', 'mob'].includes(appType) ? '当链接类型为“其他”,且链接地址以@menuid@开头时,其后内容将被视为菜单ID。' : ''),
      toolWidth: 350,
      required: true,
      options: fields
    },
@@ -678,25 +685,12 @@
      ]
    },
    {
      type: 'radio',
      key: 'joint',
      label: '拼接参数',
      initVal: card.joint || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'codemirror',
      key: 'formula',
      label: '公式',
      initVal: card.formula || '',
      tooltip: '执行时会使用查询到的数据替换相应的字段,展示获得的结果,在不使用解析时换行符或空格会替换为页面元素。可使用JS的一些语法,如:三元表达式 @field1@ > @field2@ ? 0 : 1;Math对象,取绝对值 Math.abs(@field@)、四舍五入 Math.round(@field@)等。注:会替换公式中的@username@、@fullName@、@bid@。',
      toolWidth: 450,
      placeholder: '例如:@price@ * @number@',
      required: true
    },
src/menu/components/card/cardcomponent/options.jsx
@@ -149,7 +149,7 @@
        {field: 'menu', values: ['menu']},
        {field: 'linkurl', values: ['link']},
        {field: 'open', values: ['menu', 'link', 'menus']},
        {field: 'joint', values: ['menu', 'link', 'menus', 'miniprogram']},
        {field: 'joint', values: ['miniprogram']},
        {field: 'linkbtn', values: ['button']},
        {field: 'clickType', values: ['button']},
        {field: 'menuType', values: ['menus']},
@@ -171,6 +171,7 @@
      field: 'menu',
      label: '关联菜单',
      initval: setting.menu || (appType ? '' : []),
      tooltip: `行信息${appType ? '(字段集中前40个长度不超过256的字段)' : ''}将传递至此菜单,可在url变量、表单(关联主表)、静态属性卡、浮动卡中使用。`,
      required: true,
      extendName: 'MenuNo',
      options: menulist,
@@ -180,6 +181,8 @@
      field: 'linkurl',
      label: '链接',
      initval: setting.linkurl || '',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。',
      toolWidth: 350,
      required: true,
      options: [],
      span: 24
src/menu/components/card/cardsimplecomponent/options.jsx
@@ -97,20 +97,8 @@
        {field: 'menu', values: ['menu']},
        {field: 'linkurl', values: ['link']},
        {field: 'open', values: ['menu', 'link']},
        {field: 'joint', values: ['menu', 'link']},
        {field: 'linkbtn', values: ['button']},
      ]
    },
    {
      type: 'radio',
      field: 'joint',
      label: '参数拼接',
      initval: setting.joint || 'true',
      required: false,
      options: [
        {value: 'true', label: '是'},
        {value: 'false', label: '否'},
      ],
    },
    {
      type: 'radio',
@@ -129,6 +117,7 @@
      field: 'menu',
      label: '关联菜单',
      initval: setting.menu || (appType ? '' : []),
      tooltip: `行信息${appType ? '(字段集中前40个长度不超过256的字段)' : ''}将传递至此菜单,可在url变量、表单(关联主表)、静态属性卡、浮动卡中使用。`,
      required: true,
      extendName: 'MenuNo',
      options: appType ? appmenulist : menulist,
@@ -138,6 +127,8 @@
      field: 'linkurl',
      label: '链接',
      initval: setting.linkurl || '',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。',
      toolWidth: 350,
      required: true,
      options: [],
      span: 24
@@ -245,7 +236,7 @@
        {field: 'menu', values: ['menu']},
        {field: 'linkurl', values: ['link']},
        {field: 'open', values: ['menu', 'link']},
        {field: 'joint', values: ['menu', 'link', 'miniprogram']},
        {field: 'joint', values: ['miniprogram']},
        {field: 'miniAppId', values: ['miniprogram']},
        {field: 'miniPath', values: ['miniprogram']},
      ]
@@ -255,6 +246,7 @@
      field: 'menu',
      label: '关联菜单',
      initval: setting.menu || (appType ? '' : []),
      tooltip: `行信息${appType ? '(字段集中前40个长度不超过256的字段)' : ''}将传递至此菜单,可在url变量、表单(关联主表)、静态属性卡、浮动卡中使用。`,
      required: true,
      extendName: 'MenuNo',
      options: appType ? appmenulist : menulist,
@@ -302,6 +294,8 @@
      field: 'linkurl',
      label: '链接',
      initval: setting.linkurl || '',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。',
      toolWidth: 350,
      required: true,
      options: [],
      span: 24
src/menu/components/card/data-card/options.jsx
@@ -513,7 +513,6 @@
      ],
      controlFields: [
        {field: 'jumpField', values: ['menu', 'link']},
        {field: 'joint', values: ['menu', 'link']},
        {field: 'open', values: ['menu', 'link']},
        {field: 'menu', values: ['menu']},
        {field: 'link', values: ['link']},
@@ -547,18 +546,6 @@
      tooltip: '跳转链接为查询数据的返回值。',
      required: true,
      options: columns,
      forbid: subtype !== 'propcard' || appType !== 'mob'
    },
    {
      type: 'radio',
      field: 'joint',
      label: '参数拼接',
      initval: wrap.joint || 'true',
      required: false,
      options: [
        {value: 'true', label: '是'},
        {value: 'false', label: '否'},
      ],
      forbid: subtype !== 'propcard' || appType !== 'mob'
    },
    {
src/menu/components/card/doublecardcomponent/options.jsx
@@ -109,7 +109,6 @@
        {field: 'menu', values: ['menu']},
        {field: 'linkurl', values: ['link']},
        {field: 'open', values: ['menu', 'link']},
        {field: 'joint', values: ['menu', 'link']},
        {field: 'linkbtn', values: ['button']},
        {field: 'clickType', values: ['button', 'unfold']},
      ]
@@ -119,6 +118,7 @@
      field: 'menu',
      label: '关联菜单',
      initval: setting.menu || (appType ? '' : []),
      tooltip: `行信息${appType ? '(字段集中前40个长度不超过256的字段)' : ''}将传递至此菜单,可在url变量、表单(关联主表)、静态属性卡、浮动卡中使用。`,
      required: true,
      extendName: 'MenuNo',
      options: menulist,
@@ -128,6 +128,8 @@
      field: 'linkurl',
      label: '链接',
      initval: setting.linkurl || '',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。',
      toolWidth: 350,
      required: true,
      options: [],
      span: 24
@@ -143,17 +145,6 @@
        {value: 'self', label: appType !== 'mob' ? '当前窗口' : '当前页面'},
      ],
      forbid: appType !== 'pc' && appType !== 'mob'
    },
    {
      type: 'radio',
      field: 'joint',
      label: '参数拼接',
      initval: setting.joint || 'true',
      required: false,
      options: [
        {value: 'true', label: '是'},
        {value: 'false', label: '否'},
      ],
    },
    {
      type: 'select',
src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
@@ -129,7 +129,6 @@
        {field: 'menus', values: ['menus']},
        {field: 'menuType', values: ['menus']},
        {field: 'open', values: ['menu', 'menus']},
        {field: 'joint', values: ['menu', 'menus']},
      ]
    },
    {
@@ -160,17 +159,6 @@
        {value: 'self', label: '当前窗口'},
      ],
      forbid: appType !== 'pc'
    },
    {
      type: 'radio',
      field: 'joint',
      label: '参数拼接',
      initval: card.joint || 'true',
      required: false,
      options: [
        {value: 'true', label: '是'},
        {value: 'false', label: '否'},
      ],
    },
    {
      type: 'table',
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -128,7 +128,6 @@
      controlFields: [
        {field: 'menu', values: ['menu']},
        {field: 'open', values: ['menu', 'menus']},
        {field: 'joint', values: ['menu', 'menus']},
        {field: 'menuType', values: ['menus']},
        {field: 'menus', values: ['menus']},
      ]
@@ -165,19 +164,6 @@
        {value: 'self', label: '当前窗口'},
      ],
      forbid: appType !== 'pc' || card.chartType !== 'bar',
      hidden: card.click !== 'menu' && card.click !== 'menus'
    },
    {
      type: 'radio',
      field: 'joint',
      label: '参数拼接',
      initval: card.joint || 'true',
      required: false,
      options: [
        {value: 'true', label: '是'},
        {value: 'false', label: '否'},
      ],
      forbid: appType === 'mob' || card.chartType !== 'bar',
      hidden: card.click !== 'menu' && card.click !== 'menus'
    },
    {
src/menu/components/chart/chart-custom/index.jsx
@@ -4,7 +4,6 @@
import { Popover, notification } from 'antd'
import { ToolOutlined, DeleteOutlined, FontColorsOutlined, PlusCircleOutlined } from '@ant-design/icons'
import { Chart } from '@antv/g2'
import DataSet from '@antv/data-set'
import * as echarts from 'echarts'
import MKEmitter from '@/utils/events.js'
@@ -137,8 +136,8 @@
    if (card.plot.chartType === 'antv') {
      try {
        // eslint-disable-next-line
        let func = new Function('Chart', 'DataSet', 'wrap', 'data', 'config', card.plot.script)
        func(Chart, DataSet, this.wrap, [], card)
        let func = new Function('Chart', 'chartId', 'data', 'config', card.plot.script)
        func(Chart, card.uuid + 'canvas', [], card)
      } catch (e) {
        console.warn(e)
  
@@ -151,8 +150,8 @@
    } else if (card.plot.chartType === 'echarts') {
      try {
        // eslint-disable-next-line
        let func = new Function('echarts', 'DataSet', 'wrap', 'data', 'config', card.plot.script)
        func(echarts, DataSet, this.wrap, [], card)
        let func = new Function('echarts', 'chartId', 'data', 'config', card.plot.script)
        func(echarts, card.uuid + 'canvas', [], card)
      } catch (e) {
        console.warn(e)
  
@@ -262,7 +261,7 @@
        </Popover>
        <NormalHeader config={card} updateComponent={this.updateComponent}/>
        <div className="canvas-wrap" style={{height: card.plot.height}}>
          <div className="canvas" id={card.uuid + 'canvas'} style={{height: getHeight(card.plot.height)}} ref={ref => this.wrap = ref}></div>
          <div className="canvas" id={card.uuid + 'canvas'} style={{height: getHeight(card.plot.height)}}></div>
        </div>
        <div className="component-name">
          <div className="center">
src/menu/components/form/formaction/actionform/index.jsx
@@ -57,7 +57,7 @@
    } else if (this.record.type === 'close' || this.record.type === 'reset') {
      shows = ['typeName', 'label']
    } else {
      shows = ['typeName', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'output', 'reload', 'preButton'] // 选项列表
      shows = ['typeName', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'output', 'reload', 'preButton', 'refreshTab'] // 选项列表
      if (this.record.execSuccess === 'never') {
        shows.push('resetForms')
@@ -176,6 +176,15 @@
    this.state.formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      let label = item.label
      if (item.tooltip) {
        if (item.toolWidth) {
          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        } else {
          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        }
      }
      if (item.type === 'text') {
        let _rules = []
        if (item.key === 'innerFunc') {
@@ -222,12 +231,7 @@
        }
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
@@ -244,7 +248,7 @@
      } else if (item.type === 'tip') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
            <Form.Item label={label}>
              {item.initVal}
            </Form.Item>
          </Col>
@@ -252,12 +256,7 @@
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -273,12 +272,7 @@
      } else if (item.type === 'select') { // 下拉搜索
        fields.push(
          <Col span={12} key={index}>
            <Form.Item help={item.help || null} label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item help={item.help || null} label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
@@ -309,12 +303,7 @@
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -340,7 +329,7 @@
      } else if (item.type === 'textarea') {
        fields.push(
          <Col span={24} key={index}>
            <Form.Item label={item.label} className="textarea">
            <Form.Item label={label} className="textarea">
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -356,12 +345,7 @@
      } else if (item.type === 'cascader') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || [],
                rules: [
src/menu/components/form/formaction/formconfig.jsx
@@ -123,6 +123,14 @@
    })
  }
  let closetab = []
  if (!appType && viewType !== 'popview') {
    closetab = [{
      value: 'closetab',
      text: '关闭标签'
    }]
  }
  let resets = []
  fields.forEach(item => {
    if (item.type !== 'text' && item.type !== 'number') return
@@ -246,7 +254,7 @@
      initVal: card.innerFunc || '',
      tooltip: functip,
      fields: usefulFields,
      tooltipClass: 'middle',
      toolWidth: 350,
      required: true,
      readonly: false
    },
@@ -431,7 +439,20 @@
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      }, ...refresh]
      }, {
        value: 'maingrid',
        text: '刷新上级组件'
      }, ...closetab, ...refresh]
    },
    {
      type: 'cascader',
      key: 'refreshTab',
      label: '刷新菜单',
      initVal: card.refreshTab || [],
      tooltip: '执行成功后(或功能按钮中标签关闭类型),需要同步刷新的菜单',
      required: false,
      forbid: appType === 'pc' || appType === 'mob' || viewType === 'popview',
      options: menulist
    },
    {
      type: (appType === 'pc' || appType === 'mob') ? 'select' : 'cascader',
src/menu/components/form/simple-form/index.jsx
@@ -481,6 +481,10 @@
  pasteForm = (forms, res) => {
    let _config = fromJS(this.state.card).toJS()
    forms.forEach(item => {
      delete item.focus
    })
    _config.subcards[0].fields = forms
    if (res.subButton) {
@@ -511,8 +515,6 @@
        }
      })
    } else {
      _config.subcards[0].fields = forms
      this.updateComponent(_config)
    }
  }
src/menu/components/form/step-form/index.jsx
@@ -592,6 +592,7 @@
    res.fields.forEach(item => {
      item.uuid = Utils.getuuid()
      delete item.focus
    })
    if (!res.prevButton) {
src/menu/components/form/step-form/options.jsx
@@ -128,9 +128,23 @@
        {value: 'show', label: '显示'},
        {value: 'hidden', label: '隐藏'},
      ],
      // controlFields: [
      controlFields: [
      //   {field: 'labelSize', values: ['show']},
      // ]
        {field: 'labelJump', values: ['show']},
      ]
    },
    {
      type: 'radio',
      field: 'labelJump',
      label: '名称切换',
      initval: wrap.labelJump || 'false',
      tooltip: '开启时,可通过点击分组名称向前跳转。',
      required: false,
      forbid: config.subtype === 'tabform',
      options: [
        {value: 'false', label: '关闭'},
        {value: 'true', label: '开启'},
      ]
    },
    // {
    //   type: 'number',
src/menu/components/form/tab-form/index.jsx
@@ -597,6 +597,7 @@
    res.fields.forEach(item => {
      item.uuid = Utils.getuuid()
      delete item.focus
    })
    delete res.prevButton
src/menu/components/module/account/index.jsx
@@ -80,7 +80,7 @@
  changeStyle = () => {
    const { card } = this.state
    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear'], card.style, this.getStyle)
    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear', 'position'], card.style, this.getStyle)
  }
  getStyle = (style) => {
src/menu/components/module/account/index.scss
@@ -1,5 +1,5 @@
.menu-account-box {
  position: relative;
  position: relative!important;
  box-sizing: border-box;
  background: #ffffff;
  background-position: center center;
src/menu/components/module/invoice/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Button, Modal } from 'antd'
import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons'
import { EditOutlined, ToolOutlined, DeleteOutlined, LeftOutlined, FontColorsOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons'
import moment from 'moment'
import Utils from '@/utils/utils.js'
@@ -37,12 +37,13 @@
      let _card = {
        uuid: card.uuid,
        type: card.type,
        format: 'object',   // 组件属性 - 数据格式
        format: 'array',    // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: false,  // 组件属性 - 数据是否可切换
        width: card.width || 24,
        name: '发票',
        subtype: card.subtype,
        fixedCol: true,
        wrap: { name: '发票', width: card.width || 24, datatype: 'static' },
        style: { paddingLeft: '20px', paddingRight: '20px', paddingTop: '10px', paddingBottom: '10px' },
        setting: { interType: 'system', primaryKey: 'ID' },
@@ -51,6 +52,7 @@
        buyer: {
          pageable: true,
          format: 'array',
          fixedCol: true,
          subtype: 'invTable',
          setting: { interType: 'system' },
          columns: [],
@@ -63,6 +65,7 @@
        detail: {
          pageable: true,
          format: 'array',
          fixedCol: true,
          subtype: 'invTable',
          setting: { interType: 'system' },
          columns: [],
@@ -72,8 +75,8 @@
            {field: 'productcode', label: '商品编码', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()},
          ],
        },
        billSaveBtn: {type: 'billsave', intertype: 'system', label: '保存单据'},
        billOutBtn: {type: 'billout', intertype: 'custom', label: '提交开票', procMode: 'system'},
        billSaveBtn: {type: 'billsave', parId: card.uuid, intertype: 'system', label: '保存单据'},
        billOutBtn: {type: 'billout', parId: card.uuid, intertype: 'custom', label: '提交开票', procMode: 'system'},
      }
      let buys = [
@@ -102,11 +105,12 @@
        ['单价', 'unitprice', 'Decimal(18,10)'],
        ['税务分类编码', 'tax_classify_code'],
        ['税务分类名称', 'tax_classify_name'],
        // ['税率', 'tax_rate', 'Decimal(18,2)'],
        ['一般纳税人税率', 'general_tax_rate', 'Decimal(18,2)'],
        ['小规模纳税人征收率', 'small_tax_rate', 'Decimal(18,2)'],
        ['是否享受优惠政策', 'free_tax_mark'],
        ['优惠政策类型', 'vat_special_management'],
        ['征税项目', 'tax_item'],
        ['计税方法', 'tax_method'],
      ]
      details.forEach((cell, index) => {
@@ -117,6 +121,7 @@
        ['ID', 'ID'],
        ['开票申请单号', 'io'],
        ['发票种类', 'invoice_type'],
        ['开票类型', 'business_type', 'Nvarchar(20)'],
        ['购买方名称', 'from_to_name'],
        ['购买方税号', 'from_to_tax_no'],
        ['购买方地址', 'from_to_addr', 'Nvarchar(100)'],
@@ -136,6 +141,7 @@
        ['收款人', 'payee'],
        ['复核人', 'reviewer'],
        ['开票人', 'drawer'],
        ['jskey', 'jskey'],
        ['行号', 'invoice_lp'],
        ['商品编码', 'productcode'],
        ['商品名称', 'productname'],
@@ -148,6 +154,14 @@
        ['税务分类名称', 'tax_classify_name'],
        ['税率', 'tax_rate', 'Decimal(18,2)'],
        ['税额', 'tax_amount', 'Decimal(18,2)'],
        ['是否享受优惠政策', 'free_tax_mark'],
        ['优惠政策类型', 'vat_special_management'],
        ['征税项目', 'tax_item'],
        ['计税方法', 'tax_method'],
        ['发票号码', 'invoice_no'],
        ['发票代码', 'invoice_code'],
        ['开票日期', 'invoice_date'],
        ['只读(true)', 'read_only'],
      ]
      cols.forEach((cell, index) => {
@@ -289,6 +303,8 @@
          <ToolOutlined />
        </Popover>
        <div className="inv-action">
          {card.wrap.backBtn === 'show' ? <Button className="mk-back"><LeftOutlined />返回</Button> : null}
          <Button className="mk-addinv">新增发票</Button>
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control">
              <EditOutlined style={{color: '#1890ff'}} onClick={() => this.setState({btn: card.billSaveBtn})} title="编辑"/>
src/menu/components/module/invoice/index.scss
@@ -27,6 +27,20 @@
      margin-bottom: 5px;
      height: 30px;
    }
    .mk-back {
      border: none;
      float: left;
      margin-left: 0px;
      padding: 0px;
      box-shadow: none;
    }
    .mk-back::after {
      display: none;
    }
    .mk-addinv, .mk-addinv:active, .mk-addinv:focus {
      color: #52c41a;
      border-color: #52c41a;
    }
    .mk-bill:hover, .mk-bill:active, .mk-bill:focus {
      color: var(--mk-sys-color);
      border-color: var(--mk-sys-color);
src/menu/components/module/invoice/options.jsx
@@ -56,15 +56,11 @@
      allowClear: true
    },
    {
      type: 'radio',
      type: 'text',
      field: 'business_type',
      label: '发票类型',
      initval: wrap.business_type || 'sell',
      required: true,
      options: [
        {value: 'sell', label: '销项发票'},
        {value: 'buy', label: '进项发票'},
      ]
      label: '开票类型',
      initval: wrap.business_type || 'sell_01',
      required: true
    },
    {
      type: 'color',
@@ -75,6 +71,17 @@
      allowClear: true,
      required: false
    },
    {
      type: 'radio',
      field: 'backBtn',
      label: '返回按钮',
      initval: wrap.backBtn || 'hide',
      required: true,
      options: [
        {value: 'hide', label: '隐藏'},
        {value: 'show', label: '显示'},
      ]
    },
  ]
  return wrapForm
src/menu/components/module/invoice/verifycard/baseform/index.jsx
@@ -1,8 +1,9 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input } from 'antd'
// import { QuestionCircleOutlined } from '@ant-design/icons'
import { Form, Row, Col, Input, Tooltip, Cascader } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import MenuUtils from '@/utils/utils-custom.js'
// import './index.scss'
const { TextArea } = Input
@@ -12,7 +13,31 @@
    onChange: PropTypes.func
  }
  state = {}
  state = {
    modules: [],
    menulist: [],
    appType: sessionStorage.getItem('appType')
  }
  UNSAFE_componentWillMount() {
    const { verify } = this.props
    let menu = window.GLOB.customMenu
    let modules = MenuUtils.getSubModules(menu.components, verify.parId, '', menu.interfaces || null)
    let menulist = sessionStorage.getItem('fstMenuList')
    if (menulist) {
      try {
        menulist = JSON.parse(menulist)
      } catch (e) {
        menulist = []
      }
    } else {
      menulist = []
    }
    this.setState({modules, menulist})
  }
  handleConfirm = () => {
    const { verify } = this.props
@@ -41,6 +66,7 @@
  render() {
    const { getFieldDecorator } = this.props.form
    const { verify } = this.props
    const { modules, menulist, appType } = this.state
    return (
      <Form className="base-form">
@@ -50,6 +76,34 @@
              <Input value={verify.label} disabled={true}/>
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="执行成功后需要刷新的组件。">
                <QuestionCircleOutlined className="mk-form-tip" />
                刷新组件
              </Tooltip>
            }>
              {getFieldDecorator('syncComponent', {
                initialValue: verify.syncComponent || []
              })(
                <Cascader allowClear={true} options={modules} expandTrigger="hover"/>
              )}
            </Form.Item>
          </Col>
          {!appType ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="执行成功后需要刷新的菜单。">
                <QuestionCircleOutlined className="mk-form-tip" />
                刷新菜单
              </Tooltip>
            }>
              {getFieldDecorator('refreshTab', {
                initialValue: verify.refreshTab || []
              })(
                <Cascader allowClear={true} options={menulist} expandTrigger="hover"/>
              )}
            </Form.Item>
          </Col> : null}
          {/* <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="">
@@ -81,9 +135,14 @@
            </Form.Item>
          </Col> : null} */}
          {verify.type === 'billout' ? <Col span={24}>
            <Form.Item label="测试地址">
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="接口地址需通过nginx转发,默认地址为 /fcc/di/output/invoice/issue。">
                <QuestionCircleOutlined className="mk-form-tip" />
                测试地址
              </Tooltip>
            }>
              {getFieldDecorator('interface', {
                initialValue: verify.interface || '',
                initialValue: verify.interface || '/fcc/di/output/invoice/issue',
                rules: [
                  { required: true, message: '请输入测试地址!' }
                ]
@@ -95,12 +154,24 @@
          {verify.type === 'billout' ? <Col span={24}>
            <Form.Item label="正式地址">
              {getFieldDecorator('proInterface', {
                initialValue: verify.proInterface || '',
                initialValue: verify.proInterface || '/fcc/di/output/invoice/issue',
              })(
                <TextArea rows={2}/>
              )}
            </Form.Item>
          </Col> : null}
          {verify.type === 'billout' ? <Col span={8}>
            <Form.Item label="回调表名">
              {getFieldDecorator('cbTable', {
                initialValue: verify.cbTable || '',
                rules: [
                  { required: true, message: '请输入表名!' }
                ]
              })(
                <Input autoComplete="off"/>
              )}
            </Form.Item>
          </Col> : null}
        </Row>
      </Form>
    )
src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx
@@ -195,7 +195,7 @@
  }
  render() {
    const { systemScripts, type } = this.props
    const { systemScripts, type, cbTable } = this.props
    const { getFieldDecorator } = this.props.form
    const { editItem, skip } = this.state
    const formItemLayout = {
@@ -213,6 +213,11 @@
      <Form {...formItemLayout} className="verify-form">
        <Row gutter={24}>
          {!type ? <Col span={8}>
            <Form.Item label="回调表名" style={{margin: 0, whiteSpace: 'nowrap'}}>
              {cbTable || ''}
            </Form.Item>
          </Col> : null}
          {!type ? <Col span={8}>
            <Form.Item label="报错字段" style={{margin: 0, whiteSpace: 'nowrap'}}>
              errorcode(增加后缀NT表示数据不回滚,如ENT、NNT、FNT、NMNT、CNT、-2NT), retmsg
            </Form.Item>
src/menu/components/module/invoice/verifycard/customscript/index.jsx
@@ -73,16 +73,16 @@
          
          /* 发票主表字段 */
          
          Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2)
          Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2), @business_type Nvarchar(20)
          
          Select @invoice_type='', @from_to_name='', @from_to_tax_no='', @from_to_addr='', @from_to_tel='', @from_to_bank_name='', @from_to_account_no='', @from_to_mob='', @from_to_email='', @from_to_code='', @orgname='', @tax_no='', @addr='', @tel='', @bank_name='', @account_no='', @remark='', @payee='', @reviewer='', @drawer='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0
          Select @invoice_type='', @from_to_name='', @from_to_tax_no='', @from_to_addr='', @from_to_tel='', @from_to_bank_name='', @from_to_account_no='', @from_to_mob='', @from_to_email='', @from_to_code='', @orgname='', @tax_no='', @addr='', @tel='', @bank_name='', @account_no='', @remark='', @payee='', @reviewer='', @drawer='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0, @business_type='sell_01'
          
          /* 发票明细临时表 */
          Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
          Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), tax_item Nvarchar(50), tax_method Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
          
          Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, jskey, data_type)
          Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, tax_item, tax_method, jskey, data_type)
          
          Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', ''
          Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', '', '', ''
        `
@@ -209,8 +209,8 @@
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="公共值,请按照@xxx@格式使用。"><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id, typename, datam</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="系统变量,系统会定义变量并赋值。"><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="账套字段,系统会定义变量并赋值。"><span style={{color: '#13c2c2'}}>account_id, account_year_id, account_code, account_year_code </span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="主表字段,系统会定义变量并赋值。"><span style={{color: '#8E44AD'}}>invoice_type, from_to_name, from_to_tax_no, from_to_addr, from_to_tel, from_to_bank_name, from_to_account_no, from_to_mob, from_to_email, from_to_code, orgname, tax_no, addr, tel, bank_name, account_no, remark, payee, reviewer, drawer</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="子表字段(商品明细),系统会定义变量并赋值。">productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount</Tooltip>
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="主表字段,系统会定义变量并赋值。"><span style={{color: '#8E44AD'}}>invoice_type, from_to_name, from_to_tax_no, from_to_addr, from_to_tel, from_to_bank_name, from_to_account_no, from_to_mob, from_to_email, from_to_code, orgname, tax_no, addr, tel, bank_name, account_no, remark, payee, reviewer, drawer, io, orgcode, total_net_amount, total_tax, total_amount, business_type</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="子表字段(商品明细),系统会定义变量并赋值。">productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, tax_item, tax_method, jskey, data_type</Tooltip>
            </Form.Item>
          </Col> : null}
          {/* {!_type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
src/menu/components/module/invoice/verifycard/index.jsx
@@ -537,6 +537,7 @@
            >
              <CallBackCustomScript
                type="fullscreen"
                cbTable={verify.cbTable}
                customScripts={verify.cbScripts}
                systemScripts={this.state.systemScripts}
                scriptsChange={this.cbScriptsChange}
@@ -544,6 +545,7 @@
              />
            </FullScripts>
            <CallBackCustomScript
              cbTable={verify.cbTable}
              customScripts={verify.cbScripts}
              systemScripts={this.state.systemScripts}
              scriptsChange={this.cbScriptsChange}
@@ -562,28 +564,32 @@
              </p>
              <p className="note">{`/* 发票主表字段 */`}</p>
              <p>
                Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2)
                Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2), @business_type Nvarchar(20)
              </p>
              <p>
                Select @invoice_type='', @from_to_name='', @from_to_tax_no='', @from_to_addr='', @from_to_tel='', @from_to_bank_name='', @from_to_account_no='', @from_to_mob='', @from_to_email='', @from_to_code='', @orgname='', @tax_no='', @addr='', @tel='', @bank_name='', @account_no='', @remark='', @payee='', @reviewer='', @drawer='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0
                Select @invoice_type='', @from_to_name='', @from_to_tax_no='', @from_to_addr='', @from_to_tel='', @from_to_bank_name='', @from_to_account_no='', @from_to_mob='', @from_to_email='', @from_to_code='', @orgname='', @tax_no='', @addr='', @tel='', @bank_name='', @account_no='', @remark='', @payee='', @reviewer='', @drawer='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0, @business_type='sell_01'
              </p>
              <p className="note">{`/* 发票明细临时表 */`}</p>
              <p>
                Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
                Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), tax_item Nvarchar(50), tax_method Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
              </p>
              <p>
                Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, jskey, data_type)
                Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, tax_item, tax_method, jskey, data_type)
              </p>
              <p>
                Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', ''
                Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', '', '', ''
              </p>
              <p className="note">{`/* 前置脚本 */`}</p>
              <p>
                ......
              </p>
              {card.type === 'billout' ? <p>
                aaa: if @ErrorCode!=''
                insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,''
              </p> :
              <p>
                aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg
              </p>
              </p>}
            </div>
          </TabPane>
          <TabPane tab="信息提示" key="tip">
src/menu/components/search/main-search/index.jsx
@@ -255,7 +255,8 @@
          sqlVerifing: true
        })
        let sql = res.dataSource
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '')
        let rduri = ''
src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader, Checkbox } from 'antd'
import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader, Checkbox, notification } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import { formRule } from '@/utils/option.js'
@@ -415,7 +415,7 @@
      if (shows.includes('linkmenu') && this.record.linkmenu[0] === 'multiMenu') {
        shows.push('multiMenus')
      } else if (this.record.sysId === 'js') {
      } else if (Ot === 'notRequired' && this.record.sysId === 'js') {
        shows.push('sign')
      }
@@ -425,13 +425,9 @@
      reOptions.Ot = requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value))
      if (this.record.pageTemplate === 'custom') {
        shows.push('url', 'proUrl', 'joint', 'open')
        shows.push('url', 'proUrl', 'open')
      } else if (this.record.pageTemplate === 'linkpage') {
        shows.push('linkmenu', 'open')
        if (Ot === 'requiredSgl') {
          shows.push('joint')
        }
        reRequired.linkmenu = true
        reTooltip.linkmenu = ''
@@ -517,7 +513,7 @@
        }
        reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
      } else if (_funcType === 'refund') {
        shows.push('Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu')
        shows.push('Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu', 'tipTitle')
        reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
      } else if (_funcType === 'shareLink') {
        shows.push('shortUrl', 'shareUrl', 'shareProUrl', 'shareTip')
@@ -1043,6 +1039,15 @@
          values.config = card.config || null
          values.$fixed = card.$fixed || false
          if (['pop', 'prompt', 'exec'].includes(values.OpenType) && values.Ot === 'required' && values.execError === 'never') {
            notification.warning({
              top: 92,
              message: '选择多行时,需设置失败后的刷新项!',
              duration: 5
            })
            return
          }
          if (card.OpenType === 'excelOut' && values.OpenType === 'excelIn') {
            values.verify = {columns: [], scripts: [], sheet: 'Sheet1', default: 'true', range: 1, uniques: []}
            if (card.verify && card.verify.columns) {
src/menu/components/share/actioncomponent/formconfig.jsx
@@ -532,7 +532,8 @@
      key: 'url',
      label: '页面地址',
      initVal: card.url || '',
      tooltip: appType === '' ? '地址格式为:http://******/admin/index.html#/iframe/menuId/loginuid/BID 会打开标签页。注:使用@loginuid@时自动替换为当前系统的loginuid;选择单行且拼接参数时会拼接BID。' : '',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。' + (appType === '' ? '地址格式为:******/admin/index.html#/iframe/menuId/@loginuid@ 会打开标签页。' : ''),
      toolWidth: 350,
      required: true
    },
    {
@@ -540,7 +541,8 @@
      key: 'proUrl',
      label: '正式地址',
      initVal: card.proUrl || '',
      tooltip: appType === '' ? '地址格式为:http://******/admin/index.html#/iframe/menuId/loginuid/BID 会打开标签页。注:使用@loginuid@时自动替换为当前系统的loginuid;选择单行且拼接参数时会拼接BID。' : '',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。' + (appType === '' ? '地址格式为:******/admin/index.html#/iframe/menuId/@loginuid@ 会打开标签页。' : ''),
      toolWidth: 350,
      required: false
    },
    {
@@ -728,6 +730,9 @@
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      }, {
        value: 'maingrid',
        text: '刷新上级组件'
      }, 
      ...closetab,
      ...refresh]
@@ -756,6 +761,9 @@
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      }, {
        value: 'maingrid',
        text: '刷新上级组件'
      },
      ...refresh]
    },
@@ -774,6 +782,9 @@
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      }, {
        value: 'maingrid',
        text: '刷新上级组件'
      }]
    },
    {
@@ -879,7 +890,7 @@
      initVal: card.hover || '',
      tooltip: '鼠标悬浮按钮上方时的颜色变化。',
      required: false,
      forbid: type === 'card' || appType === 'mob',
      forbid: appType === 'mob',
      options: [{
        value: '',
        text: '无'
@@ -953,20 +964,6 @@
      }]
    },
    {
      type: 'radio',
      key: 'joint',
      label: '拼接参数',
      initVal: card.joint || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'text',
      key: 'sheet',
      label: '表名',
@@ -1015,24 +1012,6 @@
    },
    {
      type: 'cascader',
      key: 'switchTab',
      label: '切换标签',
      initVal: card.switchTab || [],
      tooltip: '执行成功后,需要切换的标签页。' + (appType === 'mob' ? '注:小程序中无效' : ''),
      required: false,
      options: tabs
    },
    {
      type: 'cascader',
      key: 'anchors',
      label: '跳转锚点',
      initVal: card.anchors || [],
      tooltip: '执行成功后,需要跳转的锚点。' + (appType === 'mob' ? '注:小程序中无效' : ''),
      required: false,
      options: anchors
    },
    {
      type: 'cascader',
      key: 'refreshTab',
      label: '刷新菜单',
      initVal: card.refreshTab || [],
@@ -1053,6 +1032,24 @@
      allowClear: true,
      options: appType === 'mob' || appType === 'pc' ? appMenus : menulist,
      forbid: viewType === 'popview'
    },
    {
      type: 'cascader',
      key: 'switchTab',
      label: '切换标签',
      initVal: card.switchTab || [],
      tooltip: '执行成功后,需要切换的标签页。' + (appType === 'mob' ? '注:小程序中无效' : ''),
      required: false,
      options: tabs
    },
    {
      type: 'cascader',
      key: 'anchors',
      label: '跳转锚点',
      initVal: card.anchors || [],
      tooltip: '执行成功后,需要跳转的锚点。' + (appType === 'mob' ? '注:小程序中无效' : ''),
      required: false,
      options: anchors
    },
    {
      type: 'select',
@@ -1535,10 +1532,13 @@
      required: false,
      options: [{
        value: '',
        text: '空'
        text: '组件BID'
      }, {
        value: 'js',
        text: '前端生成'
      }, {
        value: 'empty',
        text: '空'
      }]
    },
    {
@@ -1885,7 +1885,8 @@
      key: 'url',
      label: '页面地址',
      initVal: card.url || '',
      tooltip: '地址格式为:http://******/admin/index.html#/iframe/menuId/loginuid/BID 会打开标签页。注:使用@loginuid@时自动替换为当前系统的loginuid;选择单行且拼接参数时会拼接BID。',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。地址格式为:******/admin/index.html#/iframe/menuId/@loginuid@ 会打开标签页。',
      toolWidth: 350,
      required: true
    },
    {
@@ -1893,7 +1894,8 @@
      key: 'proUrl',
      label: '正式地址',
      initVal: card.proUrl || '',
      tooltip: '地址格式为:http://******/admin/index.html#/iframe/menuId/loginuid/BID 会打开标签页。注:使用@loginuid@时自动替换为当前系统的loginuid;选择单行且拼接参数时会拼接BID。',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。地址格式为:******/admin/index.html#/iframe/menuId/@loginuid@ 会打开标签页。',
      toolWidth: 350,
      required: false
    },
    {
@@ -2079,6 +2081,9 @@
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      }, {
        value: 'maingrid',
        text: '刷新上级组件'
      }, 
      ...refresh]
    },
@@ -2104,6 +2109,9 @@
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      }, {
        value: 'maingrid',
        text: '刷新上级组件'
      },
      ...refresh]
    },
@@ -2122,6 +2130,9 @@
      }, {
        value: 'mainline',
        text: '刷新上级组件 - 行'
      }, {
        value: 'maingrid',
        text: '刷新上级组件'
      }]
    },
    {
@@ -2252,20 +2263,6 @@
      initVal: card.class,
      required: false,
      options: btnClasses
    },
    {
      type: 'radio',
      key: 'joint',
      label: '拼接参数',
      initVal: card.joint || 'true',
      required: false,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'text',
@@ -2631,10 +2628,13 @@
      required: false,
      options: [{
        value: '',
        text: '空'
        text: '组件BID'
      }, {
        value: 'js',
        text: '前端生成'
      }, {
        value: 'empty',
        text: '空'
      }]
    },
    {
src/menu/components/share/searchcomponent/index.jsx
@@ -210,7 +210,8 @@
          sqlVerifing: true
        })
        let sql = res.dataSource
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '')
        let rduri = ''
src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -103,6 +103,8 @@
      key: 'nameField',
      label: '名称字段',
      initVal: card.nameField || '',
      tooltip: '名称字段为链接在界面中显示的内容,在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。',
      toolWidth: 350,
      required: false,
      rules: [{
        max: 100,
@@ -118,20 +120,6 @@
      label: '列宽',
      initVal: card.Width || 120,
      required: true
    },
    {
      type: 'radio',
      key: 'joint',
      label: '拼接参数',
      initVal: card.joint || 'true',
      required: true,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'radio',
@@ -440,15 +428,9 @@
      key: 'linkurl',
      label: '链接地址',
      initVal: card.linkurl || '',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。',
      toolWidth: 350,
      required: true
    },
    {
      type: 'multiselect',
      key: 'linkfields',
      label: '关联字段',
      initVal: card.linkfields || [],
      required: false,
      options: fields,
    },
    {
      type: 'textarea',
src/menu/components/table/base-table/columns/editColumn/index.jsx
@@ -11,7 +11,7 @@
const columnTypeOptions = {
  text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'fieldlength', 'blacklist', 'perspective', 'rowspan'],
  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum', 'rowspan'],
  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'fieldlength', 'blacklist', 'nameField'],
  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'nameField'],
  textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'prefix', 'postfix', 'blacklist'],
  picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span', 'lostTip'],
  video: ['label', 'field', 'type', 'Align', 'Hide', 'startTime', 'Width', 'fieldlength', 'blacklist', 'aspectRatio'],
@@ -93,7 +93,7 @@
      if (this.record.perspective === 'linkmenu') {
        _options.push('linkmenu', 'open')
      } else if (this.record.perspective === 'linkurl') {
        _options.push('linkurl', 'linkfields', 'open')
        _options.push('linkurl', 'open')
      }
    } else if (this.record.type === 'formula' && this.record.eval === 'true') {
      _options.push('decimal')
@@ -209,15 +209,19 @@
    formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      let label = item.label
      if (item.tooltip) {
        if (item.toolWidth) {
          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        } else {
          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        }
      }
      if (item.type === 'text') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
@@ -234,12 +238,7 @@
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -256,7 +255,7 @@
      } else if (item.type === 'select') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
@@ -285,12 +284,7 @@
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -312,12 +306,7 @@
      } else if (item.type === 'checkbox') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(
@@ -331,7 +320,7 @@
      } else if (item.type === 'multiselect') { // 多选
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || []
              })(
@@ -351,7 +340,7 @@
      } else if (item.type === 'cascader') { // 多选
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || [],
                rules: [
@@ -374,12 +363,7 @@
        if (item.key === 'formula') {
          fields.push(
            <Col span={24} className="textarea" key={index}>
              <Form.Item label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  {item.label}
                </Tooltip> : item.label
              }>
              <Form.Item label={label}>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal || '',
                  rules: [
@@ -398,12 +382,7 @@
        } else {
          fields.push(
            <Col span={24} key={index} className="textarea">
              <Form.Item label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  {item.label}
                </Tooltip> : item.label
              }>
              <Form.Item label={label}>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal || '',
                  rules: [
src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -37,6 +37,9 @@
    value: 'colspan',
    text: '合并列'
  }, {
    value: 'extend',
    text: '扩展列'
  }, {
    value: 'index',
    text: '序号'
  }]
@@ -210,6 +213,95 @@
    },
    {
      type: 'radio',
      key: 'colUnit',
      label: '单位',
      initVal: card.colUnit || 'day',
      required: true,
      options: [{
        value: 'day',
        text: '天'
      }, {
        value: 'hour',
        text: '小时'
      }]
    },
    {
      type: 'number',
      key: 'shift',
      label: '偏移量',
      initVal: card.shift || 0,
      min: -1000,
      max: 1000,
      decimal: 0,
      required: true
    },
    {
      type: 'number',
      key: 'quota',
      label: '指标数',
      initVal: card.quota || 7,
      min: 1,
      max: 1000,
      decimal: 0,
      required: true
    },
    {
      type: 'select',
      key: 'dayFormat',
      label: '格式化',
      initVal: card.dayFormat || 'M/DD',
      required: true,
      options: [{
        value: 'M/DD',
        label: 'M/DD(4/29)'
      }, {
        value: 'M-DD',
        label: 'M-DD(4-29)'
      }, {
        value: 'M月DD日',
        label: 'M月DD日(4月29日)'
      }, {
        value: 'M/DD week',
        label: 'M/DD week(4/29 星期一)'
      }, {
        value: 'M-DD week',
        label: 'M-DD week(4-29 星期一)'
      }, {
        value: 'M月DD日 week',
        label: 'M月DD日 week(4月29日 星期一)'
      }]
    },
    {
      type: 'select',
      key: 'hourFormat',
      label: '格式化',
      initVal: card.hourFormat || 'H:00',
      required: true,
      options: [{
        value: 'H:00',
        label: 'H:00(15:00)'
      }, {
        value: 'H point',
        label: 'H(15点)'
      }, {
        value: 'h:00',
        label: 'h:00(3:00 pm)'
      }]
    },
    {
      type: 'text',
      key: 'supField',
      label: '上级字段',
      initVal: card.supField || '',
      tooltip: '来源于上级组件的字段集(上级组件为空时从url参数中选取),该字段值(用逗号分隔)可控制扩展列的列名。',
      required: false,
      rules: [{
        pattern: /^[0-9a-zA-Z_]*$/ig,
        message: '字段名只允许包含数字、字母以及_'
      }]
    },
    {
      type: 'radio',
      key: 'editable',
      label: '可编辑',
      initVal: card.editable || 'false',
@@ -276,6 +368,20 @@
      }, {
        value: 'nvarchar(50)',
        text: 'nvarchar(50)'
      }]
    },
    {
      type: 'radio',
      key: 'required',
      label: '必填',
      initVal: card.required || 'false',
      required: false,
      options: [{
        value: 'false',
        text: '否'
      }, {
        value: 'true',
        text: '是'
      }]
    },
    {
@@ -576,20 +682,6 @@
      }, {
        value: 'fixed',
        text: '定宽'
      }]
    },
    {
      type: 'radio',
      key: 'required',
      label: '必填',
      initVal: card.required || 'false',
      required: false,
      options: [{
        value: 'false',
        text: '否'
      }, {
        value: 'true',
        text: '是'
      }]
    },
    {
src/menu/components/table/edit-table/columns/editColumn/index.jsx
@@ -23,6 +23,7 @@
  textarea: ['label', 'field', 'type', 'Align', 'Hide', 'Width', 'prefix', 'initval', 'postfix', 'blacklist'],
  custom: ['label', 'type', 'Align', 'Width', 'blacklist', 'IsSort'],
  colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'],
  extend: ['label', 'field', 'type', 'Align', 'Width', 'colUnit', 'shift', 'quota', 'supField'],
  action: ['label', 'type', 'Align', 'Width'],
  formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist'],
  index: ['label', 'type', 'Align', 'Width']
@@ -65,6 +66,8 @@
  getOptions = () => {
    let _options = fromJS(columnTypeOptions[this.record.type]).toJS()
    let reLabel = {}
    if (['number', 'text'].includes(this.record.type) && this.record.editable === 'true') {
      _options.push('ctrlField')
      if (this.record.ctrlField) {
@@ -90,8 +93,18 @@
        } else {
          _options.push('required', 'enter')
        }
        reLabel.required = '必填'
      } else if (this.record.type === 'number') {
        _options.push('max', 'min', 'enter', 'clearField')
        _options.push('max', 'min', 'required', 'enter', 'clearField')
        reLabel.required = '不等于0'
      }
    } else if (this.record.type === 'extend') {
      if (this.record.colUnit === 'day') {
        _options.push('dayFormat')
      } else {
        _options.push('hourFormat')
      }
    }
    if (this.record.type === 'formula' && this.record.eval === 'true') {
@@ -108,7 +121,7 @@
      }
    }
    return _options
    return {options: _options, reLabel}
  }
  editColumn = (column) => {
@@ -124,12 +137,16 @@
      this.record[item.key] = item.initVal
    })
    
    let _options = this.getOptions()
    let { options, reLabel } = this.getOptions()
    this.setState({
      visible: true,
      formlist: formlist.map(item => {
        item.hidden = !_options.includes(item.key)
        item.hidden = !options.includes(item.key)
        if (reLabel[item.key]) {
          item.label = reLabel[item.key]
        }
        if (item.key === 'formula') {
          item.fields = this.props.fields.map(col => col.field)
@@ -159,7 +176,7 @@
        this.record.IsSort = 'false'
      }
      let _options = this.getOptions()
      let { options, reLabel } = this.getOptions()
      let _field = ''
      if (value === 'formula') {
@@ -173,7 +190,10 @@
          }
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          item.hidden = !options.includes(item.key)
          if (reLabel[item.key]) {
            item.label = reLabel[item.key]
          }
          return item
        })
@@ -205,12 +225,15 @@
      this.record.type = values.type
      if (values.type !== _type) {
        let _options = this.getOptions()
        let { options, reLabel } = this.getOptions()
        this.setState({
          formlist: this.state.formlist.map(item => {
            item.initVal = this.record[item.key]
            item.hidden = !_options.includes(item.key)
            item.hidden = !options.includes(item.key)
            if (reLabel[item.key]) {
              item.label = reLabel[item.key]
            }
            return item
          })
@@ -223,7 +246,7 @@
    } else if (key === 'format' && value === 'percent') {
      this.props.form.setFieldsValue({postfix: '%'})
    } else if (key === 'editType') {
      let _options = this.getOptions()
      let { options, reLabel } = this.getOptions()
      this.setState({
        formlist: this.state.formlist.map(item => {
@@ -232,18 +255,24 @@
          }
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          item.hidden = !options.includes(item.key)
          if (reLabel[item.key]) {
            item.label = reLabel[item.key]
          }
          return item
        })
      })
    } else if (['editable', 'editType', 'resourceType', 'ctrlField', 'eval', 'Hide', 'IsSort', 'textFormat'].includes(key)) {
      let _options = this.getOptions()
      let { options, reLabel } = this.getOptions()
      this.setState({
        formlist: this.state.formlist.map(item => {
          item.initVal = this.record[item.key]
          item.hidden = !_options.includes(item.key)
          item.hidden = !options.includes(item.key)
          if (reLabel[item.key]) {
            item.label = reLabel[item.key]
          }
          return item
        })
@@ -311,6 +340,14 @@
      let content = null
      let extra = null
      let initVal = item.initVal || ''
      let label = item.label
      if (item.tooltip) {
        if (item.toolWidth) {
          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        } else {
          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        }
      }
      if (item.type === 'text') {
        rules = [
@@ -385,12 +422,7 @@
        if (item.key === 'formula') {
          fields.push(
            <Col span={span} key={index}>
              <Form.Item className={className} extra={extra} label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  {item.label}
                </Tooltip> : item.label
              }>
              <Form.Item className={className} extra={extra} label={label}>
                {getFieldDecorator(item.key, {
                  initialValue: initVal,
                  rules: rules
@@ -447,12 +479,7 @@
      fields.push(
        <Col span={span} key={index}>
          <Form.Item className={className} extra={extra} label={item.tooltip ?
            <Tooltip placement="topLeft" title={item.tooltip}>
              <QuestionCircleOutlined className="mk-form-tip" />
              {item.label}
            </Tooltip> : item.label
          }>
          <Form.Item className={className} extra={extra} label={label}>
            {getFieldDecorator(item.key, {
              initialValue: initVal,
              rules: rules
src/menu/components/table/edit-table/columns/index.jsx
@@ -109,7 +109,7 @@
            {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
            {column.type === 'custom' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
            <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
            {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            {['text', 'number', 'formula', 'extend'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
          </div>
        } trigger="hover">
          {children}
src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx
@@ -36,7 +36,7 @@
    fields.push('jskey')
    let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
    let _sql = `create table #${sheet} (${usefulfields.map(item => item.field + ' ' + item.datatype).join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50))
    let _sql = `create table #${sheet} (${usefulfields.map(item => item.field + ' ' + item.datatype).join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(256))
      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),@tbid Nvarchar(512)
      Select @ErrorCode='', @retmsg=''
    `
src/menu/components/table/edit-table/columns/tableIn/index.jsx
@@ -566,7 +566,8 @@
                      <Select.Option value="line" disabled={config.wrap.commit !== 'change'}>刷新行</Select.Option>
                      <Select.Option value="grid">刷新组件</Select.Option>
                      <Select.Option value="line_grid" disabled={config.wrap.commit !== 'change'}>刷新行 / 组件</Select.Option>
                      <Select.Option value="mainline">上级(行)</Select.Option>
                      <Select.Option value="mainline">刷新上级组件 - 行</Select.Option>
                      <Select.Option value="maingrid">刷新上级组件</Select.Option>
                    </Select>
                  </Form.Item>
                </Col>
@@ -577,7 +578,8 @@
                      <Select.Option value="line" disabled={config.wrap.commit !== 'change'}>刷新行</Select.Option>
                      <Select.Option value="grid">刷新组件</Select.Option>
                      <Select.Option value="line_grid" disabled={config.wrap.commit !== 'change'}>刷新行 / 组件</Select.Option>
                      <Select.Option value="mainline">上级(行)</Select.Option>
                      <Select.Option value="mainline">刷新上级组件 - 行</Select.Option>
                      <Select.Option value="maingrid">刷新上级组件</Select.Option>
                    </Select>
                  </Form.Item>
                </Col>
src/menu/components/table/edit-table/index.jsx
@@ -296,12 +296,19 @@
  updatecolumn = (config) => {
    config.absFields = []
    config.mergeCol = false
    config.hasExtend = false
    config.parCtrl = false
    let mapCol = (cols) => {
      cols.forEach(col => {
        if (col.type === 'number') {
          if (col.format === 'abs') {
            config.absFields.push(col.field)
          }
        } else if (col.type === 'extend') {
          config.hasExtend = true
          if (col.supField) {
            config.parCtrl = true
          }
        } else if (col.type === 'colspan' && col.subcols) {
          mapCol(col.subcols)
@@ -316,6 +323,11 @@
        if (col.format === 'abs') {
          config.absFields.push(col.field)
        }
      } else if (col.type === 'extend') {
        config.hasExtend = true
        if (col.supField) {
          config.parCtrl = true
        }
      } else if (col.type === 'colspan' && col.subcols) {
        mapCol(col.subcols)
      } else if (col.type === 'text') {
src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -68,6 +68,10 @@
    text: '序号'
  }]
  if (appType === 'mob') {
    options = options.filter(item => item.value !== 'extend')
  }
  if (!card.linkurl && (!card.linkmenu || card.linkmenu.length === 0)) {
    card.perspective = ''
  }
@@ -101,6 +105,8 @@
      key: 'nameField',
      label: '名称字段',
      initVal: card.nameField || '',
      tooltip: '名称字段为链接在界面中显示的内容,在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。',
      toolWidth: 350,
      required: false,
      options: [{uuid: 'empty', field: '', label: '空'}, ...fields]
    },
@@ -113,20 +119,6 @@
      label: '列宽',
      initVal: card.Width || 120,
      required: true
    },
    {
      type: 'radio',
      key: 'joint',
      label: '拼接参数',
      initVal: card.joint || 'true',
      required: true,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'radio',
@@ -284,8 +276,8 @@
      tooltip: '来源于上级组件的字段集(上级组件为空时从url参数中选取),该字段值(用逗号分隔)可控制扩展列的列名。',
      required: false,
      rules: [{
        pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
        message: '字段名只允许包含数字、字母、汉字以及_'
        pattern: /^[0-9a-zA-Z_]*$/ig,
        message: '字段名只允许包含数字、字母以及_'
      }]
    },
    {
@@ -494,16 +486,9 @@
      key: 'linkurl',
      label: '链接地址',
      initVal: card.linkurl || '',
      tooltip: '在链接中以@***@形式拼接的字段(字段来源于字段集中,此外 id、appkey、userid、LoginUID 为系统字段),跳转时将替换为对应值,例如:http://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@,其中appkey与LoginUID将被替换。',
      toolWidth: 350,
      required: true,
      forbid: appType === 'mob'
    },
    {
      type: 'multiselect',
      key: 'linkfields',
      label: '关联字段',
      initVal: card.linkfields || [],
      required: false,
      options: fields,
      forbid: appType === 'mob'
    },
    {
src/menu/components/table/normal-table/columns/editColumn/index.jsx
@@ -12,7 +12,7 @@
const columnTypeOptions = {
  text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'blacklist', 'perspective', 'rowspan'],
  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum', 'rowspan'],
  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'blacklist', 'nameField'],
  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'nameField'],
  textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'blacklist'],
  picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span', 'lostTip'],
  video: ['label', 'field', 'type', 'Align', 'Hide', 'startTime', 'Width', 'blacklist', 'aspectRatio'],
@@ -92,7 +92,7 @@
      if (this.record.perspective === 'linkmenu') {
        _options.push('linkmenu', 'open')
      } else if (this.record.perspective === 'linkurl') {
        _options.push('linkurl', 'linkfields', 'open')
        _options.push('linkurl', 'open')
      }
    } else if (this.record.type === 'formula' && this.record.eval === 'true') {
      _options.push('decimal')
@@ -217,6 +217,15 @@
    formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      let label = item.label
      if (item.tooltip) {
        if (item.toolWidth) {
          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        } else {
          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
        }
      }
      if (item.type === 'text') {
        let rules = item.rules || []
        if (item.key !== 'linkurl') {
@@ -227,12 +236,7 @@
        }
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
@@ -249,12 +253,7 @@
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -271,7 +270,7 @@
      } else if (item.type === 'select') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
@@ -300,12 +299,7 @@
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
@@ -327,12 +321,7 @@
      } else if (item.type === 'checkbox') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                {item.label}
              </Tooltip> : item.label
            }>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(
@@ -346,7 +335,7 @@
      } else if (item.type === 'multiselect') { // 多选
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || []
              })(
@@ -366,7 +355,7 @@
      } else if (item.type === 'cascader') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
            <Form.Item label={label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || [],
                rules: [
@@ -389,12 +378,7 @@
        if (item.key === 'formula') {
          fields.push(
            <Col span={24} className="textarea" key={index}>
              <Form.Item label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  {item.label}
                </Tooltip> : item.label
              }>
              <Form.Item label={label}>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal || '',
                  rules: [
@@ -413,12 +397,7 @@
        } else {
          fields.push(
            <Col span={24} key={index} className="textarea">
              <Form.Item label={item.tooltip ?
                <Tooltip placement="topLeft" title={item.tooltip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  {item.label}
                </Tooltip> : item.label
              }>
              <Form.Item label={label}>
                {getFieldDecorator(item.key, {
                  initialValue: item.initVal || '',
                  rules: [
src/menu/components/table/normal-table/columns/index.jsx
@@ -109,7 +109,7 @@
            {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
            {column.type === 'custom' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
            <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
            {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            {['text', 'number', 'formula', 'extend'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
          </div>
        } trigger="hover">
          {children}
src/menu/components/table/normal-table/index.jsx
@@ -331,6 +331,7 @@
  updatecolumn = (config) => {
    config.absFields = []
    config.hasExtend = false
    config.parCtrl = false
    let mapCol = (cols) => {
      cols.forEach(col => {
        if (col.type === 'number') {
@@ -339,6 +340,9 @@
          }
        } else if (col.type === 'extend') {
          config.hasExtend = true
          if (col.supField) {
            config.parCtrl = true
          }
        } else if (col.type === 'colspan' && col.subcols) {
          mapCol(col.subcols)
        }
@@ -403,7 +407,7 @@
        </Popover>
        {appType !== 'mob' ? <SearchComponent config={card} updatesearch={this.updateComponent}/> : null}
        <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
        <ColumnComponent config={card} updatecolumn={this.updateComponent}/>
        <ColumnComponent config={card} updatecolumn={this.updatecolumn}/>
        <div className="component-name">
          <div className="center">
            <div className="title" onDoubleClick={() => {
src/menu/datasource/index.jsx
@@ -173,8 +173,10 @@
          return item
        })
        if (!config.fixedCol) {
        res.columns.reverse()
      }
      }
      let maxScript = 0
src/menu/datasource/verifycard/index.jsx
@@ -216,7 +216,9 @@
    let columns = config.columns ? fromJS(config.columns).toJS() : []
    let subColumns = config.subColumns ? fromJS(config.subColumns).toJS() : []
    if (!config.fixedCol) {
    columns.reverse()
    }
    subColumns.reverse()
    columns.forEach(col => {
@@ -959,6 +961,7 @@
  }
  copyColumns = () => {
    const { config } = this.props
    const { columns, setting } = this.state
    let m = []
@@ -983,6 +986,33 @@
      console.info('select ' + s.join(', '))
    }
    let extend = ''
    if (config.hasExtend) {
      extend = []
      let mapCol = (cols) => {
        cols.forEach(col => {
          if (col.type === 'extend') {
            let datatype = 'Nvarchar(50)'
            columns.forEach(c => {
              if (c.field === col.field) {
                datatype = c.datatype
              }
            })
            for (let i = 1; i < col.quota; i++) {
              extend.push(`${col.field}${i} ${datatype}`)
            }
          } else if (col.type === 'colspan' && col.subcols) {
            mapCol(col.subcols)
          }
        })
      }
      mapCol(config.cols)
      extend = `
      /* 扩展列字段 */
      /* ${extend.join(',')} */
      `
    }
    let oInput = document.createElement('input')
    oInput.value = `create table #${setting.tableName || 'tb'}
    (${m.join(',')},sort_id INT IDENTITY(1,1))
@@ -1005,7 +1035,7 @@
      if @pageIndex_top > 0
        delete #${setting.tableName || 'tb'} where sort_id <= @pageIndex_top
    drop table #${setting.tableName || 'tb'}`
    drop table #${setting.tableName || 'tb'}${extend}`
    document.body.appendChild(oInput)
    oInput.select()
src/menu/debug/index.jsx
@@ -1286,18 +1286,20 @@
            /* 工作流默认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,upid)
            select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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
            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,upid)
            select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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${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
@@ -1323,11 +1325,16 @@
        }
      }
  
      if (_backCustomScript) {
        _sql += _backCustomScript
      }
      _sql = _sql.replace(/@start_type@/ig, `'开始'`)
      _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, `''`)
      _sql = _sql.replace(/@works_flow_code@/ig, `'mk'`)
      _sql = _sql.replace(/@works_flow_name@/ig, `'mk'`)
      _sql = _sql.replace(/@works_flow_param@/ig, `''`)
@@ -1336,9 +1343,7 @@
      _sql = _sql.replace(/@statusname@/ig, `'${statusName}'`)
      _sql = _sql.replace(/@work_group@/ig, `'mk'`)
      _sql = _sql.replace(/@work_grade@/ig, `'0'`)
    }
    if (_backCustomScript) {
    } else if (_backCustomScript) {
      _sql += _backCustomScript
    }
  
@@ -1714,7 +1719,7 @@
      `
    }
    sql = `create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50) )
    sql = `create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(256))
      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),@tbid Nvarchar(512)
      
      Select  @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}'
src/menu/modalconfig/index.scss
@@ -274,12 +274,6 @@
        padding: 10px;
        cursor: pointer;
      }
      .paste-Icon {
        position: absolute;
        font-size: 16px;
        right: 15px;
        top: 65px;
      }
    }
  }
  .setting {
src/menu/stylecontroller/index.jsx
@@ -1095,7 +1095,7 @@
                <Col span={24}>
                  <Form.Item
                    colon={false}
                    label={<SwapOutlined title="浮动"/>}
                    label={<SwapOutlined title="显示"/>}
                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                  >
                    <Radio.Group style={{whiteSpace: 'nowrap'}} defaultValue={card.display || 'block'} onChange={(e) => this.changeNormalStyle(e.target.value, 'display')}>
src/mob/searchconfig/index.jsx
@@ -228,7 +228,8 @@
          sqlVerifing: true
        })
        let sql = res.dataSource
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '')
        
        let rduri = ''
src/tabviews/basetable/index.jsx
@@ -45,7 +45,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { MenuID, MenuName } = this.props
    const { MenuID, MenuName, param } = this.props
    let _param = {
      func: 'sPC_Get_LongParam',
@@ -161,9 +161,18 @@
      // 权限过滤
      let roleId = sessionStorage.getItem('role_id') || '' // 角色ID
      let skip = window.GLOB.mkHS
      let param = this.props.param || {} // url参数
      let urlparam = {} // url参数
      if (param) {
        Object.keys(param).forEach(key => {
          if (/^\$/.test(key)) {
            urlparam[key] = param[key]
          } else {
            urlparam[key.toLowerCase()] = param[key]
          }
        })
      }
      window.GLOB.CacheData.set(MenuID, param)
      window.GLOB.CacheData.set(MenuID, urlparam)
      let userName = sessionStorage.getItem('User_Name') || ''
      let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -181,7 +190,7 @@
      }
      if (config.urlFields) {
        config.urlFields.forEach(field => {
          let val = `'${param[field] || ''}'`
          let val = `'${urlparam[field.toLowerCase()] || ''}'`
          regs.push({
            reg: new RegExp('@' + field + '@', 'ig'),
            value: val
@@ -193,7 +202,7 @@
        regs.push({ reg: /@works_flow_code@/ig, value: `'${config.flow_code}'` })
      }
      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, skip, param, MenuID, config.MenuName, config.process === 'true')
      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, skip, urlparam, MenuID, config.MenuName, config.process === 'true')
      let autoMatic = null
      if (config.autoMatic && config.autoMatic.enable === 'true') {
@@ -224,7 +233,7 @@
        }
      })
      let BID = param.$BID || ''
      let BID = urlparam.$BID || ''
      config.components = this.formatSetting(config.components, regs)
@@ -367,7 +376,10 @@
            col.type = 'custom'
          }
          
          if (col.type === 'number') {
          if (col.type === 'index') {
            col.field = '$Index'
            col.type = 'text'
          } else if (col.type === 'number') {
            if (col.sum === 'true') {
              statFields.push(col)
            }
src/tabviews/custom/components/calendar/index.jsx
@@ -180,8 +180,8 @@
    if (config.uuid !== menuId) return
    if (position === 'mainline' && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData()
    }
src/tabviews/custom/components/card/balcony/index.jsx
@@ -71,12 +71,26 @@
        _data = window.GLOB.CacheData.get(_config.wrap.publicId)
        _data = fromJS(_data).toJS()
      }
    } else {
      _config.elements.forEach(item => {
        if (item.eleType === 'button') return
        if (item.datatype === 'dynamic' && item.field) {
          item.field = item.field.toLowerCase()
        }
      })
    }
    _data.$$BID = BID || ''
    _data.$$BData = BData || ''
    if (_config.setting.primaryKey) {
      _data.$$uuid = _data[_config.setting.primaryKey] || ''
    }
    if (_config.wrap.datatype === 'static' && BData) {
      Object.keys(BData).forEach(key => {
        if (/\$/.test(key)) return
        _data[key.toLowerCase()] = BData[key]
      })
    }
    if (!_config.style.position) {
@@ -273,8 +287,8 @@
      this.loadData()
    } else {
      if ((position === 'mainline' || position === 'popclose') && config.wrap.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
        MKEmitter.emit('reloadData', config.wrap.supModule, BID)
      if (['mainline', 'maingrid', 'popclose'].includes(position) && config.wrap.supModule) {
        MKEmitter.emit('reloadData', config.wrap.supModule, position === 'maingrid' ? '' : BID)
      } else {
        this.loadData()
      }
@@ -359,8 +373,16 @@
    }
    
    if (config.wrap.datatype === 'static') {
      let _data = {$$BID: BID || '', $$BData: BData, $$empty: true, $$time: new Date().getTime()}
      if (BData) {
        Object.keys(BData).forEach(key => {
          if (/\$/.test(key)) return
          _data[key.toLowerCase()] = BData[key]
        })
      }
      this.setState({
        data: {$$BID: BID || '', $$BData: BData, $$empty: true, $$time: new Date().getTime()},
        data: _data
      })
      return
    } else if (config.setting.supModule && !BID) { // BID 不存在时,不做查询
src/tabviews/custom/components/card/cardItem/index.jsx
@@ -53,18 +53,14 @@
        MenuID: menu.MenuID,
        MenuName: menu.MenuName,
        type: menu.tabType,
        param: {}
        param: {$BID: data.$$uuid || ''}
      }
      if (card.setting.joint === 'true') {
        newtab.param.$BID = data.$$uuid || ''
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          if (key === 'children') return
          newtab.param[key] = data[key]
        })
      }
      MKEmitter.emit('modifyTabs', newtab, true)
    } else if (card.setting.click === 'menu') {
@@ -83,17 +79,13 @@
      if (!menu) return
      menu.param = {}
      if (card.setting.joint === 'true') {
        menu.param.$BID = data.$$uuid || ''
      menu.param = {$BID: data.$$uuid || ''}
        
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          if (key === 'children') return
          menu.param[key] = data[key]
        })
      }
      MKEmitter.emit('modifyTabs', menu, true)
    } else if (card.setting.click === 'link') {
@@ -107,6 +99,17 @@
        }
        src = src + `${con}id=${data.$$uuid || ''}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
      } else if (/@/.test(src)) {
        src = src.replace(/@id@/ig, data.$$uuid || '')
        src = src.replace(/@appkey@/ig, window.GLOB.appkey)
        src = src.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
        src = src.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          let reg = new RegExp('@' + key + '@', 'ig')
          src = src.replace(reg, data[key])
        })
      }
      window.open(src)
@@ -114,7 +117,7 @@
      if (data.$$type === 'extendCard') {
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$selectedData || [])
      } else if (cards.subtype === 'datacard') {
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn')
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn', (data.$$uuid || '') + (data.$Index || ''))
      } else {
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$empty ? [] : [data])
      }
@@ -132,7 +135,7 @@
      if (data.$$type === 'extendCard') {
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$selectedData || [])
      } else if (cards.subtype === 'datacard') {
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn')
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn', (data.$$uuid || '') + (data.$Index || ''))
      } else {
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$empty ? [] : [data])
      }
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -25,7 +25,7 @@
const FuncMegvii = asyncComponent(() => import('@/tabviews/zshare/actionList/funcMegvii'))
const FuncZip = asyncComponent(() => import('@/tabviews/zshare/actionList/funczip'))
const ExportPdf = asyncComponent(() => import('@/tabviews/zshare/actionList/exportPdf'))
const ShareLink = asyncComponent(() => import('@/tabviews/zshare/actionList/shareLink'))
const FuncButton = asyncComponent(() => import('@/tabviews/zshare/actionList/funcbutton'))
const EditLine = asyncComponent(() => import('@/tabviews/zshare/actionList/editLine'))
const BarCode = asyncComponent(() => import('@/components/barcode'))
const QrCode = asyncComponent(() => import('@/components/qrcode'))
@@ -106,7 +106,7 @@
    if (card.linkType === 'linkmenu') {
      if (card.linkThdMenu) {
        let __param = {
          $BID: data.$$uuid
          $BID: data.$$uuid || ''
        }
  
        if (card.field) {
@@ -114,16 +114,11 @@
          __param.$searchval = data[card.field] || ''
        }
      
        if (card.joint === 'true' && card.linkThdMenu.urlFields) {
          let lower = {}
          Object.keys(data).forEach(key => {
            lower[key.toLowerCase()] = data[key]
          if (/^\$/.test(key)) return
          if (key === 'children') return
          __param[key] = data[key]
          })
          card.linkThdMenu.urlFields.split(',').forEach(field => {
            __param[field] = lower[field.toLowerCase()] || ''
          })
        }
        let tabmenu = card.linkThdMenu
    
@@ -239,15 +234,13 @@
      d.click()
      d.remove()
    } else {
      if (card.joint === 'true') {
        let Id = ''
      let Id = data.$$uuid || ''
  
        if (cards.subtype === 'propcard' && cardCell) {
          Id = cardCell.setting.primaryId || ''
        } else {
          Id = data[cards.setting.primaryKey] || ''
        }
  
      if (card.joint === 'true') {
        let con = '?'
  
        if (/\?/ig.test(url)) {
@@ -255,6 +248,17 @@
        }
  
        url = url + `${con}id=${Id}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
      } else if (/@/.test(url)) {
        url = url.replace(/@id@/ig, Id)
        url = url.replace(/@appkey@/ig, window.GLOB.appkey)
        url = url.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
        url = url.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          let reg = new RegExp('@' + key + '@', 'ig')
          url = url.replace(reg, data[key])
        })
      }
  
      window.open(url)
@@ -1155,12 +1159,14 @@
        }
        let MkButton = null
        let lid = (data.$$uuid || '') + (data.$Index || '')
  
        if (['exec', 'prompt', 'pop', 'form'].includes(card.OpenType)) {
          MkButton = <NormalButton
            btn={card}
            name={name}
            BID={data.$$BID}
            LID={lid}
            BData={data.$$BData || ''}
            disabled={_disabled}
            setting={cards.setting}
@@ -1171,6 +1177,7 @@
          MkButton = <ExcelInButton
            btn={card}
            BID={data.$$BID}
            LID={lid}
            BData={data.$$BData || ''}
            disabled={_disabled}
            setting={cards.setting}
@@ -1180,6 +1187,7 @@
          MkButton = <ExcelOutButton
            btn={card}
            BID={data.$$BID}
            LID={lid}
            BData={data.$$BData || ''}
            disabled={_disabled}
            setting={cards.setting}
@@ -1190,6 +1198,7 @@
            btn={card}
            name={name}
            BID={data.$$BID}
            LID={lid}
            BData={data.$$BData || ''}
            disabled={_disabled}
            setting={cards.setting}
@@ -1200,6 +1209,7 @@
            btn={card}
            name={name}
            BID={data.$$BID}
            LID={lid}
            BData={data.$$BData || ''}
            disabled={_disabled}
            selectedData={_data}
@@ -1209,6 +1219,7 @@
            btn={card}
            name={name}
            BID={data.$$BID}
            LID={lid}
            BData={data.$$BData || ''}
            disabled={_disabled}
            selectedData={_data}
@@ -1218,6 +1229,7 @@
            MkButton = <ChangeUserButton
              btn={card}
              BID={data.$$BID}
              LID={lid}
              BData={data.$$BData || ''}
              disabled={_disabled}
              setting={cards.setting}
@@ -1227,6 +1239,7 @@
            MkButton = <PrintButton
              btn={card}
              BID={data.$$BID}
              LID={lid}
              BData={data.$$BData || ''}
              disabled={_disabled}
              setting={cards.setting}
@@ -1237,6 +1250,7 @@
            MkButton = <FuncMegvii
              btn={card}
              BID={data.$$BID}
              LID={lid}
              disabled={_disabled}
              setting={cards.setting}
              selectedData={_data}
@@ -1245,6 +1259,7 @@
            MkButton = <FuncZip
              btn={card}
              BID={data.$$BID}
              LID={lid}
              BData={data.$$BData || ''}
              disabled={_disabled}
              setting={cards.setting}
@@ -1253,12 +1268,7 @@
          } else if (card.funcType === 'expPdf') {
            MkButton = <ExportPdf
              btn={card}
            />
          } else if (card.funcType === 'shareLink') {
            MkButton = <ShareLink
              BID={data.$$BID}
              btn={card}
              selectedData={_data}
              LID={lid}
            />
          } else if (card.funcType === 'addline' || card.funcType === 'delline') {
            MkButton = <EditLine
@@ -1266,6 +1276,14 @@
              disabled={_disabled}
              selectedData={_data}
            />
          } else {
            MkButton = <FuncButton
              BID={data.$$BID}
              disabled={_disabled}
              LID={lid}
              btn={card}
              selectedData={_data}
            />
          }
        }
src/tabviews/custom/components/card/cardcellList/index.scss
@@ -10,6 +10,18 @@
  .ant-btn {
    padding: 0;
  }
  .ant-btn.mk-btn-hover-bg:not([disabled]):hover {
    opacity: 1!important;
    color: #ffffff!important;
    border-color: var(--mk-sys-color)!important;
    background-color: var(--mk-sys-color)!important;
  }
  .ant-btn.mk-btn-hover-border:not([disabled]):hover {
    opacity: 1!important;
    color: var(--mk-sys-color)!important;
    border-color: var(--mk-sys-color)!important;
    background-color: #ffffff!important;
  }
  .file-image {
    max-height: 100%;
    vertical-align: top;
src/tabviews/custom/components/card/data-card/index.jsx
@@ -410,7 +410,7 @@
    if (config.uuid !== menuId) return
    if (config.supNodes) {
      if (position === 'mainline' || position === 'popclose') {
      if (['mainline', 'maingrid', 'popclose'].includes(position)) {
        let supNode = this.supModules[this.supModules.length - 1]
        config.supNodes.forEach((item, i) => {
          setTimeout(() => {
@@ -447,8 +447,8 @@
        } else {
          this.loadData(id)
        }
      } else if ((position === 'mainline' || position === 'popclose') && supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
        MKEmitter.emit('reloadData', supModule, BID)
      } else if (['mainline', 'maingrid', 'popclose'].includes(position) && supModule) {
        MKEmitter.emit('reloadData', supModule, position === 'maingrid' ? '' : BID)
      } else if (!btn || btn.resetPageIndex !== 'false') {
        this.setState({
          pageIndex: 1
src/tabviews/custom/components/card/double-data-card/index.jsx
@@ -372,8 +372,8 @@
      } else {
        this.loadData(id)
      }
    } else if ((position === 'mainline' || position === 'popclose') && supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', supModule, BID)
    } else if (['mainline', 'maingrid', 'popclose'].includes(position) && supModule) {
      MKEmitter.emit('reloadData', supModule, position === 'maingrid' ? '' : BID)
    } else if (!btn || btn.resetPageIndex !== 'false') {
      this.setState({
        pageIndex: 1
@@ -1058,17 +1058,13 @@
    if (!menu) return
    menu.param = {}
    if (card.setting.joint === 'true') {
      menu.param.$BID = item.$$uuid || ''
    menu.param = {$BID: item.$$uuid || ''}
      
      Object.keys(item).forEach(key => {
        if (/^\$/.test(key)) return
        if (key === 'children') return
        menu.param[key] = item[key]
      })
    }
    MKEmitter.emit('modifyTabs', menu, true)
  }
src/tabviews/custom/components/card/prop-card/index.jsx
@@ -72,6 +72,14 @@
      this.loaded = true
    } else if (_config.wrap.datatype === 'static') {
      this.loaded = true
      _config.subcards.forEach(card => {
        card.elements.forEach(ele => {
          if (ele.eleType === 'button') return
          if (ele.datatype === 'dynamic' && ele.field) {
            ele.field = ele.field.toLowerCase()
          }
        })
      })
    }
    _data.$$BID = BID || ''
@@ -80,7 +88,7 @@
    if (_config.wrap.datatype === 'static' && BData) {
      Object.keys(BData).forEach(key => {
        if (/\$/.test(key)) return
        _data[key] = BData[key]
        _data[key.toLowerCase()] = BData[key]
      })
    }
@@ -434,8 +442,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData('', btn)
    }
@@ -506,7 +514,7 @@
      if (BData) {
        Object.keys(BData).forEach(key => {
          if (/\$/.test(key)) return
          _data[key] = BData[key]
          _data[key.toLowerCase()] = BData[key]
        })
      }
src/tabviews/custom/components/card/table-card/index.jsx
@@ -272,8 +272,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData()
    }
@@ -466,16 +466,12 @@
      if (!menu) return
      menu.param = {}
      if (card.setting.joint === 'true') {
        menu.param.$BID = data.$$uuid || ''
      menu.param = {$BID: data.$$uuid || ''}
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          menu.param[key] = data[key]
        })
      }
      MKEmitter.emit('modifyTabs', menu, true)
    } else if (card.setting.click === 'link') {
@@ -489,11 +485,22 @@
        }
        src = src + `${con}id=${data.$$uuid || ''}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
      } else if (/@/.test(src)) {
        src = src.replace(/@id@/ig, data.$$uuid || '')
        src = src.replace(/@appkey@/ig, window.GLOB.appkey)
        src = src.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
        src = src.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          let reg = new RegExp('@' + key + '@', 'ig')
          src = src.replace(reg, data[key])
        })
      }
      window.open(src)
    } else if (card.setting.click === 'button' && card.setting.linkbtn) {
      MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn')
      MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn', (data.$$uuid || '') + (data.$Index || ''))
    }
  }
src/tabviews/custom/components/carousel/cardItem/index.jsx
@@ -57,16 +57,12 @@
      if (!menu) return
      menu.param = {}
      if (card.setting.joint === 'true') {
        menu.param.$BID = data.$$uuid || ''
      menu.param = {$BID: data.$$uuid || ''}
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          menu.param[key] = data[key]
        })
      }
      MKEmitter.emit('modifyTabs', menu, true)
    } else if (card.setting.click === 'link') {
@@ -80,12 +76,23 @@
        }
        src = src + `${con}id=${data.$$uuid || ''}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
      } else if (/@/.test(src)) {
        src = src.replace(/@id@/ig, data.$$uuid || '')
        src = src.replace(/@appkey@/ig, window.GLOB.appkey)
        src = src.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
        src = src.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          let reg = new RegExp('@' + key + '@', 'ig')
          src = src.replace(reg, data[key])
        })
      }
      window.open(src)
    } else if (card.setting.click === 'button' && card.setting.linkbtn) {
      if (cards.subtype === 'datacard') {
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn')
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn', (data.$$uuid || '') + (data.$Index || ''))
      } else {
        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$empty ? [] : [data])
      }
src/tabviews/custom/components/carousel/data-card/index.jsx
@@ -282,8 +282,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData()
    }
src/tabviews/custom/components/carousel/prop-card/index.jsx
@@ -66,11 +66,27 @@
        window.GLOB.SyncData.delete(_config.dataName)
      }
    } else {
      _config.subcards.forEach(card => {
        card.elements.forEach(ele => {
          if (ele.eleType === 'button') return
          if (ele.datatype === 'dynamic' && ele.field) {
            ele.field = ele.field.toLowerCase()
          }
        })
      })
    }
    _data.$$uuid = _data[_config.setting.primaryKey] || ''
    _data.$$BID = BID || ''
    _data.$$BData = BData || ''
    if (_config.wrap.datatype === 'static' && BData) {
      Object.keys(BData).forEach(key => {
        if (/\$/.test(key)) return
        _data[key.toLowerCase()] = BData[key]
      })
    }
    if (!_config.wrap.height) { // 兼容
      _config.wrap.height = _config.style.height || '300px'
@@ -270,8 +286,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData()
    }
@@ -319,8 +335,16 @@
    const { config, BID, BData } = this.state
    if (config.wrap.datatype === 'static') {
      let _data = {$$BID: BID || '', $$BData: BData, $$empty: true}
      if (BData) {
        Object.keys(BData).forEach(key => {
          if (/\$/.test(key)) return
          _data[key.toLowerCase()] = BData[key]
        })
      }
      this.setState({
        data: {$$BID: BID || '', $$BData: BData, $$empty: true}
        data: _data
      })
      return
    } else if (config.setting.supModule && !BID) { // BID 不存在时,不做查询
src/tabviews/custom/components/chart/antv-G6/index.jsx
@@ -1621,17 +1621,13 @@
        MenuName: menu.MenuName,
        MenuNo: menu.MenuNo || '',
        type: menu.tabType,
        param: {}
        param: {$BID: data.$$uuid || ''}
      }
      if (plot.joint === 'true') {
        newtab.param.$BID = data.$$uuid || ''
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          newtab.param[key] = data[key]
        })
      }
      MKEmitter.emit('modifyTabs', newtab, true)
    } else if (plot.click === 'menu') {
@@ -1652,16 +1648,12 @@
      if (!menu) return
      menu.param = {}
      if (plot.joint === 'true') {
        menu.param.$BID = data.$$uuid || ''
      menu.param = {$BID: data.$$uuid || ''}
        Object.keys(data).forEach(key => {
          if (/^\$/.test(key)) return
          menu.param[key] = data[key]
        })
      }
      MKEmitter.emit('modifyTabs', menu, true)
    } else {
src/tabviews/custom/components/chart/antv-X6/index.jsx
@@ -1035,7 +1035,9 @@
      let mkdata = target.prop('mkdata')
      if (target.prop('mknode') === 'end') {
      if (source.prop('mknode') === 'start' && target.prop('mknode') === 'end') {
        edge.prop('mknode', 'throughEdge')
      } else if (target.prop('mknode') === 'end') {
        edge.prop('mknode', 'endEdge')
      } else if (target.prop('mknode') === 'start') {
        edge.prop('mknode', 'startEdge')
@@ -1623,7 +1625,13 @@
        } else if (item.mknode === 'end') {
          end_num++
        } else if (item.shape === 'edge') {
          if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
          if (item.mknode === 'throughEdge') {
            if (!item.mkdata.seniorbers || item.mkdata.seniorbers.length === 0) {
              unvalid = true
            }
          } else if (item.mkdata.seniorCondition === 'open') {
          } else if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
            unvalid = true
          } else if (item.mknode === 'startEdge' || item.mkdata.flowType === 'reject') {
            if (map.has(item.source.cell)) {
@@ -1886,6 +1894,16 @@
    }
  }
  delCell = () => {
    const { node } = this.state
    let cell = this.mkGraph.getCellById(node.id)
    this.mkGraph.removeCells([cell])
    this.setState({node: null})
  }
  changeProps = (value, key) => {
    const { node } = this.state
@@ -2091,7 +2109,13 @@
        } else if (item.mknode === 'end') {
          end_num++
        } else if (item.shape === 'edge' && !unvalidId && !rejectId && !approvalId) {
          if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
          if (item.mknode === 'throughEdge') {
            if (!item.mkdata.seniorbers || item.mkdata.seniorbers.length === 0) {
              unvalidId = item.id
            }
          } else if (item.mkdata.seniorCondition === 'open') {
          } else if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
            unvalidId = item.id
          } else if (item.mknode === 'startEdge' || item.mkdata.flowType === 'reject') {
            if (map.has(item.source.cell)) {
@@ -2331,7 +2355,7 @@
          <div id={config.uuid + 'container'} className="mk-container"></div>
          <div className="mk-node-edit">
            <div className="header">设置</div>
            {!node ? <div className="empty">未选中</div> : <NodeUpdate node={node} orgs={orgs} onChange={this.changeProps}/>}
            {!node ? <div className="empty">未选中</div> : <NodeUpdate node={node} orgs={orgs} onChange={this.changeProps} onDel={this.delCell}/>}
          </div>
        </div>
      </div>
src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Form, Row, Col, Input, Select, Radio, InputNumber, Modal } from 'antd'
import { FormOutlined } from '@ant-design/icons'
import { FormOutlined, DeleteOutlined } from '@ant-design/icons'
import ColorSketch from '@/tabviews/zshare/mutilform/mkColor'
import NodeForm from './nodeform'
@@ -494,12 +494,13 @@
      } else if (item.type === 'other') {
        fields.push(
          <Col span={24} key={index}>
            <span className="split-line">{item.label}:<FormOutlined onClick={() => {this.setState({visible: true})}}/></span>
            <span className="split-line">{item.label}:<FormOutlined onClick={() => {this.setState({visible: true})}}/><DeleteOutlined onClick={() => this.props.onDel()}/></span>
            {mkdata ? <div className="mk-data">
              <div>状态:{mkdata.status}<span style={{float: 'right'}}>{mkdata.statusName}</span></div>
              {mknode.shape !== 'edge' && !mknode.mknode ? <div>标记:{mkdata.sign || ''}</div> : null}
              {mknode.shape === 'edge' && mkdata.flowType ? <div>操作:{mkdata.flowType === 'reject' ? '驳回' : '审批'}</div> : null}
              {mkdata.members && mkdata.members.length ? <div>审批人:{mkdata.members.map(item => item.workername).join('、')}</div> : null}
              {mkdata.seniorbers && mkdata.seniorbers.length ? <div>特殊审批人:{mkdata.seniorbers.map(item => item.workername).join('、')}</div> : null}
              {mkdata.copys && mkdata.copys.length ? <div>抄送人:{mkdata.copys.map(item => item.workername).join('、')}</div> : null}
              <div>备注:{mkdata.remark || ''}</div>
            </div> : null}
@@ -524,7 +525,7 @@
          visible={visible}
          closable={false}
          maskClosable={false}
          width={1050}
          width={1070}
          centered={true}
          onOk={this.confirm}
          onCancel={() => this.setState({visible: false})}
src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
@@ -7,6 +7,16 @@
    margin: 5px 12px 10px;
    padding-bottom: 2px;
    font-size: 13px;
    >.anticon-delete {
      padding: 0 5px;
      float: right;
      color: #f5222d;
      line-height: 22px;
    }
    >.anticon-form {
      padding: 0 5px;
    }
  }
  .mk-data {
    font-size: 13px;
@@ -127,6 +137,7 @@
  }
  .member-input {
    display: inline-block;
    cursor: pointer;
    width: 100%;
    height: 32px;
    padding: 4px 11px;
src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx
@@ -175,7 +175,7 @@
    return (
      <>
        <div className="member-input">{value.length > 0 ? value.length + '人' : ''}<FormOutlined onClick={this.trigger} /></div>
        <div className="member-input" onClick={this.trigger}>{value.length > 0 ? value.length + '人' : ''}<FormOutlined /></div>
        <Modal
          wrapClassName="member-modal"
          title="选择人员"
src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
@@ -17,6 +17,7 @@
  state = {
    flowType: 'approval',
    execCondition: false,
    seniorCondition: false,
    approvalMethod: 'orsign',
    readOnly: false,
    options: []
@@ -32,8 +33,10 @@
      readOnly = true
    } else if (node.mknode === 'end') {
    } else if (node.mknode === 'throughEdge') {
      options = ['senior']
    } else if (node.mknode === 'endEdge') {
      options = ['approvalMethod']
      options = ['approvalMethod', 'execCondition']
    } else if (node.mknode === 'startEdge') {
      readOnly = true
    } else if (node.mknode === 'firstEdge') {
@@ -41,12 +44,13 @@
    } else if (node.shape !== 'edge') { // node
      options = ['sign']
    } else {
      options = ['flowType', 'approvalMethod', 'approver', 'members', 'copys', 'execCondition']
      options = ['flowType', 'approvalMethod', 'approver', 'members', 'copys', 'execCondition', 'senior']
    }
    this.setState({
      flowType: data.flowType || 'approval',
      execCondition: options.includes('execCondition') && data.execCondition === 'open',
      execCondition: options.includes('execCondition') ? data.execCondition === 'open' : false,
      seniorCondition: options.includes('senior') ? data.seniorCondition === 'open' : false,
      approvalMethod: data.approvalMethod || 'orsign',
      options,
      readOnly
@@ -54,9 +58,12 @@
  }
  handleConfirm = () => {
    const { node } = this.props
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          if (values.approvalMethod === 'countersign' && values.members.length > 5) {
            notification.warning({
              top: 92,
@@ -64,6 +71,19 @@
              duration: 10
            })
            return
          } else if (node.mknode === 'throughEdge' && values.seniorCondition === false) {
            notification.warning({
              top: 92,
              message: '开始与结束直连的分支必须设置特殊审批人!',
              duration: 10
            })
            return
          }
          if (values.seniorCondition === true) {
            values.seniorCondition = 'open'
          } else if (values.seniorCondition === false) {
            values.seniorCondition = 'close'
          }
          if (values.execCondition === true) {
@@ -86,7 +106,7 @@
  render() {
    const { orgs } = this.props
    const { getFieldDecorator } = this.props.form
    const { flowType, execCondition, approvalMethod, readOnly, options } = this.state
    const { flowType, execCondition, seniorCondition, approvalMethod, readOnly, options } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -102,7 +122,7 @@
    return (
      <Form {...formItemLayout} className="normal-node-form">
        <Row gutter={24}>
          {options.includes('approver') ? <Col span={24}>
          {options.includes('approver') || options.includes('execCondition') ? <Col span={24}>
            <p className="mk-split">按钮执行命令</p>
          </Col> : null}
          <Col span={12}>
@@ -270,6 +290,49 @@
              )}
            </Form.Item>
          </Col> : null}
          {options.includes('senior') && flowType !== 'reject' && approvalMethod !== 'countersign' ? <Col span={24}>
            <p className="mk-split">高级设置<span style={{fontSize: '12px', color: 'rgba(0, 0, 0, 0.45)'}}>(启用特殊审批人时,符合审批人列表时,优先使用此分支。)</span></p>
          </Col> : null}
          {options.includes('senior') && flowType !== 'reject' && approvalMethod !== 'countersign' ? <Col span={12}>
            <Form.Item label="特殊人员">
              {getFieldDecorator('seniorCondition', {
                valuePropName: 'checked',
                initialValue: seniorCondition
              })(
                <Switch checkedChildren="启用" unCheckedChildren="禁用" onChange={(val) => this.setState({seniorCondition: val})} />
              )}
            </Form.Item>
          </Col> : null}
          {options.includes('senior') && flowType !== 'reject' && approvalMethod !== 'countersign' && seniorCondition ? <Col span={12}>
            <Form.Item label="审批人">
              {getFieldDecorator('seniorbers', {
                initialValue: data.seniorbers || [],
                rules: [
                  { required: true, message: '请添加审批人!' }
                ]
              })(
                <MemberForm orgs={orgs} title="审批人"/>
              )}
            </Form.Item>
          </Col> : null}
          {options.includes('senior') && flowType !== 'reject' && approvalMethod !== 'countersign' && seniorCondition ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="用于业务处理时的标记值@works_flow_sign@。">
                <QuestionCircleOutlined className="mk-form-tip" />
                分支标记
              </Tooltip>
            }>
              {getFieldDecorator('seniorSign', {
                initialValue: data.seniorSign || '',
                rules: [
                  { required: true, message: '请添加分支标记!' },
                  { pattern: /^[0-9a-zA-Z_]+$/, message: '只可输入英文、数字以及_。' }
                ]
              })(
                <Input autoComplete="off" onPressEnter={() => this.props.handleSubmit()}/>
              )}
            </Form.Item>
          </Col> : null}
        </Row>
      </Form>
    )
src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -548,8 +548,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData()
    }
@@ -1848,17 +1848,13 @@
          MenuName: menu.MenuName,
          MenuNo: menu.MenuNo || '',
          type: menu.tabType,
          param: {}
          param: {$BID: data.$$uuid || ''}
        }
        if (plot.joint === 'true') {
          newtab.param.$BID = data.$$uuid || ''
          Object.keys(data).forEach(key => {
            if (/^\$/.test(key)) return
            newtab.param[key] = data[key]
          })
        }
  
        MKEmitter.emit('modifyTabs', newtab, true)
      } else if (plot.click === 'menu') {
@@ -1877,16 +1873,12 @@
        if (!menu) return
  
        menu.param = {}
        if (plot.joint === 'true') {
          menu.param.$BID = data.$$uuid || ''
        menu.param = {$BID: data.$$uuid || ''}
          Object.keys(data).forEach(key => {
            if (/^\$/.test(key)) return
            menu.param[key] = data[key]
          })
        }
  
        MKEmitter.emit('modifyTabs', menu, true)
      } else {
src/tabviews/custom/components/chart/antv-scatter/index.jsx
@@ -231,8 +231,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData()
    }
src/tabviews/custom/components/chart/custom-chart/index.jsx
@@ -222,8 +222,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData()
    }
src/tabviews/custom/components/form/simple-form/index.jsx
@@ -267,8 +267,8 @@
      })
    }
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) {
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else if (position === 'grid' && config.wrap.datatype === 'static') {
      this.setState({
        data: null
src/tabviews/custom/components/form/step-form/index.jsx
@@ -115,6 +115,8 @@
      _config.sortStyle = {width: s, height: s, lineHeight: s, borderRadius: s}
    }
    _config.style['--mk-active-color'] = _config.wrap.color || '#1890ff'
    this.setState({
      data: _data,
      group: _group,
@@ -263,8 +265,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) {
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else if (position === 'grid' && config.wrap.datatype === 'static') {
      this.setState({
        data: null
@@ -457,6 +459,18 @@
    })
  }
  changeGroup = (sort) => {
    const { config, step } = this.state
    if (config.wrap.labelJump !== 'true' || sort > step) return
    let _group = config.subcards.filter(item => item.sort === sort)[0]
    this.setState({group: null, step: sort - 1}, () => {
      this.setState({group: _group})
    })
  }
  render() {
    const { config, loading, BID, BData, data, group, step } = this.state
@@ -471,13 +485,14 @@
            <Spin />
          </div> : null
        }
        {config.wrap.groupLabel !== 'hidden' ? <div className="mk-normal-form-title">
        {config.wrap.groupLabel !== 'hidden' ? <div className={'mk-normal-form-title' + (config.wrap.labelJump === 'true' ? ' jumpable' : '')}>
          {config.subcards.map(card => (
            <div key={card.uuid} style={config.titleStyle} className={'form-title' + (card.sort <= step ? ' active' : '')}>
              <span className="form-sort" style={{background: config.wrap.color, ...config.sortStyle}}>{card.sort}</span>
              <span className="before-line" style={{background: config.wrap.color}}></span>
              <span className="after-line" style={{background: config.wrap.color}}></span>
              {card.setting.title}
              <span className="form-sort" onClick={() => this.changeGroup(card.sort)} style={config.sortStyle}>{card.sort}</span>
              <br/>
              <span className="form-label" onClick={() => this.changeGroup(card.sort)}>{card.setting.title}</span>
              <span className="before-line"></span>
              <span className="after-line"></span>
            </div>))
          }
        </div> : null}
src/tabviews/custom/components/form/step-form/index.scss
@@ -5,6 +5,7 @@
  background-size: cover;
  position: relative;
  min-height: 50px;
  --mk-active-color: #1890ff;
  .mk-normal-form-title {
    display: flex;
@@ -19,7 +20,7 @@
      font-weight: inherit;
      .form-sort {
        background: #d8d8d8;
        display: block;
        display: inline-block;
        width: 20px;
        height: 20px;
        line-height: 20px;
@@ -54,11 +55,20 @@
      top: 18px;
    }
    .form-title:not(.active) {
      .form-sort {
        background: #d8d8d8!important;
      .form-sort, .before-line, .after-line {
        background: #d8d8d8;
      }
      .before-line, .after-line {
        background: #d8d8d8!important;
    }
    .form-title.active {
      .form-sort, .before-line, .after-line {
        background: var(--mk-active-color);
      }
    }
  }
  .mk-normal-form-title.jumpable {
    .form-title.active {
      .form-label, .form-sort {
        cursor: pointer;
      }
    }
  }
src/tabviews/custom/components/form/tab-form/index.jsx
@@ -229,8 +229,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) {
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else if (position === 'grid' && config.wrap.datatype === 'static') {
      this.setState({
        data: null
src/tabviews/custom/components/module/account/index.jsx
@@ -84,6 +84,7 @@
          if (res.invoice_type) {
            item.invoice_type = res.invoice_type.map(cell => ({value: cell.invoice_type_code, label: cell.invoice_type_name}))
          }
          item.$$uuid = item.id
          activeItem = item
        }
        if (item.months) {
src/tabviews/custom/components/module/invoice/index.jsx
@@ -2,8 +2,9 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Select, Form, Input, Button, Modal, Spin, notification } from 'antd'
import { EllipsisOutlined } from '@ant-design/icons'
import { EllipsisOutlined, LeftOutlined } from '@ant-design/icons'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import UtilsDM from '@/utils/utils-datamanage.js'
@@ -20,17 +21,11 @@
  state = {
    BID: '',
    ID: Utils.getuuid(),
    ID: Utils.getguid(),
    io: '',
    invTypes: [
      {value: '1', label: '电子发票(增值税专用发票)'},
      {value: '2', label: '电子发票(普通发票)'},
      {value: '3', label: '增值税纸质专用发票'},
      {value: '4', label: '增值税纸质普通发票'},
      {value: '5', label: '增值税电子普通发票'},
      {value: '6', label: '增值税电子专用发票'},
    ],
    invTypes: [],
    invoice_type: '',
    business_type: '',
    date: moment().format('YYYY年MM月DD日'),
    from_to_name: '',
    from_to_tax_no: '',
@@ -58,7 +53,13 @@
    saveType: '',
    tax_type: '',
    reqfields: [],
    requireds: []
    requireds: [],
    invoice_no: '',
    invoice_code: '',
    invoice_date: '',
    read_only: false,
    invoice_type_name: '',
    timestamp: ''
  }
  UNSAFE_componentWillMount () {
@@ -83,6 +84,7 @@
    _config.buyer = this.formatSetting(_config.buyer, 'buyer')
    _config.detail = this.formatSetting(_config.detail, 'detail')
    _config.detail.uuid = _config.uuid
    let book = null
    let pas = {}
@@ -134,12 +136,21 @@
    item.setting.arr_field = item.columns.map(col => col.field).join(',')
    item.setting.laypage = item.setting.laypage === 'true'
    if (item.refreshTab && item.refreshTab.length) {
      item.reTabId = item.refreshTab.pop()
    }
    if (item.syncComponent && item.syncComponent.length) {
      item.syncComId = item.syncComponent.pop()
    }
    if (type === 'buyer') {
      item.columns = item.columns.map(cell => {
        if (['from_to_tel', 'from_to_account_no', 'from_to_code'].includes(cell.field)) {
          cell.Hide = 'true'
        } else if (['from_to_email', 'from_to_mob'].includes(cell.field)) {
          cell.Width = 80
        } else if (['from_to_name'].includes(cell.field)) {
          cell.Width = 140
        }
        return cell
      })
@@ -149,7 +160,7 @@
          cell.field = 'tax_rate'
          cell.label = '税率'
        }
        if (['Description', 'id', 'small_tax_rate', 'free_tax_mark', 'vat_special_management'].includes(cell.field)) {
        if (['Description', 'id', 'small_tax_rate', 'free_tax_mark', 'vat_special_management', 'tax_item', 'tax_method'].includes(cell.field)) {
          cell.Hide = 'true'
        } else if (['spec'].includes(cell.field)) {
          cell.Width = 150
@@ -281,9 +292,13 @@
  }
  async loadData() {
    const { config, BID } = this.state
    const { config, BID, book } = this.state
    if (config.wrap.datatype !== 'dynamic') return
    if (config.wrap.datatype !== 'dynamic' || !book) return
    if (!BID) {
      this.clearData()
      return
    }
    let param = UtilsDM.getQueryDataParams(config.setting, [], config.setting.order, 1, 1, BID)
@@ -293,14 +308,91 @@
    let result = await Api.genericInterface(param)
    if (result.status) {
      if (!result.data[0]) {
        this.clearData()
      this.setState({
        ID: result.data[0][config.setting.primaryKey] || Utils.getuuid(),
        io: '',
        details: [],
        oriDetails: [],
        loading: false
      })
        return
      }
      let line = result.data[0]
      let details = result.data.map(item => {
        let tax_name = item.tax_rate * 100 + '%'
        if (item.vat_special_management && item.free_tax_mark === 'true') {
          tax_name = item.vat_special_management
        }
        return {
          uuid: item.jskey,
          productname: item.productname,
          productcode: item.productcode,
          spec: item.spec,
          unit: item.unit,
          bill_count: item.bill_count,
          unitprice: item.unitprice,
          tax_rate: item.tax_rate,
          free_tax_mark: item.free_tax_mark,
          vat_special_management: item.vat_special_management,
          tax_classify_code: item.tax_classify_code,
          tax_classify_name: item.tax_classify_name,
          amount_line: item.amount_line,
          tax_amount: item.tax_amount,
          invoice_lp: item.invoice_lp,
          tax_item: item.tax_item,
          tax_method: item.tax_method,
          tax_name: tax_name
        }
      })
      let invoice_type_name = ''
      if (line.read_only === 'true') {
        let types = book.invoice_type || []
        types.forEach(item => {
          if (item.value === line.invoice_type) {
            invoice_type_name = item.label
          }
        })
        invoice_type_name = invoice_type_name || line.invoice_type
      }
      this.setState({
        ID: line[config.setting.primaryKey] || Utils.getguid(),
        io: line.io,
        invoice_type: line.invoice_type,
        business_type: line.business_type,
        from_to_name: line.from_to_name,
        from_to_tax_no: line.from_to_tax_no,
        from_to_addr: line.from_to_addr,
        from_to_tel: line.from_to_tel,
        from_to_bank_name: line.from_to_bank_name,
        from_to_account_no: line.from_to_account_no,
        from_to_mob: line.from_to_mob,
        from_to_email: line.from_to_email,
        from_to_code: line.from_to_code,
        orgname: line.orgname,
        tax_no: line.tax_no,
        addr: line.addr,
        tel: line.tel,
        bank_name: line.bank_name,
        account_no: line.account_no,
        remark: line.remark,
        payee: line.payee,
        reviewer: line.reviewer,
        drawer: line.drawer,
        details: details,
        invoice_no: line.invoice_no,
        invoice_code: line.invoice_code,
        invoice_date: line.read_only === 'true' ? line.invoice_date : '',
        read_only: line.read_only === 'true',
        invoice_type_name: invoice_type_name,
        oriDetails: fromJS(details).toJS(),
        timestamp: new Date().getTime() + '',
        loading: false
      })
      this.getRequired(line.invoice_type)
      UtilsDM.querySuccess(result)
    } else {
@@ -313,6 +405,25 @@
    }
  }
  clearData = () => {
    this.setState({
      ID: Utils.getguid(),
      from_to_name: '',
      from_to_tax_no: '',
      from_to_addr: '',
      from_to_tel: '',
      from_to_bank_name: '',
      from_to_account_no: '',
      from_to_mob: '',
      from_to_email: '',
      from_to_code: '',
      business_type: '',
      details: [],
      oriDetails: [],
      timestamp: new Date().getTime() + '',
    })
  }
  changeType = (val) => {
    sessionStorage.setItem('pre_invoice_type', val)
    this.setState({invoice_type: val})
@@ -320,7 +431,13 @@
  }
  getRequired = (invoice_type) => {
    if (!invoice_type) return
    if (!invoice_type) {
      this.setState({
        reqfields: [],
        requireds: []
      })
      return
    }
    let reqfields = []
    let requireds = []
@@ -364,7 +481,7 @@
  }
  saveBill = () => {
    const { config, book, saveType } = this.state
    const { config, BID, saveType } = this.state
    if (saveType) return
@@ -377,7 +494,7 @@
          LText: sql,
          exec_type: window.GLOB.execType || 'y',
          timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
          BID: book.id
          BID: BID
        }
  
        param.secretkey = Utils.encrypt('', param.timestamp)
@@ -388,7 +505,16 @@
        })
        Api.genericInterface(param).then(res => {
          this.setState({
            saveType: ''
          })
          if (res.status) {
            if (config.billSaveBtn.reTabId) {
              MKEmitter.emit('reloadMenuView', config.billSaveBtn.reTabId, 'table')
            }
            if (config.billSaveBtn.syncComId) {
              MKEmitter.emit('reloadData', config.billSaveBtn.syncComId)
            }
            notification.success({
              top: 92,
              message: '保存成功。',
@@ -401,9 +527,6 @@
              duration: 5
            })
          }
          this.setState({
            saveType: ''
          })
        })
      }, (error) => {
        notification.warning({
@@ -411,13 +534,21 @@
          message: error,
          duration: 5
        })
        return
      })
    }, 20)
  }
  outBill = () => {
    const { config, book, saveType } = this.state
    const { config, BID, saveType } = this.state
    if (window.GLOB.systemType === 'production' && !config.billOutBtn.proInterface) {
      notification.warning({
        top: 92,
        message: '尚未设置正式系统接口地址!',
        duration: 5
      })
      return
    }
    if (saveType) return
@@ -428,16 +559,33 @@
        let param = {
          func: 'sPC_TableData_InUpDe',
          LText: sql,
          key_back_type: 'Y',
          script_type: 'Y',
          exec_type: window.GLOB.execType || 'y',
          timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
          BID: book.id
          BID: BID
        }
  
        param.secretkey = Utils.encrypt('', param.timestamp)
        param.LText = Utils.formatOptions(param.LText, param.exec_type)
        console.info(sql)
        this.setState({
          saveType: 'out'
        })
        Api.genericInterface(param).then(res => {
          if (res.status) {
            this.outPutBill(res)
          } else {
            notification.warning({
              top: 92,
              message: res.message,
              duration: 5
            })
            this.setState({
              saveType: ''
            })
          }
        })
      }, (error) => {
        notification.warning({
          top: 92,
@@ -449,10 +597,14 @@
    })
  }
  getPreSql = (btn) => {
    const { book, ID, io, details, oriDetails, invoice_type, from_to_name, from_to_tax_no, from_to_addr, from_to_tel, from_to_bank_name, from_to_account_no, from_to_mob, from_to_email, from_to_code, orgname, tax_no, addr, tel, bank_name, account_no, remark, reviewer, drawer, payee } = this.state
  goback = () => {
    const { config } = this.state
    MKEmitter.emit('closeTabView', config.$pageId)
  }
    let BID = book.id
  getPreSql = (btn) => {
    const { config, book, ID, BID, io, details, oriDetails, business_type, invoice_type, from_to_name, from_to_tax_no, from_to_addr, from_to_tel, from_to_bank_name, from_to_account_no, from_to_mob, from_to_email, from_to_code, orgname, tax_no, addr, tel, bank_name, account_no, remark, reviewer, drawer, payee } = this.state
    let userName = sessionStorage.getItem('User_Name') || '' 
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let RoleID = sessionStorage.getItem('role_id') || ''
@@ -468,8 +620,11 @@
    let price = 0
    let tax = 0
    let lines = details.map(line => {
      let _sql = `Select '${line.productcode}', '${line.productname}', '${line.spec}', '${line.unit}', ${line.bill_count}, ${line.unitprice}, ${line.amount_line}, '${line.tax_classify_code}', '${line.tax_classify_name}', ${line.tax_rate}, ${line.tax_amount}, '${line.free_tax_mark || ''}', '${line.vat_special_management || ''}', '${line.invoice_lp || ''}', '${line.uuid}'`
    let lines = []
    details.forEach(line => {
      if (!line.productcode) return
      let _sql = `Select '${line.productcode}', '${line.productname}', '${line.spec}', '${line.unit}', ${line.bill_count}, ${line.unitprice}, ${line.amount_line}, '${line.tax_classify_code}', '${line.tax_classify_name}', ${line.tax_rate}, ${line.tax_amount}, '${line.free_tax_mark || ''}', '${line.vat_special_management || ''}', '${line.invoice_lp || ''}', '${line.tax_item}', '${line.tax_method}', '${line.uuid}'`
      let data_type = 'add'
      price += line.amount_line * 100
@@ -485,7 +640,7 @@
        })
      }
      return _sql + `, '${data_type}'`
      lines.push(_sql + `, '${data_type}'`)
    })
    let _total = (price - tax) / 100
@@ -494,7 +649,7 @@
    if (options.length) {
      options.forEach(line => {
        lines.push(`Select '${line.productcode}', '${line.productname}', '${line.spec}', '${line.unit}', ${line.bill_count}, ${line.unitprice}, ${line.amount_line}, '${line.tax_classify_code}', '${line.tax_classify_name}', ${line.tax_rate}, ${line.tax_amount}, '${line.free_tax_mark || ''}', '${line.vat_special_management || ''}', '${line.invoice_lp || ''}', '${line.uuid}', 'del'`)
        lines.push(`Select '${line.productcode}', '${line.productname}', '${line.spec}', '${line.unit}', ${line.bill_count}, ${line.unitprice}, ${line.amount_line}, '${line.tax_classify_code}', '${line.tax_classify_name}', ${line.tax_rate}, ${line.tax_amount}, '${line.free_tax_mark || ''}', '${line.vat_special_management || ''}', '${line.invoice_lp || ''}', '${line.tax_item}', '${line.tax_method}', '${line.uuid}', 'del'`)
      })
    }
@@ -511,25 +666,31 @@
    let sql = `/* 系统字段 */
      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), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @bid nvarchar(50), @tbid nvarchar(50)
      Select @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}', @ErrorCode='', @retmsg='', @account_id='${book.account_id || ''}', @account_year_id='${book.account_year_id || ''}', @account_code='${book.account_code || ''}', @account_year_code='${book.account_year_code || ''}', @bid=''
      Select @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}', @ErrorCode='', @retmsg='', @account_id='${book.account_id || ''}', @account_year_id='${book.account_year_id || ''}', @account_code='${book.account_code || ''}', @account_year_code='${book.account_year_code || ''}', @bid='${BID}'
      /* 发票主表字段 */
      Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2)
      Declare @invoice_type Nvarchar(50), @from_to_name Nvarchar(50), @from_to_tax_no Nvarchar(50), @from_to_addr Nvarchar(100), @from_to_tel Nvarchar(50), @from_to_bank_name Nvarchar(50), @from_to_account_no Nvarchar(50), @from_to_mob Nvarchar(50), @from_to_email Nvarchar(50), @from_to_code Nvarchar(50), @orgname Nvarchar(50), @tax_no Nvarchar(50), @addr Nvarchar(100), @tel Nvarchar(50), @bank_name Nvarchar(50), @account_no Nvarchar(50), @remark Nvarchar(512), @payee Nvarchar(50), @reviewer Nvarchar(50), @drawer Nvarchar(50), @io Nvarchar(50), @orgcode Nvarchar(50), @total_net_amount Decimal(18,2), @total_tax Decimal(18,2), @total_amount Decimal(18,2), @business_type Nvarchar(20)
      Select @invoice_type='${invoice_type}', @from_to_name='${from_to_name}', @from_to_tax_no='${from_to_tax_no}', @from_to_addr='${from_to_addr}', @from_to_tel='${from_to_tel}', @from_to_bank_name='${from_to_bank_name}', @from_to_account_no='${from_to_account_no}', @from_to_mob='${from_to_mob}', @from_to_email='${from_to_email}', @from_to_code='${from_to_code}', @orgname='${orgname}', @tax_no='${tax_no}', @addr='${addr}', @tel='${tel}', @bank_name='${bank_name}', @account_no='${account_no}', @remark='${remark}', @payee='${payee}', @reviewer='${reviewer}', @drawer='${drawer}', @io='${io}', @orgcode='${book.orgcode || ''}', @total_net_amount=${_total}, @total_tax=${tax}, @total_amount=${price}
      Select @invoice_type='${invoice_type}', @from_to_name='${from_to_name}', @from_to_tax_no='${from_to_tax_no}', @from_to_addr='${from_to_addr}', @from_to_tel='${from_to_tel}', @from_to_bank_name='${from_to_bank_name}', @from_to_account_no='${from_to_account_no}', @from_to_mob='${from_to_mob}', @from_to_email='${from_to_email}', @from_to_code='${from_to_code}', @orgname='${orgname}', @tax_no='${tax_no}', @addr='${addr}', @tel='${tel}', @bank_name='${bank_name}', @account_no='${account_no}', @remark='${remark}', @payee='${payee}', @reviewer='${reviewer}', @drawer='${drawer}', @io='${io}', @orgcode='${book.orgcode || ''}', @total_net_amount=${_total}, @total_tax=${tax}, @total_amount=${price}, @business_type='${business_type || config.wrap.business_type || ''}'
      /* 发票明细临时表 */
      Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
      Declare @details_list table (productcode Nvarchar(50), productname Nvarchar(50), spec Nvarchar(50), unit Nvarchar(50), bill_count Decimal(18,10), unitprice Decimal(18,10), amount_line Decimal(18,2), tax_classify_code Nvarchar(50), tax_classify_name Nvarchar(50), tax_rate Decimal(18,2), tax_amount Decimal(18,2), free_tax_mark Nvarchar(50), vat_special_management Nvarchar(50), invoice_lp Nvarchar(50), tax_item Nvarchar(50), tax_method Nvarchar(50), jskey Nvarchar(50), data_type Nvarchar(50))
      Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, jskey, data_type)
      Insert into @details_list (productcode, productname, spec, unit, bill_count, unitprice, amount_line, tax_classify_code, tax_classify_name, tax_rate, tax_amount, free_tax_mark, vat_special_management, invoice_lp, tax_item, tax_method, jskey, data_type)
      ${lines}
      /* 自定义脚本 */
      ${_script}
      `
      aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    if (btn.type === 'billout') {
      sql += `aaa: if @ErrorCode!=''
      insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg, @UserID@`
    } else {
      sql += `aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    }
    sql = sql.replace(/@ID@/ig, `'${ID}'`)
    sql = sql.replace(/@BID@/ig, `'${BID}'`)
@@ -585,7 +746,7 @@
      }
      if (!error) {
        if (details.length === 0) {
        if (details.length === 0 || details.filter(line => !!line.productcode).length === 0) {
          error = '请添加明细!'
        } else {
          details.forEach((line, index) => {
@@ -596,8 +757,6 @@
              } else if (!line.unitprice) {
                error = '明细第' + (index + 1) + '行,请输入单价!'
              }
            } else {
              error = '明细第' + (index + 1) + '行,请选择货物或应税劳务、服务名称!'
            }
          })
        }
@@ -609,6 +768,249 @@
        resolve()
      }
    })
  }
  outPutBill = (res) => {
    const { config } = this.state
    if (!res.data_invoice || !res.sellerName || !res.taxNo) {
      notification.warning({
        top: 92,
        message: '缺少开票参数!',
        duration: 5
      })
      this.setState({
        saveType: ''
      })
    }
    let param = {
      data: res.data_invoice,
      sellerName: res.sellerName,
      taxNo: res.taxNo
    }
    let trans = {
      e_general: '02',
      e_special: '01'
    }
    param.data.invoiceTypeCode = trans[param.data.invoiceTypeCode] || ''
    let url = ''
    if (window.GLOB.systemType === 'production') {
      url = config.billOutBtn.proInterface
    } else {
      url = config.billOutBtn.interface
    }
    if (!/^http/.test(url)) {
      url = window.location.origin + url
    }
    let _params = {
      url: url,
      method: 'post',
      headers: { 'Content-Type': 'application/json' },
      data: param
    }
    Api.directRequest(_params).then(result => {
      result.mk_api_key = res.mk_api_key || ''
      this.callBackBill(result)
    })
  }
  callBackBill = (result) => {
    const { config, BID, ID } = this.state
    let btn = config.billOutBtn
    let lines = []
    let pre = '@'
    let getDefaultSql = (obj, tb, bid, level) => {
      let keys = []
      let vals = []
      let subObjs = []
      let id = Utils.getuuid()
      let tbName = pre + tb
      delete obj.$$key
      Object.keys(obj).forEach(key => {
        let val = obj[key]
        if (val === null || val === undefined) return
        if (typeof(val) === 'object') {
          if (Array.isArray(val)) {
            val.forEach(item => {
              if (typeof(item) !== 'object' || Array.isArray(item)) return
              if (Object.keys(item).length > 0) {
                item.$$key = tb + '_' + key
                subObjs.push(item)
              }
            })
          } else if (Object.keys(val).length > 0) {
            val.$$key = tb + '_' + key
            subObjs.push(val)
          }
        } else {
          if (typeof(val) === 'string') {
            val = val.replace(/'/ig, '"')
          }
          keys.push('[' + key + ']')
          vals.push(`'${val}'`)
        }
      })
      keys = keys.join(',')
      vals = vals.join(',')
      lines.push({
        table: md5(tb + keys),
        insert: `Insert into ${tbName} (${keys ? keys + ',' : ''}[mk_level],[mk_id],[mk_bid])`,
        select: `Select ${keys ? vals + ',' : ''}'${level}','${id}','${bid}'`
      })
      subObjs.forEach(item => {
        getDefaultSql(item, item.$$key, id, level + 1)
      })
    }
    getDefaultSql(result, btn.cbTable, '', 1)
    let lineMap = new Map()
    lines.forEach(line => {
      if (lineMap.has(line.table)) {
        let _line = lineMap.get(line.table)
        _line.selects.push(line.select)
        lineMap.set(line.table, _line)
      } else {
        lineMap.set(line.table, {
          table: line.table,
          insert: line.insert,
          selects: [line.select]
        })
      }
    })
    let param = {
      func: 'sPC_TableData_InUpDe',
      BID: BID,
      menuname: config.name + '(回调)'
    }
    let callbacksql = this.getBackSql()
    let _prevCustomScript = `${callbacksql}
    `
    let _backCustomScript = ''
    btn.cbScripts.forEach(script => {
      if (script.status === 'false') return
      if (script.position === 'front') {
        _prevCustomScript += `
      /* 自定义脚本 */
      ${script.sql}
      `
      } else {
        _backCustomScript += `
      /* 自定义脚本 */
      ${script.sql}
      `
      }
    })
    _backCustomScript += `
      aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
    let sql = [...lineMap.values()].map(item => (`
      ${item.insert}
      ${item.selects.join(` union all
      `)}
    `))
    sql = sql.join('')
    sql = _prevCustomScript + sql
    sql = sql + _backCustomScript
    sql = sql.replace(/@ID@/ig, `'${ID || ''}'`)
    sql = sql.replace(/@BID@/ig, `'${BID || ''}'`)
    sql = sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
    sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
    sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
    sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
    sql = sql.replace(/@typename@/ig, `'admin'`)
    if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
      sql = sql.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, `'Y'`)
    } else {
      sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, `''`)
    }
    if (window.GLOB.debugger === true) {
      console.info('%c' + config.name + '(回调)', 'color: blue')
      console.info(sql.replace(/\n\s{8}/ig, '\n'))
    }
    param.LText = sql
    param.exec_type = window.GLOB.execType || 'y' // 后台解码
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt('', param.timestamp)
    param.LText = Utils.formatOptions(param.LText, param.exec_type)
    if (window.GLOB.probation) {
      param.s_debug_type = 'Y'
    }
    Api.genericInterface(param).then(res => {
      this.setState({
        saveType: ''
      })
      if (res.status) {
        if (config.billOutBtn.reTabId) {
          MKEmitter.emit('reloadMenuView', config.billOutBtn.reTabId, 'table')
        }
        if (config.billOutBtn.syncComId) {
          MKEmitter.emit('reloadData', config.billOutBtn.syncComId)
        }
        this.clearData()
        notification.success({
          top: 92,
          message: '开票成功。',
          duration: 5
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
      }
    })
  }
  getBackSql = () => {
    const { book, BID } = this.state
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let RoleID = sessionStorage.getItem('role_id') || ''
    let departmentcode = sessionStorage.getItem('departmentcode') || ''
    let organization = sessionStorage.getItem('organization') || ''
    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
    let nation = sessionStorage.getItem('nation') || ''
    let province = sessionStorage.getItem('province') || ''
    let city = sessionStorage.getItem('city') || ''
    let district = sessionStorage.getItem('district') || ''
    let address = sessionStorage.getItem('address') || ''
    let sql = `/* 系统字段 */
      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), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @bid nvarchar(50), @tbid nvarchar(50)
      Select @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}', @ErrorCode='', @retmsg='', @account_id='${book.account_id || ''}', @account_year_id='${book.account_year_id || ''}', @account_code='${book.account_code || ''}', @account_year_code='${book.account_year_code || ''}', @bid='${BID || ''}'
      `
    return sql
  }
  changeBuyer = (item) => {
@@ -626,16 +1028,138 @@
    })
  }
  render() {
    const { config, book, loading, invTypes, reqfields, saveType, date, invoice_type, from_to_name, from_to_tax_no, from_to_addr, from_to_tel, from_to_bank_name, from_to_account_no, from_to_mob, from_to_email, orgname, tax_no, addr, tel, bank_name, account_no, remark, reviewer, drawer, payee, details, visible, tax_type } = this.state
  addInvice = () => {
    const { saveType } = this.state
    if (!book || (config.wrap.datatype === 'dynamic' && !tax_no)) {
    if (saveType) {
      notification.warning({
        top: 92,
        message: saveType === 'bill' ? '单据保存中,请稍后。' : '开票中,请稍后。',
        duration: 3
      })
      return
    }
    this.clearData()
    notification.success({
      top: 92,
      message: '单据已更新。',
      duration: 3
    })
  }
  // jumpSys = () => {
  //   window.open(`${window.location.origin}/kgcs/thirdPlatFormLogin?userName=admin&taxCode=91120222MA07GMNW97&taxName=天津畅享数字科技有限公司`)
  // }
  render() {
    const { config, book, loading, invTypes, reqfields, saveType, date, timestamp, invoice_type, from_to_name, from_to_tax_no, from_to_addr, from_to_tel, from_to_bank_name, from_to_account_no, from_to_mob, from_to_email, orgname, tax_no, addr, tel, bank_name, account_no, remark, reviewer, drawer, payee, details, visible, tax_type, invoice_no, invoice_code, invoice_date, read_only, invoice_type_name } = this.state
    if (!book || (config.wrap.datatype === 'dynamic' && !timestamp)) {
      return <div className="menu-invoice-wrap" style={config.style}>
        <div className="loading-mask">
          <div className="ant-spin-blur"></div>
          <Spin />
        </div>
      </div>
    }
    if (read_only) {
      return (
        <div className="menu-invoice-wrap read_only" style={config.style}>
          {loading ?
            <div className="loading-mask">
              <div className="ant-spin-blur"></div>
              <Spin />
            </div> : null
          }
          <div className="inv-action">
            {config.wrap.backBtn === 'show' ? <Button className="mk-back" onClick={this.goback}><LeftOutlined />返回</Button> : null}
          </div>
          <div className="inv-header">
            <div className="inv-type">{invoice_type_name}</div>
            <div className="inv-msg">
              {invoice_no ? <div>发票号码:{invoice_no}</div> : null}
              {invoice_code ? <div>发票代码:{invoice_code}</div> : null}
              {invoice_date ? <div>开票日期:{invoice_date}</div> : null}
            </div>
          </div>
          <div className="inv-body">
            <div className="inv-main-content">
              <div className="inv-buyer">
                <div className="inv-label">购买方</div>
                <div className="inv-content">
                  <Form.Item className="mk-name" label={<>名<span></span>称</>}>
                    {from_to_name}
                  </Form.Item>
                  <Form.Item label="纳税人识别号">
                    {from_to_tax_no}
                  </Form.Item>
                  <Form.Item label={<>地<span></span>址<span></span>、<span></span>电<span></span>话</>}>
                    {from_to_addr + ' ' + from_to_tel}
                  </Form.Item>
                  <Form.Item label="开户行及账号">
                    {from_to_bank_name + ' ' + from_to_account_no}
                  </Form.Item>
                </div>
              </div>
              <div className="inv-notice">
                <div className="inv-label">通知到</div>
                <div className="inv-content">
                  <Form.Item label={<>手<span></span>机<span></span>号</>}>
                    {from_to_mob}
                  </Form.Item>
                  <Form.Item label={<>邮<span></span>箱</>}>
                    {from_to_email}
                  </Form.Item>
                </div>
              </div>
            </div>
            <div className="inv-details">
              <InvoiceTable data={details} timestamp={timestamp} read_only={true} config={config.detail} tax_type={tax_type} onChange={(details) => this.setState({details})}/>
            </div>
            <div className="inv-main-content">
              <div className="inv-buyer">
                <div className="inv-label">销售方</div>
                <div className="inv-content">
                  <Form.Item label={<>名<span></span>称</>}>
                    {orgname}
                  </Form.Item>
                  <Form.Item label="纳税人识别号">
                    {tax_no}
                  </Form.Item>
                  <Form.Item label={<>地<span></span>址<span></span>、<span></span>电<span></span>话</>}>
                    {addr + ' ' + tel}
                  </Form.Item>
                  <Form.Item label="开户行及账号">
                    {bank_name + ' ' + account_no}
                  </Form.Item>
                </div>
              </div>
              <div className="inv-notice">
                <div className="inv-label">备注</div>
                <div className="inv-content" style={{paddingTop: '30px'}}>
                  <Form.Item label="">
                    {remark}
                  </Form.Item>
                </div>
              </div>
            </div>
          </div>
          <div className="inv-tail">
            <Form.Item label="收款人">
              {payee}
            </Form.Item>
            <Form.Item label="复核人">
              {reviewer}
            </Form.Item>
            <Form.Item label="开票人">
              {drawer}
            </Form.Item>
          </div>
        </div>
      )
    }
    return (
@@ -647,11 +1171,14 @@
          </div> : null
        }
        <div className="inv-action">
          {config.wrap.backBtn === 'show' ? <Button className="mk-back" onClick={this.goback}><LeftOutlined />返回</Button> : null}
          {/* <Button className="mk-addinv" onClick={this.jumpSys}>跳转</Button> */}
          <Button className="mk-addinv" onClick={this.addInvice}>新增发票</Button>
          <Button className="mk-bill" loading={saveType === 'bill'} onClick={this.saveBill}>保存单据</Button>
          <Button className="mk-submit" loading={saveType === 'out'} onClick={this.outBill}>提交开票</Button>
        </div>
        <div className="inv-header">
          {invoice_type ? <Select defaultValue={invoice_type} onChange={this.changeType} dropdownClassName="inv-type-select">
          {invoice_type ? <Select value={invoice_type} onChange={this.changeType} dropdownClassName="inv-type-select">
            {invTypes.map(item => (
              <Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>
            ))}
@@ -667,7 +1194,7 @@
            <div className="inv-buyer">
              <div className="inv-label">购买方</div>
              <div className="inv-content">
                <Form.Item required={reqfields.includes('from_to_name')} label={<>名<span></span>称</>} extra={<EllipsisOutlined onClick={() => this.setState({visible: true})}/>}>
                <Form.Item className="mk-name" required={reqfields.includes('from_to_name')} label={<>名<span></span>称</>} extra={<EllipsisOutlined onClick={() => this.setState({visible: true})}/>}>
                  <Input placeholder="请输入购买方名称" allowClear value={from_to_name} autoComplete="off" onChange={(e) => this.setState({from_to_name: e.target.value})}/>
                </Form.Item>
                <Form.Item required={reqfields.includes('from_to_tax_no')} label="纳税人识别号">
@@ -696,7 +1223,7 @@
            </div>
          </div>
          <div className="inv-details">
            <InvoiceTable data={details} config={config.detail} tax_type={tax_type} onChange={(details) => this.setState({details})}/>
            <InvoiceTable data={details} timestamp={timestamp} read_only={false} config={config.detail} tax_type={tax_type} onChange={(details) => this.setState({details})}/>
          </div>
          <div className="inv-main-content">
            <div className="inv-buyer">
@@ -742,7 +1269,7 @@
        <Modal
          title="客户信息"
          visible={visible}
          width="70vw"
          width="75vw"
          maskClosable={false}
          onCancel={() => { this.setState({ visible: false }) }}
          footer={null}
src/tabviews/custom/components/module/invoice/index.scss
@@ -17,6 +17,23 @@
      margin-bottom: 5px;
      height: 30px;
    }
    .mk-back {
      border: none;
      float: left;
      margin-left: 0px;
      padding: 0px;
      box-shadow: none;
    }
    .mk-back::after {
      display: none;
    }
    .mk-back:hover, .mk-back:active, .mk-back:focus {
      color: var(--mk-sys-color);
    }
    .mk-addinv, .mk-addinv:active, .mk-addinv:focus {
      color: #52c41a;
      border-color: #52c41a;
    }
    .mk-bill:hover, .mk-bill:active, .mk-bill:focus {
      color: var(--mk-sys-color);
      border-color: var(--mk-sys-color);
@@ -32,6 +49,38 @@
    position: relative;
    height: 70px;
    margin-right: 30px;
    .inv-type {
      width: 390px;
      display: inline-block;
      position: relative;
      font-size: 25px;
      text-align: center;
      font-family: kaiti;
      color: var(--inv-color, #13509c);
    }
    .inv-type::before, .inv-type::after {
      content: '';
      display: block;
      width: 100%;
      position: absolute;
      border-top: var(--inv-color, #13509c) 1px solid;
      border-bottom: var(--inv-color, #13509c) 1px solid;
      height: 1px;
    }
    .inv-type::before {
      bottom: -10px;
    }
    .inv-type::after {
      bottom: -15px;
    }
    .inv-msg {
      position: absolute;
      right: 100px;
      top: 0px;
      font-size: 13px;
      text-align: left;
      color: var(--inv-color, #13509c);
    }
    .ant-select {
      width: 390px;
      border: none;
@@ -140,6 +189,10 @@
        .inv-content {
          flex: 1;
          padding: 6px 0;
          .mk-name .ant-input-affix-wrapper .ant-input-suffix {
            right: 35px;
          }
          .ant-form-item {
            display: flex;
@@ -252,11 +305,27 @@
    }
  }
}
.menu-invoice-wrap.read_only {
  .ant-form-item-children {
    color: rgba(0, 0, 0, 0.85);
  }
  .ant-input-suffix, .ant-form-extra, .anticon-ellipsis {
    display: none;
  }
  .plus-line, .del-line {
    display: none!important;
  }
}
.inv-table {
  .ant-table .ant-table-tbody tr:hover td {
  .ant-table .ant-table-tbody {
    td {
      vertical-align: top;
    }
    tr:hover td {
    background-color: var(--mk-sys-color1);
  }
}
}
.tb-search-wrap {
  .search-item {
    display: flex;
src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx
@@ -27,7 +27,7 @@
    })
  }
  onChange = (value, key) => {
  onChange = (value, key, nextkey) => {
    let line = {...this.props.line}
    if (['bill_count', 'unitprice', 'amount_line'].includes(key)) {
@@ -75,10 +75,32 @@
    })
    this.props.changeLine(line, key)
    if (nextkey) {
      let node = document.getElementById(nextkey)
      if (node) {
        if (node.select) {
          node.select()
        } else if (node.focus) {
          node.focus()
        }
      }
    }
  }
  onSkip = (key) => {
    let node = document.getElementById(key)
    if (node) {
      if (node.select) {
        node.select()
      } else if (node.focus) {
        node.focus()
      }
    }
  }
  render() {
    const { line, delLine, trigger } = this.props
    const { line, delLine, trigger, field, pid } = this.props
    const { bill_count, unitprice, amount_line } = this.state
    
    return <div className="mk-tr active">
@@ -86,22 +108,22 @@
        <div className="mk-input">{line.productname || ''}<EllipsisOutlined onClick={trigger}/></div>
      </div>
      <div className="mk-td">
        <Input defaultValue={line.spec || ''} onChange={(e) => this.onChange(e.target.value, 'spec')}/>
        <Input defaultValue={line.spec || ''} autoFocus={field === 'spec'} onChange={(e) => this.onChange(e.target.value, 'spec')} onPressEnter={() => this.onSkip(pid + 'mk-invoice-unit')}/>
      </div>
      <div className="mk-td">
        <Input defaultValue={line.unit || ''} onChange={(e) => this.onChange(e.target.value, 'unit')}/>
        <Input id={pid + 'mk-invoice-unit'} defaultValue={line.unit || ''} autoFocus={field === 'unit'} onChange={(e) => this.onChange(e.target.value, 'unit')} onPressEnter={() => this.onSkip(pid + 'mk-invoice-billcount')}/>
      </div>
      <div className="mk-td">
        <InputNumber value={bill_count} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({bill_count: val})} onBlur={() => this.onChange(bill_count, 'bill_count')}/>
        <InputNumber id={pid + 'mk-invoice-billcount'} value={bill_count} autoFocus={field === 'bill_count'} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({bill_count: val})} onPressEnter={() => this.onChange(bill_count, 'bill_count', pid + 'mk-invoice-unitprice')} onBlur={() => this.onChange(bill_count, 'bill_count')}/>
      </div>
      <div className="mk-td">
        <InputNumber value={unitprice} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({unitprice: val})} onBlur={() => this.onChange(unitprice, 'unitprice')}/>
        <InputNumber id={pid + 'mk-invoice-unitprice'} value={unitprice} autoFocus={field === 'unitprice'} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({unitprice: val})} onPressEnter={() => this.onChange(unitprice, 'unitprice', pid + 'mk-invoice-amount')} onBlur={() => this.onChange(unitprice, 'unitprice')}/>
      </div>
      <div className="mk-td">
        <InputNumber value={amount_line} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({amount_line: val})} onBlur={() => this.onChange(amount_line, 'amount_line')}/>
        <InputNumber id={pid + 'mk-invoice-amount'} value={amount_line} autoFocus={field === 'amount_line'} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({amount_line: val})} onPressEnter={() => this.onChange(amount_line, 'amount_line')} onBlur={() => this.onChange(amount_line, 'amount_line')}/>
      </div>
      <div className="mk-td mk-right">{line.tax_name}</div>
      <div className="mk-td mk-right">{line.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} <span className="del-line" onClick={() => delLine(line.uuid)}></span> </div>
      <div className="mk-td mk-right">{line.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} <span className="del-line" onClick={(e) => delLine(line.uuid, e)}></span> </div>
    </div>
  }
}
@@ -109,6 +131,8 @@
class InvoiceTable extends Component {
  static propTpyes = {
    config: PropTypes.object,
    timestamp: PropTypes.string,
    read_only: PropTypes.any,
    data: PropTypes.any,
    onChange: PropTypes.func
  }
@@ -116,6 +140,7 @@
  state = {
    data: [],
    editKey: '',
    key: '',
    total: {}
  }
@@ -140,6 +165,21 @@
  componentDidMount () {
    MKEmitter.addListener('resetDetails', this.resetDetails)
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (this.props.timestamp !== nextProps.timestamp) {
      let _data = fromJS(nextProps.data).toJS()
      if (!_data.length) {
        _data = [{uuid: Utils.getguid(), productname: '', spec: '', unit: '', bill_count: '', unitprice: 0, amount_line: 0, tax_rate: '', tax_name: '', tax_amount: 0}]
      }
      this.setState({
        data: _data
      }, () => {
        this.getTotal(_data)
      })
    }
  }
  /**
@@ -268,8 +308,10 @@
    this.setState({data: [...data, line]})
  }
  delLine = () => {
    const { editKey, data } = this.state
  delLine = (uuid, e) => {
    const { data } = this.state
    e.stopPropagation()
    if (data.length === 1) {
      notification.warning({
@@ -280,7 +322,7 @@
      return
    }
    let _data = data.filter(item => item.uuid !== editKey)
    let _data = data.filter(item => item.uuid !== uuid)
    this.setState({data: _data}, () => {
      this.getTotal(_data)
@@ -306,8 +348,18 @@
    this.props.onChange(_data)
  }
  checkLine = (uuid) => {
    this.setState({editKey: uuid})
  checkLine = (uuid, key, e) => {
    const { read_only } = this.props
    e && e.stopPropagation()
    if (read_only) return
    this.setState({editKey: uuid, key: key || ''}, () => {
      if (key === 'productname') {
        this.setState({visible: true})
      }
    })
  }
  changeDetail = (prod) => {
@@ -323,6 +375,8 @@
        item.tax_name = prod.tax_rate * 100 + '%'
        item.free_tax_mark = prod.free_tax_mark || ''
        item.vat_special_management = prod.vat_special_management || ''
        item.tax_item = prod.tax_item || ''
        item.tax_method = prod.tax_method || ''
        if (prod.vat_special_management && prod.free_tax_mark === 'true') {
          item.tax_name = prod.vat_special_management
@@ -356,7 +410,7 @@
  render() {
    const { config, tax_type } = this.props
    const { editKey, data, total, visible } = this.state
    const { editKey, key, data, total, visible } = this.state
    return (
      <div className="detail-wrap">
@@ -373,18 +427,18 @@
        </div>
        {data.map(item => {
          if (editKey === item.uuid) {
            return <DetailLine key={item.uuid} line={item} changeLine={this.changeLine} delLine={this.delLine} trigger={() => this.setState({visible: true})}/>
            return <DetailLine key={item.uuid} pid={config.uuid} line={item} field={key} changeLine={this.changeLine} delLine={this.delLine} trigger={() => this.setState({visible: true})}/>
          }
          return <div className="mk-tr" key={item.uuid} onClick={() => this.checkLine(item.uuid)}>
            <div className="mk-td mk-left">{item.productname || ''}</div>
            <div className="mk-td mk-left">{item.spec || ''}</div>
            <div className="mk-td mk-left">{item.unit || ''}</div>
            <div className="mk-td mk-right">{`${item.bill_count || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right">{`${item.unitprice || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right">{`${item.amount_line || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-left" onClick={(e) => this.checkLine(item.uuid, item.productname ? '' : 'productname', e)}>{item.productname || ''}</div>
            <div className="mk-td mk-left" onClick={(e) => this.checkLine(item.uuid, 'spec', e)}>{item.spec || ''}</div>
            <div className="mk-td mk-left" onClick={(e) => this.checkLine(item.uuid, 'unit', e)}>{item.unit || ''}</div>
            <div className="mk-td mk-right" onClick={(e) => this.checkLine(item.uuid, 'bill_count', e)}>{`${item.bill_count || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right" onClick={(e) => this.checkLine(item.uuid, 'unitprice', e)}>{`${item.unitprice || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right" onClick={(e) => this.checkLine(item.uuid, 'amount_line', e)}>{`${item.amount_line || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
            <div className="mk-td mk-right">{item.tax_name}</div>
            <div className="mk-td mk-right">{item.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}<span className="del-line" onClick={() => this.delLine(item.uuid)}></span></div>
            <div className="mk-td mk-right">{item.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}<span className="del-line" onClick={(e) => this.delLine(item.uuid, e)}></span></div>
          </div>
        })}
        <div className="mk-total">
src/tabviews/custom/components/module/invoice/subTable/index.jsx
@@ -89,7 +89,7 @@
    config.columns.forEach(item => {
      if (item.Hide === 'true') return
      _columns.push({
        align: 'center',
        align: 'left',
        dataIndex: item.field,
        title: item.label,
        sorter: false,
src/tabviews/custom/components/share/normalTable/index.jsx
@@ -35,20 +35,10 @@
      __param.$searchval = record[item.field] || ''
    }
  
    if (item.linkThdMenu.urlFields) {
      let lower = {}
      Object.keys(record).forEach(key => {
        lower[key.toLowerCase()] = record[key]
      if (/^\$/.test(key)) return
      __param[key] = record[key]
      })
      item.linkThdMenu.urlFields.split(',').forEach(field => {
        __param[field] = lower[field.toLowerCase()] || ''
      })
    } else if (item.linkfields && item.linkfields.length > 0) {
      item.linkfields.forEach(field => {
        __param[field] = record[field] || ''
      })
    }
    let tabmenu = item.linkThdMenu
@@ -58,20 +48,18 @@
  } else if (item.linkurl) {
    let src = item.linkurl
    let con = '?'
    if (/@/.test(src)) {
      src = src.replace(/@id@/ig, record.$$uuid)
      src = src.replace(/@appkey@/ig, window.GLOB.appkey)
      src = src.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
      src = src.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
    if (/\?/ig.test(src)) {
      con = '&'
    }
    if (item.linkfields && item.linkfields.length > 0) {
      item.linkfields.forEach(field => {
        if (field.toLowerCase() === 'id') return
        con += `${field}=${record[field] || ''}&`
      Object.keys(record).forEach(key => {
        if (/^\$/.test(key)) return
        let reg = new RegExp('@' + key + '@', 'ig')
        src = src.replace(reg, record[key])
      })
    }
    src = src + `${con}id=${record.$$uuid}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
    window.open(src)
  }
@@ -384,6 +372,17 @@
        } else {
          _href += '?' + _param
        }
      } else if (/@/.test(_href)) {
        _href = _href.replace(/@id@/ig, record.$$uuid || '')
        _href = _href.replace(/@appkey@/ig, window.GLOB.appkey)
        _href = _href.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
        _href = _href.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
        Object.keys(record).forEach(key => {
          if (/^\$/.test(key)) return
          let reg = new RegExp('@' + key + '@', 'ig')
          _href = _href.replace(reg, record[key])
        })
      }
      if (col.blur) {
@@ -507,7 +506,8 @@
    chgSelectData: PropTypes.func,   // 数据切换
    autoMatic: PropTypes.any,
    allSearch: PropTypes.any,
    colsCtrls: PropTypes.any
    colsCtrls: PropTypes.any,
    parCtrl: PropTypes.any
  }
  state = {
@@ -556,10 +556,7 @@
            if (item.rowspan === 'true') {
              rowspans.push(item.field)
            }
            if (item.type === 'index') {
              item.field = '$Index'
              item.type = 'text'
            } else if (_format && !Math.floor(Math.random() * radio)) {
            if (_format && !Math.floor(Math.random() * radio)) {
              item.blur = true
            }
  
@@ -655,7 +652,7 @@
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    const { allSearch } = this.props
    const { allSearch, parCtrl } = this.props
    const { allColumns } = this.state
    if (allSearch && !is(fromJS(allSearch), fromJS(nextProps.allSearch))) {
@@ -664,6 +661,36 @@
        columns: this.getCurColumns(allColumns, nextProps.allSearch)
      }, () => {
        this.setState({reseting: false})
      })
    } else if (parCtrl && !is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
      let getColumns = (cols) => {
        return cols.map(item => {
          let cell = null
          if (item.type === 'colspan') {
            cell = { title: item.label, align: item.Align }
            cell.children = getColumns(item.subcols)
          } else {
            cell = {
              align: item.Align,
              dataIndex: item.uuid,
              title: item.label,
              sorter: (item.field || item.sortField) && item.IsSort === 'true',
              width: item.Width || 120,
              onCell: record => ({
                record,
                col: item,
                config: item.type === 'custom' ? {setting: this.props.setting, columns: this.props.fields} : null,
              })
            }
          }
          return cell
        })
      }
      this.setState({
        columns: getColumns(nextProps.columns)
      })
    }
  }
@@ -1085,7 +1112,7 @@
    if (!setting.doubleClick) return
    if (record.$disabled) return
    MKEmitter.emit('triggerBtnId', setting.doubleClick, [record], 'linkbtn')
    MKEmitter.emit('triggerBtnId', setting.doubleClick, [record], 'linkbtn', (record.$$uuid || '') + (record.$Index || ''))
  }
  render() {
src/tabviews/custom/components/table/base-table/index.jsx
@@ -573,8 +573,8 @@
      } else {
        this.reloadtable(btn, id)
      }
    } else if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    } else if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.reloadtable(btn, id)
    }
src/tabviews/custom/components/table/edit-table/index.jsx
@@ -1,6 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
@@ -74,7 +75,6 @@
      }
    })
    let _columns = []
    let initId = ''
    setting.hasSubmit = false
@@ -82,6 +82,7 @@
      setting.commit = 'change'
    }
    let index = 0
    let getColumns = (cols) => {
      return cols.filter(item => {
        if (item.Hide === 'true') return false
@@ -95,6 +96,8 @@
            return false
          }
        } else if (item.type === 'custom') {
          item.config = {setting: _config.setting, columns: _config.columns}
          item.elements.forEach(btn => {
            if (btn.eleType !== 'button') return
            if (btn.funcType === 'addline') {
@@ -107,15 +110,16 @@
            }
          })
        } else {
          if (item.type === 'index') {
            item.field = '$Index'
            item.type = 'text'
          }
          if (item.editable === 'true') {
            item.$sort = index
            index++
            setting.hasSubmit = setting.commit !== 'change'
            item.$ctrl = setting.commit === 'change'
            
            if (item.ctrlField) {
              item.ctrlValue = item.ctrlValue.split(',')
            }
            if (!initId) {
              initId = item.uuid
            }
@@ -130,8 +134,26 @@
            }
            if (item.type === 'number') {
              if (item.clearField) {
                _config.columns.forEach(cell => {
                  if (cell.field === item.clearField) {
                    item.clearName = cell.label
                  }
                })
              }
            } else if (item.editType === 'date') {
              item.format = 'YYYY-MM-DD'
              if (item.precision === 'hour') {
                item.format = 'YYYY-MM-DD HH'
              } else if (item.precision === 'minute') {
                item.format = 'YYYY-MM-DD HH:mm'
              } else if (item.precision === 'second') {
                item.format = 'YYYY-MM-DD HH:mm:ss'
              }
            } else if (item.editType === 'select') {
              item.map = new Map()
              item.options = item.options || []
              item.options = item.options.filter(cell => {
                cell.value = cell.Value
@@ -139,6 +161,12 @@
        
                return !cell.Hide
              })
              if (item.resourceType !== '1') {
                item.options.forEach(cell => {
                  item.map.set(cell.value, cell.label)
                })
              }
            } else if (item.editType === 'popSelect') {
              if (item.pops) {
                item.pops.forEach(cell => {
@@ -157,7 +185,12 @@
      })
    }
    _columns = getColumns(_config.cols)
    _config.cols = getColumns(_config.cols)
    let _columns = _config.cols
    if (_config.hasExtend) {
      _columns = this.getCols(_config.cols, BData, _config.setting.extendTime)
    }
    setting.initId = initId
@@ -256,6 +289,132 @@
    config.placeholder = placeholder
    config.arr_field = arrfield.join(',')
  }
  getCols = (cols, BData, time) => {
    let _cols = []
    let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
    let excols = (col) => {
      let _s = []
      let _marks = col.marks || []
      let names = []
      let fields = []
      for (let i = 0; i < col.quota; i++) {
        fields.push(col.field + (i === 0 ? '' : i))
        if (col.colUnit === 'day') {
          let hasweek = col.dayFormat.indexOf('week') > -1
          let format = col.dayFormat.replace(/\sweek/, '')
          let day = moment().add(col.shift + i, 'days').format(format)
          if (hasweek) {
            let _w = moment().add(col.shift + i, 'days').weekday()
            day = day + ' ' + weeks[_w]
          }
          names.push(day)
        } else {
          let format = col.hourFormat
          if (format === 'H point') {
            format = 'H点'
          }
          let hour = moment(time).add(col.shift + i, 'hours').format(format)
          if (format === 'h:00') {
            if (hour === '12:00') {
              hour = hour + ' pm'
            } else if (hour === moment(time).add(col.shift + i, 'hours').format('H:00')) {
              hour = hour + ' am'
            } else {
              hour = hour + ' pm'
            }
          }
          names.push(hour)
        }
      }
      if (col.supField) {
        names = []
        let val = ''
        if (BData) {
          let field = col.supField.toLowerCase()
          Object.keys(BData).forEach(key => {
            if (key.toLowerCase() === field) {
              val = BData[key] + ''
            }
          })
        }
        if (val) {
          names = val.split(',')
          if (names.length > fields.length) {
            names.length = fields.length
          } else if (fields.length > names.length) {
            fields.length = names.length
          }
        }
      }
      if (names.length === 0) return _s
      _s = fields.map((f, i) => {
        return {
          type: 'text',
          Align: col.Align,
          Width: col.Width,
          field: f,
          label: names[i],
          uuid: col.uuid + i,
          marks: _marks.filter(mark => mark.field[0] === f || !fields.includes(mark.field[0]))
        }
      })
      return _s
    }
    cols.forEach(col => {
      if (col.type === 'extend') {
        let exs = excols(col)
        _cols.push(...exs)
      } else if (col.type === 'colspan') {
        let subs = []
        col.subcols.forEach(subcol => {
          if (subcol.type === 'extend') {
            let exs = excols(subcol)
            subs.push(...exs)
          } else {
            subs.push(col)
          }
        })
        if (subs.length) {
          _cols.push({...col, subcols: subs})
        }
      } else {
        _cols.push(col)
      }
    })
    return _cols
  }
  resetCols = (BData) => {
    const { config, setting } = this.state
    MKEmitter.emit('transferData' + setting.tableId, [], 'clear')
    let columns = this.getCols(config.cols, BData, config.setting.extendTime)
    this.setState({
      columns: columns,
      data: [],
      selectedData: [],
      total: 0
    })
  }
  /**
@@ -555,10 +714,14 @@
  }
  resetParentParam = (MenuID, id, data) => {
    const { setting } = this.state
    const { setting, config } = this.state
    if (!setting.supModule || setting.supModule !== MenuID) return
    if (id !== this.state.BID || id !== '') {
      if (config.parCtrl) {
        this.resetCols(data)
      }
      this.setState({
        pageIndex: 1,
        BID: id,
@@ -590,8 +753,8 @@
      } else {
        this.reloadtable(btn)
      }
    } else if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    } else if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.reloadtable(btn)
    }
@@ -695,6 +858,7 @@
          submit={config.submit}
          fields={config.columns}
          total={this.state.total}
          parCtrl={config.parCtrl}
          colsCtrls={config.colsCtrls}
          lineMarks={config.lineMarks}
          loading={this.state.loading}
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -562,6 +562,10 @@
      if (config.noValue === 'hide' && !value) {
        value = 0
      }
      if (config.required === 'true' && !value) {
        err = `${config.label}不可为${config.noValue === 'hide' ? '空' : '0'}`
      } else {
        if (typeof(config.max) === 'number' && value > config.max) {
          err = config.label + '最大为' + config.max
@@ -727,7 +731,7 @@
  }
  render() {
    let { col, config, record, style, className, ...resProps } = this.props
    let { col, record, style, className, ...resProps } = this.props
    const { editing } = this.state
    if (!col) return (<td {...resProps} className={className} style={style}/>)
@@ -747,10 +751,10 @@
      if (col.editType === 'select' && col.options.length > 0) {
        content = col.map.get(content) || content
      } else if (col.editType === 'switch') {
        if (content === config.openVal) {
          content = config.openText
        } else if (content === config.closeVal) {
          content = config.closeText
        if (content === col.openVal) {
          content = col.openText
        } else if (content === col.closeVal) {
          content = col.closeText
        }
      } else if (col.editType === 'popSelect') {
        if (col.showField) {
@@ -1010,7 +1014,7 @@
      }
      children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
        <CardCellComponent data={record} cards={col.config} elements={col.elements}/>
      )
    }
@@ -1041,7 +1045,7 @@
  }
  render() {
    let { col, config, record, style, className, ...resProps } = this.props
    let { col, record, style, className, ...resProps } = this.props
    if (!col) return (<td {...resProps} className={className} style={style}/>)
@@ -1092,10 +1096,10 @@
        if (col.editType === 'select' && col.options.length > 0) {
          content = col.map.get(content) || content
        } else if (col.editType === 'switch') {
          if (content === config.openVal) {
            content = config.openText
          } else if (content === config.closeVal) {
            content = config.closeText
          if (content === col.openVal) {
            content = col.openText
          } else if (content === col.closeVal) {
            content = col.closeText
          }
        } else if (col.editType === 'popSelect') {
          if (col.showField) {
@@ -1324,7 +1328,7 @@
      }
      children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
        <CardCellComponent data={record} cards={col.config} elements={col.elements}/>
      )
    }
@@ -1385,7 +1389,6 @@
    let deForms = []
    let _forms = {}
    let hasBid = false
    let index = 0
    let checkForms = []
    let allForms = []
@@ -1398,25 +1401,12 @@
          cell.children = getColumns(item.subcols, sk || item.uuid)
        } else {
          if (item.editable === 'true') {
            item.$sort = index
            index++
            _forms[item.field] = item
            allForms.push({uuid: sk || item.uuid, field: item.field})
            checkForms.push(item.field)
            if (item.ctrlField) {
              item.ctrlValue = item.ctrlValue.split(',')
            }
            if (item.type === 'number' && item.clearField) {
              fields.forEach(cell => {
                if (cell.field === item.clearField) {
                  item.clearName = cell.label
                }
              })
            } else if (item.type === 'text' && item.editType === 'select') {
              item.map = new Map()
            if (item.type === 'text' && item.editType === 'select') {
              if (item.resourceType === '1') {
                let _option = Utils.getSelectQueryOptions(item)
  
@@ -1428,20 +1418,6 @@
                item.arr_field = _option.field
        
                deForms.push(item)
              } else {
                item.options.forEach(cell => {
                  item.map.set(cell.value, cell.label)
                })
              }
            } else if (item.type === 'text' && item.editType === 'date') {
              item.format = 'YYYY-MM-DD'
              if (item.precision === 'hour') {
                item.format = 'YYYY-MM-DD HH'
              } else if (item.precision === 'minute') {
                item.format = 'YYYY-MM-DD HH:mm'
              } else if (item.precision === 'second') {
                item.format = 'YYYY-MM-DD HH:mm:ss'
              }
            }
          }
@@ -1461,8 +1437,7 @@
            $key: item.uuid,
            onCell: record => ({
              record,
              col: item,
              config: item.type === 'custom' ? {setting, columns: fields} : null,
              col: item
            })
          }
        }
@@ -1539,11 +1514,44 @@
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    const { BID } = this.props
    const { BID, parCtrl } = this.props
    const { deForms } = this.state
    if (deForms && nextProps.BID !== BID) {
      this.improveActionForm(deForms, nextProps.BID)
    }
    if (parCtrl && !is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
      let getColumns = (cols, sk) => {
        return cols.map(item => {
          let cell = null
          if (item.type === 'colspan') {
            cell = { title: item.label, align: item.Align, $key: item.uuid }
            cell.children = getColumns(item.subcols, sk || item.uuid)
          } else {
            cell = {
              align: item.Align,
              dataIndex: item.uuid,
              title: item.editable === 'true' ? <span>{item.label}<EditOutlined className="system-color mk-edit-sign"/></span> : item.label,
              sorter: (item.field || item.sortField) && item.IsSort === 'true',
              width: item.Width || 120,
              $key: item.uuid,
              onCell: record => ({
                record,
                col: item
              })
            }
          }
          return cell
        })
      }
      let _columns = getColumns(nextProps.columns)
      this.setState({
        columns: _columns
      })
    }
  }
@@ -1658,7 +1666,9 @@
      } else if (col.type === 'number') {
        let val = record[col.field]
        if (col.noValue === 'hide' && !val) {
        if (col.required === 'true' && !val) {
          err = `${col.label}不可为${col.noValue === 'hide' ? '空' : '0'}`
        } else if (col.noValue === 'hide' && !val) {
          if (col.clearField && checkForms.includes(col.clearField) && !record[col.clearField]) {
            err = `请填写 ${col.label} 或 ${col.clearName}`
          }
@@ -1750,7 +1760,10 @@
  transferData = (data, type) => {
    const { edData, tableId } = this.state
    if (type === 'delete') {
    if (type === 'clear') {
      this.setState({edData: [], midData: []})
      return
    } else if (type === 'delete') {
    } else if (type === 'line') {
      let value = ''
@@ -2272,7 +2285,9 @@
          item[col.field] = val
        } else if (col.type === 'number') {
          let val = item[col.field]
          if (col.noValue === 'hide' && !val) {
          if (col.required === 'true' && !val) {
            err = `${col.label}不可为${col.noValue === 'hide' ? '空' : '0'}`
          } else if (col.noValue === 'hide' && !val) {
            if (col.clearField && checkForms.includes(col.clearField) && !item[col.clearField]) {
              let msg = `请填写 ${col.label} 或 ${col.clearName}`
              if (!line.includes(msg)) {
src/tabviews/custom/components/table/normal-table/index.jsx
@@ -2,6 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Collapse } from 'antd'
import moment from 'moment'
import Api from '@/api'
import UtilsDM from '@/utils/utils-datamanage.js'
@@ -152,6 +153,11 @@
      _config.colsCtrls = null
    }
    let columns = _config.cols
    if (_config.hasExtend) {
      columns = this.getCols(_config.cols, BData, _config.setting.extendTime)
    }
    this.setState({
      pageSize: setting.pageSize || 10,
      BID: BID || '',
@@ -161,7 +167,7 @@
      config: _config,
      setting: setting,
      actions: _config.action,
      columns: _config.cols,
      columns: columns,
      search: _config.$searches,
      allSearch
    })
@@ -377,6 +383,130 @@
    window.GLOB.SyncData.delete(config.dataName)
    MKEmitter.removeListener('transferSyncData', this.transferSyncData)
  }
  getCols = (cols, BData, time) => {
    let _cols = []
    let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
    let excols = (col) => {
      let _s = []
      let _marks = col.marks || []
      let names = []
      let fields = []
      for (let i = 0; i < col.quota; i++) {
        fields.push(col.field + (i === 0 ? '' : i))
        if (col.colUnit === 'day') {
          let hasweek = col.dayFormat.indexOf('week') > -1
          let format = col.dayFormat.replace(/\sweek/, '')
          let day = moment().add(col.shift + i, 'days').format(format)
          if (hasweek) {
            let _w = moment().add(col.shift + i, 'days').weekday()
            day = day + ' ' + weeks[_w]
          }
          names.push(day)
        } else {
          let format = col.hourFormat
          if (format === 'H point') {
            format = 'H点'
          }
          let hour = moment(time).add(col.shift + i, 'hours').format(format)
          if (format === 'h:00') {
            if (hour === '12:00') {
              hour = hour + ' pm'
            } else if (hour === moment(time).add(col.shift + i, 'hours').format('H:00')) {
              hour = hour + ' am'
            } else {
              hour = hour + ' pm'
            }
          }
          names.push(hour)
        }
      }
      if (col.supField) {
        names = []
        let val = ''
        if (BData) {
          let field = col.supField.toLowerCase()
          Object.keys(BData).forEach(key => {
            if (key.toLowerCase() === field) {
              val = BData[key] + ''
            }
          })
        }
        if (val) {
          names = val.split(',')
          if (names.length > fields.length) {
            names.length = fields.length
          } else if (fields.length > names.length) {
            fields.length = names.length
          }
        }
      }
      if (names.length === 0) return _s
      _s = fields.map((f, i) => {
        return {
          type: 'text',
          Align: col.Align,
          Width: col.Width,
          field: f,
          label: names[i],
          uuid: col.uuid + i,
          marks: _marks.filter(mark => mark.field[0] === f || !fields.includes(mark.field[0]))
        }
      })
      return _s
    }
    cols.forEach(col => {
      if (col.type === 'extend') {
        let exs = excols(col)
        _cols.push(...exs)
      } else if (col.type === 'colspan') {
        let subs = []
        col.subcols.forEach(subcol => {
          if (subcol.type === 'extend') {
            let exs = excols(subcol)
            subs.push(...exs)
          } else {
            subs.push(col)
          }
        })
        if (subs.length) {
          _cols.push({...col, subcols: subs})
        }
      } else {
        _cols.push(col)
      }
    })
    return _cols
  }
  resetCols = (BData) => {
    const { config } = this.state
    let columns = this.getCols(config.cols, BData, config.setting.extendTime)
    this.setState({
      columns: columns,
      data: [],
      selectedData: [],
      total: 0
    })
  }
  /**
@@ -780,6 +910,9 @@
      if (!setting.supModule || setting.supModule !== MenuID) return
  
      if (id !== this.state.BID || id !== '') {
        if (config.parCtrl) {
          this.resetCols(data)
        }
        this.setState({
          pageIndex: 1,
          BID: id,
@@ -805,7 +938,7 @@
    if (config.uuid !== menuId) return
    if (config.supNodes) {
      if (position === 'mainline' || position === 'popclose') {
      if (['mainline', 'maingrid', 'popclose'].includes(position)) {
        let supNode = this.supModules[this.supModules.length - 1]
        config.supNodes.forEach((item, i) => {
          setTimeout(() => {
@@ -834,8 +967,8 @@
        } else {
          this.reloadtable(btn, id)
        }
      } else if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
        MKEmitter.emit('reloadData', config.setting.supModule, BID)
      } else if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
        MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
      } else {
        this.reloadtable(btn, id)
      }
@@ -904,6 +1037,7 @@
        data={this.state.data}
        fields={config.columns}
        total={this.state.total}
        parCtrl={config.parCtrl}
        colsCtrls={config.colsCtrls}
        lineMarks={config.lineMarks}
        loading={this.state.loading}
src/tabviews/custom/components/timeline/normal-timeline/index.jsx
@@ -252,8 +252,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData()
    }
src/tabviews/custom/components/tree/antd-tree/index.jsx
@@ -275,8 +275,8 @@
    if (config.uuid !== menuId) return
    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
    } else {
      this.loadData()
    }
src/tabviews/custom/index.jsx
@@ -77,7 +77,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { MenuID, MenuName } = this.props
    const { MenuID, MenuName, param } = this.props
    let _param = {
      func: 'sPC_Get_LongParam',
@@ -205,9 +205,18 @@
      let roleId = sessionStorage.getItem('role_id') || '' // 角色ID
      let balMap = new Map()
      let skip = config.permission === 'false' || window.GLOB.mkHS
      let param = this.props.param || {} // url参数
      let urlparam = {} // url参数
      if (param) {
        Object.keys(param).forEach(key => {
          if (/^\$/.test(key)) {
            urlparam[key] = param[key]
          } else {
            urlparam[key.toLowerCase()] = param[key]
          }
        })
      }
      window.GLOB.CacheData.set(MenuID, param)
      window.GLOB.CacheData.set(MenuID, urlparam)
      let userName = sessionStorage.getItem('User_Name') || ''
      let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -225,7 +234,7 @@
      }
      if (config.urlFields) {
        config.urlFields.forEach(field => {
          let val = `'${param[field] || ''}'`
          let val = `'${urlparam[field.toLowerCase()] || ''}'`
          regs.push({
            reg: new RegExp('@' + field + '@', 'ig'),
            value: val
@@ -252,10 +261,10 @@
      let initInters = []
      config.interfaces = this.formatInterSetting(config.interfaces, regs, MenuID, initInters, config.MenuName)
      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, param, MenuID, config.interfaces, config.$cache, config.$time, config.MenuName, MenuID, MenuID, config.process === 'true')
      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, urlparam, MenuID, config.interfaces, config.$cache, config.$time, config.MenuName, MenuID, MenuID, config.process === 'true')
      let params = []
      let BID = param.$BID || ''
      let BID = urlparam.$BID || ''
      let inherit = {}
      if (config.cacheUseful === 'true') { // 缓存继承
@@ -451,12 +460,7 @@
          if (item.setting.supModule === 'preview') {
            item.setting.supModule = ''
            let val = ''
            Object.keys(urlparam).forEach(key => {
              if (key.toLowerCase() === item.setting.controlField) {
                val = urlparam[key]
              }
            })
            let val = urlparam[item.setting.controlField] || ''
            item.subtabs = item.subtabs.filter(tab => {
              if (tab.$pass) return true
@@ -469,12 +473,7 @@
        if (item.setting.selectField) {
          item.setting.selectField = item.setting.selectField.toLowerCase()
          let val = ''
          Object.keys(urlparam).forEach(key => {
            if (key.toLowerCase() === item.setting.selectField) {
              val = urlparam[key]
            }
          })
          let val = urlparam[item.setting.selectField] || ''
          let activeKey = ''
@@ -633,7 +632,10 @@
              col.type = 'custom'
            }
            
            if (col.type === 'number') {
            if (col.type === 'index') {
              col.field = '$Index'
              col.type = 'text'
            } else if (col.type === 'number') {
              if (typeof(col.decimal) === 'number') {
                col.round = Math.pow(10, col.decimal)
                if (col.format === 'percent') {
@@ -691,6 +693,7 @@
        if (item.hasExtend) {
          item.setting.hasExtend = true
          item.setting.tableMode = 'compatible'
          item.setting.extendTime = moment().format('YYYY-MM-DD HH:mm:ss')
          item.colsCtrls = null
        }
src/tabviews/custom/popview/index.jsx
@@ -2,6 +2,7 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { notification, Spin, Row, Col, Modal } from 'antd'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
@@ -61,7 +62,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { Tab } = this.props
    const { Tab, param } = this.props
    let config = Tab.config || ''
@@ -105,9 +106,18 @@
    // 权限过滤
    let roleId = sessionStorage.getItem('role_id') || '' // 角色ID
    let balMap = new Map()
    let param = this.props.param || {} // url参数
    let urlparam = {} // url参数
    if (param) {
      Object.keys(param).forEach(key => {
        if (/^\$/.test(key)) {
          urlparam[key] = param[key]
        } else {
          urlparam[key.toLowerCase()] = param[key]
        }
      })
    }
    window.GLOB.CacheData.set(Tab.uuid, param)
    window.GLOB.CacheData.set(Tab.uuid, urlparam)
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -129,7 +139,7 @@
      regs.push({ reg: /@works_flow_code@/ig, value: `'${flow.flow_code || ''}'` })
    }
    config.components = this.filterComponent(config.components, roleId, balMap, param, Tab, Tab.uuid, Tab.uuid)
    config.components = this.filterComponent(config.components, roleId, balMap, urlparam, Tab, Tab.uuid, Tab.uuid)
    
    // 获取主搜索条件
    config.components.forEach(component => {
@@ -143,7 +153,7 @@
    })
    let params = []
    let BID = param.$BID || ''
    let BID = urlparam.$BID || ''
    config.components = this.formatSetting(config.components, params, regs, balMap)
@@ -226,12 +236,7 @@
          if (item.setting.supModule === 'preview') {
            item.setting.supModule = ''
            let val = ''
            Object.keys(urlparam).forEach(key => {
              if (key.toLowerCase() === item.setting.controlField) {
                val = urlparam[key]
              }
            })
            let val = urlparam[item.setting.controlField] || ''
            item.subtabs = item.subtabs.filter(tab => {
              if (tab.$pass) return true
@@ -244,12 +249,7 @@
        if (item.setting.selectField) {
          item.setting.selectField = item.setting.selectField.toLowerCase()
          let val = ''
          Object.keys(urlparam).forEach(key => {
            if (key.toLowerCase() === item.setting.selectField) {
              val = urlparam[key]
            }
          })
          let val = urlparam[item.setting.selectField] || ''
          let activeKey = ''
@@ -361,7 +361,10 @@
              col.type = 'custom'
            }
            
            if (col.type === 'number') {
            if (col.type === 'index') {
              col.field = '$Index'
              col.type = 'text'
            } else if (col.type === 'number') {
              if (typeof(col.decimal) === 'number') {
                col.round = Math.pow(10, col.decimal)
                if (col.format === 'percent') {
@@ -412,6 +415,13 @@
        
        item.cols = getCols(item.cols)
        if (item.hasExtend) {
          item.setting.hasExtend = true
          item.setting.tableMode = 'compatible'
          item.setting.extendTime = moment().format('YYYY-MM-DD HH:mm:ss')
          item.colsCtrls = null
        }
        if (item.subtype === 'editable') {
          item.submit.logLabel = item.$menuname + '-提交'
          item.submit.$menuId = item.uuid
src/tabviews/zshare/actionList/changeuserbutton/index.jsx
@@ -102,12 +102,13 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { setting, selectedData, btn, MenuID } = this.props
  actionTrigger = (triggerId, record, type, lid) => {
    const { setting, selectedData, btn, MenuID, LID } = this.props
    const { loading, disabled } = this.state
    
    if (loading || disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    if (btn.funcType === 'closetab') {
      MKEmitter.emit('closeTabView', MenuID || btn.$MenuID)
@@ -115,8 +116,6 @@
      if (btn.refreshTab && btn.refreshTab.length > 0) {
        MKEmitter.emit('reloadMenuView', btn.refreshTab[btn.refreshTab.length - 1], 'table')
      }
      return
    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
      return
    }
    
@@ -239,7 +238,7 @@
        loading={loading}
        disabled={disabled}
        style={btn.style}
        className={btn.$toolbtn ? (btn.hover || '') : ''}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
src/tabviews/zshare/actionList/editLine/index.jsx
@@ -124,7 +124,7 @@
        title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
        disabled={disabled}
        style={btn.style}
        className={btn.$toolbtn ? (btn.hover || '') : ''}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
src/tabviews/zshare/actionList/excelInbutton/index.jsx
@@ -106,12 +106,15 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { setting, BID, btn, selectedData } = this.props
  actionTrigger = (triggerId, record, type, lid) => {
    const { setting, BID, btn, selectedData, LID } = this.props
    const { loading, disabled } = this.state
    if (loading || disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    let data = record || selectedData || []
    if (setting.supModule && !BID) {
      notification.warning({
@@ -119,30 +122,20 @@
        message: '需要上级主键值!',
        duration: 5
      })
      return
    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
      return
    }
    let data = record || selectedData || []
    if (btn.Ot === 'requiredSgl' && data.length !== 1) {
    } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
      // 需要选择单行时,校验数据
      notification.warning({
        top: 92,
        message: '请选择单行数据!',
        duration: 5
      })
      return
    } else if (!btn.verify || !btn.verify.sheet || !btn.verify.columns || btn.verify.columns.length === 0) {
      notification.warning({
        top: 92,
        message: 'excel导入验证信息未设置!',
        duration: 5
      })
      return
    }
    } else {
    let primaryId = '' // 导入时行Id
    if (btn.Ot === 'requiredSgl' && setting.primaryKey) {
      primaryId = data[0][setting.primaryKey] || ''
@@ -157,6 +150,7 @@
    if (window.GLOB.systemType === 'production') {
      MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '导入Excel'})
      }
    }
  }
@@ -554,7 +548,7 @@
        loading={loading}
        disabled={disabled}
        style={btn.style}
        className={btn.$toolbtn ? (btn.hover || '') : ''}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
      <ExcelIn btn={btn} triggerExcelIn={() => this.setState({ loading: true })} returndata={this.getexceldata} ref="excelIn" />
src/tabviews/zshare/actionList/exceloutbutton/index.jsx
@@ -90,12 +90,13 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { setting, BID, btn } = this.props
  actionTrigger = (triggerId, _, type, lid) => {
    const { setting, BID, btn, LID } = this.props
    const { loading, disabled } = this.state
    if (loading || disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    if (setting.supModule && !BID) {
      notification.warning({
@@ -103,30 +104,23 @@
        message: '需要上级主键值!',
        duration: 5
      })
      return
    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(this.props.selectedData || []), fromJS(record))) {
      return
    }
    if (btn.errorType === 'error1') {
    } else if (btn.errorType === 'error1') {
      notification.warning({
        top: 92,
        message: '请设置导出列!',
        duration: 5
      })
      return
    } else if (btn.errorType === 'error2') {
      notification.warning({
        top: 92,
        message: '按钮需自定义导出数据源!',
        duration: 5
      })
      return
    }
    } else {
    MKEmitter.emit('queryModuleParam', btn.$menuId, this.triggerExcelout)
    if (window.GLOB.systemType === 'production') {
      MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '导出Excel'})
      }
    }
  }
@@ -1097,7 +1091,7 @@
        loading={loading}
        disabled={disabled}
        style={btn.style || null}
        className={btn.$toolbtn ? (btn.hover || '') : ''}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
src/tabviews/zshare/actionList/exportPdf/index.jsx
@@ -130,7 +130,7 @@
        type="link"
        title={btn.show === 'icon' ? btn.label : ''}
        style={style}
        className={btn.$toolbtn ? (btn.hover || '') : ''}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
src/tabviews/zshare/actionList/funcMegvii/index.jsx
@@ -108,12 +108,16 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { BID, btn, selectedData, setting } = this.props
  actionTrigger = (triggerId, record, type, lid) => {
    const { BID, btn, selectedData, setting, LID } = this.props
    const { loading, disabled } = this.state
    if (loading || disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    let data = record || selectedData || []
    // let data = fromJS(mockdata.data).toJS()
    if (setting.supModule && !BID) {
      notification.warning({
@@ -121,29 +125,20 @@
        message: '需要上级主键值!',
        duration: 5
      })
      return
    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
      return
    }
    let data = record || selectedData || []
    // let data = fromJS(mockdata.data).toJS()
    if (data.length === 0) {
    } else if (data.length === 0) {
      // 需要选择行时,校验数据
      notification.warning({
        top: 92,
        message: '请选择行!',
        duration: 5
      })
      return
    }
    } else {
    this.setState({
      loading: true,
      lines: data
    })
    this.getIpList()
    }
  }
  getIpList = () => {
@@ -533,7 +528,7 @@
          loading={loading}
          disabled={disabled}
          style={btn.style}
          className={btn.$toolbtn ? (btn.hover || '') : ''}
          className={btn.hover || ''}
          onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
        >{label}</Button>
        {this.getModels()}
src/tabviews/zshare/actionList/funcbutton/index.jsx
New file
@@ -0,0 +1,344 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Button, notification, message, Modal } from 'antd'
import md5 from 'md5'
import Api from '@/api'
import MKEmitter from '@/utils/events.js'
import MkIcon from '@/components/mk-icon'
// import './index.scss'
const { confirm } = Modal
class FuncButton extends Component {
  static propTpyes = {
    BID: PropTypes.string,
    btn: PropTypes.object,
    selectedData: PropTypes.any,
    disabled: PropTypes.any
  }
  state = {
    loading: false,
    disabled: false,
    hidden: false,
  }
  UNSAFE_componentWillMount () {
    const { btn, selectedData, BData, disabled } = this.props
    if (btn.controlField) {
      this.setStatus(btn, selectedData || [], BData, disabled)
    } else if (disabled) {
      this.setState({disabled: true})
    }
  }
  componentDidMount () {
    MKEmitter.addListener('triggerBtnId', this.actionTrigger)
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    const { btn } = this.props
    if (btn.controlField) {
      this.setStatus(btn, nextProps.selectedData || [], nextProps.BData, nextProps.disabled)
    } else {
      this.setState({disabled: nextProps.disabled === true})
    }
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('triggerBtnId', this.actionTrigger)
  }
  setStatus = (btn, data, BData, disprop) => {
    let disabled = false
    let hidden = false
    if (btn.control !== 'parent') {
      if (data.length > 0) {
        data.forEach(item => {
          let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
          if (btn.controlVals.includes(s)) {
            disabled = true
          }
        })
      } else if (btn.controlVals.includes('')) {
        disabled = true
      }
    } else {
      if (!BData || !BData.hasOwnProperty(btn.controlField)) {
        hidden = true
      } else {
        let s = BData[btn.controlField] + ''
        if (btn.controlVals.includes(s)) {
          hidden = true
        }
      }
    }
    if (disabled && btn.control === 'hidden') {
      hidden = true
    }
    if (disprop) {
      disabled = true
    }
    this.setState({hidden, disabled})
  }
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type, lid) => {
    const { btn, BID, selectedData, LID } = this.props
    const { loading } = this.state
    if (loading) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    let data = record || selectedData || []
    let error = ''
    if (btn.funcType === 'shareLink' && window.GLOB.systemType === 'production' && !btn.shareProUrl) {
      error = '尚未设置正式系统链接地址!'
    } else if (btn.funcType === 'refund') {
      if (data.length === 0) {
        error = '请选择行!'
      } else if (data.length !== 1) {
        error = '请选择单行数据!'
      } else if (!data[0].$$uuid) {
        error = '未获取到订单编号!'
      }
    }
    if (error) {
      notification.warning({
        top: 92,
        message: error,
        duration: 5
      })
      return
    }
    if (btn.funcType === 'shareLink') {
      let bid = BID || ''
      let id = ''
      if (data[0]) {
        id = data[0].$$uuid || ''
      }
      let url = btn.shareUrl
      if (window.GLOB.systemType === 'production') {
        url = btn.shareProUrl
      }
      url = url.replace(/@BID@/ig, bid).replace(/@ID@/ig, id)
      if (btn.shortUrl === 'true') {
        this.setState({
          loading: true
        }, () => {
          this.getShortUrl(url)
        })
      } else {
        this.copyUrl(url)
      }
    } else if (btn.funcType === 'refund') {
      let orderId = data[0].$$uuid
      const that = this
      confirm({
        title: btn.tipTitle || '确定要执行吗?',
        onOk() {
          that.execRefund(orderId)
        },
        onCancel() {}
      })
    }
  }
  execRefund = (orderId) => {
    Api.setRefund(orderId).then(res => {
      if (!res.status) {
        this.execError({ErrCode: 'E', message: '执行失败!', ...res})
      } else {
        this.execSuccess({ErrCode: 'S', ...res})
      }
    })
  }
  getShortUrl = (url) => {
    let _rduri = window.atob('aHR0cHM6Ly9lcGMubWs5aC5$mkjbi93ZWJhcGkvZG9zdGFycw=='.replace(/\$mk/ig, ''))
    let _id = window.atob('YmgwYmFwYWJ0ZDQ1ZXBz$mkZ3JhNzlzZWdiY2g2YzFpYms='.replace(/\$mk/ig, ''))
    let param = {
      func: 's_url_db_adduptdel',
      appkey: window.GLOB.appkey,
      userid: _id,
      LoginUID: _id,
      type: 'add_only',
      validity: 15,
      linkurl: url,
      nonc: '' + new Date().getTime(),
      id: md5(url + window.GLOB.appkey)
    }
    let keys = Object.keys(param).sort()
    let values = ''
    keys.forEach(key => {
      values += key + param[key]
    })
    param.sign = md5(values)
    param.t = new Date().getTime()
    Api.directRequest({
      url: _rduri + '/s_url_db_adduptdel',
      method: 'post',
      data: JSON.stringify(param)
    }).then(res => {
      this.setState({
        loading: false
      })
      if (res.status && res.id) {
        this.copyUrl('https://mk9h.cn/m.asp?m=' + res.id)
      } else {
        notification.warning({
          top: 92,
          message: res.message || '链接生成失败!',
          duration: 5
        })
      }
    }, () => {
      this.setState({
        loading: false
      })
    })
  }
  copyUrl = (url) => {
    const { btn } = this.props
    let oInput = document.createElement('input')
    oInput.value = url
    document.body.appendChild(oInput)
    oInput.select()
    document.execCommand('Copy')
    document.body.removeChild(oInput)
    if (btn.shareTip) {
      Modal.success({
        title: btn.shareTip
      })
    } else {
      message.success('已复制到剪切板。')
    }
  }
  execSuccess = (res = {}) => {
    const { btn } = this.props
    if (res.ErrCode === 'S' || !res.ErrCode) { // 执行成功
      notification.success({
        top: 92,
        message: res.message || '执行成功!',
        duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
      })
    } else if (res.ErrCode === 'Y') { // 执行成功
      Modal.success({
        title: res.message || '执行成功!'
      })
    } else if (res.ErrCode === '-1') { // 完成后不提示
    }
    this.setState({
      loading: false
    })
    if (btn.execSuccess !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn)
    }
  }
  execError = (res) => {
    const { btn } = this.props
    if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
      res.ErrCode = 'E'
    }
    if (res.ErrCode === 'E') {
      Modal.error({
        title: res.message || '执行失败!',
      })
    } else if (res.ErrCode === 'N') {
      notification.error({
        top: 92,
        message: res.message || '执行失败!',
        duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
      })
    } else if (res.ErrCode === 'F') {
      notification.error({
        className: 'notification-custom-error',
        top: 92,
        message: res.message || '执行失败!',
        duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
      })
    } else if (res.ErrCode === 'NM') {
      message.error(res.message || '执行失败!')
    }
    this.setState({
      loading: false
    })
    if (res.ErrCode === '-2') return
    if (btn.execError !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn)
    }
  }
  render() {
    const { btn } = this.props
    const { loading, hidden } = this.state
    if (hidden) return null
    let label = ''
    if (btn.show === 'link') {
      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
    } else if (btn.show === 'icon') {
      label = !loading ? <MkIcon type={btn.icon} /> : null
    } else {
      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
    }
    return (
      <Button
        type="link"
        title={btn.show === 'icon' ? btn.label : ''}
        loading={loading}
        style={btn.style || null}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
  }
}
export default FuncButton
src/tabviews/zshare/actionList/funcbutton/index.scss
src/tabviews/zshare/actionList/funczip/index.jsx
@@ -99,12 +99,15 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { BID, btn, selectedData, setting } = this.props
  actionTrigger = (triggerId, record, type, lid) => {
    const { BID, btn, selectedData, setting, LID } = this.props
    const { loading, disabled } = this.state
    if (loading || disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    let data = record || selectedData || []
    if (setting.supModule && !BID) {
      notification.warning({
@@ -113,13 +116,7 @@
        duration: 5
      })
      return
    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
      return
    }
    let data = record || selectedData || []
    if (btn.Ot !== 'notRequired' && data.length === 0) {
    } else if (btn.Ot !== 'notRequired' && data.length === 0) {
      notification.warning({
        top: 92,
        message: '请选择行!',
@@ -425,7 +422,7 @@
        loading={loading}
        disabled={disabled}
        style={btn.style}
        className={btn.$toolbtn ? (btn.hover || '') : ''}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
src/tabviews/zshare/actionList/index.jsx
@@ -19,7 +19,7 @@
const FuncZip = asyncComponent(() => import('./funczip'))
const EditLine = asyncComponent(() => import('./editLine'))
const ExportPdf = asyncComponent(() => import('./exportPdf'))
const ShareLink = asyncComponent(() => import('./shareLink'))
const FuncButton = asyncComponent(() => import('./funcbutton'))
class ActionList extends Component {
  static propTpyes = {
@@ -197,15 +197,6 @@
              btn={item}
            />
          )
        } else if (item.funcType === 'shareLink') {
          return (
            <ShareLink
              key={item.uuid}
              BID={BID}
              btn={item}
              selectedData={selectedData}
            />
          )
        } else if (item.funcType === 'addline' || item.funcType === 'delline') {
          return (
            <EditLine
@@ -216,6 +207,15 @@
            />
          )
        }
        } else {
          return (
            <FuncButton
              key={item.uuid}
              BID={BID}
              btn={item}
              selectedData={selectedData}
            />
          )
      }
      return null
    })
src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -100,16 +100,13 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { btn, selectedData, BID } = this.props
  actionTrigger = (triggerId, record, type, lid) => {
    const { btn, selectedData, BID, LID } = this.props
    const { disabled } = this.state
    if (disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
      return
    }
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    let data = record || selectedData || []
@@ -270,10 +267,7 @@
      
      if (/#\/iframe\//.test(url)) {
        url = url.replace(/@loginuid@/ig, sessionStorage.getItem('LoginUID'))
        if (btn.joint === 'true' && Id) {
          url = url + '/' + Id
        }
        let menu = {
          MenuID: btn.uuid,
@@ -287,16 +281,26 @@
        return
      }
      
      if (btn.joint === 'true') {
      let con = '?'
      if (/\?/ig.test(url)) {
        con = '&'
      }
      if (btn.joint === 'true') {
        url = url + `${con}id=${Id}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
      } else if (Id) {
        url = url + `${con}id=${Id}`
      } else if (/@/.test(url)) {
        url = url.replace(/@id@/ig, Id)
        url = url.replace(/@appkey@/ig, window.GLOB.appkey)
        url = url.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
        url = url.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
        if (btn.Ot === 'requiredSgl' && data[0]) {
          Object.keys(data[0]).forEach(key => {
            if (/^\$/.test(key)) return
            let reg = new RegExp('@' + key + '@', 'ig')
            url = url.replace(reg, data[0][key])
          })
        }
      }
      window.open(url)
@@ -330,7 +334,7 @@
        title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
        style={btn.style || null}
        disabled={disabled}
        className={btn.$toolbtn ? (btn.hover || '') : ''}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -204,8 +204,8 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type, callback) => {
    const { btn, selectedData } = this.props
  actionTrigger = (triggerId, record, type, lid, callback) => {
    const { btn, selectedData, LID } = this.props
    const { loading, disabled } = this.state
    if (type === 'preButton') {
@@ -219,7 +219,7 @@
    if (loading || disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) return
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    if (btn.OpenType === 'form' && btn.formType === 'count_line') return
    this.setState({autoMatic: type === 'autoMatic'})
@@ -1093,7 +1093,7 @@
    let node = document.getElementById('button' + btnId)
    if (node) {
      MKEmitter.emit('triggerBtnId', btnId, null, 'preButton', (res) => {
      MKEmitter.emit('triggerBtnId', btnId, null, 'preButton', null, (res) => {
        if (!res) {
          this.setState({loading: false})
          resolve()
@@ -1638,11 +1638,12 @@
      })
      keys = keys.join(',')
      vals = vals.join(',')
      lines.push({
        table: md5(tb + keys),
        insert: `Insert into ${tbName} (${keys},[mk_level],[mk_id],[mk_bid])`,
        select: `Select ${vals.join(',')},'${level}','${id}','${bid}'`
        insert: `Insert into ${tbName} (${keys ? keys + ',' : ''}[mk_level],[mk_id],[mk_bid])`,
        select: `Select ${keys ? vals + ',' : ''}'${level}','${id}','${bid}'`
      })
      subObjs.forEach(item => {
@@ -2434,6 +2435,24 @@
    if (btn.execSuccess === 'popclose' && btn.$tabId) { // 标签关闭刷新
      MKEmitter.emit('refreshPopButton', btn.$tabId)
    }
    if (btn.verify && btn.verify.linkEnable === 'true') {
      let url = ''
      if (window.GLOB.systemType === 'production') {
        url = btn.verify.linkProUrl
        if (!url) {
          notification.warning({
            top: 92,
            message: '尚未添加正式系统链接地址!',
            duration: 5
          })
          return
        }
      } else {
        url = btn.verify.linkUrl
      }
      window.open(url)
    }
  }
@@ -3567,7 +3586,7 @@
      loading={loading}
      disabled={disabled}
      style={btn.style}
      className={btn.$toolbtn ? (btn.hover || '') : ''}
      className={btn.hover || ''}
      onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
    >{label}</Button>
src/tabviews/zshare/actionList/popupbutton/index.jsx
@@ -141,12 +141,15 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { setting, BID, btn, selectedData } = this.props
  actionTrigger = (triggerId, record, type, lid) => {
    const { setting, BID, btn, selectedData, LID } = this.props
    const { loading, disabled } = this.state
    if (loading || disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    let data = record || selectedData || []
    if (setting.supModule && !BID) {
      notification.warning({
@@ -155,13 +158,7 @@
        duration: 5
      })
      return
    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
      return
    }
    let data = record || selectedData || []
    if (btn.Ot === 'requiredSgl' && data.length !== 1) {
    } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
      // 需要选择单行时,校验数据
      notification.warning({
        top: 92,
@@ -328,7 +325,7 @@
          loading={loading && !name}
          disabled={disabled}
          style={btn.style}
          className={btn.$toolbtn ? (btn.hover || '') : ''}
          className={btn.hover || ''}
          onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
        >{label}</Button>
        <span onClick={(e) => {e.stopPropagation()}} onDoubleClick={(e) => {e.stopPropagation()}}>{this.getPop()}</span>
src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -130,12 +130,13 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { BID, btn, selectedData, setting } = this.props
  actionTrigger = (triggerId, record, type, lid) => {
    const { BID, btn, selectedData, setting, LID } = this.props
    const { loading, disabled } = this.state
    if (loading || disabled) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    if (setting.supModule && !BID) {
      notification.warning({
@@ -143,8 +144,6 @@
        message: '需要上级主键值!',
        duration: 5
      })
      return
    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
      return
    }
@@ -2385,7 +2384,7 @@
        loading={loading}
        disabled={disabled}
        style={btn.style || null}
        className={btn.$toolbtn ? (btn.hover || '') : ''}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
      <span onClick={(e) => {e.stopPropagation()}}>{this.getModels()}</span>
src/tabviews/zshare/actionList/shareLink/index.jsx
File was deleted
src/tabviews/zshare/actionList/tabbutton/index.jsx
@@ -100,16 +100,13 @@
  /**
   * @description 触发按钮操作
   */
  actionTrigger = (triggerId, record, type) => {
    const { btn, selectedData, BID } = this.props
  actionTrigger = (triggerId, record, type, lid) => {
    const { btn, selectedData, BID, LID } = this.props
    const { disabled } = this.state
    if (disabled || btn.multiMenus) return
    if (triggerId && btn.uuid !== triggerId) return
    if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
      return
    }
    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
    
    let data = record || selectedData || []
@@ -152,7 +149,7 @@
          return uuid
        })()
        primaryId = primaryId + (btn.sign || '')
      } else {
      } else if (btn.sysId !== 'empty') {
        primaryId = BID || ''
      }
    }
@@ -194,6 +191,14 @@
          duration: 5
        })
        return
      }
      if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
        Object.keys(data[0]).forEach(key => {
          if (/^\$/.test(key)) return
          if (key === 'children') return
          menu.param[key] = data[0][key]
        })
      }
      newtab = menu
@@ -256,7 +261,7 @@
          return uuid
        })()
        primaryId = primaryId + (tab.sign || '')
      } else {
      } else if (btn.sysId !== 'empty') {
        primaryId = BID || ''
      }
    }
@@ -325,7 +330,7 @@
          type="link"
          title={btn.show === 'icon' ? btn.label : ''}
          style={btn.style || null}
          className={btn.$toolbtn ? (btn.hover || '') : ''}
          className={btn.hover || ''}
        >{label}</Button>
      </Dropdown>)
    }
@@ -337,7 +342,7 @@
        title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
        style={btn.style || null}
        disabled={disabled}
        className={btn.$toolbtn ? (btn.hover || '') : ''}
        className={btn.hover || ''}
        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
      >{label}</Button>
    )
src/tabviews/zshare/mutilform/index.jsx
@@ -404,11 +404,13 @@
          message: item.label + '不可为空!'
        }]
        if (typeof(item.min) === 'number' || typeof(item.max) === 'number') {
        if (typeof(item.min) === 'number' || typeof(item.max) === 'number' || item.notZero === 'true') {
          item.rules.push({
            validator: (rule, value, callback) => {
              if (isNaN(value)) {
                callback()
              } else if (item.notZero === 'true' && value === 0) {
                callback(item.label + '不可为0')
              } else if (typeof(item.min) === 'number' && value < item.min) {
                if (item.min < 1e-6) {
                  if (item.min === 1e-6) {
@@ -628,7 +630,11 @@
        item.supInitVal = ''
        if (fieldMap.has(item.linkField)) {
          item.supInitVal = fieldMap.get(item.linkField).initval || ''
          let supitem = fieldMap.get(item.linkField)
          item.supInitVal = supitem.initval || ''
          if (supitem.$first) {
            item.$resetSup = true
          }
        } else if (data.hasOwnProperty(item.linkField.toLowerCase())) {
          item.supInitVal = data[item.linkField.toLowerCase()]
        }
@@ -1098,7 +1104,11 @@
        // if (item.type === 'link') {
        if (item.linkField) {
          item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.value === '')
          let supInitVal = item.supInitVal
          if (item.$resetSup) {
            supInitVal = this.record[item.linkField]
          }
          item.options = item.oriOptions.filter(option => option.ParentID === supInitVal || option.value === '')
        // } else if (['select', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type)) {
        } else {
          item.options = item.oriOptions
@@ -1240,11 +1250,17 @@
      if (item.hidden) return
      if (item.type === 'split') {
        if (item.opacity === 'false') {
          fields.push(
            <div key={index}></div>
          )
        } else {
        fields.push(
          <Col span={24} key={index}>
            <p className="mk-form-split-line" style={item.style}>{item.label}</p>
          </Col>
        )
        }
      } else if (item.type === 'hint') {
        fields.push(
          <Col span={item.span || 24} key={index}>
src/tabviews/zshare/normalTable/index.jsx
@@ -343,6 +343,7 @@
  triggerLink = (e, item, record) => {
    e.stopPropagation()
    if (item.linkThdMenu) {
    let __param = {
      $BID: record.$$uuid
    }
@@ -352,13 +353,11 @@
      __param.$searchval = record[item.field] || ''
    }
    if (item.linkfields && item.linkfields.length > 0) {
      item.linkfields.forEach(field => {
        __param[field] = record[field] || ''
      Object.keys(record).forEach(key => {
        if (/^\$/.test(key)) return
        __param[key] = record[key]
      })
    }
    if (item.linkThdMenu) {
      let tabmenu = item.linkThdMenu
      tabmenu.param = __param
@@ -741,6 +740,7 @@
        </div>
      )
    } else if (item.type === 'action') {
      let lid = (record.$$uuid || '') + (record.$Index || '')
      return (
        <div className="action-col">
          {item.operations.map(btn => {
@@ -750,6 +750,7 @@
                  key={btn.uuid}
                  btn={btn}
                  BID={record.$$BID}
                  LID={lid}
                  disabled={record.$disabled}
                  selectedData={[record]}
                  BData={this.props.BData}
@@ -763,6 +764,7 @@
                  key={btn.uuid}
                  btn={btn}
                  BID={record.$$BID}
                  LID={lid}
                  disabled={record.$disabled}
                  selectedData={[record]}
                  BData={this.props.BData}
@@ -777,6 +779,7 @@
                  disabled={record.$disabled}
                  selectedData={[record]}
                  BID={record.$$BID}
                  LID={lid}
                  BData={this.props.BData}
                  MenuID={this.props.MenuID}
                />
@@ -787,6 +790,7 @@
                  key={btn.uuid}
                  btn={btn}
                  BID={record.$$BID}
                  LID={lid}
                  disabled={record.$disabled}
                  selectedData={[record]}
                  BData={this.props.BData}
@@ -1212,7 +1216,7 @@
    if (!setting.doubleClick) return
    if (record.$disabled) return
    MKEmitter.emit('triggerBtnId', setting.doubleClick, [record], 'linkbtn')
    MKEmitter.emit('triggerBtnId', setting.doubleClick, [record], 'linkbtn', (record.$$uuid || '') + (record.$Index || ''))
  }
  render() {
src/tabviews/zshare/topSearch/index.jsx
@@ -188,20 +188,21 @@
        // 数据源查询语句
        if (item.resourceType === '1' && item.dataSource) {
          let _option = Utils.getSelectQueryOptions(item)
          let _declare = `Declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)  select @mk_departmentcode='${sessionStorage.getItem('departmentcode') || ''}',@mk_organization='${sessionStorage.getItem('organization') || ''}',@mk_user_type='${sessionStorage.getItem('mk_user_type') || ''}'\n`
          let exec = true
          if (item.checkBid) {
            item.sql = _option.sql
            item.sql = _declare + _option.sql
            item.arr_field = _option.field
            exec = !!BID
          }
          if (exec) {
            _option.sql = _option.sql.replace(/@BID@/ig, `'${BID || ''}'`)
            let _sql = _option.sql.replace(/@BID@/ig, `'${BID || ''}'`)
  
            if (window.GLOB.debugger === true) {
              console.info(_option.sql)
              console.info(_declare + _sql)
            }
  
            // 测试系统单个请求
@@ -209,13 +210,20 @@
              deForms.push({
                ...item,
                arr_field: _option.field,
                data_sql: Utils.formatOptions(_option.sql, window.GLOB.execType)
                data_sql: Utils.formatOptions(_declare + _sql, window.GLOB.execType)
              })
            } else { // 合并请求,区分本地及系统
              _sql = _sql.replace(/%/ig, ' mpercent ')
              if (item.database === 'sso') {
                mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
                if (mainItems.length === 0) {
                  _sql = _declare + _sql
                }
                mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_sql))}' as LText`)
              } else {
                localItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
                if (localItems.length === 0) {
                  _sql = _declare + _sql
                }
                localItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_sql))}' as LText`)
              }
            }
          }
src/templates/comtableconfig/updatetable/index.jsx
@@ -1080,14 +1080,10 @@
        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
          _btn.syncComponent.push(oldtabs[newCon.equalTab])
        }
      } else if (_btn.execSuccess === 'maingrid') {
        _btn.execSuccess = 'mainline'
      }
      if (_btn.execError === 'equaltab') {
        _btn.execError = 'grid'
      } else if (_btn.execError === 'maingrid') {
        _btn.execError = 'mainline'
      }
      if (_btn.popClose === 'equaltab') {
@@ -1097,8 +1093,6 @@
        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
          _btn.syncComponent.push(oldtabs[newCon.equalTab])
        }
      } else if (_btn.popClose === 'maingrid') {
        _btn.popClose = 'mainline'
      }
      if (_btn.OpenType === 'pop' || (_btn.OpenType === 'funcbutton' && _btn.funcType === 'print' && _btn.execMode === 'pop')) {
src/templates/modalconfig/checkCard/index.jsx
@@ -15,7 +15,7 @@
  }
  getCards = () => {
    const { display, width, options, fields, ratio, picratio, backgroundColor } = this.props.config
    const { display, width, options, fields, ratio, picratio, backgroundColor, field, labelShow } = this.props.config
    let _options = []
    let _fields = fields || []
@@ -86,7 +86,7 @@
        return <Col span={width}>
          <div className="card-cell no-margin-bottom" style={style}>
            <div className="bg-mask" style={_style}></div>
            <span style={{color: '#000000', fontSize: '14px', height: '21px'}}>示例</span>
            <span style={{color: '#000000', fontSize: '14px', height: '21px'}}>示例 {labelShow === 'false' ? field : ''}</span>
          </div>
        </Col>
      }
src/templates/modalconfig/dragelement/card.jsx
@@ -138,7 +138,7 @@
  } else if (card.type === 'formula') {
    formItem = <div style={{marginTop: '8px', color: 'rgba(0, 0, 0, 0.85)', lineHeight: '1.5', ...card.style}}>{card.formula}{card.postfix || ''}</div>
  } else if (card.type === 'split') {
    formItem = <div className="split-line" style={card.style}>{card.label}</div>
    formItem = <div className="split-line" style={card.style}>{card.label}{showField && card.supField ? <span style={{color: '#8E44AD'}}>{`(上级${card.supField})`}</span> : null}</div>
  } else if (card.type === 'vercode') {
    formItem = <Input style={{marginTop: '4px'}} placeholder={card.placeholder || ''} value={card.initval} addonAfter={
      <Button type="link" style={{padding: 0}} size="small">
src/templates/modalconfig/index.scss
@@ -172,12 +172,6 @@
        padding: 10px;
        cursor: pointer;
      }
      .paste-Icon {
        position: absolute;
        font-size: 16px;
        right: 15px;
        top: 65px;
      }
    }
  }
  .setting {
src/templates/sharecomponent/actioncomponent/formconfig.jsx
@@ -64,13 +64,11 @@
    }
    refresh.push({
      value: 'maingrid',
      text: '刷新主表(行)'
      text: '刷新主表'
    }, {
      value: 'equaltab',
      text: '刷新同级标签'
    })
  } else if (card.execSuccess === 'maingrid') {
    card.execSuccess = 'grid'
  }
  if (card.OpenType === 'blank') {
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -278,7 +278,7 @@
        <Row gutter={24}>
          {!type && btn.sheet ? <Col span={8}>
            <Form.Item label="表名" style={{whiteSpace: 'nowrap', margin: 0}}>
              {btn.sheet}(表变量请使用#{btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')})
              {btn.sheet}(临时表请使用#{btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')})
            </Form.Item>
          </Col> : null}
          {!type ? <Col span={10}>
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -217,10 +217,10 @@
          _select.push(`@${_f.field}='1949-10-01'`)
        } else if (_f.type === 'number') {
          _type = `decimal(18,${_fieldlen})`
          _select.push(`@${_f.field}=0`)
          _select.push(`@${_f.field}=1`)
        } else if (_f.type === 'rate') {
          _type = `decimal(18,2)`
          _select.push(`@${_f.field}=0`)
          _select.push(`@${_f.field}=1`)
        } else {
          _select.push(`@${_f.field}=''`)
        }
@@ -245,8 +245,8 @@
        fieldArr.push(_f.field.toLowerCase())
        _usefulfields.push(_f.field)
        if (/decimal/ig.test(_f.datatype)) {
          _select.push(`@${_f.field}=0`)
        if (/decimal|int/ig.test(_f.datatype)) {
          _select.push(`@${_f.field}=1`)
        } else {
          _select.push(`@${_f.field}=''`)
        }
src/templates/sharecomponent/fieldscomponent/index.jsx
@@ -332,6 +332,8 @@
            newcard.span = 24
            newcard.labelwidth = 16.2
          }
        } else if (item.type === 'text') {
          newcard.fieldlength = item.length || 50
        }
        items.push(newcard)
src/templates/sharecomponent/searchcomponent/index.jsx
@@ -210,7 +210,8 @@
          sqlVerifing: true
        })
        let sql = res.dataSource
        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
        ${res.dataSource}`
        sql = sql.replace(/@\$|\$@/ig, '')
        let rduri = ''
src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -600,6 +600,9 @@
        if (this.record.type === 'select' || this.record.type === 'link') {
          extra = <span className="add-resource-empty" onClick={this.handleEmpty}>全部</span>
        }
        if (item.placeholder) {
          extra = <><span className="resource-public-var">{item.placeholder}</span>{extra}</>
        }
        content = <CodeMirror />
      } else if (item.type === 'options') {
src/templates/sharecomponent/searchcomponent/searchform/index.scss
@@ -40,9 +40,15 @@
  .add-resource-empty {
    position: absolute;
    right: 10px;
    top: -25px;
    top: -22px;
    color: #1890ff;
    cursor: pointer;
    font-size: 14px;
  }
  .resource-public-var {
    position: absolute;
    left: 0px;
    top: -22px;
    font-size: 14px;
  }
}
src/templates/treepageconfig/updatetable/index.jsx
@@ -1121,14 +1121,10 @@
        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
          _btn.syncComponent.push(oldtabs[newCon.equalTab])
        }
      } else if (_btn.execSuccess === 'maingrid') {
        _btn.execSuccess = 'mainline'
      }
      if (_btn.execError === 'equaltab') {
        _btn.execError = 'grid'
      } else if (_btn.execError === 'maingrid') {
        _btn.execError = 'mainline'
      }
      if (_btn.popClose === 'equaltab') {
@@ -1138,8 +1134,6 @@
        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
          _btn.syncComponent.push(oldtabs[newCon.equalTab])
        }
      } else if (_btn.popClose === 'maingrid') {
        _btn.popClose = 'mainline'
      }
      if (_btn.OpenType === 'pop' || (_btn.OpenType === 'funcbutton' && _btn.funcType === 'print' && _btn.execMode === 'pop')) {
src/templates/zshare/formconfig.jsx
@@ -261,6 +261,7 @@
      label: '数据源',
      initVal: card.dataSource || '',
      tooltip: '数据权限替换符 $@ -> /* 或 \'\'、 @$ -> */ 或 \'\'',
      placeholder: '系统变量:mk_departmentcode、mk_organization、mk_user_type。',
      required: true
    },
    {
@@ -1794,6 +1795,19 @@
    },
    {
      type: 'radio',
      key: 'notZero',
      label: "不可为0",
      initVal: card.notZero || 'false',
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'radio',
      key: 'database',
      label: '数据库',
      initVal: card.database || 'local',
@@ -2510,6 +2524,22 @@
      readonly: false
    },
    {
      type: 'radio',
      key: 'opacity',
      label: '是否可见',
      initVal: card.opacity || 'true',
      tooltip: '不可见时仅用作表单分隔,不显示名称。',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'true',
        text: '可见'
      }, {
        value: 'false',
        text: '不可见'
      }]
    },
    {
      type: 'text',
      key: 'regularExtra',
      label: '正则扩展符',
src/templates/zshare/modalform/index.jsx
@@ -21,7 +21,7 @@
const modalTypeOptions = {
  text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType', 'constant', 'mkfocus'],
  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom', 'mkfocus', 'format'],
  number: ['initval', 'readonly', 'notZero', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom', 'mkfocus', 'format'],
  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
  checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
@@ -39,7 +39,7 @@
  color: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'colorType', 'extra', 'marginTop', 'marginBottom'],
  rate: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'splitline', 'tooltip', 'extra', 'marginTop', 'marginBottom', 'allowHalf', 'color', 'rateCount', 'character', 'place'],
  hint: ['label', 'field', 'type', 'blacklist', 'supField', 'message', 'span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
  split: ['label', 'type', 'marginTop', 'marginBottom', 'splitline', 'splitctrl', 'supField'],
  split: ['label', 'type', 'marginTop', 'marginBottom', 'splitline', 'splitctrl', 'supField', 'opacity'],
  formula: ['label', 'type', 'marginTop', 'marginBottom', 'splitline', 'supField', 'span', 'labelwidth', 'formula', 'eval', 'postfix'],
  brafteditor: ['required', 'hidelabel', 'hidden', 'readin', 'fieldlength', 'readonly', 'span', 'labelwidth', 'tooltip', 'extra', 'encryption', 'marginTop', 'marginBottom'],
  funcvar: ['span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
src/templates/zshare/verifycard/baseform/index.jsx
@@ -134,6 +134,8 @@
      error = '开启邮件发送时,需要选择邮件模板!'
    } else if (verify.printEnable === 'true' && !verify.printTempId) {
      error = '使用单据打印时,需要选择打印模板!'
    } else if (verify.linkEnable === 'true' && !verify.linkUrl) {
      error = '打开链接开启时,需要添加链接地址!'
    } else if (verify.accountdate === 'true' && !verify.accountfield) {
      error = '开启账期时,需要选择验证公司!'
    } else if (verify.preHandle === 'true' && !verify.pre_func) {
@@ -166,6 +168,10 @@
    }
    if (_verify.printEnable !== 'true') {
      _verify.printTempId = ''
    }
    if (_verify.linkEnable !== 'true') {
      delete _verify.linkUrl
      delete _verify.linkProUrl
    }
    if (_verify.accountdate !== 'true') {
      _verify.accountfield = ''
@@ -292,7 +298,7 @@
  }
  render() {
    const { unionFields, verify, notes, emailCodes, card, appType, columns } = this.props
    const { unionFields, verify, notes, emailCodes, card, appType, columns, fields } = this.props
    const { wxTemps, selectTemp } = this.state
    const formItemLayout = {
      labelCol: {
@@ -306,13 +312,29 @@
    }
    let _columns = []
    if (window.GLOB.process) {
      _columns = columns.filter(col => {
        if (!col.field) return false
        if (col.field.toLowerCase() === 'id') return false
        if (col.type === 'text' && col.fieldlength > 100)  return false
    let remarks = []
    if (window.GLOB.process && card.intertype !== 'inner') {
      let cols = []
      fields.forEach(col => {
        if (!col.field) return
  
        return true
        cols.push(col.field.toLowerCase())
        _columns.push(col)
        if ((col.type === 'text' || col.type === 'textarea') && col.field !== 'BID') {
          remarks.push(col)
        }
      })
      columns.forEach(col => {
        if (!col.field) return
        let key = col.field.toLowerCase()
        if (key === 'id' || cols.includes(key)) return
        if (col.type === 'text' && col.fieldlength > 100)  return
        _columns.push(col)
      })
    }
@@ -524,7 +546,31 @@
            </Form.Item>
          </Col> : null}
          <Col span={24}></Col>
          {window.GLOB.process ? <Col span={8}>
          <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="按钮执行成功后需要打开的链接地址。">
                <QuestionCircleOutlined className="mk-form-tip" />
                打开链接
              </Tooltip>
            }>
              <Radio.Group value={verify.linkEnable || 'false'} onChange={(e) => {this.onOptionChange(e.target.value, 'linkEnable')}}>
                <Radio value="true">开启</Radio>
                <Radio value="false">不开启</Radio>
              </Radio.Group>
            </Form.Item>
          </Col>
          {verify.linkEnable === 'true' ? <Col span={24} className="dz-link">
            <Form.Item label="链接地址" required>
              <Input.TextArea autoComplete="off" value={verify.linkUrl || ''} onChange={(e) => {this.onOptionChange(e.target.value, 'linkUrl')}}/>
            </Form.Item>
          </Col> : null}
          {verify.linkEnable === 'true' ? <Col span={24} className="dz-link">
            <Form.Item label="正式地址">
              <Input.TextArea autoComplete="off" value={verify.linkProUrl || ''} onChange={(e) => {this.onOptionChange(e.target.value, 'linkProUrl')}}/>
            </Form.Item>
          </Col> : null}
          <Col span={24}></Col>
          {window.GLOB.process && card.intertype !== 'inner' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="在菜单开启工作流时有效。">
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -537,7 +583,7 @@
              </Radio.Group>
            </Form.Item>
          </Col> : null}
          {window.GLOB.process && verify.workFlow === 'true' ? <Col span={8}>
          {window.GLOB.process && card.intertype !== 'inner' && verify.workFlow === 'true' ? <Col span={8}>
            <Form.Item label="类型">
              <Radio.Group value={verify.flowType} onChange={(e) => {this.onOptionChange(e.target.value, 'flowType')}}>
                <Radio value="start">发起</Radio>
@@ -546,7 +592,7 @@
              </Radio.Group>
            </Form.Item>
          </Col> : null}
          {window.GLOB.process && verify.workFlow === 'true' ? <Col span={8}>
          {window.GLOB.process && card.intertype !== 'inner' && verify.workFlow === 'true' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="执行位置在系统默认sql之后。">
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -559,9 +605,9 @@
              </Radio.Group>
            </Form.Item>
          </Col> : null}
          {window.GLOB.process && verify.workFlow === 'true' && verify.flowType === 'approval' ? <Col span={8}>
          {window.GLOB.process && card.intertype !== 'inner' && verify.workFlow === 'true' && verify.flowType === 'approval' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="如果审批存在多条分支,可添加审批流程的控制字段,通过行信息控制流程走向。注:需在流程图中完善分支的执行条件。">
              <Tooltip placement="bottomLeft" title="如果审批存在多条分支,可添加审批流程的控制字段,通过表单信息或行信息控制流程走向。注:需在流程图中完善分支的执行条件。">
                <QuestionCircleOutlined className="mk-form-tip" />
                流程控制
              </Tooltip>
@@ -575,6 +621,22 @@
              </Select>
            </Form.Item>
          </Col> : null}
          {window.GLOB.process && card.intertype !== 'inner' && verify.workFlow === 'true' && verify.flowType !== 'start' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="bottomLeft" title="可通过表单字段填写审批或驳回的备注信息。">
                <QuestionCircleOutlined className="mk-form-tip" />
                备注字段
              </Tooltip>
            }>
              <Select allowClear value={verify.flowRemark} onChange={(val) => {this.onOptionChange(val || '', 'flowRemark')}}>
                {remarks.map(option =>
                  <Select.Option key={option.field} value={option.field}>
                    {option.label}
                  </Select.Option>
                )}
              </Select>
            </Form.Item>
          </Col> : null}
          <Col span={24}></Col>
          <Col span={8}>
            <Form.Item label={
src/templates/zshare/verifycard/baseform/index.scss
@@ -25,3 +25,13 @@
    }
  }
}
.dz-link {
  .ant-form-item {
    .ant-form-item-label {
      width: 10.8%;
    }
    .ant-form-item-control-wrapper {
      width: 89.2%;
    }
  }
}
src/templates/zshare/verifycard/customscript/index.jsx
@@ -46,7 +46,7 @@
  }
  handleConfirm = () => {
    const { type, workFlow, flowType, flowSql, useDefaultSql, defaultsql } = this.props
    const { type, workFlow, flowType, flowSql, flowRemark, useDefaultSql, defaultsql } = this.props
    const { editItem, skip } = this.state
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
@@ -142,18 +142,20 @@
              /* 工作流默认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,upid)
              select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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
              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,upid)
              select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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${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
@@ -206,13 +208,10 @@
          sql = sql.replace(/@check_type@/ig, `'审核'`)
          sql = sql.replace(/@notice_type@/ig, `'抄送'`)
          if (flowType !== 'start') {
            sql = sql.replace(/@check_userids@/ig, `'checkuserids'`)
            sql = sql.replace(/@notice_userids@/ig, `'noticeuserids'`)
          } else {
            sql = sql.replace(/@check_userids@/ig, `''`)
            sql = sql.replace(/@notice_userids@/ig, `''`)
          }
          sql = sql.replace(/@works_flow_sign@/ig, `''`)
        }
        
        if (skip) {
@@ -262,7 +261,7 @@
  }
  selectScript = (value, option) => {
    const { flowType } = this.props
    const { flowType, flowRemark } = this.props
    if (!value || !option) return
@@ -280,15 +279,17 @@
      if (flowType === 'start') {
        value = `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,upid)
        select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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@`
        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 {
        value = `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
        value = `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,upid)
        select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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${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
@@ -359,7 +360,7 @@
          {!_type ? <Col span={24} className="sqlfield">
            <Form.Item label={'可用字段'}>
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="公共值,请按照@xxx@格式使用。"><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id, typename, datam</span></Tooltip>,&nbsp;
              {window.GLOB.process && workFlow === 'true' ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="工作流变量,请按照@xxx@格式使用。"><span style={{color: '#26C281'}}>works_flow_code, works_flow_name, works_flow_param, works_flow_detail_id, status, statusname, work_group, work_grade, start_type, check_type, notice_type, check_userids, notice_userids, </span></Tooltip> : null}
              {window.GLOB.process && workFlow === 'true' ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="工作流变量,请按照@xxx@格式使用,works_flow_sign 为分支启用高级设置时的标记值。"><span style={{color: '#26C281'}}>works_flow_code, works_flow_name, works_flow_param, works_flow_detail_id, status, statusname, work_group, work_grade, start_type, check_type, notice_type, check_userids, notice_userids, works_flow_sign, </span></Tooltip> : null}
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="系统变量,系统会定义变量并赋值。"><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address, mk_deleted</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="系统变量,系统会定义变量并在单号生成或创建凭证时使用。"><span style={{color: '#13c2c2'}}>BillCode, BVoucher, FIBVoucherDate, FiYear, ModularDetailCode</span></Tooltip>
              {formfields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="表单变量,系统会定义变量并赋值。">, <span style={{color: '#8E44AD'}}>{formfields}</span></Tooltip> : ''}
src/templates/zshare/verifycard/index.jsx
@@ -649,12 +649,13 @@
    _verify.scripts = _verify.scripts || []
    _verify.cbScripts = _verify.cbScripts || []
    if (window.GLOB.process) {
    if (window.GLOB.process && card.intertype !== 'inner') {
      _verify.workFlow = _verify.workFlow || 'false'
      _verify.flowType = _verify.flowType || (card.sqlType === 'insert' ? 'start' : 'approval')
      _verify.flowSql = _verify.flowSql || 'true'
    } else {
      delete _verify.workFlow
      delete _verify.flowRemark
      delete _verify.flowType
      delete _verify.flowSql
    }
@@ -774,13 +775,13 @@
        _select.push(`@${_f.field}='1949-10-01'`)
      } else if (_f.type === 'number') {
        _type = `decimal(18,${_fieldlen})`
        _select.push(`@${_f.field}=0`)
        _select.push(`@${_f.field}=1`)
      } else if (_f.declare === 'decimal') {
        _type = `decimal(18,${_f.decimal || 0})`
        _select.push(`@${_f.field}=0`)
        _select.push(`@${_f.field}=1`)
      } else if (_f.type === 'rate') {
        _type = `decimal(18,2)`
        _select.push(`@${_f.field}=0`)
        _select.push(`@${_f.field}=1`)
      } else {
        _select.push(`@${_f.field}=''`)
      }
@@ -816,8 +817,8 @@
        colfields.push(_f.field)
        if (_f.datatype) { // 自定义字段
          if (/decimal/ig.test(_f.datatype)) {
            _select.push(`@${_f.field}=0`)
          if (/decimal|int/ig.test(_f.datatype)) {
            _select.push(`@${_f.field}=1`)
          } else {
            _select.push(`@${_f.field}=''`)
          }
@@ -841,7 +842,7 @@
        }
        if (_f.type === 'number') {
          _select.push(`@${_f.field}=0`)
          _select.push(`@${_f.field}=1`)
        } else {
          _select.push(`@${_f.field}=''`)
        }
@@ -1562,7 +1563,7 @@
    
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      if ((card.sqlType === 'custom' || verify.default === 'false') && verify.scripts.length === 0) {
      if ((card.sqlType === 'custom' || verify.default === 'false') && !(verify.workFlow === 'true' && verify.flowSql === 'true') && verify.scripts.length === 0) {
        notification.warning({
          top: 92,
          message: '不执行默认sql时,必须设置自定义脚本!',
@@ -1687,7 +1688,7 @@
              {verify.default === 'false' ? <span className="count-tip"><ExclamationOutlined style={{color: 'orange'}}/></span> : null}
            </span>
          } key="base">
            <BaseForm card={card} appType={appType} columns={columns} unionFields={unionFields} verify={verify} notes={notes} emailCodes={emailCodes} onChange={(verify) => this.setState({verify})} wrappedComponentRef={(inst) => this.baseForm = inst}/>
            <BaseForm card={card} appType={appType} fields={fields} columns={columns} unionFields={unionFields} verify={verify} notes={notes} emailCodes={emailCodes} onChange={(verify) => this.setState({verify})} wrappedComponentRef={(inst) => this.baseForm = inst}/>
          </TabPane> : null}
          {verifyInter === 'system' ? <TabPane tab={
            <span>
@@ -1778,6 +1779,7 @@
                btn={this.props.card}
                initsql={this.state.initsql}
                workFlow={verify.workFlow}
                flowRemark={verify.flowRemark}
                flowType={verify.flowType}
                flowSql={verify.flowSql}
                customScripts={verify.scripts}
@@ -1794,6 +1796,7 @@
              btn={this.props.card}
              initsql={this.state.initsql}
              workFlow={verify.workFlow}
              flowRemark={verify.flowRemark}
              flowType={verify.flowType}
              flowSql={verify.flowSql}
              customScripts={verify.scripts}
src/utils/utils.js
@@ -854,24 +854,6 @@
  }
  /**
   * @description 获取云端图片真实路径
   * @return {String}    url 图片路径
   */
  static getcloudurl (url) {
    if (!url) return ''
    let baseurl = ''
    if (window.GLOB.cloudServiceApi) {
      baseurl = window.GLOB.cloudServiceApi.replace(/webapi(.*)$/, '')
    } else {
      baseurl = window.GLOB.baseurl
    }
    return url.match(/^http/) || url.match(/^\/\//) ? url : baseurl + url
  }
  /**
   * @description 获取下拉搜索查询条件
   * @return {String} item   搜索条件信息
   */
@@ -1439,7 +1421,7 @@
    sql = `
      /* 系统生成 */
      create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50) )
      create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(256))
      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),@tbid Nvarchar(512)
      
      Select  @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}'
@@ -2149,8 +2131,13 @@
    let status = 0
    let statusName = ''
    let detailId = ''
    let sign = ''
    let error = ''
    let userid = sessionStorage.getItem('UserID') || ''
    let checkIds = []
    let checkUsers = []
    let noticeIds = []
    let work_grade = sessionStorage.getItem('work_grade') || 0
    if (verify.flowType === 'start') {
      target = flow.cells.filter(cell => cell.mknode === 'start')[0]
@@ -2174,24 +2161,17 @@
        if (verify.flowType === 'reject') {
          line = lines.filter(cell => cell.mkdata.flowType === 'reject' || cell.mknode === 'startEdge')[0]
        } else {
          let endEdge = null
          lines = lines.filter(cell => {
            if (cell.mknode === 'endEdge') {
              endEdge = cell
              return false
            }
            return cell.mkdata.flowType !== 'reject' && cell.mknode !== 'startEdge'
          })
          lines = lines.filter(cell => cell.mkdata.flowType !== 'reject' && cell.mknode !== 'startEdge')
          if (lines.length === 0) {
            if (!endEdge) {
              error = '无可执行的流程分支'
            } else {
              line = endEdge
            }
          } else {
            let branchKey = verify.flowBranch ? verify.flowBranch.toLowerCase() : ''
            formdata && formdata.forEach(form => {
              let _key = form.key.toLowerCase()
              _data[_key] = form.value
            })
  
            if (!branchKey) {
              lines.forEach(line => {
@@ -2200,18 +2180,31 @@
                }
              })
              if (!error) {
                line = lines[0]
                lines = lines.filter(cell => {
                  if (cell.mkdata.seniorCondition === 'open' && !line) {
                    cell.mkdata.seniorbers && cell.mkdata.seniorbers.forEach(per => {
                      if (per.worker_id === userid) {
                        line = cell
              }
            } else if (!_data.hasOwnProperty(branchKey)) {
              error = '行信息中无流程控制字段。'
            } else {
              if (endEdge) {
                line = endEdge
                    })
                    return false
              }
              let equalLine = null
              let gtOrLtLine = []
              let unEqualLine = null
                  return true
                })
                if (!line) {
                  line = lines[0]
                }
              }
            } else if (!_data.hasOwnProperty(branchKey)) {
              error = '信息中无流程控制字段。'
            } else {
              let _def_lines = []
              let _equ_lines = []
              let _unequ_lines = []
              let _or_lines = []
              let branchVal = _data[branchKey]
              if (branchVal && typeof(branchVal) === 'string' && !isNaN(branchVal)) {
@@ -2220,45 +2213,58 @@
              lines.forEach(item => {
                if (item.mkdata.execCondition !== 'open') {
                  line = item
                  _def_lines.push(item)
                } else {
                  if (item.mkdata.match === '=') {
                    if (item.mkdata.matchVal === branchVal + '') {
                      equalLine = item
                      _equ_lines.push(item)
                    }
                  } else if (item.mkdata.match === '!=') {
                    if (item.mkdata.matchVal !== branchVal + '') {
                      unEqualLine = item
                      _unequ_lines.push(item)
                    }
                  } else {
                    if (item.mkdata.match === '<') {
                      if (item.mkdata.matchVal < branchVal) {
                        gtOrLtLine.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                        _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                      }
                    } else if (item.mkdata.match === '>') {
                      if (item.mkdata.matchVal > branchVal) {
                        gtOrLtLine.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                        _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                      }
                    } else if (item.mkdata.match === '<=') {
                      if (item.mkdata.matchVal <= branchVal) {
                        gtOrLtLine.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                        _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                      }
                    } else if (item.mkdata.match === '>=') {
                      if (item.mkdata.matchVal >= branchVal) {
                        gtOrLtLine.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                        _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                      }
                    }
                  }
                }
              })
              if (equalLine) {
                line = equalLine
              } else if (gtOrLtLine.length > 0) {
                gtOrLtLine.sort((a, b) => a.dist - b.dist)
                line = gtOrLtLine[0]
              } else if (unEqualLine) {
                line = unEqualLine
              _or_lines.sort((a, b) => a.dist - b.dist)
              let _lines = [..._equ_lines, ..._or_lines, ..._unequ_lines, ..._def_lines]
              _lines = _lines.filter(cell => {
                if (cell.mkdata.seniorCondition === 'open' && !line) {
                  cell.mkdata.seniorbers && cell.mkdata.seniorbers.forEach(per => {
                    if (per.worker_id === userid) {
                      line = cell
                    }
                  })
                  return false
                }
                return true
              })
              if (!line) {
                line = _lines[0]
              }
            }
          }
@@ -2271,7 +2277,36 @@
        detailId = line.id
        status = line.mkdata.status
        statusName = line.mkdata.statusName
        sign = line.mkdata.seniorSign || ''
        target = flow.cells.filter(cell => cell.id === line.target.cell)[0]
        line.mkdata.members && line.mkdata.members.forEach(item => {
          if (line.mkdata.approver === 'departmentManager') {
            if (item.job_type === 'manage' && departmentcode === item.parentIds[1]) {
              checkIds.push(item.worker_id)
              checkUsers.push(item)
            }
          } else if (line.mkdata.approver === 'directManager') {
            if (departmentcode === item.parentIds[1] && item.work_grade > work_grade) {
              checkIds.push(item.worker_id)
              checkUsers.push(item)
            }
          } else {
            checkIds.push(item.worker_id)
            checkUsers.push(item)
          }
        })
        line.mkdata.copys && line.mkdata.copys.forEach(item => {
          noticeIds.push(item.worker_id)
        })
        if (!target) {
          error = '未查询到工作流目标节点'
        } else if (checkIds.length === 0 && !['startEdge', 'endEdge', 'throughEdge'].includes(line.mknode)) {
          error = '未获取到下一步审批人'
        } else if (line.approvalMethod === 'countersign' && (!node.checkIds || !node.checkIds.includes(userid))) {
          error = '当前用户不在审批人列表中'
        }
      } else if (!error) {
        error = '工作流中无对应流程'
      }
@@ -2287,26 +2322,20 @@
      /* 工作流异常sql */
      select @ErrorCode='E',@retmsg='${error}' goto aaa
      `
    } else if (verify.flowSql === 'true' && target) {
    } else 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,upid)
      select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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 if (line && line.approvalMethod === 'countersign' && (!node.checkIds || !node.checkIds.includes(userid))) {
        status = 0
        statusName = '异常'
        _sql += `
        /* 工作流异常sql */
        select @ErrorCode='E',@retmsg='当前用户不在审批人列表中' goto aaa
        `
      } else if (line && line.approvalMethod === 'countersign' && node.checkIds.length > 1) {
      } else if (line.approvalMethod === 'countersign' && node.checkIds.length > 1) {
        let label = ''
        let field = ''
        let mark = line.mark || '已审核'
@@ -2346,11 +2375,11 @@
      if @works_flow_key_status='Y'
      begin
            update s_my_works_flow set ${field}=${label},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
            update s_my_works_flow set ${field}=${label},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 id=@works_flow_key_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,upid,${field})
            select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@time_id@,${label}
            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' : ''},${field})
            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 : ''},${label}
            
            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
@@ -2375,11 +2404,11 @@
      end
      else
      begin
            update s_my_works_flow set ${field}=${label},modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
            update s_my_works_flow set ${field}=${label},modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname${verify.flowRemark ? ',remark=@' + verify.flowRemark : ''}
            where id =@works_flow_key_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,upid,${field})
            select @ID@,@works_flow_code@,@works_flow_name@ ,@s_my_works_flow_log_param,@s_my_works_flow_log_status,@s_my_works_flow_log_statusname,@s_my_works_flow_log_detail_id,@work_group@,@work_grade@,@time_id@,${label}
            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' : ''},${field})
            select @ID@,@works_flow_code@,@works_flow_name@ ,@s_my_works_flow_log_param,@s_my_works_flow_log_status,@s_my_works_flow_log_statusname,@s_my_works_flow_log_detail_id,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@${verify.flowRemark ? ',@' + verify.flowRemark : ''},${label}
          
            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 and userid =@userid@
@@ -2406,13 +2435,16 @@
      end
      set @retmsg=''
      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
      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,upid)
      select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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${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
      ${line.mknode === 'startEdge' ? `update s_my_works_flow_role set deleted=0,modifydate=getdate(),upid=@time_id@,modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
      where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and typecharone='begin'` : ''}
      if @check_userids@ != ''
      begin
@@ -2433,51 +2465,16 @@
      end
      `
      }
    } else if (verify.flowSql === 'true') {
      status = 0
      statusName = '异常'
      _sql += `
      /* 工作流异常sql */
      select @ErrorCode='E',@retmsg='${error || '工作流执行异常'}' goto aaa
      `
    }
    let checkIds = []
    let checkUsers = []
    let work_grade = sessionStorage.getItem('work_grade') || 0
    if (verify.flowType !== 'start') {
      if (line) {
        let noticeIds = []
        line.mkdata.members && line.mkdata.members.forEach(item => {
          if (line.mkdata.approver === 'departmentManager') {
            if (item.job_type === 'manage' && departmentcode === item.parentIds[1]) {
              checkIds.push(item.worker_id)
              checkUsers.push(item)
    if (_backCustomScript) {
      _sql += _backCustomScript
            }
          } else if (line.mkdata.approver === 'directManager') {
            if (departmentcode === item.parentIds[1] && item.work_grade > work_grade) {
              checkIds.push(item.worker_id)
              checkUsers.push(item)
            }
          } else {
            checkIds.push(item.worker_id)
            checkUsers.push(item)
          }
        })
        line.mkdata.copys && line.mkdata.copys.forEach(item => {
          noticeIds.push(item.worker_id)
        })
    _sql = _sql.replace(/@works_flow_sign@/ig, `'${sign}'`)
        _sql = _sql.replace(/@check_userids@/ig, `'${checkIds.join(',')}'`)
        _sql = _sql.replace(/@notice_userids@/ig, `'${noticeIds.join(',')}'`)
      } else {
        _sql = _sql.replace(/@check_userids@/ig, `''`)
        _sql = _sql.replace(/@notice_userids@/ig, `''`)
      }
    } else {
      _sql = _sql.replace(/@check_userids@/ig, `''`)
      _sql = _sql.replace(/@notice_userids@/ig, `''`)
    }
    _sql = _sql.replace(/@start_type@/ig, `'开始'`)
    _sql = _sql.replace(/@check_type@/ig, verify.flowType === 'reject' ? `'驳回'` : `'审核'`)
@@ -2498,9 +2495,7 @@
    _sql = _sql.replace(/@statusname@/ig, `'${statusName}'`)
    _sql = _sql.replace(/@work_group@/ig, `'${sessionStorage.getItem('work_group') || ''}'`)
    _sql = _sql.replace(/@work_grade@/ig, `'${work_grade}'`)
  }
  if (_backCustomScript) {
  } else if (_backCustomScript) {
    _sql += _backCustomScript
  }
src/views/basedesign/updateFormTab/index.jsx
@@ -1195,14 +1195,10 @@
        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
          _btn.syncComponent.push(oldtabs[newCon.equalTab])
        }
      } else if (_btn.execSuccess === 'maingrid') {
        _btn.execSuccess = 'mainline'
      }
      if (_btn.execError === 'equaltab') {
        _btn.execError = 'grid'
      } else if (_btn.execError === 'maingrid') {
        _btn.execError = 'mainline'
      }
      if (_btn.popClose === 'equaltab') {
@@ -1212,8 +1208,6 @@
        if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
          _btn.syncComponent.push(oldtabs[newCon.equalTab])
        }
      } else if (_btn.popClose === 'maingrid') {
        _btn.popClose = 'mainline'
      }
      if (_btn.OpenType === 'pop' || (_btn.OpenType === 'funcbutton' && _btn.funcType === 'print' && _btn.execMode === 'pop')) {
src/views/design/sidemenu/thdmenuform/index.jsx
@@ -147,7 +147,7 @@
          </Col>
          {menu.Template === 'NewPage' ? <Col span={22}>
            <Form.Item label={
              <Tooltip overlayStyle={{minWidth: 500}} placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>使用同一单点系统下的其他业务系统,链接格式为:http://<span style={{color: 'orange'}}>******</span>/admin/index.html#/iframe/<span style={{color: 'orange'}}>menuId</span>/<span style={{color: 'orange'}}>loginuid</span>/<span style={{color: 'orange'}}>BID</span>。注:******为域名+虚拟目录;menuId为菜单ID;loginuid为登录信息(使用@loginuid@时自动替换为当前系统的loginuid);BID是向菜单中的传参,可为空。</div>}><QuestionCircleOutlined className="mk-form-tip" />链接地址</Tooltip>
              <Tooltip overlayStyle={{minWidth: 500}} placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>使用同一单点系统下的其他业务系统,链接格式为:http://<span style={{color: 'orange'}}>******</span>/admin/index.html#/iframe/<span style={{color: 'orange'}}>menuId</span>/<span style={{color: 'orange'}}>@loginuid@</span>/<span style={{color: 'orange'}}>BID</span>。注:******为域名+虚拟目录;menuId为菜单ID;@loginuid@为登录信息(系统自动替换);BID是向菜单中的传参,可为空。</div>}><QuestionCircleOutlined className="mk-form-tip" />链接地址</Tooltip>
            }>
              {getFieldDecorator('url', {
                initialValue: menu.url || '',
src/views/login/index.scss
@@ -291,6 +291,12 @@
        }
      }
    }
    .qr-wrap + img {
      width: 24px;
      margin-right: 5px;
      vertical-align: middle;
    }
  }
}
.mk-user-option {
src/views/login/loginform.jsx
@@ -9,6 +9,7 @@
import Utils from '@/utils/utils.js'
import options from '@/store/options.js'
import asyncLoadComponent from '@/utils/asyncLoadComponent'
import wxicon from '@/assets/img/wx-icon.png'
import './index.scss'
const { warning } = Modal
@@ -71,6 +72,11 @@
        item.label = '账号登录'
        _loginWays.push(item)
      } else if (item.type === 'app_scan') {
        item.label = 'APP扫码'
        _loginWays.push(item)
        hasScan = true
      } else if (item.type === 'weixin_scan') {
        item.label = '微信扫码'
        _loginWays.push(item)
        hasScan = true
      }
@@ -102,13 +108,13 @@
      smsId: smsId,
      loginWays: _loginWays,
      activeKey,
      scanId: activeKey === 'app_scan' ? Utils.getuuid() : '',
      scanId: activeKey === 'app_scan' || activeKey === 'weixin_scan' ? Utils.getuuid() : '',
      timeout: false,
      remember,
      hasScan
    })
    if (activeKey === 'app_scan') {
    if (activeKey === 'app_scan' || activeKey === 'weixin_scan') {
      this.splitTime = 0
      this.timer = setTimeout(() => {
        this.checkResult()
@@ -236,14 +242,20 @@
    }
  }
  onChangeTab = (activeKey) => {
    this.setState({activeKey, scanId: activeKey === 'app_scan' ? Utils.getuuid() : ''})
  onChangeTab = (key) => {
    const { activeKey, loginWays } = this.state
    if (this.state.activeKey === 'app_scan') {
    if (key === 'scan') {
      key = loginWays.filter(item => item.type === 'app_scan' || item.type === 'weixin_scan')[0].type
    }
    this.setState({activeKey: key, scanId: key === 'app_scan' || key === 'weixin_scan' ? Utils.getuuid() : ''})
    if (activeKey === 'app_scan' || activeKey === 'weixin_scan') {
      this.timer && clearTimeout(this.timer)
    }
    if (activeKey === 'app_scan') {
    if (key === 'app_scan' || key === 'weixin_scan') {
      this.splitTime = 0
      this.setState({timeout: false})
      this.timer = setTimeout(() => {
@@ -429,12 +441,12 @@
    const { langList } = this.props
    const { getFieldDecorator } = this.props.form
    const { activeKey, verdisabled, delay, loginWays, remember, scanId, timeout, hasScan, users } = this.state
    const wayLabels = {app_scan: '扫码登录', uname_pwd: '账号登录', sms_vcode: '短信登录'}
    const wayLabels = {app_scan: 'APP扫码', weixin_scan: '微信扫码', uname_pwd: '账号登录', sms_vcode: '短信登录'}
    return (
      <Form className="login-form" id="login-form" onSubmit={this.handleSubmit}>
        <div className="login-way-title">{wayLabels[activeKey]}</div>
        {hasScan && activeKey !== 'app_scan' ? <div className="scan-icon" onClick={() => this.onChangeTab('app_scan')}><QrcodeOutlined /></div> : null}
        {hasScan && activeKey !== 'app_scan' && activeKey !== 'weixin_scan' ? <div className="scan-icon" onClick={() => this.onChangeTab('scan')}><QrcodeOutlined /></div> : null}
        {activeKey === 'uname_pwd' ? <div className="form-item-wrap">
          <Form.Item>
            {getFieldDecorator('username', {
@@ -559,6 +571,18 @@
            <a href="http://www.minkesoft.com/forgotPwd" target="_blank" rel="noopener noreferrer" className="forgot">忘记密码?</a>
          </Form.Item> : null}
        </div> : null}
        {activeKey === 'weixin_scan' ? <div className="form-item-wrap">
          <div className="form-scan-wrap">
            <div className="qr-wrap">
              {scanId ? <QrCode card={{qrWidth: 500, color: '#000000'}} value={`https://cloud.mk9h.cn/mob/mknotice.html?originurl=${window.btoa(window.GLOB.baseurl + 'mob/index.html#/wx/' + scanId)}`}/> : null}
              {timeout ? <div className="qrcode-out">
                <RedoOutlined onClick={this.reCode} />
                二维码已失效。
              </div> : null}
            </div>
            <img src={wxicon} alt=""/>请使用微信扫一扫登录
          </div>
        </div> : null}
        {activeKey === 'app_scan' ? <div className="form-item-wrap">
          <div className="form-scan-wrap">
            <div className="qr-wrap">
@@ -571,9 +595,11 @@
            请使用客户端扫一扫登录
          </div>
        </div> : null}
        <div className={'login-ways ' + (activeKey === 'app_scan' ? 'center' : '')}>
        <div className={'login-ways ' + (activeKey === 'app_scan' || activeKey === 'weixin_scan' ? 'center' : '')}>
          {loginWays.map(item => {
            if (item.type === 'app_scan' || activeKey === item.type) return null
            if (activeKey === item.type) return null
            if (item.type === 'app_scan' && activeKey !== 'weixin_scan') return null
            if (item.type === 'weixin_scan' && activeKey !== 'app_scan') return null
            return (<span key={item.type} onClick={() => this.onChangeTab(item.type)}>{item.label}</span>)
          })}
        </div>
src/views/menudesign/index.jsx
@@ -888,10 +888,21 @@
  
            Api.fileuploadbase64(param).then(result => {
              if (result.status) {
                let url = result.Images
                let baseurl = ''
                if (window.GLOB.cloudServiceApi) {
                  baseurl = window.GLOB.cloudServiceApi.replace(/webapi(.*)$/, '')
                } else {
                  baseurl = window.GLOB.baseurl
                }
                url = url.match(/^http/) || url.match(/^\/\//) ? url : baseurl + url
                Api.getCloudConfig({
                  func: 's_PrintTemplateMSub',
                  ID: config.uuid,
                  Images: Utils.getcloudurl(result.Images),
                  Images: url,
                  Remark: '',
                  temp_type: 'billprint',
                }).then(response => {
@@ -1160,6 +1171,7 @@
  updateLogConfig = (config) => {
    config.fstMenuId = this.state.config.fstMenuId || config.fstMenuId || ''
    config.parentId = this.state.config.parentId || config.parentId || ''
    config.open_edition = this.state.config.open_edition || ''
    
    this.setState({
      config: null
src/views/menudesign/popview/index.jsx
@@ -72,13 +72,13 @@
    const { oriConfig, config } = this.state
    if (!is(fromJS(oriConfig), fromJS(config))) {
      const _this = this
      const that = this
      confirm({
        title: '配置已修改,放弃保存吗?',
        content: '',
        onOk() {
          _this.props.cancel()
          that.props.cancel()
        },
        onCancel() {}
      })
src/views/mobdesign/index.jsx
@@ -2030,6 +2030,8 @@
  }
  updateLogConfig = (config) => {
    config.open_edition = this.state.config.open_edition || ''
    this.setState({
      config: null
    }, () => {
src/views/mobdesign/popview/index.jsx
@@ -74,13 +74,13 @@
    const { oriConfig, config } = this.state
    if (!is(fromJS(oriConfig), fromJS(config))) {
      const _this = this
      const that = this
      confirm({
        title: '配置已修改,放弃保存吗?',
        content: '',
        onOk() {
          _this.props.cancel()
          that.props.cancel()
        },
        onCancel() {}
      })
src/views/pcdesign/index.jsx
@@ -1679,6 +1679,8 @@
  }
  updateLogConfig = (config) => {
    config.open_edition = this.state.config.open_edition || ''
    this.setState({
      config: null
    }, () => {
src/views/printTemplate/index.jsx
@@ -831,7 +831,18 @@
        
        Api.fileuploadbase64(param).then(result => { // 图片上传,并获取图片路径
          if (result.status) {
            resolve(Utils.getcloudurl(result.Images))
            let url = result.Images
            let baseurl = ''
            if (window.GLOB.cloudServiceApi) {
              baseurl = window.GLOB.cloudServiceApi.replace(/webapi(.*)$/, '')
            } else {
              baseurl = window.GLOB.baseurl
            }
            url = url.match(/^http/) || url.match(/^\/\//) ? url : baseurl + url
            resolve(url)
          } else {
            notification.warning({
              top: 92,
src/views/tabledesign/index.jsx
@@ -827,6 +827,7 @@
  updateLogConfig = (config) => {
    config.fstMenuId = this.state.config.fstMenuId || config.fstMenuId || ''
    config.parentId = this.state.config.parentId || config.parentId || ''
    config.open_edition = this.state.config.open_edition || ''
    this.setState({
      config: null
src/views/tabledesign/popview/index.jsx
@@ -68,13 +68,13 @@
    const { oriConfig, config } = this.state
    if (!is(fromJS(oriConfig), fromJS(config))) {
      const _this = this
      const that = this
      confirm({
        title: '配置已修改,放弃保存吗?',
        content: '',
        onOk() {
          _this.props.cancel()
          that.props.cancel()
        },
        onCancel() {}
      })