king
2022-10-10 78eed586f6a0d15162c89878c53a301e7b142a8a
Merge branch 'master' into positec
120个文件已修改
10个文件已添加
9个文件已删除
6079 ■■■■■ 已修改文件
public/README.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/options.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/design.scss 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/viewstyle.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/breadview/index.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.scss 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/mkPicture/index.jsx 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/mkPicture/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tabview/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/index.jsx 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/options.jsx 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/options.jsx 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/prop-card/index.jsx 159 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/table-card/index.jsx 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/data-card/index.jsx 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/prop-card/index.jsx 98 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-scatter/index.jsx 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/chart-custom/chartcompile/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/chart-custom/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/editor/braft-editor/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/dragtitle/card.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/dragtitle/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/simple-form/index.jsx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/index.jsx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/tab-form/index.jsx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/actionform/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/dragaction/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/formconfig.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/index.jsx 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/logcomponent/index.jsx 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/logcomponent/index.scss 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/sourcecomponent/inputform/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/usercomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/index.jsx 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/tableIn/index.jsx 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/index.jsx 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/index.jsx 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/timeline/normal-timeline/index.jsx 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tree/antd-tree/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/settingform/index.jsx 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/verifycard/utils.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/index.jsx 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/index.scss 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/settingform/baseform/index.jsx 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/settingform/baseform/index.scss 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/settingform/index.jsx 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/settingform/index.scss 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/settingform/simplescript/index.jsx 454 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/settingform/simplescript/index.scss 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/sysinterface/settingform/utils.jsx 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/tablenodes/index.jsx 426 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/tablenodes/index.scss 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/bgcontroller/index.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/action-type.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/action.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/reducer.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/basetable/index.jsx 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/calendar/index.jsx 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/balcony/index.jsx 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardItem/index.jsx 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/prop-card/index.jsx 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/table-card/index.jsx 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/carousel/prop-card/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-pie/index.jsx 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/simple-form/index.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/step-form/index.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/form/tab-form/index.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/interfaces/index.jsx 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/interfaces/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/interfaces/interItem/index.jsx 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/interfaces/interItem/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 368 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/debugtable/index.jsx 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/debugtable/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/formtab/index.jsx 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/home/index.jsx 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtable/index.jsx 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtabtable/index.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/treepage/index.jsx 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/tabbutton/index.jsx 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.jsx 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/settingcomponent/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/actionform/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/index.jsx 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/utils.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tablecomponent/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/customscript/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/editTable/index.jsx 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/baseform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customscript/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.scss 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-custom.js 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-datamanage.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/editthdmenu/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/imdesign/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/main/index.jsx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 72 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.jsx 68 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/header/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/header/index.scss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/README.txt
@@ -11,6 +11,7 @@
defaultLang       -- 打开的子应用语言类型,默认为zh-CN
WXAppID           -- 使用公众号时,绑定的公众号ID
WXminiAppID       -- 使用微信小程序时,绑定的小程序ID
nginx             -- 是否开启了nginx服务,值为 true 时开启,如需使用微信模板消息等服务,请先设置nginx服务并开启此配置
debugger          -- 值为 true 时开启调试模式,开启后移动端子应用中会有控制台
licenseKey        -- 许可密钥,在内部网络中使用系统时,会跳过epc验证
probation         -- 试用期(YYYY-MM-DD),在正式系统中,试用期内调用系统接口的脚本会记录下来
public/options.json
@@ -10,6 +10,7 @@
  "defaultLang": "zh-CN",
  "WXAppID": "wxa5dd6f28cae613fc",
  "WXminiAppID": "",
  "nginx": "true",
  "debugger": false,
  "licenseKey": "",
  "probation": "",
src/assets/css/design.scss
@@ -4,6 +4,7 @@
  }
  .ant-modal-body {
    padding: 0;
    min-height: 150px;
    .mk-com-name {
      position: absolute;
@@ -84,9 +85,4 @@
    height: 200px;
  }
}
.mk-color-move {
  .color-sketch-block {
    position: relative;
    top: 7px;
  }
}
src/assets/css/viewstyle.scss
@@ -523,6 +523,12 @@
          }
        }
      }
      .header-menu::-webkit-scrollbar-track {
        box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.05);
        border: 1px solid rgba(255, 255, 255, 0.07);
        background: rgba(255, 255, 255, 255);
        border-radius: 3px;
      }
    }
  }
}
src/components/breadview/index.jsx
@@ -1,5 +1,4 @@
import React, {Component} from 'react'
import {connect} from 'react-redux'
import { BackTop, Breadcrumb, notification} from 'antd'
import { HomeOutlined, RightOutlined, RedoOutlined } from '@ant-design/icons'
import moment from 'moment'
@@ -9,7 +8,6 @@
import NotFount from '@/components/404'
import options from '@/store/options.js'
import MKEmitter from '@/utils/events.js'
import { initActionPermission } from '@/store/action'
import Api from '@/api'
import './index.scss'
@@ -57,7 +55,7 @@
              })
            }
  
            this.props.initActionPermission(_permAction)
            window.GLOB.mkActions = _permAction
          }
          resolve()
@@ -189,14 +187,4 @@
  }
}
const mapStateToProps = () => {
  return {}
}
const mapDispatchToProps = (dispatch) => {
  return {
    initActionPermission: (permAction) => dispatch(initActionPermission(permAction)),
  }
}
export default connect(mapStateToProps, mapDispatchToProps)(BreadView)
export default BreadView
src/components/header/index.jsx
@@ -4,14 +4,12 @@
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import moment from 'moment'
import { Dropdown, Menu, Modal, Form, notification, Switch, Input } from 'antd'
import { Dropdown, Menu, Modal, notification, Switch, Input } from 'antd'
import { SearchOutlined, DownOutlined, MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
import {
  toggleCollapse,
  modifyMainMenu,
  initActionPermission,
  initMenuPermission,
  logout
} from '@/store/action'
import asyncComponent from '@/utils/asyncSpinComponent'
@@ -185,7 +183,8 @@
      }
      this.props.modifyMainMenu(mainMenu)
      this.props.initMenuPermission([...thdMenuList, {MenuID: 'home_page_id', EasyCode: '', MenuName: 'home', type: 'CustomPage'}])
      window.GLOB.mkThdMenus = [...thdMenuList, {MenuID: 'home_page_id', EasyCode: '', MenuName: 'home', type: 'CustomPage'}]
      if (_menu) { // 延时打开,防止标签组未完成加载
        setTimeout(() => {
@@ -196,6 +195,7 @@
          }
        }, 200)
      }
      MKEmitter.emit('mkMenuLoaded')
    })
    
    // 获取角色权限, edition_type 接口版本控制 ''、'Y'、'A'
@@ -207,14 +207,14 @@
      }).then(result => {
        let _permAction = {loaded: true} // 按钮权限
        if (result && result.status) {
        if (result.status) {
          if (result.UserRoles_Menu) {
            result.UserRoles_Menu.forEach(menu => {
              if (!menu.MenuID) return
              _permAction[menu.MenuID] = true
            })
          }
        } else if (result) {
        } else {
          notification.error({
            top: 92,
            message: result.message,
@@ -222,7 +222,8 @@
          })
        }
        this.props.initActionPermission(_permAction)
        MKEmitter.emit('mkActionLoaded')
        window.GLOB.mkActions = _permAction
      })
    }, 50)
  }
@@ -617,9 +618,9 @@
    return (
      <header className="header-container ant-menu-dark" id="main-header-container">
        <div className={'header-logo ' + (collapse && navBar !== 'topmenu' ? 'collapse' : '')} onClick={this.changeToHome}><img src={this.state.logourl} alt=""/></div>
        <div className={'header-collapse ' + (collapse && navBar !== 'topmenu' ? 'collapse' : '')}>
          {navBar !== 'topmenu' ? (collapse ? <MenuUnfoldOutlined onClick={this.handleCollapse}/> : <MenuFoldOutlined onClick={this.handleCollapse}/>) : null}
        </div>
        {navBar !== 'topmenu' ? <div className={'header-collapse ' + (collapse ? 'collapse' : '')}>
          {collapse ? <MenuUnfoldOutlined onClick={this.handleCollapse}/> : <MenuFoldOutlined onClick={this.handleCollapse}/>}
        </div> : <div style={{width: '20px', height: '45px'}}></div>}
        {/* 正常菜单 */}
        {navBar !== 'topmenu' && menulist ?
          <ul className="header-menu">{
@@ -713,15 +714,9 @@
            })}
          </ul> : null
        }
        {/* 头像、用户名 */}
        <Dropdown className="header-setting" overlay={menu}>
          <div>
            <img src={this.state.avatar || avatar} alt=""/>
            <span>
              <span className="username"><span>{this.state.fullName}</span>{this.state.userName ? <span>{this.state.userName}</span> : null}</span> <DownOutlined />
            </span>
          </div>
        </Dropdown>
        {!menulist ?
          <div className="header-menu"></div> : null
        }
        {/* 菜单搜索 */}
        {thdMenuList.length > 0 ?
          <Dropdown overlayClassName="menu-select-dropdown" getPopupContainer={() => document.getElementById('main-header-container')} overlay={
@@ -758,6 +753,15 @@
            <SearchOutlined className="search-menu" />
          </Dropdown> : null
        }
        {/* 头像、用户名 */}
        <Dropdown className="header-setting" overlay={menu}>
          <div>
            <img src={this.state.avatar || avatar} alt=""/>
            <span>
              <span className="username"><span>{this.state.fullName}</span>{this.state.userName ? <span>{this.state.userName}</span> : null}</span> <DownOutlined />
            </span>
          </div>
        </Dropdown>
        {/* 修改密码 */}
        <Modal
          title={this.state.dict['main.password']}
@@ -797,10 +801,8 @@
  return {
    toggleCollapse: (collapse) => dispatch(toggleCollapse(collapse)),
    modifyMainMenu: (mainMenu) => dispatch(modifyMainMenu(mainMenu)),
    initActionPermission: (permAction) => dispatch(initActionPermission(permAction)),
    initMenuPermission: (permMenus) => dispatch(initMenuPermission(permMenus)),
    logout: () => dispatch(logout())
  }
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Form.create()(Header)))
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header))
src/components/header/index.scss
@@ -6,9 +6,9 @@
  font-weight: bold!important;
  width: 100%;
  height: 48px;
  display: flex;
  .header-logo {
    float: left;
    width: 180px;
    line-height: 48px;
    text-align: center;
@@ -28,7 +28,6 @@
  }
  .header-collapse {
    float: left;
    width: 35px;
    min-height: 48px;
    line-height: 48px;
@@ -48,13 +47,17 @@
    padding-left: 20px;
  }
  .header-menu {
    float: left;
    margin: 0;
    min-height: 20px;
    line-height: 48px;
    flex: 1;
    overflow-x: auto;
    overflow-y: hidden;
    white-space: nowrap;
    li {
      float: left;
      font-size: 1.3rem;
      cursor: pointer;
      display: inline-block;
      span {
        padding: 0 10px;
        height: 42px;
@@ -83,8 +86,22 @@
    }
  }
  .header-menu::-webkit-scrollbar {
    height: 5px;
  }
  .header-menu::-webkit-scrollbar-thumb {
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
    background: rgba(0, 0, 0, 0.13);
    border-radius: 5px;
  }
  .header-menu::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(0, 0, 0, 0);
    border-radius: 3px;
  }
  .header-setting {
    float: right;
    line-height: 48px;
    margin-right: 10px;
    img {
@@ -117,10 +134,10 @@
  }
  .search-menu {
    float: right;
    font-size: 18px;
    margin-top: 17px;
    margin-right: 20px;
    margin-left: 10px;
    cursor: pointer;
  }
  .menu-select-dropdown {
src/components/mkPicture/index.jsx
New file
@@ -0,0 +1,74 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import LostPng from '@/assets/img/lost.png'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class MkPicture extends Component {
  static propTpyes = {
    style: PropTypes.object,
    scale: PropTypes.bool,
    url: PropTypes.string,
    urls: PropTypes.array,
  }
  state = {
    url: '',
    lost: false
  }
  UNSAFE_componentWillMount() {
    const { url } = this.props
    if (url) {
      this.setState({url: url, lost: false})
      this.checkUrl(url)
    } else {
      this.setState({url: LostPng, lost: true})
    }
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (nextProps.url) {
      if (nextProps.url !== this.state.url) {
        this.setState({url: nextProps.url, lost: false})
        this.checkUrl(nextProps.url)
      }
    } else {
      this.setState({url: LostPng, lost: true})
    }
  }
  checkUrl = (url) => {
    let img = new Image()
    img.addEventListener('error', this.loadHandler)
    img.src = url
  }
  loadHandler = (e) => {
    this.setState({url: LostPng, lost: true})
  }
  render() {
    const { style, scale, urls } = this.props
    const { url, lost } = this.state
    return (
      <div
        className={'ant-mk-picture' + (scale ? ' scale' : '') + (lost ? ' lost' : '')}
        onClick={(e) => {
          if (!scale) return
          e.stopPropagation()
          MKEmitter.emit('mkImageScale', url, urls)
        }}
        style={{...style, backgroundImage: `url('${url}')`}}
      ></div>
    )
  }
}
export default MkPicture
src/components/mkPicture/index.scss
New file
@@ -0,0 +1,11 @@
.ant-mk-picture {
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
}
.ant-mk-picture.lost {
  background-size: contain!important;
}
.ant-mk-picture.scale {
  cursor: zoom-in;
}
src/components/tabview/index.jsx
@@ -7,7 +7,6 @@
import moment from 'moment'
import 'moment/locale/zh-cn'
import { initActionPermission } from '@/store/action'
import asyncComponent from '@/utils/asyncLoadComponent'
import NotFount from '@/components/404'
import options from '@/store/options.js'
@@ -101,7 +100,7 @@
              })
            }
  
            this.props.initActionPermission(_permAction)
            window.GLOB.mkActions = _permAction
          }
          resolve()
@@ -304,9 +303,7 @@
}
const mapDispatchToProps = (dispatch) => {
  return {
    initActionPermission: (permAction) => dispatch(initActionPermission(permAction))
  }
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(TabViews)
src/index.js
@@ -73,6 +73,7 @@
    GLOB.watermark = config.watermark + '' !== 'false'
    GLOB.transfer = config.transfer + '' === 'true'
    GLOB.keepKey = config.keepPassword + '' !== 'false'
    GLOB.nginx = config.nginx + '' === 'true'
    GLOB.WXAppID = config.WXAppID || ''
    GLOB.WXminiAppID = config.WXminiAppID || ''
    GLOB.accessToken = {}
@@ -243,6 +244,15 @@
      }
    }
    GLOB.memberLevel = _level
    GLOB.mkThdMenus = [] // 三级菜单
    GLOB.mkActions = {}  // 按钮权限集
    if (sessionStorage.getItem('breakpoint')) {
      window.debugger = true
      GLOB.breakpoint = sessionStorage.getItem('breakpoint')
    } else {
      GLOB.breakpoint = false
    }
    Object.defineProperty(GLOB, 'appId', {
      writable: false,
src/menu/components/card/balcony/index.jsx
@@ -2,11 +2,11 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Checkbox } from 'antd'
import { PlusOutlined, PlusSquareOutlined, EditOutlined, FontColorsOutlined, DeleteOutlined, SettingOutlined, ToolOutlined } from '@ant-design/icons'
import { PlusOutlined, PlusSquareOutlined, EditOutlined, FontColorsOutlined, DeleteOutlined, SettingOutlined, ToolOutlined, ClockCircleOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from './options'
@@ -85,12 +85,31 @@
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentDidMount () {
    MKEmitter.addListener('mkUpdateInter', this.mkUpdateInter)
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('mkUpdateInter', this.mkUpdateInter)
  }
  mkUpdateInter = (inter, split) => {
    const { card } = this.state
    if (card.wrap.datatype === 'public' && card.wrap.publicId === inter.uuid) {
      let _card = {...card, columns: fromJS(inter.columns).toJS()}
      split.delay = split.delay + 10
      setTimeout(() => {
        this.updateComponent(_card)
      }, split.delay)
    }
  }
@@ -100,7 +119,6 @@
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
@@ -114,39 +132,35 @@
    card.errors = []
    if (card.wrap.datatype === 'static') {
      // let supModule = card.wrap.linkType === 'static' ? '' : 'has'
      card.elements.forEach(cell => {
        if (cell.eleType === 'button') {
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            // } else if (!supModule) {
            //   cell.modal.fields.forEach(m => {
            //     if (m.type === 'linkMain') {
            //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
            //     }
            //   })
            }
          }
        } else if (cell.datatype === 'dynamic' && cell.field) {
          card.errors.push({ level: 1, detail: `卡片中动态字段“${cell.field}”无效`})
        }
      })
      card.$tables = getTables(card)
    } else {
      // let supModule = card.wrap.linkType === 'static' ? '' : 'has'
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!columns.includes(card.setting.primaryKey)) {
        card.errors.push({ level: 0, detail: '主键已失效!'})
      if (card.wrap.datatype === 'dynamic') {
        if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
          card.errors.push({ level: 0, detail: '未设置数据源!'})
        } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
          card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
        } else if (!card.setting.primaryKey) {
          card.errors.push({ level: 0, detail: '未设置主键!'})
        } else if (!columns.includes(card.setting.primaryKey)) {
          card.errors.push({ level: 0, detail: '主键已失效!'})
        }
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
      card.elements.forEach(cell => {
@@ -154,14 +168,6 @@
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            // } else {
            //   cell.modal.fields.forEach(m => {
            //     if (m.type === 'linkMain' && !supModule) {
            //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
            //     } else if (m.field && card.wrap.linkType !== 'sync' && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
            //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
            //     }
            //   })
            }
          }
        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
@@ -249,7 +255,20 @@
  updateWrap = (res) => {
    delete res.quick
    this.updateComponent({...this.state.card, wrap: res})
    let _card = {...this.state.card, wrap: res}
    if (res.datatype === 'public') {
      let interfaces = window.GLOB.customMenu.interfaces || []
      let d = interfaces.filter(m => m.uuid === res.publicId && m.status === 'true')[0]
      if (d) {
        _card.columns = fromJS(d.columns).toJS()
      }
    }
    this.updateComponent(_card)
  }
  render() {
@@ -269,11 +288,10 @@
            <CopyComponent type="balcony" card={card}/>
            <PasteComponent options={['action', 'customCardElement']} updateConfig={this.pasteComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle} />
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
            {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
            {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
          </div>
        } trigger="hover">
          <ToolOutlined />
src/menu/components/card/balcony/options.jsx
@@ -6,10 +6,24 @@
 * @description Wrap表单配置信息
 */
export default function (wrap) {
  let modules = MenuUtils.getLinkModules(fromJS(window.GLOB.customMenu).toJS().components) || []
  let supmodules = MenuUtils.getSupModules(fromJS(window.GLOB.customMenu).toJS().components, '') || []
  let menu = fromJS(window.GLOB.customMenu).toJS()
  let modules = MenuUtils.getLinkModules(menu.components) || []
  let supmodules = MenuUtils.getSupModules(menu.components, '') || []
  let roleList = sessionStorage.getItem('sysRoles')
  let appType = sessionStorage.getItem('appType')
  let interfaces = []
  if (menu.interfaces) {
    menu.interfaces.forEach(item => {
      if (item.status === 'true') {
        interfaces.push({
          value: item.uuid,
          label: item.name
        })
      }
    })
  }
  if (roleList) {
    try {
@@ -51,12 +65,22 @@
      options: [
        {value: 'dynamic', label: '动态'},
        {value: 'static', label: '静态'},
        {value: 'public', label: '公共数据源'},
      ],
      controlFields: [
        {field: 'empty', values: ['dynamic']}
        {field: 'empty', values: ['dynamic']},
        {field: 'publicId', values: ['public']},
      ]
    },
    {
      type: 'select',
      field: 'publicId',
      label: '数据源',
      initval: wrap.publicId || '',
      required: true,
      options: interfaces
    },
    {
      type: 'radio',
      field: 'linkType',
      label: '受控类型',
src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -114,7 +114,6 @@
    background-size: cover;
    background-position: center center;
    background-repeat: no-repeat;
    background-color: #f5f5f5;
  }
  .ant-mk-icon {
    vertical-align: top;
src/menu/components/card/cardcellcomponent/index.jsx
@@ -297,17 +297,6 @@
      <p style={{marginBottom: '5px'}}>{this.state.dict['model.tooltip.func.innerface'].replace('@ableField', ableField)}</p>
    </div>
    let menulist = sessionStorage.getItem('fstMenuList')
    if (menulist) {
      try {
        menulist = JSON.parse(menulist)
      } catch (e) {
        menulist = []
      }
    } else {
      menulist = []
    }
    let supId = ''
    if (cards.setting && cards.setting.supModule) {
      let pid = cards.setting.supModule[cards.setting.supModule.length - 1]
@@ -324,7 +313,7 @@
    this.setState({
      actvisible: true,
      card: card,
      formlist: getActionForm(card, functip, cards, usefulFields, menulist, modules, anchors)
      formlist: getActionForm(card, functip, cards, usefulFields, modules, anchors)
    })
  }
@@ -487,8 +476,6 @@
        if (card.OpenType === 'popview' || card.verify || card.modal) {
          card.$parentId = cardCell.uuid
          card.$side = side || ''
          // MKEmitter.emit('logButton', cards.uuid, card)
        }
        _this.setState({
src/menu/components/card/cardcellcomponent/index.scss
@@ -3,6 +3,9 @@
  .ant-btn {
    padding: 0;
  }
  .card-detail-row {
    min-height: 16px;
  }
  .card-button-cell {
    float: left;
src/menu/components/card/data-card/index.jsx
@@ -6,7 +6,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from './options'
@@ -16,7 +16,6 @@
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CardComponent = asyncComponent(() => import('../cardcomponent'))
const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
@@ -64,7 +63,6 @@
        scripts: [],
        action: [],
        search: [],
        btnlog: [],
        subcards: [{
          uuid: Utils.getuuid(),
          setting: { width: appType === 'mob' ? 24 : 6, type: 'simple'},
@@ -147,7 +145,6 @@
  componentDidMount () {
    MKEmitter.addListener('submitModal', this.handleSave)
    // MKEmitter.addListener('logButton', this.logButton)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -162,20 +159,8 @@
      return
    }
    MKEmitter.removeListener('submitModal', this.handleSave)
    // MKEmitter.removeListener('logButton', this.logButton)
  }
  // logButton = (id, item) => {
  //   const { card } = this.state
  //   if (id !== card.uuid) return
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
  //   this.updateComponent({...card, btnlog})
  // }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
@@ -184,7 +169,6 @@
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
@@ -197,7 +181,6 @@
    card.errors = []
    let columns = card.columns.map(c => c.field)
    // let lowcols = card.columns.map(c => c.field.toLowerCase())
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -210,31 +193,15 @@
    } else if (card.wrap.supType !== 'multi' && !card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    // let supModule = ''
    // if (card.wrap.supType === 'multi') { // 数据卡多上级组件
    //   if (card.supNodes && card.supNodes[0]) {
    //     supModule = card.supNodes[0].componentId
    //   }
    // } else if (card.setting.supModule) {
    //   supModule = card.setting.supModule[card.setting.supModule.length - 1] || ''
    //   if (supModule === 'empty') {
    //     supModule = ''
    //   }
    // }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    card.action.forEach(cell => {
      if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
        if (!cell.modal || cell.modal.fields.length === 0) {
          card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
        // } else {
        //   cell.modal.fields.forEach(m => {
        //     if (m.type === 'linkMain' && !supModule) {
        //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
        //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
        //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
        //     }
        //   })
        }
      }
      // $check@有效性检测
@@ -256,14 +223,6 @@
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            // } else {
            //   cell.modal.fields.forEach(m => {
            //     if (m.type === 'linkMain' && !supModule) {
            //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
            //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
            //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
            //     }
            //   })
            }
          }
          if (linkbtn && linkbtn === cell.uuid) {
@@ -280,14 +239,6 @@
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              // } else {
              //   cell.modal.fields.forEach(m => {
              //     if (m.type === 'linkMain' && !supModule) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
              //     }
              //   })
              }
            }
            if (linkbtn && linkbtn === cell.uuid) {
@@ -341,10 +292,6 @@
      content: '确定删除卡片吗?',
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.updateComponent(card)
@@ -478,47 +425,6 @@
    this.updateComponent(card)
  }
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.subcards.forEach(col => {
  //         if (item.$parentId === col.uuid) {
  //           if (item.$side !== 'back') {
  //             col.elements = col.elements ? [...col.elements, item] : [item]
  //           } else {
  //             col.backElements = col.backElements ? [...col.backElements, item] : [item]
  //           }
  //           done = true
  //         }
  //       })
  //     }
  //     if (!done) {
  //       card.action = card.action ? [...card.action, item] : [item]
  //     }
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  addCard = (copy) => {
    let card = fromJS(this.state.card).toJS()
@@ -779,7 +685,6 @@
            <CopyComponent type="datacard" card={card}/>
            <PasteComponent options={['action', 'search', 'form', 'cardcell']} updateConfig={this.pasteComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
src/menu/components/card/data-card/options.jsx
@@ -9,6 +9,17 @@
  let MenuType = ''
  let menu = fromJS(window.GLOB.customMenu).toJS()
  let laypage = setting && setting.laypage !== 'false'
  let interfaces = []
  if (subtype === 'propcard' && menu.interfaces) {
    menu.interfaces.forEach(item => {
      if (item.status === 'true') {
        interfaces.push({
          value: item.uuid,
          label: item.name
        })
      }
    })
  }
  if (menu.parentId === 'BillPrintTemp') {
    MenuType = 'billPrint'
@@ -82,14 +93,25 @@
      options: [
        {value: 'dynamic', label: '动态', priKeyType: 'static'},
        {value: 'static', label: '静态', priKeyType: 'static'},
        {value: 'public', label: '公共数据源', priKeyType: 'static'},
      ],
      linkFields: ['priKeyType'],
      controlFields: [
        {field: 'goback', values: ['dynamic']},
        {field: 'empty', values: ['dynamic']},
        {field: 'empty', values: ['dynamic', 'public']},
        {field: 'jump', values: ['dynamic']},
        {field: 'supModule', values: ['static']},
        {field: 'publicId', values: ['public']},
      ],
      forbid: subtype !== 'propcard'
    },
    {
      type: 'select',
      field: 'publicId',
      label: '数据源',
      initval: wrap.publicId || '',
      required: true,
      options: interfaces,
      forbid: subtype !== 'propcard'
    },
    {
@@ -160,6 +182,9 @@
        {ParentID: 'dynamic', value: 'static', label: '静态值'},
        {ParentID: 'dynamic', value: 'dynamic', label: '动态值'},
        {ParentID: 'dynamic', value: 'joint', label: '拼接值'},
        {ParentID: 'public', value: 'static', label: '静态值'},
        {ParentID: 'public', value: 'dynamic', label: '动态值'},
        {ParentID: 'public', value: 'joint', label: '拼接值'},
      ],
      forbid: subtype !== 'propcard'
    },
src/menu/components/card/prop-card/index.jsx
@@ -2,11 +2,11 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Modal } from 'antd'
import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, ClockCircleOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from '../data-card/options'
@@ -17,7 +17,6 @@
const CardComponent = asyncComponent(() => import('../cardcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
@@ -72,7 +71,6 @@
          elements: [],
          backElements: []
        }],
        btnlog: [],
      }
      if (card.config) {
@@ -109,7 +107,7 @@
  }
  componentDidMount () {
    // MKEmitter.addListener('logButton', this.logButton)
    MKEmitter.addListener('mkUpdateInter', this.mkUpdateInter)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
@@ -124,7 +122,7 @@
    this.setState = () => {
      return
    }
    // MKEmitter.removeListener('logButton', this.logButton)
    MKEmitter.removeListener('mkUpdateInter', this.mkUpdateInter)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
@@ -145,17 +143,19 @@
    })
  }
  // 按钮历史记录
  // logButton = (id, item) => {
  //   const { card } = this.state
  mkUpdateInter = (inter, split) => {
    const { card } = this.state
    if (card.wrap.datatype === 'public' && card.wrap.publicId === inter.uuid) {
      let _card = {...card, columns: fromJS(inter.columns).toJS()}
  //   if (id !== card.uuid) return
      split.delay = split.delay + 10
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
  //   this.updateComponent({...card, btnlog})
  // }
      setTimeout(() => {
        this.updateComponent(_card)
      }, split.delay)
    }
  }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
@@ -165,7 +165,6 @@
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
@@ -183,7 +182,8 @@
    }
    if (card.wrap.datatype === 'static') {
      // let supModule = card.wrap.supModule ? card.wrap.supModule[card.wrap.supModule.length - 1] : ''
      card.$tables = getTables(card)
      card.subcards.forEach((item, i) => {
        let linkbtn = item.setting.linkbtn || ''
@@ -192,12 +192,6 @@
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              // } else if (!supModule) {
              //   cell.modal.fields.forEach(m => {
              //     if (m.type === 'linkMain') {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              //     }
              //   })
              }
            }
            if (linkbtn && linkbtn === cell.uuid) {
@@ -214,12 +208,6 @@
              if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
                if (!cell.modal || cell.modal.fields.length === 0) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
                // } else if (!supModule) {
                //   cell.modal.fields.forEach(m => {
                //     if (m.type === 'linkMain') {
                //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                //     }
                //   })
                }
              }
              if (linkbtn && linkbtn === cell.uuid) {
@@ -236,23 +224,24 @@
        }
      })
    } else {
      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      // if (supModule === 'empty') {
      //   supModule = ''
      // }
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
        card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
      } else if (!card.setting.primaryKey) {
        card.errors.push({ level: 0, detail: '未设置主键!'})
      } else if (!columns.includes(card.setting.primaryKey)) {
        card.errors.push({ level: 0, detail: '主键已失效!'})
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      if (card.wrap.datatype === 'dynamic') {
        if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
          card.errors.push({ level: 0, detail: '未设置数据源!'})
        } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
          card.errors.push({ level: 0, detail: '数据源中无可用脚本!'})
        } else if (!card.setting.primaryKey) {
          card.errors.push({ level: 0, detail: '未设置主键!'})
        } else if (!columns.includes(card.setting.primaryKey)) {
          card.errors.push({ level: 0, detail: '主键已失效!'})
        } else if (!card.setting.supModule) {
          card.errors.push({ level: 0, detail: '未设置上级组件!'})
        }
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
      card.subcards.forEach((item, i) => {
@@ -262,14 +251,6 @@
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              // } else {
              //   cell.modal.fields.forEach(m => {
              //     if (m.type === 'linkMain' && !supModule) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
              //     }
              //   })
              }
            }
            if (linkbtn && linkbtn === cell.uuid) {
@@ -286,14 +267,6 @@
              if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
                if (!cell.modal || cell.modal.fields.length === 0) {
                  card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
                // } else {
                //   cell.modal.fields.forEach(m => {
                //     if (m.type === 'linkMain' && !supModule) {
                //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
                //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
                //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
                //     }
                //   })
                }
              }
              if (linkbtn && linkbtn === cell.uuid) {
@@ -344,10 +317,6 @@
      content: '确定删除卡片吗?',
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.updateComponent(card)
@@ -424,53 +393,6 @@
    this.updateComponent(card)
  }
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.subcards.forEach(col => {
  //         if (item.$parentId === col.uuid) {
  //           if (item.$side !== 'back') {
  //             col.elements = col.elements ? [...col.elements, item] : [item]
  //           } else {
  //             col.backElements = col.backElements ? [...col.backElements, item] : [item]
  //           }
  //           done = true
  //         }
  //       })
  //     }
  //     card.btnlog = logs
  //     this.setState({ card: {...card, subcards: []} }, () => {
  //       this.updateComponent(card)
  //     })
  //     if (!done) {
  //       notification.warning({
  //         top: 92,
  //         message: '附属卡片已删除!',
  //         duration: 2
  //       })
  //     } else {
  //       notification.success({
  //         top: 92,
  //         message: '恢复成功!',
  //         duration: 2
  //       })
  //     }
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  move = (item, direction) => {
    let card = fromJS(this.state.card).toJS()
@@ -580,7 +502,16 @@
      } else {
        _card.setting.supModule = ''
      }
    } else if (res.datatype === 'public') {
      let interfaces = window.GLOB.customMenu.interfaces || []
      let d = interfaces.filter(m => m.uuid === res.publicId && m.status === 'true')[0]
      if (d) {
        _card.columns = fromJS(d.columns).toJS()
      }
    }
    if (res.layout === 'flex') {
      _card.wrap.pagestyle = 'page'
    }
@@ -631,12 +562,10 @@
            <CopyComponent type="propcard" card={card}/>
            <PasteComponent options={['cardcell']} updateConfig={this.pasteComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
            {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
            {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
          </div>
        } trigger="hover">
          <ToolOutlined />
src/menu/components/card/table-card/index.jsx
@@ -6,7 +6,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from '../data-card/options'
@@ -18,7 +18,6 @@
const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
@@ -71,7 +70,6 @@
          elements: []
        }],
        action: [],
        btnlog: [],
      }
      
      if (card.config) {
@@ -150,24 +148,12 @@
    }
  }
  // logButton = (id, item) => {
  //   const { card } = this.state
  //   if (id !== card.uuid) return
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
  //   this.updateComponent({...card, btnlog})
  // }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
@@ -203,6 +189,10 @@
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    card.subcards.forEach((item, i) => {
      let linkbtn = item.setting.linkbtn || ''
      item.elements.forEach(cell => {
@@ -210,14 +200,6 @@
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            // } else {
            //   cell.modal.fields.forEach(m => {
            //     if (m.type === 'linkMain' && !supModule) {
            //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
            //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
            //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
            //     }
            //   })
            }
          }
          if (linkbtn && linkbtn === cell.uuid) {
@@ -266,10 +248,6 @@
      content: '确定删除卡片吗?',
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.updateComponent(card)
@@ -358,51 +336,6 @@
    // 注册事件-添加搜索
    MKEmitter.emit('addSearch', card.uuid, newcard)
  }
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.subcards.forEach(col => {
  //         if (item.$parentId === col.uuid) {
  //           if (item.$side !== 'back') {
  //             col.elements = col.elements ? [...col.elements, item] : [item]
  //           } else {
  //             col.backElements = col.backElements ? [...col.backElements, item] : [item]
  //           }
  //           done = true
  //         }
  //       })
  //     }
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     if (!done) {
  //       notification.warning({
  //         top: 92,
  //         message: '附属卡片已删除!',
  //         duration: 2
  //       })
  //     } else {
  //       notification.success({
  //         top: 92,
  //         message: '恢复成功!',
  //         duration: 2
  //       })
  //     }
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  move = (item, direction) => {
    let card = fromJS(this.state.card).toJS()
@@ -589,7 +522,6 @@
            <CopyComponent type="tablecard" card={card}/>
            <PasteComponent options={['cardcell', 'search', 'form']} updateConfig={this.pasteComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
src/menu/components/carousel/data-card/index.jsx
@@ -6,7 +6,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from './options'
@@ -15,7 +15,6 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CardSimpleComponent = asyncComponent(() => import('@/menu/components/card/cardsimplecomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
@@ -56,7 +55,6 @@
        style: { borderWidth: '1px', borderColor: '#e8e8e8', marginTop: '8px', marginBottom: '8px', height: '300px' },
        columns: [],
        scripts: [],
        btnlog: [],
        subcards: [{
          uuid: Utils.getuuid(),
          setting: {},
@@ -109,24 +107,12 @@
    }
  }
  // logButton = (id, item) => {
  //   const { card } = this.state
  //   if (id !== card.uuid) return
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
  //   this.updateComponent({...card, btnlog})
  // }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
@@ -139,13 +125,7 @@
    card.errors = []
    // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
    // if (supModule === 'empty') {
    //   supModule = ''
    // }
    let columns = card.columns.map(c => c.field)
    // let lowcols = card.columns.map(c => c.field.toLowerCase())
    if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
      card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -159,20 +139,16 @@
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    card.subcards.forEach((item, i) => {
      item.elements.forEach(cell => {
        if (cell.eleType === 'button') {
          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
            if (!cell.modal || cell.modal.fields.length === 0) {
              card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
            // } else {
            //   cell.modal.fields.forEach(m => {
            //     if (m.type === 'linkMain' && !supModule) {
            //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
            //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
            //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
            //     }
            //   })
            }
          }
        } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
@@ -215,10 +191,6 @@
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.updateComponent(card)
        if (appType === 'mob') return
@@ -251,36 +223,6 @@
    this.updateComponent(_card)
  }
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
  //   if (type === 'revert') {
  //     card.subcards.forEach(col => {
  //       col.elements = [...col.elements, item]
  //       if (item.$parentId === col.uuid) {
  //         col.elements = [...col.elements, item]
  //       }
  //     })
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  getWrapForms = () => {
    const { card } = this.state
@@ -311,7 +253,6 @@
            </NormalForm>
            <CopyComponent type="datacard" card={card}/>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog}/> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)}/>
src/menu/components/carousel/prop-card/index.jsx
@@ -2,11 +2,11 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover, Modal, Carousel } from 'antd'
import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, ClockCircleOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from '../data-card/options'
@@ -17,7 +17,6 @@
const CardSimpleComponent = asyncComponent(() => import('@/menu/components/card/cardsimplecomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
@@ -62,8 +61,7 @@
          setting: {},
          style: {},
          elements: [],
        }],
        btnlog: [],
        }]
      }
      if (card.config) {
@@ -96,7 +94,6 @@
  }
  componentDidMount () {
    // MKEmitter.addListener('logButton', this.logButton)
    MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
  }
@@ -111,7 +108,6 @@
    this.setState = () => {
      return
    }
    // MKEmitter.removeListener('logButton', this.logButton)
    MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
  }
@@ -132,24 +128,12 @@
    })
  }
  // logButton = (id, item) => {
  //   const { card } = this.state
  //   if (id !== card.uuid) return
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
  //   this.updateComponent({...card, btnlog})
  // }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    card.btnlog = []
    if (window.GLOB.styling && card.errors) { // 样式修改时不做筛查
      this.setState({
@@ -167,18 +151,13 @@
    }
    if (card.wrap.datatype === 'static') {
      card.$tables = getTables(card)
      card.subcards.forEach(item => {
        item.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              // } else {
              //   cell.modal.fields.forEach(m => {
              //     if (m.type === 'linkMain') {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              //     }
              //   })
              }
            }
          } else if (cell.datatype === 'dynamic' && cell.field) {
@@ -187,12 +166,7 @@
        })
      })
    } else {
      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      // if (supModule === 'empty') {
      //   supModule = ''
      // }
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -206,20 +180,16 @@
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
      card.subcards.forEach((item, i) => {
        item.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              // } else {
              //   cell.modal.fields.forEach(m => {
              //     if (m.type === 'linkMain' && !supModule) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
              //     }
              //   })
              }
            }
          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
@@ -262,10 +232,6 @@
      content: '确定删除卡片吗?',
      onOk() {
        card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
        // if (card.btnlog) {
        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
        // }
        _this.updateComponent(card)
@@ -323,49 +289,6 @@
    this.updateComponent(card)
  }
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.subcards.forEach(col => {
  //         if (item.$parentId === col.uuid) {
  //           col.elements = [...col.elements, item]
  //           done = true
  //         }
  //       })
  //     }
  //     card.btnlog = logs
  //     this.setState({ card: {...card, subcards: []} }, () => {
  //       this.updateComponent(card)
  //     })
  //     if (!done) {
  //       notification.warning({
  //         top: 92,
  //         message: '附属卡片已删除!',
  //         duration: 2
  //       })
  //     } else {
  //       notification.success({
  //         top: 92,
  //         message: '恢复成功!',
  //         duration: 2
  //       })
  //     }
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  move = (item, direction) => {
    let card = fromJS(this.state.card).toJS()
@@ -419,12 +342,11 @@
            <CopyComponent type="propcard" card={card}/>
            <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
            {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
            {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
          </div>
        } trigger="hover">
          <ToolOutlined/>
src/menu/components/chart/antv-bar/index.jsx
@@ -9,7 +9,7 @@
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import Utils from '@/utils/utils.js'
import { chartColors } from '@/utils/option.js'
import zhCN from '@/locales/zh-CN/model.js'
@@ -18,7 +18,6 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
@@ -91,7 +90,6 @@
        search: [],
        action: [],
        plot: _plot,
        btnlog: [],
      }
      if (card.config) {
@@ -1228,7 +1226,6 @@
    card.width = card.plot.width
    card.name = card.plot.name
    card.btnlog = []
    card.errors = []
    let columns = card.columns.map(c => c.field)
@@ -1243,6 +1240,10 @@
      card.errors.push({ level: 0, detail: '主键已失效!'})
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    
    if (!card.plot.Xaxis) {
@@ -1345,30 +1346,6 @@
    this.updateComponent(_card)
  }
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
  //   if (type === 'revert') {
  //     card.action = card.action ? [...card.action, item] : [item]
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
@@ -1390,7 +1367,6 @@
            <CopyComponent type="line" card={card}/>
            <PasteComponent config={card} options={['action', 'search']} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
src/menu/components/chart/antv-dashboard/index.jsx
@@ -8,7 +8,7 @@
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import './index.scss'
@@ -494,6 +494,10 @@
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    
    if (!card.plot.valueField) {
      card.errors.push({ level: 0, detail: '显示值尚未设置!'})
src/menu/components/chart/antv-pie/index.jsx
@@ -9,7 +9,7 @@
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
@@ -83,7 +83,6 @@
        search: [],
        action: [],
        plot: _plot,
        btnlog: [],
      }
      if (card.config) {
@@ -628,6 +627,10 @@
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    
    if (!card.plot.Xaxis) {
      card.errors.push({ level: 0, detail: '名称字段尚未设置!'})
src/menu/components/chart/antv-scatter/index.jsx
@@ -8,7 +8,7 @@
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
@@ -16,7 +16,6 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
@@ -78,7 +77,6 @@
        search: [],
        action: [],
        plot: _plot,
        btnlog: [],
      }
      if (card.config) {
@@ -276,6 +274,10 @@
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    
    if (!card.plot.Xaxis) {
      card.errors.push({ level: 0, detail: '坐标轴尚未设置!'})
@@ -363,30 +365,6 @@
    this.updateComponent(_card)
  }
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
  //   if (type === 'revert') {
  //     card.action = card.action ? [...card.action, item] : [item]
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  clickComponent = (e) => {
    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
      e.stopPropagation()
@@ -408,7 +386,6 @@
            <CopyComponent type="line" card={card}/>
            <PasteComponent config={card} options={['action', 'search']} updateConfig={this.updateComponent}/>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog}/> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)}/>
src/menu/components/chart/chart-custom/chartcompile/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Modal, Form, Tabs } from 'antd'
import { Modal, Tabs } from 'antd'
import { EditOutlined } from '@ant-design/icons'
import { getBaseForm } from './formconfig'
@@ -118,4 +118,4 @@
  }
}
export default Form.create()(CustomChartDrawerForm)
export default CustomChartDrawerForm
src/menu/components/chart/chart-custom/index.jsx
@@ -10,7 +10,7 @@
import MKEmitter from '@/utils/events.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
@@ -70,7 +70,6 @@
        search: [],
        action: [],
        plot: _plot,
        btnlog: [],
      }
      if (card.config) {
@@ -205,6 +204,10 @@
    } else if (!card.setting.supModule) {
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    
    this.setState({
      card: card
src/menu/components/editor/braft-editor/index.jsx
@@ -6,6 +6,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { getTables } from '@/utils/utils-custom.js'
import getWrapForm from './options'
import MKEmitter from '@/utils/events.js'
@@ -114,6 +115,10 @@
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
    }
    this.setState({
src/menu/components/form/dragtitle/card.jsx
@@ -11,7 +11,7 @@
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const Card = ({ id, card, active, moveCard, findCard, closeCard, selectCard, updateGroup }) => {
const Card = ({ id, card, sort, active, moveCard, findCard, closeCard, selectCard, updateGroup }) => {
  const originalIndex = findCard(id).index
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'form', id, originalIndex },
@@ -80,7 +80,7 @@
    } trigger="hover">
      <div className={'page-card ' + (active ? 'active' : '')} onClick={select} style={{ opacity: opacity}}>
        <div ref={node => drag(drop(node))}>
          <span className="form-sort">{card.sort}</span>
          <span className="form-sort">{sort}</span>
          {card.setting.title}
        </div>
      </div>
src/menu/components/form/dragtitle/index.jsx
@@ -40,10 +40,11 @@
  return (
    <div className={'normal-form-titles ' + (tabtype || '') } >
      {cards.map(card => (
      {cards.map((card, i) => (
        <Card
          id={card.uuid}
          key={card.uuid}
          sort={i + 1}
          active={card.uuid === selectId}
          card={card}
          moveCard={moveCard}
src/menu/components/form/simple-form/index.jsx
@@ -9,7 +9,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { getModalForm } from '@/templates/zshare/formconfig'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from './options'
@@ -160,7 +160,6 @@
        supModule = ''
      }
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -174,22 +173,26 @@
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
      card.subcards.forEach(item => {
        item.fields.forEach(m => {
          if (m.type === 'linkMain' && !supModule) {
            card.errors.push({ level: 1, detail: `关联主表表单“${m.label}”无效`})
          // } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
          //   card.errors.push({ level: 1, detail: `表单“${m.label}”大小写与字段集不一致`})
            card.errors.push({ level: 1, detail: `请检查关联主表“${m.label}”是否有效`})
          }
        })
      })
    } else {
      let supModule = card.wrap.supModule ? card.wrap.supModule[card.wrap.supModule.length - 1] : ''
      card.$tables = getTables(card)
      card.subcards.forEach(item => {
        item.fields.forEach(m => {
          if (m.type === 'linkMain' && !supModule) {
            card.errors.push({ level: 1, detail: `关联主表表单“${m.label}”无效`})
            card.errors.push({ level: 1, detail: `请检查关联主表“${m.label}”是否有效`})
          }
        })
      })
src/menu/components/form/step-form/index.jsx
@@ -9,7 +9,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { getModalForm } from '@/templates/zshare/formconfig'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from './options'
@@ -167,7 +167,6 @@
        supModule = ''
      }
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -181,22 +180,26 @@
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
      card.subcards.forEach(item => {
        item.fields.forEach(m => {
          if (m.type === 'linkMain' && !supModule) {
            card.errors.push({ level: 1, detail: `分组“${item.setting.title}”中关联主表表单“${m.label}”无效`})
          // } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
          //   card.errors.push({ level: 1, detail: `分组“${item.setting.title}”中表单“${m.label}”大小写与字段集不一致`})
            card.errors.push({ level: 1, detail: `请检查分组“${item.setting.title}”中关联主表“${m.label}”是否有效`})
          }
        })
      })
    } else {
      let supModule = card.wrap.supModule ? card.wrap.supModule[card.wrap.supModule.length - 1] : ''
      card.$tables = getTables(card)
      card.subcards.forEach(item => {
        item.fields.forEach(m => {
          if (m.type === 'linkMain' && !supModule) {
            card.errors.push({ level: 1, detail: `分组“${item.setting.title}”中关联主表表单“${m.label}”无效`})
            card.errors.push({ level: 1, detail: `请检查分组“${item.setting.title}”中关联主表“${m.label}”是否有效`})
          }
        })
      })
src/menu/components/form/tab-form/index.jsx
@@ -9,7 +9,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { getModalForm } from '@/templates/zshare/formconfig'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from '../step-form/options'
@@ -179,7 +179,6 @@
        supModule = ''
      }
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -193,22 +192,26 @@
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
      card.subcards.forEach(item => {
        item.fields.forEach(m => {
          if (m.type === 'linkMain' && !supModule) {
            card.errors.push({ level: 1, detail: `分组“${item.setting.title}”中关联主表表单“${m.label}”无效`})
          // } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
          //   card.errors.push({ level: 1, detail: `分组“${item.setting.title}”中表单“${m.label}”大小写与字段集不一致`})
            card.errors.push({ level: 1, detail: `请检查分组“${item.setting.title}”中关联主表“${m.label}”是否有效`})
          }
        })
      })
    } else {
      let supModule = card.wrap.supModule ? card.wrap.supModule[card.wrap.supModule.length - 1] : ''
      card.$tables = getTables(card)
      card.subcards.forEach(item => {
        item.fields.forEach(m => {
          if (m.type === 'linkMain' && !supModule) {
            card.errors.push({ level: 1, detail: `分组“${item.setting.title}”中关联主表表单“${m.label}”无效`})
            card.errors.push({ level: 1, detail: `请检查分组“${item.setting.title}”中关联主表“${m.label}”是否有效`})
          }
        })
      })
src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -734,6 +734,11 @@
            { pattern: _patten, message: formRule.func.innerMessage },
            { max: formRule.func.max, message: formRule.func.maxMessage }
          )
        } else if (item.key === 'sql' || item.key === 'sheet') {
          rules.push(
            { pattern: /^[a-zA-Z_]+$/, message: '表名只可使用字母以及_' },
            { max: formRule.func.max, message: formRule.func.maxMessage }
          )
        } else if (item.key === 'outerFunc' || item.key === 'callbackFunc') {
          rules.push(
            { pattern: formRule.func.pattern, message: formRule.func.message },
src/menu/components/share/actioncomponent/dragaction/index.jsx
@@ -119,6 +119,7 @@
          newcard.Ot = 'requiredSgl'
          newcard.OpenType = item.value
          newcard.class = 'primary'
          newcard.style = { marginRight: '15px' }
          if (newcard.OpenType === 'excelIn') {
            newcard.label = item.text
src/menu/components/share/actioncomponent/formconfig.jsx
@@ -12,7 +12,7 @@
 * @param {*} usefulFields   存储过程可用的开始字段
 * @param {*} type           按钮类型,用于区分可选的打开方式
 */
export function getActionForm (card, functip, config, usefulFields, menulist = [], modules = [], anchors = []) {
export function getActionForm (card, functip, config, usefulFields, modules = [], anchors = []) {
  let appType = sessionStorage.getItem('appType')
  let viewType = sessionStorage.getItem('editMenuType') // 弹窗 popview
  let printTemps = sessionStorage.getItem('printTemps')
@@ -20,6 +20,7 @@
  let setting = config.setting || {}
  let columns = config.columns || []
  let appMenus = []
  let menulist = []
  let type = ''
  if (card.eleType === 'button') {
@@ -115,6 +116,17 @@
    } else {
      appMenus = []
    }
  } else {
    menulist = sessionStorage.getItem('fstMenuList')
    if (menulist) {
      try {
        menulist = JSON.parse(menulist)
      } catch (e) {
        menulist = []
      }
    } else {
      menulist = []
    }
  }
  if (appType === 'mob') {
    opentypes = opentypes.filter(item => ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton'].includes(item.value))
src/menu/components/share/actioncomponent/index.jsx
@@ -171,17 +171,6 @@
      functip = ''
    }
    let menulist = sessionStorage.getItem('fstMenuList')
    if (menulist) {
      try {
        menulist = JSON.parse(menulist)
      } catch (e) {
        menulist = []
      }
    } else {
      menulist = []
    }
    let supId = ''
    if (config.setting && config.setting.supModule) {
      let pid = config.setting.supModule[config.setting.supModule.length - 1]
@@ -198,7 +187,7 @@
    this.setState({
      visible: true,
      card: card,
      formlist: getActionForm(card, functip, config, usefulFields, menulist, modules, anchors)
      formlist: getActionForm(card, functip, config, usefulFields, modules, anchors)
    })
  }
@@ -293,15 +282,10 @@
        _actionlist = _actionlist.filter(item => item.uuid !== card.uuid)
        let btnlog = config.btnlog || []
        if (card.OpenType === 'popview' || card.verify || card.modal) {
          btnlog.push(card)
        }
        _this.setState({
          actionlist: _actionlist
        }, () => {
          _this.props.updateaction({...config, action: _actionlist, btnlog})
          _this.props.updateaction({...config, action: _actionlist})
        })
        if (card.origin || appType === 'mob') return
src/menu/components/share/logcomponent/index.jsx
File was deleted
src/menu/components/share/logcomponent/index.scss
File was deleted
src/menu/components/share/sourcecomponent/inputform/index.jsx
@@ -18,9 +18,7 @@
class PopSource extends Component {
  static propTpyes = {
    btnlog: PropTypes.array,
    keyword: PropTypes.string,
    handlelog: PropTypes.func
    keyword: PropTypes.string
  }
  state = {
src/menu/components/share/usercomponent/index.jsx
@@ -16,7 +16,7 @@
class UserComponent extends Component {
  static propTpyes = {
    btnlog: PropTypes.array
    config: PropTypes.object
  }
  state = {
src/menu/components/table/base-table/index.jsx
@@ -71,7 +71,6 @@
          { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label3', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
        ],
        scripts: [],
        btnlog: [],
        isNew: true
      }
@@ -193,14 +192,9 @@
    if (!window.GLOB.styling || !card.errors) { // 样式修改时不做筛查
      card.errors = []
      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      // if (supModule === 'empty') {
      //   supModule = ''
      // }
      let doubleClick = card.wrap.doubleClick || ''
  
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
  
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -218,14 +212,6 @@
        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
          if (!cell.modal || cell.modal.fields.length === 0) {
            card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
          // } else {
          //   cell.modal.fields.forEach(m => {
          //     if (m.type === 'linkMain' && !supModule) {
          //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
          //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
          //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
          //     }
          //   })
          }
        }
        if (doubleClick === cell.uuid) {
@@ -239,14 +225,6 @@
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              // } else {
              //   cell.modal.fields.forEach(m => {
              //     if (m.type === 'linkMain' && !supModule) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
              //     }
              //   })
              }
            }
            if (doubleClick === cell.uuid) {
@@ -399,44 +377,6 @@
    this.updateComponent(card)
  }
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.cols.forEach(col => {
  //         if (col.type !== 'action') return
  //         if (item.$parentId === col.uuid) {
  //           col.elements = col.elements ? [...col.elements, item] : [item]
  //           done = true
  //         }
  //       })
  //     }
  //     if (!done) {
  //       card.action = card.action ? [...card.action, item] : [item]
  //     }
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  getWrapForms = () => {
    const { wrap, action, columns, cols } = this.state.card
@@ -493,7 +433,6 @@
            <CopyComponent type="normaltable" card={card}/>
            <PasteComponent config={card} options={options} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
            <SettingComponent config={card} updateConfig={this.updateComponent} />
src/menu/components/table/edit-table/columns/index.scss
@@ -75,12 +75,6 @@
    }
  }
  .model-menu-card-cell-list {
    .card-detail-row {
      min-height: 21px;
    }
  }
  .ant-table-thead {
    th {
      position: relative;
src/menu/components/table/edit-table/columns/tableIn/index.jsx
@@ -196,6 +196,17 @@
  }
  componentDidMount () {
    this.getsysScript()
  }
  getsysScript = () => {
    if (sessionStorage.getItem('mk_sys_scripts')) {
      this.setState({
        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
      })
      return
    }
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
@@ -214,13 +225,17 @@
    
    Api.getSystemConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = res.data.map(item => {
          return {
            name: item.funcname,
            value: window.decodeURIComponent(window.atob(item.longparam))
          }
        })
        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
        this.setState({
          systemScripts: res.data.map(item => {
            return {
              name: item.funcname,
              value: window.decodeURIComponent(window.atob(item.longparam))
            }
          })
          systemScripts: _scripts
        })
      } else {
        notification.warning({
src/menu/components/table/edit-table/index.jsx
@@ -6,7 +6,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import getWrapForm from './options'
import Utils from '@/utils/utils.js'
@@ -68,7 +68,6 @@
          { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label3', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
        ],
        scripts: [],
        btnlog: [],
        submit: {intertype: 'system', default: 'true', innerFunc: '', execSuccess: 'grid', execError: 'never', scripts: [], uniques: []},
        isNew: true
      }
@@ -167,14 +166,8 @@
    if (!window.GLOB.styling || !card.errors) { // 样式修改时不做筛查
      card.errors = []
      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      // if (supModule === 'empty') {
      //   supModule = ''
      // }
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -187,19 +180,15 @@
      } else if (!card.setting.supModule) {
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
  
      card.action.forEach(cell => {
        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
          if (!cell.modal || cell.modal.fields.length === 0) {
            card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
          // } else {
          //   cell.modal.fields.forEach(m => {
          //     if (m.type === 'linkMain' && !supModule) {
          //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
          //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
          //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
          //     }
          //   })
          }
        }
      })
@@ -210,14 +199,6 @@
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              // } else {
              //   cell.modal.fields.forEach(m => {
              //     if (m.type === 'linkMain' && !supModule) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
              //     }
              //   })
              }
            }
          })
src/menu/components/table/normal-table/columns/index.scss
@@ -65,11 +65,6 @@
      background: #ffffff!important;
    }
  }
  .model-menu-card-cell-list {
    .card-detail-row {
      min-height: 21px;
    }
  }
  .ant-table-thead {
    th {
src/menu/components/table/normal-table/index.jsx
@@ -6,7 +6,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import getWrapForm from './options'
import Utils from '@/utils/utils.js'
@@ -22,7 +22,6 @@
const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
const ColumnComponent = asyncComponent(() => import('./columns'))
class TableCardEditComponent extends Component {
@@ -75,7 +74,6 @@
          { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label3', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
        ],
        scripts: [],
        btnlog: [],
        isNew: true
      }
@@ -145,7 +143,6 @@
  componentDidMount () {
    MKEmitter.addListener('submitModal', this.handleSave)
    // MKEmitter.addListener('logButton', this.logButton)
    MKEmitter.addListener('completeSave', this.completeSave)
  }
@@ -161,7 +158,6 @@
      return
    }
    MKEmitter.removeListener('submitModal', this.handleSave)
    // MKEmitter.removeListener('logButton', this.logButton)
    MKEmitter.removeListener('completeSave', this.completeSave)
  }
@@ -207,14 +203,9 @@
    if (!window.GLOB.styling || !card.errors) { // 样式修改时不做筛查
      card.errors = []
      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      // if (supModule === 'empty') {
      //   supModule = ''
      // }
      let doubleClick = card.wrap.doubleClick || ''
  
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
  
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -228,18 +219,14 @@
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
      card.action.forEach(cell => {
        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
          if (!cell.modal || cell.modal.fields.length === 0) {
            card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
          // } else {
          //   cell.modal.fields.forEach(m => {
          //     if (m.type === 'linkMain' && !supModule) {
          //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
          //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
          //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
          //     }
          //   })
          }
        }
        if (doubleClick === cell.uuid) {
@@ -253,14 +240,6 @@
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              // } else {
              //   cell.modal.fields.forEach(m => {
              //     if (m.type === 'linkMain' && !supModule) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
              //     }
              //   })
              }
            }
            if (doubleClick === cell.uuid) {
@@ -298,17 +277,6 @@
    
    this.props.updateConfig(_card)
  }
  // logButton = (id, item) => {
  //   const { card } = this.state
  //   if (id !== card.uuid) return
  //   let btnlog = card.btnlog || []
  //   btnlog.push(item)
  //   this.updateComponent({...card, btnlog})
  // }
  changeStyle = () => {
    const { card } = this.state
@@ -424,44 +392,6 @@
    this.updateComponent(card)
  }
  // handleLog = (type, logs, item) => {
  //   let card = fromJS(this.state.card).toJS()
  //   if (type === 'revert') {
  //     let done = false
  //     if (item.$parentId) {
  //       card.cols.forEach(col => {
  //         if (col.type !== 'action') return
  //         if (item.$parentId === col.uuid) {
  //           col.elements = col.elements ? [...col.elements, item] : [item]
  //           done = true
  //         }
  //       })
  //     }
  //     if (!done) {
  //       card.action = card.action ? [...card.action, item] : [item]
  //     }
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '恢复成功!',
  //       duration: 2
  //     })
  //   } else {
  //     card.btnlog = logs
  //     this.updateComponent(card)
  //     notification.success({
  //       top: 92,
  //       message: '清除成功!',
  //       duration: 2
  //     })
  //   }
  // }
  getWrapForms = () => {
    const { wrap, action, columns, cols } = this.state.card
@@ -522,7 +452,6 @@
            <CopyComponent type="normaltable" card={card}/>
            <PasteComponent config={card} options={options} updateConfig={this.updateComponent} />
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
            <ClockComponent config={card} updateConfig={this.updateComponent}/>
            <UserComponent config={card}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
src/menu/components/timeline/normal-timeline/index.jsx
@@ -6,7 +6,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import Utils from '@/utils/utils.js'
import getWrapForm from './options'
@@ -115,12 +115,7 @@
    if (!window.GLOB.styling || !card.errors) { // 样式修改时不做筛查
      card.errors = []
      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
      // if (supModule === 'empty') {
      //   supModule = ''
      // }
      let columns = card.columns.map(c => c.field)
      // let lowcols = card.columns.map(c => c.field.toLowerCase())
  
      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
        card.errors.push({ level: 0, detail: '未设置数据源!'})
@@ -134,20 +129,16 @@
        card.errors.push({ level: 0, detail: '未设置上级组件!'})
      }
      if (card.errors.length === 0) {
        card.$tables = getTables(card)
      }
      card.subcards.forEach(col => {
        col.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (!cell.modal || cell.modal.fields.length === 0) {
                card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单尚未添加`})
              // } else {
              //   cell.modal.fields.forEach(m => {
              //     if (m.type === 'linkMain' && !supModule) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中关联主表表单“${m.label}”无效`})
              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
              //       card.errors.push({ level: 1, detail: `按钮“${cell.label}”中表单“${m.label}”大小写与字段集不一致`})
              //     }
              //   })
              }
            }
          } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
src/menu/components/tree/antd-tree/index.jsx
@@ -6,7 +6,7 @@
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import { resetStyle } from '@/utils/utils-custom.js'
import { resetStyle, getTables } from '@/utils/utils-custom.js'
import MKEmitter from '@/utils/events.js'
import getWrapForm from './options'
@@ -114,6 +114,10 @@
      card.errors.push({ level: 0, detail: '未设置上级组件!'})
    }
    if (card.errors.length === 0) {
      card.$tables = getTables(card)
    }
    if (!card.wrap.parentField || !card.wrap.valueField || !card.wrap.labelField) {
      card.errors.push({ level: 0, detail: '未设置基本信息!'})
    }
src/menu/datasource/index.jsx
@@ -40,6 +40,11 @@
    const { config } = this.props
    const { appType } = this.state
    if (config.type === 'interface') { // 公共数据源不使用搜索
      this.setState({visible: true})
      return
    }
    let search = []
    let menu = fromJS(window.GLOB.customMenu).toJS()
src/menu/datasource/verifycard/index.jsx
@@ -202,6 +202,13 @@
  }
  getsysScript = () => {
    if (sessionStorage.getItem('mk_sys_scripts')) {
      this.setState({
        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
      })
      return
    }
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
@@ -220,16 +227,14 @@
    
    Api.getSystemConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = []
        res.data.forEach(item => {
          let _item = {
        let _scripts = res.data.map(item => {
          return {
            name: item.funcname,
            value: window.decodeURIComponent(window.atob(item.longparam))
          }
          _scripts.push(_item)
        })
        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
        this.setState({
          systemScripts: _scripts
@@ -738,14 +743,18 @@
              wrappedComponentRef={(inst) => this.settingForm = inst}
            />
          </TabPane>
          <TabPane tab="字段集" key="columns">
          <TabPane tab={
            <span>
              字段集
              <CopyOutlined title="以逗号拼接形式复制字段" className="mk-copy-fields" onClick={this.copyColumns}/>
            </span>
          } key="columns">
            <ColForm dict={this.props.dict} columnChange={this.columnChange}/>
            <FieldsComponent
              config={{...config, columns}}
              type="fields"
              updatefield={this.updatefields}
            />
            <CopyOutlined title="以逗号拼接形式复制字段" onClick={this.copyColumns} style={{position: 'absolute', cursor: 'pointer', zIndex: 1, top: '-35px', right: '0px', color: '#1890ff'}} />
            <EditTable actions={['edit', 'move', 'copy', 'del', 'clear']} type="datasourcefield" wrappedComponentRef={(inst) => this.datasource = inst} data={columns} columns={colColumns} onChange={(columns) => this.setState({columns})}/>
          </TabPane>
          <TabPane tab={
src/menu/datasource/verifycard/index.scss
@@ -9,6 +9,18 @@
    .ant-tabs-nav-scroll {
      text-align: center;
    }
    .mk-copy-fields {
      position: absolute;
      cursor: pointer;
      z-index: 1;
      top: 19px;
      right: -210px;
      color: rgb(24, 144, 255);
      display: none;
    }
    .ant-tabs-tab-active .mk-copy-fields {
      display: inline-block;
    }
    .count-tip {
      position: absolute;
      top: 0px;
src/menu/datasource/verifycard/settingform/index.jsx
@@ -1,5 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Input, Radio, Tooltip, notification, Select, InputNumber, Cascader } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
@@ -22,18 +23,15 @@
  }
  state = {
    interType: this.props.setting.interType || 'system',
    laypage: this.props.setting.laypage || 'true',
    setting: null,
    modules: [],
    usefulFields: [],
    useMSearch: this.props.setting.useMSearch || 'false',
    sysInterface: this.props.setting.sysInterface || 'false',
    supModule: this.props.setting.supModule || [],
    innerRules: [],
    innertip: '',
    appType: sessionStorage.getItem('appType')
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    const { config, setting } = this.props
    let modules = MenuUtils.getSupModules(window.GLOB.customMenu.components, config.uuid) || []
@@ -43,17 +41,36 @@
    })
    let usefulFields = sessionStorage.getItem('permFuncField')
    let innerRules = []
    let innertip = ''
    if (usefulFields) {
      try {
        usefulFields = JSON.parse(usefulFields)
        if (usefulFields.length > 0) {
          innertip = '开头可用字符:' + usefulFields.join(', ')
          let str = '^(' + usefulFields.join('|') + ')'
          let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
          innerRules.push({
            pattern: _patten,
            message: formRule.func.innerMessage
          })
        }
      } catch (e) {
        usefulFields = []
        innerRules = []
      }
    } else {
      usefulFields = []
    }
    this.setState({modules, usefulFields})
    let _setting = fromJS(setting).toJS()
    _setting.interType = setting.interType || 'system'
    _setting.laypage = setting.laypage || 'true'
    _setting.useMSearch = setting.useMSearch || 'false'
    _setting.sysInterface = setting.sysInterface || 'false'
    _setting.supModule = setting.supModule || []
    _setting.execute = setting.execute || 'true'
    this.setState({modules, innerRules, innertip, setting: _setting})
  }
  handleConfirm = () => {
@@ -69,15 +86,7 @@
          }
          // 数据源前端验证
          if (values.interType === 'system' && values.execute !== 'false' && !values.dataresource) {
            notification.warning({
              top: 92,
              message: '请填写内部函数或数据源!',
              duration: 5
            })
            reject()
            return
          } else if (values.interType === 'system' && values.execute !== 'false' && values.dataresource) {
          if (values.interType === 'system' && values.execute !== 'false' && values.dataresource) {
            let _quot = values.dataresource.match(/'{1}/g)
            let _lparen = values.dataresource.match(/\({1}/g)
            let _rparen = values.dataresource.match(/\){1}/g)
@@ -133,35 +142,21 @@
    })
  }
  onRadioChange = (e, key) => {
    let value = e.target.value
  onOptionChange = (value, key) => {
    let setting = fromJS(this.state.setting).toJS()
    setting[key] = value
    if (key === 'interType') {
      this.setState({
        interType: value
      })
    }
  }
  onSysInter = (e) => {
    let value = e.target.value
    this.setState({
      sysInterface: value
    })
    if (value === 'true') {
    this.setState({setting})
    if (key === 'sysInterface' && value === 'true') {
      this.props.form.setFieldsValue({interface: window.GLOB.mainSystemApi})
    }
  }
  changeSupModule = (val) => {
    this.setState({supModule: val})
  }
  render() {
    const { setting, columns, config } = this.props
    const { columns, config } = this.props
    const { getFieldDecorator } = this.props.form
    const { interType, modules, useMSearch, laypage, supModule, usefulFields, appType, sysInterface } = this.state
    const { setting, modules, innerRules, appType, innertip } = this.state
    const formItemLayout = {
      labelCol: {
@@ -174,24 +169,23 @@
      }
    }
    let tooltip = null
    let rules = []
    if (usefulFields.length > 0) {
      tooltip = '开头可用字符:' + usefulFields.join(', ')
      let str = '^(' + usefulFields.join('|') + ')'
      let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
      rules.push({
        pattern: _patten,
        message: formRule.func.innerMessage
      })
    }
    return (
      <div className="model-datasource-setting-form-box">
        <Form {...formItemLayout} className="model-setting-form">
          <Row gutter={24}>
            {config.type === 'interface' ? <Col span={8}>
              <Form.Item label="数据源名称">
                {getFieldDecorator('name', {
                  initialValue: setting.name,
                  rules: [
                    {
                      required: true,
                      message: this.props.dict['form.required.input'] + '数据源名称!'
                    }
                  ]
                })(<Input placeholder={''} autoComplete="off" />)}
              </Form.Item>
            </Col> : null}
            <Col span={8}>
              <Form.Item label="表名">
                {getFieldDecorator('tableName', {
@@ -204,6 +198,10 @@
                    {
                      max: 50,
                      message: '表名最长为50个字符!'
                    },
                    {
                      pattern: /^[a-zA-Z_]+$/,
                      message: '表名只可使用字母以及_'
                    }
                  ]
                })(<Input placeholder={''} autoComplete="off" />)}
@@ -212,7 +210,7 @@
            <Col span={8}>
              <Form.Item label="接口类型">
                {getFieldDecorator('interType', {
                  initialValue: interType,
                  initialValue: setting.interType,
                  rules: [
                    {
                      required: true,
@@ -220,17 +218,17 @@
                    },
                  ]
                })(
                <Radio.Group onChange={(e) => {this.onRadioChange(e, 'interType')}}>
                <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'interType')}}>
                  <Radio value="system">系统</Radio>
                  <Radio value="inner">内部</Radio>
                  <Radio value="outer">外部</Radio>
                </Radio.Group>)}
              </Form.Item>
            </Col>
            {interType === 'outer' ? <Col span={8}>
            {setting.interType === 'outer' ? <Col span={8}>
              <Form.Item label="系统接口">
                {getFieldDecorator('sysInterface', {
                  initialValue: sysInterface,
                  initialValue: setting.sysInterface,
                  rules: [
                    {
                      required: true,
@@ -238,15 +236,15 @@
                    }
                  ]
                })(
                <Radio.Group onChange={this.onSysInter}>
                <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'sysInterface')}}>
                  <Radio value="true">是</Radio>
                  <Radio value="false">否</Radio>
                </Radio.Group>)}
              </Form.Item>
            </Col> : null}
            {interType === 'inner' ? <Col span={8}>
              <Form.Item label={tooltip ?
                <Tooltip placement="topLeft" title={tooltip}>
            {setting.interType === 'inner' ? <Col span={8}>
              <Form.Item label={innertip ?
                <Tooltip placement="topLeft" title={innertip}>
                  <QuestionCircleOutlined className="mk-form-tip" />
                  内部函数
                </Tooltip> : '内部函数'
@@ -258,25 +256,25 @@
                      required: true,
                      message: this.props.dict['form.required.input'] + '内部函数!'
                    },
                    ...rules
                    ...innerRules
                  ]
                })(<Input placeholder={''} autoComplete="off" />)}
              </Form.Item>
            </Col> : null}
            {interType === 'outer' ? <Col className="outer-interface" span={24}>
            {setting.interType === 'outer' ? <Col className="outer-interface" span={24}>
              <Form.Item label="接口地址">
                {getFieldDecorator('interface', {
                  initialValue: setting.interface || (sysInterface === 'true' ? window.GLOB.mainSystemApi : ''),
                  initialValue: setting.interface || (setting.sysInterface === 'true' ? window.GLOB.mainSystemApi : ''),
                  rules: [
                    {
                      required: sysInterface !== 'true' ? true : false,
                      required: setting.sysInterface !== 'true' ? true : false,
                      message: this.props.dict['form.required.input'] + '接口地址!'
                    }
                  ]
                })(<TextArea rows={2} readOnly={sysInterface === 'true'}/>)}
                })(<TextArea rows={2} readOnly={setting.sysInterface === 'true'}/>)}
              </Form.Item>
            </Col> : null}
            {interType === 'outer' && sysInterface !== 'true' ? <Col className="outer-interface" span={24}>
            {setting.interType === 'outer' && setting.sysInterface !== 'true' ? <Col className="outer-interface" span={24}>
              <Form.Item label={<Tooltip placement="topLeft" title="正式系统接口地址,为空时使用接口地址">
                  <QuestionCircleOutlined className="mk-form-tip" />
                  正式地址
@@ -287,17 +285,14 @@
                })(<TextArea rows={2}/>)}
              </Form.Item>
            </Col> : null}
            {interType === 'outer' ? <Col span={8}>
            {setting.interType === 'outer' ? <Col span={8}>
              <Form.Item label="外部函数">
                {getFieldDecorator('outerFunc', {
                  initialValue: setting.outerFunc || '',
                  rules: [
                  ]
                  initialValue: setting.outerFunc || ''
                })(<Input placeholder={''} autoComplete="off" />)}
              </Form.Item>
            </Col> : null}
            {interType === 'system' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}>
            {setting.interType === 'system' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}>
              <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={
                <Tooltip placement="topLeft" title={`使用系统函数时,需填写数据源。注:数据权限替换符 $@ -> /* 或 ''、 @$ -> */ 或 '';查询替换符 $select@ -> /* 或 ''、 @select$ -> */ 或 '';统计替换符 $sum@ -> /* 或 ''、 @sum$ -> */ 或 ''。`}>
                  <QuestionCircleOutlined className="mk-form-tip" />
@@ -305,11 +300,17 @@
                </Tooltip>
              }>
                {getFieldDecorator('dataresource', {
                  initialValue: setting.dataresource || ''
                  initialValue: setting.dataresource || '',
                  rules: [
                    {
                      required: setting.execute !== 'false' ? true : false,
                      message: this.props.dict['form.required.input'] + '数据源!'
                    }
                  ]
                })(<CodeMirror />)}
              </Form.Item>
            </Col> : null}
            {interType === 'system' ? <Col span={8}>
            {setting.interType === 'system' ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'查询时,搜索条件以where条件拼接进入sql,统计时,将数据源中以“@+搜索字段+@”的内容,以搜索条件中的值进行替换后,提交查询,注:查询类型仅在使用系统函数时有效。'}>
                  <QuestionCircleOutlined className="mk-form-tip" />
@@ -354,18 +355,18 @@
                })(<Input placeholder={'ID asc, UID desc'} autoComplete="off" />)}
              </Form.Item>
            </Col> : null}
            {interType === 'system' ? <Col span={8}>
            {setting.interType === 'system' ? <Col span={8}>
              <Form.Item label="默认sql">
                {getFieldDecorator('execute', {
                  initialValue: setting.execute || 'true'
                  initialValue: setting.execute
                })(
                <Radio.Group>
                <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'execute')}}>
                  <Radio value="true">执行</Radio>
                  <Radio value="false">不执行</Radio>
                </Radio.Group>)}
              </Form.Item>
            </Col> : null}
            {!['navbar', 'balcony', 'menubar'].includes(config.type) && (!config.wrap || config.wrap.supType !== 'multi') ? <Col span={8}>
            {!['navbar', 'balcony', 'menubar', 'interface'].includes(config.type) && (!config.wrap || config.wrap.supType !== 'multi') ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'该组件如果受其他组件控制,请选项相应的组件,没有时选“无”。'}>
                  <QuestionCircleOutlined className="mk-form-tip" />
@@ -373,7 +374,7 @@
                </Tooltip>
              }>
                {getFieldDecorator('supModule', {
                  initialValue: supModule,
                  initialValue: setting.supModule,
                  rules: [
                    {
                      required: true,
@@ -381,7 +382,7 @@
                    }
                  ]
                })(
                  <Cascader options={modules} onChange={this.changeSupModule} expandTrigger="hover" placeholder="" />
                  <Cascader options={modules} onChange={(val) => {this.onOptionChange(val, 'supModule')}} expandTrigger="hover" placeholder="" />
                )}
              </Form.Item>
            </Col> : null}
@@ -390,14 +391,14 @@
                {getFieldDecorator('laypage', {
                  initialValue: setting.laypage || 'true'
                })(
                  <Radio.Group onChange={(e) => this.setState({laypage: e.target.value})}>
                  <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'laypage')}}>
                    <Radio value="true">是</Radio>
                    <Radio value="false">否</Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col> : null}
            {config.pageable && laypage !== 'false' ? <Col span={8}>
            {config.pageable && setting.laypage !== 'false' ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="选择分页时有效。">
                  <QuestionCircleOutlined className="mk-form-tip" />
@@ -416,7 +417,7 @@
              </Form.Item>
            </Col> : null}
            {/* 1、不分页且不存在上级模块 */}
            {!['navbar'].includes(config.type) && !['editable'].includes(config.subtype) && (!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}>
            {!['navbar', 'interface'].includes(config.type) && !['editable'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'初始化加载时,是否与其他组件一同加载数据,注:仅在使用系统函数,且初始化加载数据时有效,分页请求时无效。'}>
                  <QuestionCircleOutlined className="mk-form-tip" />
@@ -433,7 +434,7 @@
                )}
              </Form.Item>
            </Col> : null}
            {!['navbar', 'balcony', 'menubar'].includes(config.type) ? <Col span={8}>
            {!['navbar', 'balcony', 'menubar', 'interface'].includes(config.type) ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'优先使用同级的搜索条件组件,同级搜索不存在时,依次向上选取,与当前组件的搜索条件一同用作数据过滤(当前组件的搜索条件优先)。'}>
                  <QuestionCircleOutlined className="mk-form-tip" />
@@ -443,14 +444,14 @@
                {getFieldDecorator('useMSearch', {
                  initialValue: setting.useMSearch || 'true'
                })(
                  <Radio.Group onChange={(e) => this.setState({useMSearch: e.target.value})}>
                  <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'useMSearch')}}>
                    <Radio value="true">使用</Radio>
                    <Radio value="false">不使用</Radio>
                  </Radio.Group>
                )}
              </Form.Item>
            </Col> : null}
            {!['navbar', 'balcony', 'menubar'].includes(config.type) && useMSearch === 'true' && appType !== 'mob' ? <Col span={8}>
            {!['navbar', 'balcony', 'menubar', 'interface'].includes(config.type) && setting.useMSearch === 'true' && appType !== 'mob' ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title={'外层搜索条件改变时,是否刷新当前组件数据。'}>
                  <QuestionCircleOutlined className="mk-form-tip" />
@@ -478,7 +479,7 @@
                </Radio.Group>)}
              </Form.Item>
            </Col>
            {!['navbar', 'balcony', 'menubar'].includes(config.type) ? <Col span={8}>
            {!['navbar', 'balcony', 'menubar', 'interface'].includes(config.type) ? <Col span={8}>
              <Form.Item label="初始化数据">
                {getFieldDecorator('onload', {
                  initialValue: setting.onload || 'true'
@@ -490,6 +491,39 @@
                )}
              </Form.Item>
            </Col> : null}
            {config.type === 'interface' ? <Col span={8}>
              <Form.Item label="定时器">
                {getFieldDecorator('timer', {
                  initialValue: setting.timer || ''
                })(
                  <Select onChange={(value) => {this.onOptionChange(value, 'timer')}}>
                    <Select.Option value=""> 无 </Select.Option>
                    <Select.Option value="2s"> 2秒 </Select.Option>
                    <Select.Option value="5s"> 5秒 </Select.Option>
                    <Select.Option value="15s"> 15秒 </Select.Option>
                    <Select.Option value="30s"> 30秒 </Select.Option>
                    <Select.Option value="1min"> 1分钟 </Select.Option>
                    <Select.Option value="5min"> 5分钟 </Select.Option>
                    <Select.Option value="10min"> 10分钟 </Select.Option>
                    <Select.Option value="15min"> 15分钟 </Select.Option>
                    <Select.Option value="30min"> 30分钟 </Select.Option>
                    <Select.Option value="1hour"> 1小时 </Select.Option>
                  </Select>
                )}
              </Form.Item>
            </Col> : null}
            {config.type === 'interface' && setting.timer ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="定时器执行次数。注:0表示没有限制。">
                  <QuestionCircleOutlined className="mk-form-tip" />
                  执行次数
                </Tooltip>
              }>
                {getFieldDecorator('timerRepeats', {
                  initialValue: setting.timerRepeats || 0
                })(<InputNumber min={0} max={500} precision={0} />)}
              </Form.Item>
            </Col> : null}
          </Row>
        </Form>
      </div>
src/menu/datasource/verifycard/utils.jsx
@@ -221,7 +221,7 @@
        }
        scripts && scripts.forEach(script => {
          if (reg.test(script.sql)) {
            errors.push(`自定义脚本(${script.$index})存在未替换值${item}`)
            errors.push(`自定义脚本(${script.$index || ''})存在未替换值${item}`)
          }
        })
      })
src/menu/sysinterface/index.jsx
@@ -1,14 +1,15 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Modal, Button, Popconfirm, message } from 'antd'
import { StopTwoTone, ApiOutlined, CopyOutlined, EditOutlined, CheckCircleTwoTone, DeleteOutlined } from '@ant-design/icons'
import { Modal, Button, Popconfirm, message, notification } from 'antd'
import { StopTwoTone, DatabaseOutlined, CopyOutlined, CheckCircleTwoTone, DeleteOutlined, PlusOutlined, SwapOutlined } from '@ant-design/icons'
import Utils from '@/utils/utils.js'
import asyncComponent from '@/utils/asyncComponent'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const SettingForm = asyncComponent(() => import('./settingform'))
const DataSource = asyncComponent(() => import('@/menu/datasource'))
const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
class InterfaceController extends Component {
@@ -19,12 +20,10 @@
  state = {
    visible: false,
    setvisible: false,
    interfaces: [],
    card: null,
    columns: [
      {
        title: '接口名称',
        title: '名称',
        dataIndex: 'name',
        width: '50%'
      },
@@ -53,8 +52,9 @@
        dataIndex: 'operation',
        render: (text, record) =>
          (<div style={{textAlign: 'center'}}>
            <span onClick={() => this.handleEdit(record)} style={{color: '#1890ff', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><EditOutlined /></span>
            <span onClick={() => {this.copy(record)}} style={{color: '#26C281', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><CopyOutlined /></span>
            <DataSource config={record} updateConfig={this.update}/>
            <span onClick={() => this.handleStatus(record)} style={{color: '#8E44AD', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><SwapOutlined /></span>
            <span onClick={() => this.copy(record)} style={{color: '#26C281', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><CopyOutlined /></span>
            <Popconfirm
              overlayClassName="popover-confirm"
              title="确定删除?"
@@ -107,8 +107,46 @@
    })
  }
  handleEdit = (record) => {
    this.setState({card: record, setvisible: true})
  handleStatus = (record) => {
    const { config } = this.props
    if (record.status === 'false') {
      if (record.setting.interType === 'system' && record.setting.execute !== 'false' && !record.setting.dataresource) {
        notification.warning({
          top: 92,
          message: '未设置数据源,不可启用!',
          duration: 5
        })
        return
      } else if (!record.setting.primaryKey) {
        notification.warning({
          top: 92,
          message: '未设置主键,不可启用!',
          duration: 5
        })
        return
      } else if (record.columns.length === 0) {
        notification.warning({
          top: 92,
          message: '未添加字段集,不可启用!',
          duration: 5
        })
        return
      }
    }
    record = fromJS(record).toJS()
    record.status = record.status === 'false' ? 'true' : 'false'
    let interfaces = this.state.interfaces.map(item => {
      if (item.uuid !== record.uuid) {
        return item
      }
      return record
    })
    this.setState({ interfaces })
    this.props.updateConfig({...config, interfaces})
  }
  deleteScript = (record) => {
@@ -126,37 +164,30 @@
    this.props.updateConfig({...config, interfaces})
  }
  settingSave = () => {
  update = (record) => {
    const { config } = this.props
    const { card } = this.state
    let interfaces = fromJS(this.state.interfaces).toJS()
    this.settingRef.handleConfirm().then(res => {
      interfaces = interfaces.map(item => {
        if (item.uuid === card.uuid) {
          res.uuid = item.uuid
    if (record.setting.primaryKey && record.columns.length > 0) {
      record.status = 'true'
    } else if (record.columns.length === 0) {
      record.status = 'false'
    }
    record.name = record.setting.name
          if (res.procMode !== 'inner' && res.preScripts && res.preScripts.filter(item => item.status !== 'false').length === 0) {
            message.warning('未设置前置脚本,不可启用!')
            res.status = 'false'
          } else if (res.callbackType === 'script' && res.cbScripts && res.cbScripts.filter(item => item.status !== 'false').length === 0) {
            message.warning('未设置回调脚本,不可启用!')
            res.status = 'false'
          }
          return res
        }
    let interfaces = this.state.interfaces.map(item => {
      if (item.uuid !== record.uuid) {
        return item
      })
      this.setState({
        card: null,
        setvisible: false,
        interfaces
      })
      this.props.updateConfig({...config, interfaces})
      }
      return record
    })
    this.setState({ interfaces })
    this.props.updateConfig({...config, interfaces})
    setTimeout(() => {
      MKEmitter.emit('mkUpdateInter', record, {delay: 0})
    }, 10)
  }
  addInterface = () => {
@@ -165,11 +196,14 @@
    interfaces.push({
      uuid: Utils.getuuid(),
      name: 'interface ' + (interfaces.length + 1),
      procMode: 'script',
      callbackType: 'script',
      preScripts: [],
      cbScripts: []
      name: '数据源' + (interfaces.length + 1),
      status: 'false',
      format: 'array',
      type: 'interface',
      pageable: false,
      setting: { interType: 'system', name: '数据源' + (interfaces.length + 1), status: 'false' },
      columns: [],
      scripts: [],
    })
    this.setState({
@@ -179,13 +213,13 @@
  }
  render() {
    const { visible, setvisible, columns, interfaces, card } = this.state
    const { visible, columns, interfaces } = this.state
    return (
      <div className="mk-sys-interface" style={{display: 'inline-block'}}>
        <Button className="mk-border-green" onClick={this.trigger}><ApiOutlined /> 接口管理</Button>
        <Button className="mk-border-green" onClick={this.trigger}><DatabaseOutlined /> 公共数据源</Button>
        <Modal
          title="接口管理"
          title="公共数据源"
          wrapClassName="interface-controller-modal"
          visible={visible}
          width={800}
@@ -198,21 +232,9 @@
          ]}
          destroyOnClose
        > 
          <Button key="add-interface" className="mk-border-green" onClick={this.addInterface}> 添加 </Button>
          <PlusOutlined key="add-interface" onClick={this.addInterface}/>
          {/* <div style={{fontSize: '12px', position: 'relative', top: '20px'}}>注:接口执行完成后,会触发默认不加载的组件刷新数据。</div> */}
          <EditTable key="manage-interface" actions={['move', 'copy']} type="interface" data={interfaces} columns={columns} onChange={this.changeScripts}/>
        </Modal>
        <Modal
          title={card ? card.name : '接口'}
          wrapClassName="interface-edit-modal"
          visible={setvisible}
          width={900}
          maskClosable={false}
          onOk={this.settingSave}
          onCancel={() => { this.setState({ setvisible: false })}}
          destroyOnClose
        >
          <SettingForm config={card} wrappedComponentRef={(inst) => this.settingRef = inst}/>
          <EditTable key="manage-interface" actions={['copy']} type="interface" data={interfaces} columns={columns} onChange={this.changeScripts}/>
        </Modal>
      </div>
    )
src/menu/sysinterface/index.scss
@@ -1,20 +1,22 @@
.interface-controller-modal {
  >.ant-modal >.ant-modal-content >.ant-modal-body {
  .ant-modal-body {
    min-height: 400px;
    >.mk-border-green {
    >.anticon-plus {
      float: right;
      position: relative;
      z-index: 1;
      margin-bottom: 10px;
      margin: 0px 10px 10px;
      font-size: 20px;
      color: #26C281;
    }
    .model-datasource {
      position: relative;
      top: 0;
      color: #1890ff;
      display: inline-block;
      > .anticon-setting {
        font-size: 16px;
      }
    }
  }
}
.interface-edit-modal {
  .ant-modal {
    top: 70px;
  }
  .ant-modal-body {
    min-height: 300px;
    padding-top: 5px;
  }
}
src/menu/sysinterface/settingform/baseform/index.jsx
File was deleted
src/menu/sysinterface/settingform/baseform/index.scss
File was deleted
src/menu/sysinterface/settingform/index.jsx
File was deleted
src/menu/sysinterface/settingform/index.scss
File was deleted
src/menu/sysinterface/settingform/simplescript/index.jsx
File was deleted
src/menu/sysinterface/settingform/simplescript/index.scss
File was deleted
src/menu/sysinterface/settingform/utils.jsx
File was deleted
src/menu/tablenodes/index.jsx
New file
@@ -0,0 +1,426 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Modal, Button, notification, Spin, Input } from 'antd'
import { ForkOutlined } from '@ant-design/icons'
import Api from '@/api'
import G6 from "@antv/g6"
import Utils from '@/utils/utils.js'
import './index.scss'
const { Search } = Input
class TableNodes extends Component {
  static propTpyes = {
    config: PropTypes.object
  }
  state = {
    visible: false,
    loading: false,
    nodes: null,
    empty: false
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  getTbs = (config) => {
    let tbs = []
    let ptbs = []
    let traversal = (components) => {
      components.forEach(item => {
        if (item.$tables) {
          ptbs.push(...item.$tables)
          item.$tables.forEach(tb => {
            tbs.push({
              label: item.name,
              table: tb,
              color: '#5AD8A6',
              id: Utils.getuuid(),
              direction: 'left'
            })
          })
        }
        if (item.type === 'tabs') {
          item.subtabs.forEach(tab => {
            traversal(tab.components)
          })
        } else if (item.type === 'group') {
          traversal(item.components)
        }
      })
    }
    traversal(config.components)
    return {tbs, ptbs}
  }
  trigger = () => {
    const { config } = this.props
    if (!config) return
    this.setState({visible: true, loading: true, empty: false}, () => {
      let param = {
        func: 's_get_menus_tb_list',
        TypeCharOne: sessionStorage.getItem('kei_no') || '',
        typename: sessionStorage.getItem('typename') || '',
        MenuID: config.uuid
      }
      Api.getSystemConfig(param).then(result => {
        if (!result.status) {
          notification.warning({
            top: 92,
            message: result.message,
            duration: 5
          })
          this.setState({empty: true, loading: false})
          return
        }
        let data = {
          label: config.MenuName || '空',
          id: config.uuid,
          MenuID: config.MenuID,
          children: []
        }
        let { tbs, ptbs } = this.getTbs(config)
        ptbs = Array.from(new Set(ptbs))
        ptbs.sort()
        if (ptbs.length && sessionStorage.getItem('mk_tb_names')) {
          let names = sessionStorage.getItem('mk_tb_names')
          ptbs = ptbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
        }
        if (ptbs.length) {
          ptbs.forEach((item, i) => {
            let cell = {
              label: item,
              id: 'par' + i,
              direction: 'left',
              color: '#5AD8A6',
              children: []
            }
            tbs.forEach(t => {
              if (t.table === item) {
                cell.children.push(t)
              }
            })
            data.children.push(cell)
          })
        }
        if (result.tb_list) {
          result.tb_list.sort((a, b) => a.tbname > b.tbname ? 1 : -1)
          result.tb_list.forEach((item, i) => {
            let cell = {
              label: item.tbname,
              name: item.tbname.toLowerCase(),
              id: 'table' + i,
              direction: 'right',
              color: '#1890ff',
              children: []
            }
            if (item[item.tbname]) {
              item[item.tbname].forEach((m, i) => {
                if (m.debug_url) {
                  let _param = JSON.parse(window.decodeURIComponent(window.atob(m.debug_url)))
                  let label = _param.MenuName
                  if (_param && _param.type === 'app') {
                    label += ` (${_param.kei_no} | ${_param.typename}${param.lang !== 'zh-CN' ? ' | ' + param.lang : ''})`
                  }
                  cell.children.push({
                    label: label,
                    id: item.tbname + 'menu' + i,
                    direction: 'right',
                    color: '#1890ff',
                    param: _param
                  })
                }
              })
            }
            data.children.push(cell)
          })
        }
        if (data.children.length === 0) {
          this.setState({empty: true, loading: false})
        } else {
          this.setState({loading: false, nodes: data})
          this.getForks(data)
        }
      })
    })
  }
  changeMenu = (menu) => {
    if (menu.direction !== 'right') return
    if (menu.depth === 1) {
      window.open('#/hs')
    } else if (menu.param) {
      if (menu.param.type === 'admin') {
        if (menu.param.MenuType === 'custom') {
          let _param = {...menu.param}
          delete _param.type
          _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
          window.open(`#/menudesign/${_param}`)
        }
      } else if (menu.param.type === 'app') {
        if (menu.param.typename !== 'pc') {
          let _param = {...menu.param}
          _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
          window.open(`#/mobdesign/${_param}`)
        } else {
          let _param = {...menu.param}
          _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
          window.open(`#/pcdesign/${_param}`)
        }
      }
    }
  }
  resetNodes = (key) => {
    let data = fromJS(this.state.nodes).toJS()
    key = key ? key.toLowerCase() : ''
    data.children.forEach(cell => {
      if (cell.direction === 'right') {
        cell.fontcolor = ''
        if (key && cell.name.indexOf(key) > -1) {
          cell.fontcolor = 'orange'
        }
      }
    })
    let _element = document.getElementById('mkTableNode')
    if (_element) {
      _element.innerHTML = ''
    }
    this.setState({}, () => {
      this.getForks(data)
    })
  }
  getForks = (data) => {
    const { Util } = G6
    const that = this
    G6.registerNode(
      'dice-mind-map-root', {
        jsx: (cfg) => {
          const width = Util.getTextSize(cfg.label, 14)[0] + 12;
          const stroke = cfg.style.stroke || '#096dd9';
          return `
          <group>
            <rect draggable="true" style={{width: ${width}, height: 30, stroke: ${stroke}, radius: 4}} keyshape>
              <text style={{ fontSize: 14, marginLeft: 6, marginTop: 6 }}>${cfg.label}</text>
            </rect>
          </group>
        `;
        },
        getAnchorPoints() {
          return [
            [0, 0.5],
            [1, 0.5],
          ];
        },
      },
      'single-node',
    );
    G6.registerNode(
      'dice-mind-map-leaf', {
        jsx: (cfg) => {
          const width = Util.getTextSize(cfg.label, 12)[0] + 24;
          const color = cfg.color;
          return `
          <group>
            <rect draggable="true" style={{width: ${width}, height: 26, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, fill: 'transparent' }}>
              <text style={{ fontSize: 12, fill: ${cfg.fontcolor ? cfg.fontcolor : 'black'}, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, marginLeft: 12, marginTop: 6 }}>${cfg.label}</text>
            </rect>
            <rect style={{ fill: ${color}, width: ${width}, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, height: 2, x: 0, y: 32 }} />
          </group>
        `;
        },
        getAnchorPoints() {
          return [
            [0, 0.965],
            [1, 0.965],
          ];
        },
      },
      'single-node',
    );
    G6.registerBehavior('dice-mindmap', {
      getEvents() {
        return {
          'node:dblclick': 'editNode',
        };
      },
      editNode(evt) {
        const item = evt.item;
        const model = item.get('model');
        that.changeMenu(model)
      }
    });
    G6.registerBehavior('scroll-canvas', {
      getEvents: function getEvents() {
        return {
          wheel: 'onWheel',
        };
      },
      onWheel: function onWheel(ev) {
        const {
          graph
        } = this;
        if (!graph) {
          return;
        }
        if (ev.ctrlKey) {
          const canvas = graph.get('canvas');
          const point = canvas.getPointByClient(ev.clientX, ev.clientY);
          let ratio = graph.getZoom();
          if (ev.wheelDelta > 0) {
            ratio += ratio * 0.05;
          } else {
            ratio *= ratio * 0.05;
          }
          graph.zoomTo(ratio, {
            x: point.x,
            y: point.y,
          });
        } else {
          const x = ev.deltaX || ev.movementX;
          const y = ev.deltaY || ev.movementY || (-ev.wheelDelta * 125) / 3;
          graph.translate(-x, -y);
        }
        ev.preventDefault();
      },
    });
    const dataTransform = (data) => {
      const changeData = (d, level = 0, color) => {
        const data = {
          ...d,
        };
        switch (level) {
          case 0:
            data.type = 'dice-mind-map-root';
            break;
          default:
            data.type = 'dice-mind-map-leaf';
            break;
        }
        data.hover = false;
        if (color) {
          data.color = color;
        }
        if (d.children) {
          data.children = d.children.map((child) => changeData(child, level + 1, data.color));
        }
        return data;
      };
      return changeData(data);
    };
    const tree = new G6.TreeGraph({
      container: 'mkTableNode',
      width: this.wrap.offsetWidth,
      height: this.wrap.offsetHeight,
      fitView: true,
      fitViewPadding: [10, 20],
      layout: {
        type: 'mindmap',
        direction: 'H',
        getHeight: () => {
          return 16;
        },
        getWidth: (node) => {
          return node.level === 0 ?
            Util.getTextSize(node.label, 16)[0] + 12 :
            Util.getTextSize(node.label, 12)[0];
        },
        getVGap: () => {
          return 10;
        },
        getHGap: () => {
          return 60;
        },
        getSide: (node) => {
          return node.data.direction;
        },
      },
      defaultEdge: {
        type: 'cubic-horizontal',
        style: {
          lineWidth: 2,
        },
      },
      minZoom: 0.5,
      modes: {
        default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap'],
      },
    });
    tree.data(dataTransform(data));
    tree.render();
  }
  render() {
    const { visible, loading, empty } = this.state
    return (
      <div style={{display: 'inline-block'}}>
        <Button style={{borderColor: '#8E44AD', color: '#8E44AD'}} onClick={this.trigger}><ForkOutlined /> 表关系图</Button>
        <Modal
          title=""
          wrapClassName="view-table-modal"
          visible={visible}
          width={'90vw'}
          closable={false}
          maskClosable={false}
          footer={[]}
          destroyOnClose
        >
          <div className="header">表关系图</div>
          <Search className="tb-search" placeholder="请输入表名" onSearch={value => this.resetNodes(value)} enterButton />
          <div className="wrap">
            {loading ? <Spin size="large" /> : null}
            {empty ? <div className="empty">未查询到表名信息。</div> : null}
            <div className="mountNode" id="mkTableNode" ref={ref => this.wrap = ref}></div>
          </div>
          <div className="footer">
            <Button key="cancel" onClick={() => { this.setState({ visible: false })}}>关闭</Button>
          </div>
        </Modal>
      </div>
    )
  }
}
export default TableNodes
src/menu/tablenodes/index.scss
New file
@@ -0,0 +1,54 @@
.view-table-modal {
  .ant-modal {
    top: 55px;
  }
  .ant-modal-body {
    padding: 20px 50px 20px;
    user-select: none;
  }
  .ant-modal-footer {
    display: none;
  }
  .wrap {
    position: relative;
    height: calc(100vh - 200px);
    margin: 10px 0px;
    overflow: hidden;
    .mountNode {
      height: 100%;
    }
    .ant-spin {
      position: absolute;
      top: calc(50% - 16px);
      left: calc(50% - 16px);
    }
    .empty {
      position: relative;
      text-align: center;
      color: #959595;
      padding-top: 200px;
    }
    .empty + .mountNode {
      opacity: 0;
    }
  }
  .header {
    color: #1890ff;
    font-weight: 500;
    text-align: center;
    font-size: 18px;
  }
  .footer {
    text-align: center;
  }
  .tb-search {
    position: absolute;
    width: 200px;
    z-index: 1;
    right: 40px;
    top: 16px;
  }
}
src/pc/bgcontroller/index.jsx
@@ -215,28 +215,28 @@
            className="normal-view"
            label={<ArrowUpOutlined title="上边距"/>}
          >
            <StyleInput defaultValue={config.style.paddingTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingTop')}/>
            <StyleInput defaultValue={config.style.paddingTop || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingTop')}/>
          </Form.Item>
          <Form.Item
            colon={false}
            className="normal-view"
            label={<ArrowDownOutlined title="下边距"/>}
          >
            <StyleInput defaultValue={config.style.paddingBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingBottom')}/>
            <StyleInput defaultValue={config.style.paddingBottom || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingBottom')}/>
          </Form.Item>
          <Form.Item
            colon={false}
            className="normal-view"
            label={<ArrowLeftOutlined title="左边距"/>}
          >
            <StyleInput defaultValue={config.style.paddingLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingLeft')}/>
            <StyleInput defaultValue={config.style.paddingLeft || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingLeft')}/>
          </Form.Item>
          <Form.Item
            colon={false}
            className="normal-view"
            label={<ArrowRightOutlined title="右边距"/>}
          >
            <StyleInput defaultValue={config.style.paddingRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingRight')}/>
            <StyleInput defaultValue={config.style.paddingRight || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingRight')}/>
          </Form.Item>
          <p className="normal-view" style={{borderBottom: '1px solid #eaeaea', color: '#40a9ff'}}>外边距</p>
          <Form.Item
@@ -244,28 +244,28 @@
            className="normal-view"
            label={<ArrowUpOutlined title="上边距"/>}
          >
            <StyleInput defaultValue={config.style.marginTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginTop')}/>
            <StyleInput defaultValue={config.style.marginTop || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginTop')}/>
          </Form.Item>
          <Form.Item
            colon={false}
            className="normal-view"
            label={<ArrowDownOutlined title="下边距"/>}
          >
            <StyleInput defaultValue={config.style.marginBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginBottom')}/>
            <StyleInput defaultValue={config.style.marginBottom || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginBottom')}/>
          </Form.Item>
          <Form.Item
            colon={false}
            className="normal-view"
            label={<ArrowLeftOutlined title="左边距"/>}
          >
            <StyleInput defaultValue={config.style.marginLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginLeft')}/>
            <StyleInput defaultValue={config.style.marginLeft || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginLeft')}/>
          </Form.Item>
          <Form.Item
            colon={false}
            className="normal-view"
            label={<ArrowRightOutlined title="右边距"/>}
          >
            <StyleInput defaultValue={config.style.marginRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginRight')}/>
            <StyleInput defaultValue={config.style.marginRight || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginRight')}/>
          </Form.Item>
        </Form>
      </div>
src/store/action-type.js
@@ -13,11 +13,5 @@
// 重置编辑级别
export const RESET_EDITLEVEL = 'RESET_EDITLEVEL'
// 初始化按钮权限
export const INIT_ACTIONPERMISSION = 'INIT_ACTIONPERMISSION'
// 初始化菜单权限
export const INIT_MENUPERMISSION = 'INIT_MENUPERMISSION'
// 退出
export const LOGOUT = 'LOGOUT'
src/store/action.js
@@ -32,22 +32,6 @@
  }
}
// 初始化按钮权限
export const initActionPermission = (permAction) => {
  return {
    type: user.INIT_ACTIONPERMISSION,
    permAction: permAction
  }
}
// 初始化菜单权限
export const initMenuPermission = (permMenus) => {
  return {
    type: user.INIT_MENUPERMISSION,
    permMenus: permMenus
  }
}
// 退出重置
export const logout = () => {
  return {
src/store/reducer.js
@@ -8,8 +8,6 @@
  mainMenu: _mainMenu,  // 已选主菜单
  collapse: _collapse,  // 是否收起侧边栏导航
  editLevel: null,      // 编辑菜单级别,值为level1、level2、level3、HS
  permAction: {},       // 用户按钮权限
  permMenus: [],        // 用户三级菜单列表
}
// 用户消息
@@ -39,26 +37,12 @@
        ...state,
        editLevel: action.editLevel
      }
    case Type.INIT_ACTIONPERMISSION:
    // 初始化按钮权限
      return {
        ...state,
        permAction: action.permAction
      }
    case Type.INIT_MENUPERMISSION:
    // 初始化三级菜单权限
      return {
        ...state,
        permMenus: action.permMenus
      }
    case Type.LOGOUT:
      return {
        menuTree: null,
        mainMenu: null,
        collapse: localStorage.getItem('collapse') === 'true',
        editLevel: null,
        permAction: {},
        permMenus: [],
        editLevel: null
      }
    default:
      return state
src/tabviews/basetable/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Tabs, Switch, Row, Col } from 'antd'
@@ -76,7 +75,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, permMenus, param, MenuName, MenuID } = this.props
    const { param, MenuName, MenuID } = this.props
    let _param = {
      func: 'sPC_Get_LongParam',
@@ -159,13 +158,13 @@
      // 权限过滤
      if (!window.GLOB.mkHS) {
        config.action = config.action.filter(item => item.hidden !== 'true' && permAction[item.uuid])
        config.action = config.action.filter(item => item.hidden !== 'true' && window.GLOB.mkActions[item.uuid])
        config.tabgroups.forEach(group => {
          group.sublist = group.sublist.filter(tab => {
            if (tab.supMenu === 'mainTable') {
              tab.supMenu = MenuID
            }
            return permAction[tab.linkTab]
            return window.GLOB.mkActions[tab.linkTab]
          })
        })
      } else {
@@ -336,7 +335,7 @@
          if (col.linkmenu && col.linkmenu.length > 0) {
            let menu_id = col.linkmenu.slice(-1)[0]
            col.linkThdMenu = permMenus.filter(m => m.MenuID === menu_id)[0] || ''
            col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
          } else {
            col.linkThdMenu = ''
          }
@@ -1266,22 +1265,11 @@
        }
        {!window.GLOB.mkHS && autoMatic ? <AutoMatic autoMatic={autoMatic} config={config} /> : null}
        {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts}/> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
      </div>
    )
  }
}
const mapStateToProps = (state) => {
  return {
    permAction: state.permAction,
    permMenus: state.permMenus
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(NormalTable)
export default NormalTable
src/tabviews/calendar/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Modal, Button } from 'antd'
import moment from 'moment'
@@ -22,7 +21,7 @@
const SubTabTable = asyncSpinComponent(() => import('@/tabviews/subtabtable'))
const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
class NormalTable extends Component {
class MkCalendar extends Component {
  static propTpyes = {
    param: PropTypes.any,        // 其他页面传递的参数
    MenuID: PropTypes.string,    // 菜单Id
@@ -55,7 +54,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, param } = this.props
    const { param } = this.props
    let _param = {
      func: 'sPC_Get_LongParam',
@@ -107,7 +106,7 @@
      // 权限过滤
      if (!window.GLOB.mkHS) {
        if (config.tab && !permAction[config.tab.linkTab]) {
        if (config.tab && !window.GLOB.mkActions[config.tab.linkTab]) {
          config.tab = null
        }
      }
@@ -574,14 +573,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permAction: state.permAction
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(NormalTable)
export default MkCalendar
src/tabviews/commontable/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Tabs, Switch, Row, Col } from 'antd'
@@ -28,6 +27,7 @@
const ChartComponent = asyncSpinComponent(() => import('@/tabviews/zshare/chartcomponent'))
const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
const AutoMatic = asyncComponent(() => import('@/tabviews/zshare/automatic'))
const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
const { TabPane } = Tabs
@@ -69,14 +69,15 @@
    absFields: [],        // 绝对值字段
    loadCustomApi: true,  // 加载外部资源
    hasReqFields: false,
    autoMatic: null
    autoMatic: null,
    visible: false
  }
  /**
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, permMenus, param, MenuName, MenuID } = this.props
    const { param, MenuName, MenuID } = this.props
    let _param = {
      func: 'sPC_Get_LongParam',
@@ -159,13 +160,13 @@
      // 权限过滤
      if (!window.GLOB.mkHS) {
        config.action = config.action.filter(item => item.hidden !== 'true' && permAction[item.uuid])
        config.action = config.action.filter(item => item.hidden !== 'true' && window.GLOB.mkActions[item.uuid])
        config.tabgroups.forEach(group => {
          group.sublist = group.sublist.filter(tab => {
            if (tab.supMenu === 'mainTable') {
              tab.supMenu = MenuID
            }
            return permAction[tab.linkTab]
            return window.GLOB.mkActions[tab.linkTab]
          })
        })
      } else {
@@ -336,7 +337,7 @@
          if (col.linkmenu && col.linkmenu.length > 0) {
            let menu_id = col.linkmenu.slice(-1)[0]
            col.linkThdMenu = permMenus.filter(m => m.MenuID === menu_id)[0] || ''
            col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
          } else {
            col.linkThdMenu = ''
          }
@@ -432,7 +433,7 @@
        chartId,
        config,
        statFields,
        shortcuts,
        shortcuts: shortcuts.length > 0 ? shortcuts : null,
        setting: config.setting,
        searchlist: config.search,
        actions: _actions,
@@ -463,11 +464,6 @@
  setShortcut = () => {
    const { shortcuts } = this.state
    if (!shortcuts || shortcuts.length === 0) {
      document.onkeydown = () => {}
      return
    }
    document.onkeydown = (event) => {
      let e = event || window.event
      let keyCode = e.keyCode || e.which || e.charCode
@@ -484,6 +480,16 @@
      if (!preKey || !keyCode) return
      let _shortcut = `${preKey}+${keyCode}`
      if (window.GLOB.breakpoint && _shortcut === 'ctrl+67') {
        window.debugger = false
        window.GLOB.breakpoint = false
        sessionStorage.removeItem('breakpoint')
        MKEmitter.emit('debugChange')
      }
      if (!shortcuts) return
      shortcuts.some(item => {
        if (item.$shortcut === _shortcut) {
@@ -1090,6 +1096,10 @@
    }
  }
  debugChange = () => {
    this.setState({visible: !this.state.visible})
  }
  UNSAFE_componentWillMount () {
    // 组件加载时,获取菜单数据
    this.loadconfig()
@@ -1101,6 +1111,7 @@
  componentDidMount () {
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('debugChange', this.debugChange)
    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.addListener('changeTableLine', this.changeTableLine)
    MKEmitter.addListener('resetActiveMenu', this.resetActiveMenu)
@@ -1117,6 +1128,7 @@
    }
    document.onkeydown = () => {}
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('debugChange', this.debugChange)
    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.removeListener('changeTableLine', this.changeTableLine)
    MKEmitter.removeListener('resetActiveMenu', this.resetActiveMenu)
@@ -1273,24 +1285,14 @@
            })}
          </Tabs>))
        }
        {setting && window.GLOB.breakpoint ? <DebugTable /> : null}
        {!window.GLOB.mkHS && autoMatic ? <AutoMatic autoMatic={autoMatic} config={config} /> : null}
        {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
        {!window.GLOB.mkHS && setting ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts || []}/> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
      </div>
    )
  }
}
const mapStateToProps = (state) => {
  return {
    permAction: state.permAction,
    permMenus: state.permMenus
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(NormalTable)
export default NormalTable
src/tabviews/custom/components/card/balcony/index.jsx
@@ -50,13 +50,13 @@
      BID = BData.$BID || ''
    }
    
    if (_config.wrap.datatype !== 'static') {
    if (_config.wrap.datatype === 'dynamic') {
      _sync = _config.setting.sync === 'true'
      if (_sync && data) {
        _data = data[_config.dataName] || {}
        _data = data[_config.dataName] || {$$empty: true}
        if (_data && Array.isArray(_data)) {
          _data = _data[0] || {}
          _data = _data[0] || {$$empty: true}
        }
        _sync = false
      } else if (_sync && initdata) {
@@ -66,10 +66,15 @@
        }
        _sync = false
      }
    } else if (_config.wrap.datatype === 'public' && window.GLOB.CacheData.get(_config.wrap.publicId)) {
      _data = window.GLOB.CacheData.get(_config.wrap.publicId)
      _data = fromJS(_data).toJS()
    }
    if (_data) {
      _data.$$BID = BID || ''
    _data.$$BID = BID || ''
    _data.$$BData = BData || ''
    if (_config.setting.primaryKey) {
      _data.$$uuid = _data[_config.setting.primaryKey] || ''
    }
    if (_config.wrap.position === 'fixed' || _config.wrap.position === 'absolute') {
@@ -113,7 +118,7 @@
      config: _config,
      arr_field: _config.columns.map(col => col.field).join(','),
    }, () => {
      if (_config.wrap.datatype !== 'static' && _config.setting && _config.setting.sync !== 'true') {
      if (_config.wrap.datatype === 'dynamic' && _config.setting && _config.setting.sync !== 'true') {
        setTimeout(() => {
          this.loadData()
        }, _config.setting.delay || 0)
@@ -129,8 +134,12 @@
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
    if (config.wrap.datatype === 'public') {
      MKEmitter.addListener('mkPublicData', this.mkPublicData)
    }
    
    if (config.timer) {
    if (config.timer && config.wrap.datatype === 'dynamic') {
      this.timer = new TimerTask()
      this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {this.loadData(true)})
    }
@@ -145,6 +154,7 @@
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('mkPublicData', this.mkPublicData)
    MKEmitter.removeListener('syncBalconyData', this.syncBalconyData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
@@ -157,25 +167,39 @@
   * @description 图表数据更新,刷新内容
   */
  UNSAFE_componentWillReceiveProps (nextProps) {
    const { sync, config, BID } = this.state
    const { sync, config, BID, BData } = this.state
    if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
      let _data = {$$empty: true}
      if (nextProps.data && nextProps.data[config.dataName]) {
        _data = nextProps.data[config.dataName]
        if (_data && Array.isArray(_data)) {
          _data = _data[0]
          _data = _data[0] || {$$empty: true}
        }
      }
      if (_data) {
        _data.$$BID = BID || ''
      }
      _data.$$BID = BID || ''
      _data.$$BData = BData || ''
      _data.$$uuid = _data[config.setting.primaryKey] || ''
      this.setState({sync: false, data: _data})
    }
  }
  mkPublicData = (publicId, data) => {
    const { config, BID, BData } = this.state
    if (config.wrap.datatype === 'public' && config.wrap.publicId === publicId) {
      let _data = fromJS(data).toJS()
      _data.$$BID = BID || ''
      _data.$$BData = BData || ''
      _data.$$uuid = _data[config.setting.primaryKey] || ''
      this.setState({data: _data})
    }
  }
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
src/tabviews/custom/components/card/cardItem/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification } from 'antd'
@@ -81,29 +80,26 @@
      } else {
        MKEmitter.emit('modifyTabs', newtab, 'plus', true)
      }
    } else if (card.setting.click === 'menu') {
      let menu = null
    } else if (card.setting.click === 'menu' && card.setting.menu) {
      let menuId = card.setting.MenuID || card.setting.menu.slice(-1)[0]
      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
      if (card.setting.MenuID) {
        let _menu = this.props.permMenus.filter(m => m.MenuID === card.setting.MenuID)[0] || ''
      if (!menu && card.setting.MenuName && card.setting.tabType) {
        menu = {
          MenuID: card.setting.MenuID,
          MenuName: _menu ? _menu.MenuName : card.setting.MenuName,
          MenuNo: card.setting.MenuNo,
          type: _menu ? _menu.type : card.setting.tabType
          MenuID: menuId,
          MenuName: card.setting.MenuName,
          MenuNo: card.setting.MenuNo || '',
          type: card.setting.tabType
        }
      } else if (card.setting.menu && card.setting.menu.length > 0) {
        let menu_id = card.setting.menu.slice(-1)[0]
        menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
      }
        if (!menu) {
          notification.warning({
            top: 92,
            message: '菜单已删除或没有访问权限!',
            duration: 5
          })
          return
        }
      if (!menu) {
        notification.warning({
          top: 92,
          message: '菜单已删除或没有访问权限!',
          duration: 5
        })
        return
      }
      let newtab = {
@@ -175,14 +171,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permMenus: state.permMenus
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(CardBoxComponent)
export default CardBoxComponent
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -9,8 +9,6 @@
import asyncElementComponent from '@/utils/asyncComponent'
import { getMark } from '@/utils/utils.js'
import MkIcon from '@/components/mk-icon'
import MKEmitter from '@/utils/events.js'
import LostPng from '@/assets/img/lost.png'
import Encrypts from '@/components/encrypts'
import './index.scss'
@@ -29,6 +27,7 @@
const QrCode = asyncElementComponent(() => import('@/components/qrcode'))
const MkProgress = asyncElementComponent(() => import('@/components/mkProgress'))
const Video = asyncComponent(() => import('@/components/video'))
const MkPicture = asyncComponent(() => import('@/components/mkPicture'))
const PicRadio = {
  '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%',
  '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%',
@@ -555,26 +554,12 @@
        }
  
        let scale = url && card.scale === 'true'
        let urls = url ? url.split(',').filter(Boolean) : [LostPng]
        if (!url) {
          _imagestyle = {backgroundSize: 'contain'}
        }
        let urls = url ? url.split(',').filter(Boolean) : ['']
        urls.forEach((u, i) => {
          contents.push(<Col key={card.uuid + i} span={card.width}>
            <div style={_style} onClick={(e) => {this.openNewView(e, card)}}>
              <div
                className={'ant-mk-picture' + (scale ? ' scale' : '')}
                onClick={(e) => {
                  if (!scale) return
                  e.stopPropagation()
                  MKEmitter.emit('mkImageScale', url, urls)
                }}
                style={{..._imagestyle, backgroundImage: `url('${u}')`}}
              ></div>
              <MkPicture style={_imagestyle} scale={scale} url={u} urls={urls}/>
            </div>
          </Col>)
        })
src/tabviews/custom/components/card/cardcellList/index.scss
@@ -151,15 +151,6 @@
      }
    }
  }
  .ant-mk-picture {
    background-size: cover;
    background-position: center center;
    background-repeat: no-repeat;
    background-color: #f5f5f5;
  }
  .ant-mk-picture.scale {
    cursor: zoom-in;
  }
  .ant-mk-icon {
    vertical-align: top;
    line-height: inherit;
src/tabviews/custom/components/card/prop-card/index.jsx
@@ -51,7 +51,7 @@
      BID = BData.$BID || ''
    }
    
    if (_config.wrap.datatype !== 'static') {
    if (_config.wrap.datatype === 'dynamic') {
      _sync = _config.setting.sync === 'true'
      if (_sync && data) {
@@ -67,6 +67,9 @@
        }
        _sync = false
      }
    } else if (_config.wrap.datatype === 'public' && window.GLOB.CacheData.get(_config.wrap.publicId)) {
      _data = window.GLOB.CacheData.get(_config.wrap.publicId)
      _data = fromJS(_data).toJS()
    }
    _data.$$BID = BID || ''
@@ -122,10 +125,16 @@
      config: _config,
      arr_field: _config.columns.map(col => col.field).join(','),
    }, () => {
      if (_config.wrap.datatype !== 'static' && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
      if (_config.wrap.datatype === 'dynamic' && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
        setTimeout(() => {
          this.loadData()
        }, _config.setting.delay || 0)
      } else if (_config.wrap.datatype === 'public') {
        if (_data.$$loaded && selected !== 'false') {
          setTimeout(() => {
            this.checkTopLine()
          }, 200)
        }
      } else if (!_sync && selected !== 'false') {
        setTimeout(() => {
          this.checkTopLine()
@@ -142,7 +151,11 @@
    MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
    if (config.timer) {
    if (config.wrap.datatype === 'public') {
      MKEmitter.addListener('mkPublicData', this.mkPublicData)
    }
    if (config.timer && config.wrap.datatype === 'dynamic') {
      this.timer = new TimerTask()
      this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {this.loadData(true)})
    }
@@ -157,6 +170,7 @@
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('mkPublicData', this.mkPublicData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
@@ -190,13 +204,33 @@
          }, 200)
        }
      })
    } else if ( config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
    } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
      this.setState({}, () => {
        this.loadData()
      })
    }
  }
  mkPublicData = (publicId, data) => {
    const { config, selected, BID, BData } = this.state
    if (config.wrap.datatype === 'public' && config.wrap.publicId === publicId) {
      let _data = fromJS(data).toJS()
      _data.$$BID = BID || ''
      _data.$$BData = BData || ''
      _data.$$uuid = _data[config.setting.primaryKey] || ''
      this.setState({data: _data}, () => {
        if (selected !== 'false') {
          setTimeout(() => {
            this.checkTopLine()
          }, 200)
        }
      })
    }
  }
  checkTopLine = () => {
    const { config, data, selected } = this.state
src/tabviews/custom/components/card/table-card/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { Spin, notification, Row, Col, Empty, Pagination } from 'antd'
import { DownOutlined } from '@ant-design/icons'
@@ -348,29 +347,26 @@
  }
  openView = (card, data) => {
    if (card.setting.click === 'menu') {
      let menu = null
    if (card.setting.click === 'menu' && card.setting.menu) {
      let menuId = card.setting.MenuID || card.setting.menu.slice(-1)[0]
      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
      if (card.setting.MenuID) {
        let _menu = this.props.permMenus.filter(m => m.MenuID === card.setting.MenuID)[0] || ''
      if (!menu && card.setting.MenuName && card.setting.tabType) {
        menu = {
          MenuID: card.setting.MenuID,
          MenuName: _menu ? _menu.MenuName : card.setting.MenuName,
          MenuNo: card.setting.MenuNo,
          type: _menu ? _menu.type : card.setting.tabType
          MenuID: menuId,
          MenuName: card.setting.MenuName,
          MenuNo: card.setting.MenuNo || '',
          type: card.setting.tabType
        }
      } else if (card.setting.menu && card.setting.menu.length > 0) {
        let menu_id = card.setting.menu.slice(-1)[0]
        menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
      }
        if (!menu) {
          notification.warning({
            top: 92,
            message: '菜单已删除或没有访问权限!',
            duration: 5
          })
          return
        }
      if (!menu) {
        notification.warning({
          top: 92,
          message: '菜单已删除或没有访问权限!',
          duration: 5
        })
        return
      }
      let newtab = {
@@ -496,14 +492,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permMenus: state.permMenus,
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(TableCard)
export default TableCard
src/tabviews/custom/components/carousel/prop-card/index.jsx
@@ -48,7 +48,7 @@
      BID = BData.$BID || ''
    }
    
    if (_config.setting && _config.wrap.datatype !== 'static') {
    if (_config.setting && _config.wrap.datatype === 'dynamic') {
      _sync = _config.setting.sync === 'true'
      if (_sync && data) {
@@ -97,7 +97,7 @@
      config: _config,
      arr_field: _config.columns.map(col => col.field).join(','),
    }, () => {
      if (_config.wrap.datatype !== 'static' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
      if (_config.wrap.datatype === 'dynamic' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
        setTimeout(() => {
          this.loadData()
        }, _config.setting.delay || 0)
@@ -113,7 +113,7 @@
    MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
    if (config.timer) {
    if (config.timer && config.wrap.datatype === 'dynamic') {
      this.timer = new TimerTask()
      this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
        this.loadData('timer')
src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -2,7 +2,6 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Chart } from '@antv/g2'
import { connect } from 'react-redux'
import DataSet, { DataView } from '@antv/data-set'
import { Spin, Empty, notification } from 'antd'
import { DownloadOutlined } from '@ant-design/icons'
@@ -923,9 +922,10 @@
    
    if (plot.linkmenu && plot.linkmenu.length > 0) {
      let menu_id = plot.linkmenu.slice(-1)[0]
      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
      chart.on('element:dblclick', (ev) => {
        let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
        if (!menu) {
          notification.warning({
            top: 92,
@@ -1042,14 +1042,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permMenus: state.permMenus,
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(PieChart)
export default PieChart
src/tabviews/custom/components/form/simple-form/index.jsx
@@ -1,7 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { connect } from 'react-redux'
import { Spin, notification } from 'antd'
import Api from '@/api'
@@ -196,7 +195,7 @@
  execSuccess = (btn, id) => {
    if (btn.linkmenu && btn.linkmenu.length > 0) {
      let menu_id = btn.linkmenu[btn.linkmenu.length - 1]
      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
      if (!menu) return
@@ -312,14 +311,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permMenus: state.permMenus,
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(SimpleForm)
export default SimpleForm
src/tabviews/custom/components/form/step-form/index.jsx
@@ -1,7 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { connect } from 'react-redux'
import { Spin, notification, Button } from 'antd'
import Api from '@/api'
@@ -245,7 +244,7 @@
    if (btn.linkmenu && btn.linkmenu.length > 0) {
      let menu_id = btn.linkmenu[btn.linkmenu.length - 1]
      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
      if (!menu) return
@@ -411,14 +410,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permMenus: state.permMenus,
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(StepForm)
export default StepForm
src/tabviews/custom/components/form/tab-form/index.jsx
@@ -1,7 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { connect } from 'react-redux'
import { Spin, notification } from 'antd'
import Api from '@/api'
@@ -206,7 +205,7 @@
  execSuccess = (btn, id) => {
    if (btn.linkmenu && btn.linkmenu.length > 0) {
      let menu_id = btn.linkmenu[btn.linkmenu.length - 1]
      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
      if (!menu) return
@@ -336,14 +335,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permMenus: state.permMenus,
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(TabForm)
export default TabForm
src/tabviews/custom/components/interfaces/index.jsx
New file
@@ -0,0 +1,37 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import MkInterItem from './interItem'
// import './index.scss'
class MkInterfaces extends Component {
  static propTpyes = {
    BID: PropTypes.any,
    interfaces: PropTypes.array
  }
  state = {}
  shouldComponentUpdate (nextProps, nextState) { return false }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  render() {
    const { interfaces, BID } = this.props
    return (
      <>
        {interfaces.map(m => <MkInterItem key={m.uuid} config={m} BID={BID}/>)}
      </>
    )
  }
}
export default MkInterfaces
src/tabviews/custom/components/interfaces/index.scss
src/tabviews/custom/components/interfaces/interItem/index.jsx
New file
@@ -0,0 +1,73 @@
import {Component} from 'react'
import PropTypes from 'prop-types'
import { notification } from 'antd'
import Api from '@/api'
import UtilsDM from '@/utils/utils-datamanage.js'
import MKEmitter from '@/utils/events.js'
import TimerTask from '@/utils/timer-task.js'
// import './index.scss'
class MkInterItem extends Component {
  static propTpyes = {
    BID: PropTypes.any,        // 上级主键值
    config: PropTypes.object,  // 配置信息
  }
  state = {}
  componentDidMount () {
    const { config } = this.props
    if (config.setting.timer) {
      this.timer = new TimerTask()
      this.timer.init(config.uuid, config.setting.timer, config.setting.timerRepeats, () => {this.loadData()})
    }
    setTimeout(() => {
      this.loadData()
    }, config.setting.delay)
  }
  shouldComponentUpdate (nextProps, nextState) { return false }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    this.timer && this.timer.stop()
  }
  async loadData () {
    const { config, BID } = this.props
    let param = UtilsDM.getQueryDataParams(config.setting, config.columns.map(col => col.field).join(','), [], config.setting.order, 1, 1, BID)
    let result = await Api.genericInterface(param)
    if (result.status) {
      let _data = { $$empty: true }
      if (result.data && result.data[0]) {
        _data = result.data[0]
      }
      _data.$$loaded = true
      MKEmitter.emit('mkPublicData', config.uuid, _data)
    } else {
      this.timer && this.timer.stop()
      notification.error({
        top: 92,
        message: result.message,
        duration: 10
      })
    }
  }
  render() {return null}
}
export default MkInterItem
src/tabviews/custom/components/interfaces/interItem/index.scss
src/tabviews/custom/components/share/normalTable/index.jsx
@@ -16,6 +16,7 @@
const { Paragraph } = Typography
const CardCellComponent = asyncComponent(() => import('@/tabviews/custom/components/card/cardcellList'))
const MkPicture = asyncComponent(() => import('@/components/mkPicture'))
const PicRadio = {
  '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%',
  '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%',
@@ -253,10 +254,7 @@
        <div>
          {photos.map((url, i) => (
            <Col key={i} span={col.span || 24}>
              <div className={'ant-mk-picture' + (scale ? ' scale' : '')} onClick={() => {
                if (!scale) return
                MKEmitter.emit('mkImageScale', url, photos)
              }} style={{paddingTop, backgroundImage: `url('${url}')`}}></div>
              <MkPicture style={{paddingTop}} scale={scale} url={url} urls={photos}/>
            </Col>
          ))}
        </div>
src/tabviews/custom/components/share/normalTable/index.scss
@@ -98,14 +98,7 @@
        }
        .ant-mk-picture {
          position: relative;
          background-position: center center;
          background-size: cover;
          background-repeat: no-repeat;
          background-color: #f5f5f5;
          margin: 2px;
        }
        .ant-mk-picture.scale {
          cursor: zoom-in;
        }
        .action-col {
          .ant-btn > .anticon + span {
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -893,7 +893,7 @@
  static propTpyes = {
    statFValue: PropTypes.any,       // 合计字段数据
    MenuID: PropTypes.string,        // 菜单Id
    setting: PropTypes.object,       // 表格全局设置:tableType(表格是否可选、单选、多选)、columnfixed(列固定)、actionfixed(按钮固定)
    setting: PropTypes.object,       // 表格全局设置:tableType(表格是否可选、单选、多选)、actionfixed(按钮固定)
    columns: PropTypes.array,        // 表格列
    lineMarks: PropTypes.any,        // 行标记
    fields: PropTypes.array,         // 组件字段集
src/tabviews/custom/components/table/edit-table/normalTable/index.scss
@@ -74,17 +74,6 @@
        .card-cell-list {
          color: rgba(0, 0, 0, 0.85);
        }
        .ant-mk-picture {
          position: relative;
          background-position: center center;
          background-size: cover;
          background-repeat: no-repeat;
          background-color: #f5f5f5;
          margin: 2px;
        }
        .ant-mk-picture.scale {
          cursor: zoom-in;
        }
        .action-col {
          .ant-btn > .anticon + span {
            margin-left: 3px;
src/tabviews/custom/index.jsx
@@ -1,15 +1,13 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Row, Col } from 'antd'
import Api from '@/api'
import options from '@/store/options.js'
import zhCN from '@/locales/zh-CN/main.js'
import enUS from '@/locales/en-US/main.js'
import Utils from '@/utils/utils.js'
import UtilsDM, { getStructuredParams, getStructDefaultParam } from '@/utils/utils-datamanage.js'
import { getStructuredParams, getStructDefaultParam } from '@/utils/utils-datamanage.js'
import asyncComponent from '@/utils/asyncComponent'
import MKEmitter from '@/utils/events.js'
import NotFount from '@/components/404'
@@ -42,6 +40,8 @@
const CustomChart = asyncComponent(() => import('./components/chart/custom-chart'))
const TimeLine = asyncComponent(() => import('./components/timeline/normal-timeline'))
const Voucher = asyncComponent(() => import('./components/module/voucher'))
const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
const MkInterfaces = asyncComponent(() => import('@/tabviews/custom/components/interfaces'))
class CustomPage extends Component {
  static propTpyes = {
@@ -65,7 +65,6 @@
    data: null,           // 列表数据集
    loading: false,       // 列表数据加载中
    visible: false,       // 标签页控制
    treevisible: false,   // 菜单结构树弹框显示隐藏控制
    shortcuts: null       // 快捷键
  }
@@ -73,7 +72,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, MenuID } = this.props
    const { MenuID } = this.props
    let _param = {
      func: 'sPC_Get_LongParam',
@@ -144,35 +143,6 @@
      window.GLOB.CacheData.set(MenuID, param)
      config.components = this.filterComponent(config.components, roleId, permAction, balMap, skip, param, MenuID)
      // 获取主搜索条件
      let mainSearch = []
      config.components.forEach(component => {
        if (component.type !== 'search') return
        component.search = component.search.map(item => {
          item.oriInitval = item.initval
          if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
            item.initval = param.$searchval
          }
          return item
        })
        mainSearch = Utils.initMainSearch(component.search)
      })
      let params = []
      let BID = param.$BID || ''
      let inherit = {}
      if (config.cacheUseful === 'true') { // 缓存继承
        inherit.cacheUseful = config.cacheUseful
        inherit.timeUnit = config.timeUnit
        inherit.cacheTime = config.cacheTime
      }
      let userName = sessionStorage.getItem('User_Name') || ''
      let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -202,6 +172,37 @@
        })
      }
      config.interfaces = this.formatInterSetting(config.interfaces, regs)
      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, param, MenuID, config.interfaces)
      // 获取主搜索条件
      let mainSearch = []
      config.components.forEach(component => {
        if (component.type !== 'search') return
        component.search = component.search.map(item => {
          item.oriInitval = item.initval
          if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
            item.initval = param.$searchval
          }
          return item
        })
        mainSearch = Utils.initMainSearch(component.search)
      })
      let params = []
      let BID = param.$BID || ''
      let inherit = {}
      if (config.cacheUseful === 'true') { // 缓存继承
        inherit.cacheUseful = config.cacheUseful
        inherit.timeUnit = config.timeUnit
        inherit.cacheTime = config.cacheTime
      }
      config.components = this.formatSetting(config.components, params, mainSearch, inherit, regs, balMap)
      if ([...balMap.keys()].length > 0) {
@@ -210,11 +211,11 @@
      this.setState({
        BID: BID,
        shortcuts,
        shortcuts: shortcuts.length > 0 ? shortcuts : null,
        config,
        mainSearch
      }, () => {
        if (!params || params.length === 0) {
        if (params.length === 0) {
          setTimeout(() => { // 延时加载状态
            this.setState({
              loadingview: false
@@ -227,8 +228,6 @@
        if (!this.props.Tab) {
          this.setShortcut()
        }
        this.loadData()
      })
    } else {
      this.setState({
@@ -246,11 +245,6 @@
  setShortcut = () => {
    const { shortcuts } = this.state
    if (!shortcuts || shortcuts.length === 0) {
      document.onkeydown = () => {}
      return
    }
    document.onkeydown = (event) => {
      let e = event || window.event
      let keyCode = e.keyCode || e.which || e.charCode
@@ -265,8 +259,18 @@
      }
      if (!preKey || !keyCode) return
      let _shortcut = `${preKey}+${keyCode}`
      if (window.GLOB.breakpoint && _shortcut === 'ctrl+67') {
        window.debugger = false
        window.GLOB.breakpoint = false
        sessionStorage.removeItem('breakpoint')
        MKEmitter.emit('debugChange')
      }
      if (!shortcuts) return
      shortcuts.some(item => {
        if (item.$shortcut === _shortcut) {
@@ -278,176 +282,7 @@
    }
  }
  loadData = () => {
    const { config } = this.state
    if (!config.interfaces || config.interfaces.length === 0) return
    let inters = []
    config.interfaces.forEach(item => {
      if (item.status !== 'true') return
      if (window.GLOB.systemType === 'production' && !item.proInterface) {
        notification.warning({
          top: 92,
          message: `《${item.name}》未设置正式系统地址!`,
          duration: 3
        })
        return
      }
      item.MenuName = config.MenuName || ''
      inters.push(item)
    })
    if (inters.length > 0) {
      this.loadOutResource(inters)
    }
  }
  loadOutResource = (inters) => {
    let setting = inters.shift()
    let param = UtilsDM.getPrevQueryParams(setting, [], this.state.BID)
    Api.genericInterface(param).then(res => {
      if (res.status) {
        if (res.mk_ex_invoke === 'false' || res.mk_ex_invoke === false) {
          if (inters.length > 0) {
            this.loadOutResource(inters)
          }
        } else {
          this.customOuterRequest(res, setting, inters)
        }
      } else {
        notification.error({
          top: 92,
          message: res.message,
          duration: 10
        })
      }
    })
  }
  customOuterRequest = (result, setting, inters) => {
    let url = ''
    if (window.GLOB.systemType === 'production') {
      url = setting.proInterface
    } else {
      url = setting.interface
    }
    let mkey = result.mk_api_key || ''
    delete result.mk_ex_invoke
    delete result.status
    delete result.message
    delete result.ErrCode
    delete result.ErrMesg
    delete result.mk_api_key
    let param = {}
    Object.keys(result).forEach(key => {
      key = key.replace(/^mk_/ig, '')
      param[key] = result[key]
    })
    Api.directRequest(url, setting.method, param, setting.cross).then(res => {
      if (typeof(res) !== 'object') {
        let error = '未知的返回结果!'
        if (typeof(res) === 'string') {
          error = res.replace(/'/ig, '"')
        }
        let _result = {
          mk_api_key: mkey,
          $ErrCode: 'E',
          $ErrMesg: error
        }
        this.customCallbackRequest(_result, setting, inters)
      } else {
        if (Array.isArray(res)) {
          res = { data: res }
        }
        res.mk_api_key = mkey
        this.customCallbackRequest(res, setting, inters)
      }
    }, (e) => {
      let _result = {
        mk_api_key: mkey,
        $ErrCode: 'E',
        $ErrMesg: e && e.statusText ? e.statusText : ''
      }
      this.customCallbackRequest(_result, setting, inters)
    })
  }
  customCallbackRequest = (result, setting, inters) => {
    let errSql = ''
    if (result.$ErrCode === 'E') {
      errSql = `
        set @ErrorCode='E'
        set @retmsg='${result.$ErrMesg}'
      `
      delete result.$ErrCode
      delete result.$ErrMesg
    }
    let lines = UtilsDM.getCallBackSql(setting, result)
    let param = {}
    if (setting.callbackType === 'script') { // 使用自定义脚本
      let sql = lines.map(item => (`
        ${item.insert}
        ${item.selects.join(` union all
        `)}
      `))
      sql = sql.join('')
      param = UtilsDM.getCallBackQueryParams(setting, sql, errSql, this.state.BID)
    } else {
      param.func = 's_ex_result_back'
      param.s_ex_result = lines.map((item, index) => ({
        MenuID: this.props.MenuID || '',
        MenuName: this.props.MenuName || '',
        TableName: item.table,
        LongText: window.btoa(window.encodeURIComponent(`${item.insert}  ${item.selects.join(` union all `)}`)),
        Sort: index + 1
      }))
      if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
        let sql = lines.map(item => (`
          ${item.insert}
          ${item.selects.join(` union all
          `)}
        `))
        sql = sql.join('')
        console.info(sql.replace(/\n\s{10}/ig, '\n'))
      }
    }
    Api.genericInterface(param).then(res => {
      if (res.status) {
        if (inters.length > 0) {
          this.loadOutResource(inters)
        }
      } else {
        notification.error({
          top: 92,
          message: res.message,
          duration: 10
        })
      }
    })
  }
  filterComponent = (components, roleId, permAction, balMap, skip, urlparam, pageId) => {
  filterComponent = (components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces) => {
    return components.filter(item => {
      item.$pageId = pageId
      
@@ -533,7 +368,7 @@
        item.subtabs = item.subtabs.map(tab => {
          tab.$pageId = pageId
          tab.components = this.filterComponent(tab.components, roleId, permAction, balMap, skip, urlparam, pageId)
          tab.components = this.filterComponent(tab.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces)
          return tab
        })
@@ -546,7 +381,7 @@
          return false
        }
        item.components = this.filterComponent(item.components, roleId, permAction, balMap, skip, urlparam, pageId)
        item.components = this.filterComponent(item.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces)
        return true
      } else if (['pie', 'bar', 'line', 'dashboard', 'scatter', 'chart'].includes(item.type)) {
@@ -562,6 +397,15 @@
          item.wrap.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0
        ) {
          return false
        }
        if (item.wrap.datatype === 'public') {
          let inter = interfaces.filter(int => item.wrap.publicId === int.uuid)[0]
          if (!inter) {
            item.wrap.datatype = 'static'
          } else {
            item.setting = inter.setting
          }
        }
      }
@@ -617,7 +461,7 @@
      
            if (col.linkmenu && col.linkmenu.length > 0) {
              let menu_id = col.linkmenu.pop()
              col.linkThdMenu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
              col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
            } else {
              col.linkThdMenu = ''
            }
@@ -996,6 +840,8 @@
        component.components = this.formatSetting(component.components, null, null, inherit, regs, balMap)
        component = {...component, ...inherit}
        return component
      } else if (component.wrap && component.wrap.datatype === 'public') {
        return component
      }
      if (component.setting) {
@@ -1092,6 +938,61 @@
    })
  }
  // 格式化默认设置
  formatInterSetting = (inters, regs) => {
    if (!inters) return []
    let interfaces = inters.filter(m => m.status === 'true')
    let delay = 15
    return interfaces.map(inter => {
      inter.setting.delay = delay
      delay += 15
      if (inter.setting.interType !== 'system') return inter
      let _customScript = ''
      inter.scripts.forEach(script => {
        if (script.status !== 'false') {
          _customScript += `
          ${script.sql}
          `
        }
      })
      delete inter.scripts
      inter.setting.$name = '公共数据源-' + inter.setting.name
      inter.setting.execute = inter.setting.execute !== 'false'
      inter.setting.laypage = true
      if (!inter.setting.execute) {
        inter.setting.dataresource = ''
      }
      if (/\s/.test(inter.setting.dataresource)) {
        inter.setting.dataresource = '(' + inter.setting.dataresource + ') tb'
      }
      if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
        inter.setting.dataresource = inter.setting.dataresource.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
        inter.setting.dataresource = inter.setting.dataresource.replace(/@\$/ig, '*/')
        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
        _customScript = _customScript.replace(/@\$/ig, '*/')
      } else {
        inter.setting.dataresource = inter.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
        _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
      }
      regs.forEach(cell => {
        inter.setting.dataresource = inter.setting.dataresource.replace(cell.reg, cell.value)
        _customScript = _customScript.replace(cell.reg, cell.value)
      })
      inter.setting.customScript = _customScript // 整理后自定义脚本
      return inter
    })
  }
  /**
   * @description 主表数据加载
   */ 
@@ -1151,6 +1052,7 @@
  }
  componentDidMount () {
    MKEmitter.addListener('debugChange', this.debugChange)
    MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.addListener('resetActiveMenu', this.resetActiveMenu)
  }
@@ -1162,11 +1064,21 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('debugChange', this.debugChange)
    MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
    MKEmitter.removeListener('resetActiveMenu', this.resetActiveMenu)
    window.GLOB.CacheData.delete(this.props.MenuID)
    this.deleteCache(this.state.config.components)
    if (this.state.config) {
      this.deleteCache(this.state.config.components)
      this.state.config.interfaces.forEach(m => {
        window.GLOB.CacheData.delete(m.uuid)
      })
    }
  }
  debugChange = () => {
    this.setState({visible: !this.state.visible})
  }
  deleteCache = (components) => {
@@ -1360,30 +1272,20 @@
  }
  render() {
    const { loadingview, viewlost, config, loading, shortcuts } = this.state
    const { loadingview, viewlost, config, loading, shortcuts, BID } = this.state
    return (
      <div className={'custom-page-wrap ' + (loadingview || loading ? 'loading' : '')} id={this.state.ContainerId} style={config ? config.style : null}>
        {(loadingview || loading) ? <Spin className="view-spin" size="large" /> : null}
        <Row className="component-wrap">{this.getComponents()}</Row>
        {config && config.interfaces.length > 0 ? <MkInterfaces BID={BID} interfaces={config.interfaces}/> : null}
        {config && window.GLOB.breakpoint ? <DebugTable /> : null}
        {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
        {!window.GLOB.mkHS && config ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts || []}/> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
      </div>
    )
  }
}
const mapStateToProps = (state) => {
  return {
    refreshTab: state.refreshTab,
    permAction: state.permAction,
    permMenus: state.permMenus
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(CustomPage)
export default CustomPage
src/tabviews/debugtable/index.jsx
New file
@@ -0,0 +1,117 @@
import React, {Component} from 'react'
import { is, fromJS } from 'immutable'
import { notification, Table} from 'antd'
import { RedoOutlined } from '@ant-design/icons'
import Api from '@/api'
import MKEmitter from '@/utils/events.js'
import UtilsDM from '@/utils/utils-datamanage.js'
import './index.scss'
class DebugTable extends Component {
  state = {
    columns: [
      {align: 'left', dataIndex: 'Sort', sorter: false, title: 'Sort', width: 120},
      {align: 'left', dataIndex: 'CDefine1', sorter: false, title: '文本1', width: 120},
      {align: 'left', dataIndex: 'CDefine2', sorter: false, title: '文本2', width: 120},
      {align: 'left', dataIndex: 'CDefine3', sorter: false, title: '文本3', width: 120},
      {align: 'left', dataIndex: 'CDefine4', sorter: false, title: '文本4', width: 120},
      {align: 'left', dataIndex: 'CDefine5', sorter: false, title: '文本5', width: 120},
      {align: 'left', dataIndex: 'CDefine6', sorter: false, title: '文本6', width: 120},
      {align: 'left', dataIndex: 'CDefine7', sorter: false, title: '文本7', width: 120},
    ],
    data: [],
    loading: false,
    setting: {
      interType: 'system',
      execute: true,
      dataresource: '(select * from s_debug_value_log where createuserid=@userid@) tb'
    },
    arr_field: 'ID,Sort,CDefine1,CDefine2,CDefine3,CDefine4,CDefine5,CDefine6,CDefine7'
  }
  /**
   * @description 子表数据加载
   */
  async loadmaindata () {
    const { setting, arr_field } = this.state
    this.setState({
      loading: true
    })
    let param = UtilsDM.getQueryDataParams(setting, arr_field, [], 'sort', 1, 9999, '')
    let result = await Api.genericInterface(param)
    if (result.status) {
      let start = 1
      this.setState({
        data: result.data.map((item, index) => {
          item.key = index
          item.$$uuid = item.ID || ''
          item.$Index = start + index + ''
          return item
        }),
        loading: false
      })
    } else {
      this.setState({
        loading: false
      })
      notification.error({
        top: 92,
        message: result.message,
        duration: 10
      })
    }
  }
  refreshDebugTable = () => {
    const { loading } = this.state
    if (!loading) {
      this.loadmaindata()
    }
  }
  UNSAFE_componentWillMount() {
    // 组件加载时,获取菜单数据
    this.loadmaindata()
  }
  componentDidMount() {
    MKEmitter.addListener('refreshDebugTable', this.refreshDebugTable)
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('refreshDebugTable', this.refreshDebugTable)
  }
  render() {
    const { data, loading, columns } = this.state
    return (
      <div className="debugtable">
        <RedoOutlined className="mk-debug-reload" onClick={() => this.loadmaindata()}/>
        <Table size="middle" columns={columns} dataSource={data} pagination={false} loading={loading} scroll={{ x: '100%', y: false }}/>
      </div>
    )
  }
}
export default DebugTable
src/tabviews/debugtable/index.scss
New file
@@ -0,0 +1,14 @@
.debugtable {
  position: relative;
  min-height: 200px;
  margin: 20px;
  .mk-debug-reload {
    color: var(--mk-sys-color);
    position: absolute;
    z-index: 1;
    top: 5px;
    right: 10px;
    font-size: 16px;
  }
}
src/tabviews/formtab/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Tabs} from 'antd'
import moment from 'moment'
@@ -48,7 +47,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, MenuID } = this.props
    const { MenuID } = this.props
    let param = {
      func: 'sPC_Get_LongParam',
@@ -104,13 +103,13 @@
      }
      if (!window.GLOB.mkHS) {
        config.action = config.action.filter(item => permAction[item.uuid])
        config.action = config.action.filter(item => window.GLOB.mkActions[item.uuid])
        config.tabgroups.forEach(group => {
          group.sublist = group.sublist.filter(tab => {
            if (tab.supMenu === 'mainTable') {
              tab.supMenu = MenuID
            }
            return permAction[tab.linkTab]
            return window.GLOB.mkActions[tab.linkTab]
          })
        })
      } else {
@@ -669,14 +668,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permAction: state.permAction
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(NormalTable)
export default NormalTable
src/tabviews/home/index.jsx
@@ -1,10 +1,10 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { notification, Spin } from 'antd'
import Api from '@/api'
import asyncComponent from '@/utils/asyncComponent'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const DefaultHome = asyncComponent(() => import('./defaulthome'))
@@ -18,25 +18,50 @@
  state = {
    loading: true,
    background: sessionStorage.getItem('home_background'),
    waiting: true,
    waitMenu: true,
    waitAction: true,
    view: ''
  }
  componentDidMount () {
    this.loadHomeConfig()
    if (this.props.permMenus.length > 0 && JSON.stringify(this.props.permAction) !== '{}') {
    if (window.GLOB.mkThdMenus.length > 0) {
      this.setState({
        waiting: false
        waitMenu: false
      })
    } else {
      MKEmitter.addListener('mkMenuLoaded', this.mkMenuLoaded)
    }
    if (window.GLOB.mkActions.loaded) {
      this.setState({
        waitAction: false
      })
    } else {
      MKEmitter.addListener('mkActionLoaded', this.mkActionLoaded)
    }
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (nextProps.permMenus.length > 0 && JSON.stringify(nextProps.permAction) !== '{}') {
      this.setState({
        waiting: false
      })
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('mkMenuLoaded', this.mkMenuLoaded)
    MKEmitter.removeListener('mkActionLoaded', this.mkActionLoaded)
  }
  mkMenuLoaded = () => {
    this.setState({
      waitMenu: false
    })
  }
  mkActionLoaded = () => {
    this.setState({
      waitAction: false
    })
  }
  loadHomeConfig = () => {
@@ -54,7 +79,8 @@
        } else {
          this.setState({
            loading: false,
            waiting: false,
            waitMenu: false,
            waitAction: false,
            view: 'default'
          })
        }
@@ -73,9 +99,9 @@
  }
  render() {
    const { loading, waiting, view, background } = this.state
    const { loading, waitAction, waitMenu, view, background } = this.state
    if (loading || waiting) {
    if (loading || waitAction || waitMenu) {
      return (<div className="home-loading-view" style={{background: background}}><Spin className="home-box-spin" size="large" /></div>)
    } else if (view === 'custom') {
      return (<CustomPage MenuID={this.props.MenuID} MenuName="首页"/>)
@@ -85,15 +111,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permAction: state.permAction,
    permMenus: state.permMenus
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(Home)
export default Home
src/tabviews/subtable/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Switch, Row, Col, Tabs} from 'antd'
@@ -84,7 +83,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, permMenus, Tab } = this.props
    const { Tab } = this.props
    let param = {
      func: 'sPC_Get_LongParam',
@@ -134,7 +133,7 @@
      // 权限过滤
      if (!window.GLOB.mkHS) {
        config.action = config.action.filter(item => item.hidden !== 'true' && permAction[item.uuid])
        config.action = config.action.filter(item => item.hidden !== 'true' && window.GLOB.mkActions[item.uuid])
      } else {
        config.action = config.action.filter(item => item.hidden !== 'true')
      }
@@ -183,7 +182,7 @@
          if (col.linkmenu && col.linkmenu.length > 0) {
            let menu_id = col.linkmenu.slice(-1)[0]
            col.linkThdMenu = permMenus.filter(m => m.MenuID === menu_id)[0] || ''
            col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
          } else {
            col.linkThdMenu = ''
          }
@@ -1129,15 +1128,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permAction: state.permAction,
    permMenus: state.permMenus,
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(SubTabViewTable)
export default SubTabViewTable
src/tabviews/subtabtable/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin} from 'antd'
@@ -61,7 +60,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, Tab } = this.props
    const { Tab } = this.props
    let param = {
      func: 'sPC_Get_LongParam',
@@ -129,7 +128,7 @@
      // 权限过滤
      if (!window.GLOB.mkHS) {
        config.action = config.action.filter(item => item.hidden !== 'true' && permAction[item.uuid])
        config.action = config.action.filter(item => item.hidden !== 'true' && window.GLOB.mkActions[item.uuid])
      } else {
        config.action = config.action.filter(item => item.hidden !== 'true')
      }
@@ -891,14 +890,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permAction: state.permAction
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(SubTabModalTable)
export default SubTabModalTable
src/tabviews/treepage/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { notification, Spin, Tabs, Tree, Row, Col, Card, Input, Empty } from 'antd'
import { FolderOpenOutlined, FolderOutlined, FileOutlined } from '@ant-design/icons'
@@ -59,7 +58,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, param, MenuName, MenuID } = this.props
    const { param, MenuName, MenuID } = this.props
    let _param = {
      func: 'sPC_Get_LongParam',
@@ -123,7 +122,7 @@
          if (tab.supMenu === 'mainTable') {
            tab.supMenu = MenuID
          }
          return permAction[tab.linkTab]}
          return window.GLOB.mkActions[tab.linkTab]}
        )
      })
@@ -632,21 +631,11 @@
          </Col>
        </Row> : null}
        {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts}/> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
      </div>
    )
  }
}
const mapStateToProps = (state) => {
  return {
    permAction: state.permAction
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(TreePage)
export default TreePage
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -376,7 +376,6 @@
        
        let item = {
          type: type,
          readonly: false,
          readin: true,
          writein: true,
          fieldlen: fieldlen,
@@ -555,6 +554,10 @@
        this.setState({checkParam: check_param})
      }
      if (window.GLOB.breakpoint) {
        param.func = 'sPC_TableData_InUpDe_debug'
      }
      _params.push(param)
    } else if (btn.Ot === 'required') {
      _params = data.map((cell, index) => {
@@ -672,6 +675,10 @@
          param.s_debug_type = 'Y'
        }
        if (window.GLOB.breakpoint) {
          param.func = 'sPC_TableData_InUpDe_debug'
        }
        return param
      })
    }
@@ -775,7 +782,7 @@
  /**
   * @description 获取回调脚本的字段定义
   */
  getSysDeclareSql = (btn, formdata, data, columns, primaryId, BID) => {
  getSysDeclareSql = (btn, formdata, data, columns, primaryId, BID = '') => {
    let datavars = {}                 // 声明的变量,表单及显示列
    // 需要声明的变量集
    let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
@@ -798,14 +805,11 @@
  
        if (form.type === 'number' || form.type === 'rate') {
          let val = form.value
          if (typeof(val) !== 'number') {
            val = parseFloat(val)
            if (isNaN(val)) {
              val = 0
            }
          if (isNaN(val)) {
            val = 0
          }
          _initFormfields.push(`@${_key}=${val}`)
        } else if (['date', 'datemonth', 'datetime'].includes(form.type)) {
        } else if (['date', 'datemonth'].includes(form.type)) {
          _initFormfields.push(`@${_key}='${form.value || '1949-10-01'}'`)
        } else {
          _initFormfields.push(`@${_key}='${form.value}'`)
@@ -840,7 +844,7 @@
    }
  
    // 添加数据中字段,表单值优先(按钮不选行或多行拼接时跳过)
    if (data && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce') {
    if (data && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce' && columns && columns.length > 0) {
      datavars = {...data, ...datavars}
  
      const setField = (col) => {
@@ -882,17 +886,15 @@
        }
      }
  
      if (columns && columns.length > 0) {
        columns.forEach(col => {
          if (col.type === 'colspan' || col.type === 'old_colspan') {
            col.subcols.forEach(cell => {
              setField(cell)
            })
          } else {
            setField(col)
          }
        })
      }
      columns.forEach(col => {
        if (col.type === 'colspan' || col.type === 'old_colspan') {
          col.subcols.forEach(cell => {
            setField(cell)
          })
        } else {
          setField(col)
        }
      })
    }
  
    // 变量声明
@@ -924,7 +926,7 @@
    // 初始化凭证及用户信息字段
    _sql += `
        /* 凭证及用户信息初始化赋值 */
        select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @BillCode='', @ModularDetailCode=''
        select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @bid='${BID}', @BillCode='', @ModularDetailCode=''
        `
  
    // 表单变量赋值
@@ -943,7 +945,7 @@
    }
    _sql = _sql.replace(/@ID@/ig, `'${primaryId || ''}'`)
    _sql = _sql.replace(/@BID@/ig, `'${BID || ''}'`)
    _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') || ''}'`)
@@ -1882,6 +1884,10 @@
    } else if (btn.execSuccess !== 'never') {
      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn, id, this.state.selines)
    }
    if (window.GLOB.breakpoint) {
      MKEmitter.emit('refreshDebugTable')
    }
    
    btn.syncComponentId && MKEmitter.emit('reloadData', btn.syncComponentId)
@@ -1941,6 +1947,15 @@
  }
  sendWxMessage = (verify, id) => {
    if (!window.GLOB.nginx) {
      notification.warning({
        top: 92,
        message: 'nginx服务尚未开启,不可发送模板消息。',
        duration: 5
      })
      return
    }
    let param = {
      func: 's_get_sms_weixin_local',
      upid: id
@@ -2020,6 +2035,7 @@
                upid: id,
                send_id: n.client_msg_id || '',
                status_result: re.errcode === 0 ? 'S' : 'E',
                errcode: re.errcode,
                msg_result: re.errmsg
              }
@@ -2037,9 +2053,23 @@
                }
              })
            } else if (re.errcode !== 0 && re.errmsg) {
              let msgs = [
                {errcode: -1, errmsg: '系统繁忙,请稍候再试'},
                {errcode: 40001, errmsg: 'access_token 无效'},
                {errcode: 40003, errmsg: '不合法的 OpenID'},
                {errcode: 40014, errmsg: '不合法的 access_token'},
                {errcode: 40033, errmsg: '不合法的请求字符'},
                {errcode: 43004, errmsg: '需要接收者关注'},
                {errcode: 43019, errmsg: '需要将接收者从黑名单中移除'},
                {errcode: 50005, errmsg: '用户未关注公众号'}
              ]
              let msg = msgs.filter(m => m.errcode === re.errcode)[0]
              msg = msg || re
              notification.warning({
                top: 92,
                message: re.errmsg,
                message: msg.errmsg,
                duration: 5
              })
            }
@@ -2262,6 +2292,10 @@
      let data = this.props.selectedData && this.props.selectedData[0] ? this.props.selectedData[0] : null
      this.setState({check: data && data[btn.field] === btn.openVal})
    }
    if (window.GLOB.breakpoint) {
      MKEmitter.emit('refreshDebugTable')
    }
  }
  handleModelConfig = (config) => {
@@ -2398,73 +2432,86 @@
    btnconfig.fields.forEach(item => {
      if (!item.field) return
      let _readin = item.readin !== 'false'
      let _initval = item.initval
      let _item = {
        key: item.field,
        readin: item.readin !== 'false' && item.readin !== 'top',
        fieldlen: item.fieldlength || 50,
        writein: item.writein !== 'false',
        type: item.type
      }
      if (item.type === 'linkMain' || item.type === 'funcvar') {
      let _initval = item.initval
      let _readin = item.readin !== 'false'
      let _format = item.precision || 'day' // 时间格式化
      if (item.type === 'funcvar') {
        _initval = ''
        _readin = false
        _item.readin = false
      } else if (item.type === 'linkMain') {
        _readin = false
        _item.readin = false
      } else if (item.type === 'date') {
        if (_format !== 'day') {
          _format = 'YYYY-MM-DD HH:mm:ss'
        } else {
          _format = 'YYYY-MM-DD'
        }
      } else if (item.type === 'datetime') {
        _item.type = 'date'
        _format = 'YYYY-MM-DD HH:mm:ss'
      }
      let key = item.field.toLowerCase()
      if (item.type === 'linkMain' && BData.hasOwnProperty(key)) {
      if (_item.type === 'linkMain' && BData.hasOwnProperty(key)) {
        _initval = BData[key]
      } else if (_readin && _data.hasOwnProperty(key)) {
        _initval = _data[key]
      } else if (item.type === 'date' && _initval) {
        _initval = moment().subtract(_initval, 'days').format('YYYY-MM-DD')
      } else if (item.type === 'datemonth' && _initval) {
      } else if (_item.type === 'date' && _initval) {
        _initval = moment().subtract(_initval, 'days').format(_format)
      } else if (_item.type === 'datemonth' && _initval) {
        _initval = moment().subtract(_initval, 'month').format('YYYY-MM')
      } else if (item.type === 'datetime' && _initval) {
        _initval = moment().subtract(_initval, 'days').format('YYYY-MM-DD HH:mm:ss')
      }
      if (_initval === undefined) {
        _initval = ''
      }
      _item.value = _initval === undefined ? '' : _initval
      let _fieldlen = item.fieldlength || 50
      if (item.type === 'textarea' || item.type === 'fileupload' || item.type === 'multiselect') {
        _fieldlen = item.fieldlength || 512
      } else if (item.type === 'number') {
        _fieldlen = item.decimal ? item.decimal : 0
      } else if (item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_initval)) { // 特殊字段替换
        _initval = _initval.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (BID || ''))
      }
      if (_item.type === 'number' || item.declare === 'decimal') {
        _item.type = 'number'
        _item.fieldlen = item.decimal || 0
      } else if (['text', 'textarea', 'linkMain'].includes(_item.type)) {
        _item.value = _item.value + ''
        _item.value = _item.value.replace(/\t*|\v*/g, '')       // 去除制表符
      let _type = item.type
      if (['date', 'datemonth', 'datetime'].includes(_type) && item.declareType === 'nvarchar(50)') {
        _type = 'text'
      } else if (item.type === 'rate') {
        item.rateCount = item.rateCount || 5
        let allowHalf = item.allowHalf === 'true'
        if (allowHalf) {
          _initval = parseFloat(_initval)
          if (_initval % 0.5 !== 0) {
            _initval = parseInt(_initval)
        if (item.interception !== 'false') {                    // 去除首尾空格
          _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
        }
        if (_item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 特殊字段替换
          _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (BID || ''))
        }
        if (_item.type === 'text' && item.lenControl && item.lenControl !== 'limit') {
          if (item.lenControl === 'left') {
            _item.value = _item.value.substr(0, item.fieldlength)
          } else {
            _item.value = _item.value.slice(-item.fieldlength)
          }
        } else {
          _initval = parseInt(_initval)
        }
      } else if (_item.type.indexOf('date') > -1) {
        if (item.declareType === 'nvarchar(50)') {
          _item.type = 'text'
        }
      } else if (_item.type === 'rate') {
        let count = item.rateCount || 5
        _item.value = parseInt(_item.value)
        if (isNaN(_initval) || _initval < 0) {
          _initval = 0
        } else if (_initval > item.rateCount) {
          _initval = item.rateCount
        if (isNaN(_item.value) || _item.value < 0) {
          _item.value = 0
        } else if (_item.value > count) {
          _item.value = count
        }
      }
      result.push({
        key: item.field,
        readonly: item.readonly === 'true',
        readin: item.readin !== 'false' && item.readin !== 'top',
        fieldlen: _fieldlen,
        writein: item.writein !== 'false',
        type: _type,
        value: _initval
      })
      result.push(_item)
    })
    if (btnconfig.setting.display === 'exec') {
src/tabviews/zshare/actionList/tabbutton/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { Button, notification } from 'antd'
@@ -153,20 +152,17 @@
          primaryId: primaryId
        }
      }
    } else {
      let menu = null
    } else if (btn.MenuID || btn.linkmenu) {
      let menuId = btn.MenuID || btn.linkmenu.slice(-1)[0]
      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
      if (btn.MenuID) {
        let _menu = this.props.permMenus.filter(m => m.MenuID === btn.MenuID)[0] || ''
      if (!menu && btn.MenuName && btn.tabType) {
        menu = {
          MenuID: btn.MenuID,
          MenuName: _menu ? _menu.MenuName : btn.MenuName,
          MenuName: btn.MenuName,
          MenuNo: btn.MenuNo,
          type: _menu ? _menu.type : btn.tabType
          type: btn.tabType
        }
      } else if (btn.linkmenu && btn.linkmenu.length > 0) {
        let menu_id = btn.linkmenu.slice(-1)[0]
        menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
      }
      if (!menu) {
@@ -242,14 +238,4 @@
  }
}
const mapStateToProps = (state) => {
  return {
    permMenus: state.permMenus,
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(TabButton)
export default TabButton
src/tabviews/zshare/mutilform/index.jsx
@@ -133,6 +133,9 @@
        readin = false
        item.readin = false
        item.hidden = true
      } else if (item.type === 'linkMain') {
        readin = false
        item.readin = false
      } else if (item.type === 'number') {
        item.decimal = item.decimal || 0
        item.fieldlength = item.decimal
@@ -163,23 +166,16 @@
      if (readin && data.hasOwnProperty(key)) {
        newval = data[key]
      }
      if (item.type === 'linkMain') {
        newval = BData[key] || '$empty'
      } else if (item.type === 'date') { // 时间搜索
        let format = 'YYYY-MM-DD'
      if (item.type === 'linkMain' && BData.hasOwnProperty(key)) {
        newval = BData[key]
      } else if (item.type === 'date') { // 时间表单,提交值为天或秒
        let _format = 'YYYY-MM-DD HH:mm:ss'
        if (item.precision === 'day') {
          _format = 'YYYY-MM-DD'
        } else if (item.precision === 'hour') {
          format = 'YYYY-MM-DD HH'
        } else if (item.precision === 'minute') {
          format = 'YYYY-MM-DD HH:mm'
        } else if (item.precision === 'second') {
          format = 'YYYY-MM-DD HH:mm:ss'
        }
        if (newval !== '$empty') {
          newval = moment(newval, format).format(_format)
          newval = moment(newval, 'YYYY-MM-DD HH:mm:ss').format(_format)
          newval = newval === 'Invalid date' ? '$empty' : newval
        }
        if (newval === '$empty' && item.initval) {
@@ -193,18 +189,6 @@
        if (newval === '$empty' && item.initval) {
          newval = moment().subtract(item.initval, 'month').format('YYYY-MM')
        }
      // } else if (item.type === 'datetime') {
      //   if (newval !== '$empty') {
      //     newval = moment(newval, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss')
      //     newval = newval === 'Invalid date' ? '$empty' : newval
      //   }
      //   if (newval === '$empty' && item.initval) {
      //     if (item.initval === '0') {
      //       newval = moment().format('YYYY-MM-DD HH:mm:ss')
      //     } else {
      //       newval = moment().subtract(item.initval, 'days').format('YYYY-MM-DD') + ' 00:00:00'
      //     }
      //   }
      } else if (item.type === 'switch') { // 开关只接收固定值
        if (newval !== '$empty' && (newval === item.closeVal || newval === item.openVal)) {
@@ -221,7 +205,11 @@
        item.initval = ''
      }
      if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect', 'cascader'].includes(item.type) && item.resourceType === '1') {
      if (item.type === 'number') {
        if (isNaN(item.initval)) {
          item.initval = 0
        }
      } else if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect', 'cascader'].includes(item.type) && item.resourceType === '1') {
        deForms.push(item)
      } else if (item.type === 'rate') {
        item.rateCount = item.rateCount || 5
@@ -244,9 +232,7 @@
      }
      if (item.type === 'text') {
        if (typeof(item.initval) === 'number') {
          item.initval = item.initval + ''
        }
        item.initval = item.initval + ''
        let _rules = [{
          pattern: /^[^']*$/ig,
          message: '不可使用英文状态的单引号!'
@@ -274,37 +260,32 @@
          if (item.regular === 'number') {
            _rules.push({
              pattern: /^[0-9.-]*$/,
              message: formRule.input.numbermsg
              message: item.regularText || formRule.input.numbermsg
            })
          } else if (item.regular === 'letter') {
            _rules.push({
              pattern: /^[a-zA-Z]*$/,
              message: formRule.input.lettermsg
              message: item.regularText || formRule.input.lettermsg
            })
          } else if (item.regular === 'letter_number') {
            _rules.push({
              pattern: /^[a-zA-Z0-9]*$/,
              message: '请输入数字或字母'
              message: item.regularText || '请输入数字或字母'
            })
          } else if (item.regular === 'letter&number') {
            _rules.push({
              pattern: /^[a-zA-Z0-9@_.]*$/,
              message: '请输入数字、字母以及@_.'
              message: item.regularText || '请输入数字、字母以及@_.'
            })
          } else if (item.regular === 'phone') {
            _rules.push({
              pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
              message: '请正确输入手机号'
              message: item.regularText || '请正确输入手机号'
            })
          } else if (item.regular === 'email') {
            _rules.push({
              pattern: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/,
              message: '请正确输入邮箱地址'
            })
          } else if (item.regular === 'funcname') {
            _rules.push({
              pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/,
              message: formRule.input.funcname
              message: item.regularText || '请正确输入邮箱地址'
            })
          }
        }
@@ -962,7 +943,6 @@
    
          let _item = {
            type: item.type,
            readonly: item.readonly,
            readin: item.readin,
            writein: item.writein,
            fieldlen: item.fieldlength,
@@ -973,29 +953,29 @@
    
          if (item.type === 'funcvar') {
            _item.value = ''
          } else if (_item.value && (item.type === 'text' || item.type === 'textarea' || item.type === 'linkMain') && typeof(_item.value) === 'string') {
          } else if (item.declare === 'decimal') {
            _item.type = 'number'
            _item.fieldlen = item.decimal || 0
          } else if (['text', 'textarea', 'linkMain'].includes(item.type)) {
            _item.value = _item.value + ''
            _item.value = _item.value.replace(/\t*|\v*/g, '')       // 去除制表符
    
            if (item.interception !== 'false') {           // 去除首尾空格
            if (item.interception !== 'false') {                    // 去除首尾空格
              _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
            }
            if (item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 特殊字段替换
              _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || ''))
            }
            if (item.type === 'text' && item.lenControl && item.lenControl !== 'limit') {
              if (item.lenControl === 'left') {
                _item.value = _item.value.substr(0, item.fieldlength)
              } else {
                _item.value = _item.value.slice(-item.fieldlength)
              }
            }
          } else if (item.type.indexOf('date') > -1) {
            if (item.declareType === 'nvarchar(50)') {
              _item.type = 'text'
            }
          } else if (item.declare === 'decimal' && ['select', 'link', 'radio', 'checkcard'].includes(item.type)) {
            _item.type = 'number'
            _item.fieldlen = item.decimal || 0
          }
          if (item.type === 'text' && item.lenControl && item.lenControl !== 'limit') {
            if (item.lenControl === 'left') {
              _item.value = _item.value.substr(0, item.fieldlength)
            } else {
              _item.value = _item.value.slice(-item.fieldlength)
            }
          }
    
src/tabviews/zshare/normalTable/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import md5 from 'md5'
import { is, fromJS } from 'immutable'
import { Table, Affix, Typography, Col } from 'antd'
import { Table, Typography, Col } from 'antd'
import asyncComponent from '@/utils/asyncComponent'
import MKEmitter from '@/utils/events.js'
@@ -18,6 +18,7 @@
const TabButton = asyncComponent(() => import('@/tabviews/zshare/actionList/tabbutton'))
const NewPageButton = asyncComponent(() => import('@/tabviews/zshare/actionList/newpagebutton'))
const Video = asyncComponent(() => import('@/components/video'))
const MkPicture = asyncComponent(() => import('@/components/mkPicture'))
const PicRadio = {
  '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%',
@@ -660,17 +661,7 @@
      return (
        <div className="picture-col">
          {photos.map((url, i) => (<Col key={i} span={item.span || 24}>
            <div
              className={'mk-picture' + (scale ? ' image-scale' : '')}
              onClick={(e) => {
                if (!scale) return
                e.stopPropagation()
                MKEmitter.emit('mkImageScale', url, photos)
              }}
              style={{...style, backgroundImage: `url('${url}')`}}
            ></div>
            <MkPicture style={style} scale={scale} url={url} urls={photos}/>
          </Col>))}
        </div>
      )
@@ -1250,21 +1241,6 @@
      }
    }
    // 表格头部固定于顶部时,判断距顶部高度
    let offset = null
    if (this.props.tableId === 'mainTable' && setting.columnfixed) {
      if (!setting.actionfixed) {
        offset = 48
      } else {
        let box = document.getElementById(this.props.MenuID + 'mainaction')
        if (box) {
          offset = 48 + box.offsetHeight
        } else {
          offset = 105
        }
      }
    }
    // 数据收起时,过滤已选数据
    let _data = this.props.data ? this.props.data : []
@@ -1308,22 +1284,6 @@
    return (
      <div className={'normal-data-table mingke-table ' + (height ? 'fixed-height' : '')}>
        {offset && <Affix offsetTop={offset} className="fix-header">
          <Table
            size={setting.size || 'middle'}
            style={style}
            bordered={setting.bordered !== 'false'}
            rowSelection={rowSelection}
            columns={this.state.columns.map(column => {
              return {
                align: column.align,
                dataIndex: column.dataIndex,
                title: column.title,
                width: column.width
              }
            })}
          />
        </Affix>}
        <Table
          components={components}
          size={setting.size || 'middle'}
src/tabviews/zshare/normalTable/index.scss
@@ -174,15 +174,6 @@
          >.ant-col {
            padding: 5px;
          }
          .mk-picture {
            background-color: #f5f5f5;
            background-position: center center;
            background-size: cover;
            background-repeat: no-repeat;
          }
          .image-scale {
            cursor: zoom-in;
          }
        }
        .action-col {
          .ant-btn > .anticon + span {
src/tabviews/zshare/settingcomponent/index.jsx
@@ -17,7 +17,6 @@
    dict: PropTypes.object,           // 字典表
    config: PropTypes.object,         // 页面配置信息
    shortcuts: PropTypes.any,         // 自定义设置
    permAction: PropTypes.object,     // 按钮权限
  }
  state = {
@@ -183,7 +182,7 @@
  }
  getPageConfig = () => {
    const { shortcuts, permAction } = this.props
    const { shortcuts } = this.props
    let config = fromJS(this.props.config).toJS()
    let userConfig = {}
    let components = []
@@ -262,7 +261,7 @@
          let _comp = {title: res.tab.label, uuid: res.tab.uuid, action: []}
          subconfig.action.forEach(item => {
            if (!permAction[item.uuid]) return
            if (!window.GLOB.mkActions[item.uuid]) return
            item.$expanded = false
            if (item.OpenType === 'funcbutton' && item.funcType === 'print') {
src/templates/formtabconfig/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
@@ -1805,12 +1804,4 @@
  }
}
const mapStateToProps = () => {
  return {}
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(ComTableConfig)
export default ComTableConfig
src/templates/modalconfig/index.jsx
@@ -1,6 +1,5 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
@@ -888,12 +887,4 @@
  }
}
const mapStateToProps = () => {
  return {}
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(ComModalConfig)
export default ComModalConfig
src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -561,6 +561,11 @@
            { pattern: _patten, message: formRule.func.innerMessage },
            { max: formRule.func.max, message: formRule.func.maxMessage }
          )
        } else if (item.key === 'sql' || item.key === 'sheet') {
          rules.push(
            { pattern: /^[a-zA-Z_]+$/, message: '表名只可使用字母以及_' },
            { max: formRule.func.max, message: formRule.func.maxMessage }
          )
        } else if (item.key === 'outerFunc' || item.key === 'callbackFunc') {
          rules.push(
            { pattern: formRule.func.pattern, message: formRule.func.message },
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -277,6 +277,17 @@
  }
  componentDidMount () {
    this.getsysScript()
  }
  getsysScript = () => {
    if (sessionStorage.getItem('mk_sys_scripts')) {
      this.setState({
        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
      })
      return
    }
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
@@ -290,18 +301,21 @@
    
    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
    _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 云端数据验证
    
    Api.getSystemConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = res.data.map(item => {
          return {
            name: item.funcname,
            value: window.decodeURIComponent(window.atob(item.longparam))
          }
        })
        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
        this.setState({
          systemScripts: res.data.map(item => {
            return {
              name: item.funcname,
              value: window.decodeURIComponent(window.atob(item.longparam))
            }
          })
          systemScripts: _scripts
        })
      } else {
        notification.warning({
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -294,6 +294,17 @@
  }
  componentDidMount () {
    this.getsysScript()
  }
  getsysScript = () => {
    if (sessionStorage.getItem('mk_sys_scripts')) {
      this.setState({
        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
      })
      return
    }
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
@@ -307,18 +318,21 @@
    
    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
    _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 云端数据验证
    
    Api.getSystemConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = res.data.map(item => {
          return {
            name: item.funcname,
            value: window.decodeURIComponent(window.atob(item.longparam))
          }
        })
        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
        this.setState({
          systemScripts: res.data.map(item => {
            return {
              name: item.funcname,
              value: window.decodeURIComponent(window.atob(item.longparam))
            }
          })
          systemScripts: _scripts
        })
      } else {
        notification.warning({
@@ -900,6 +914,11 @@
  sqlverify = (_resolve, _reject, scripts) => {
    const { searches, verify } = this.state
    if (verify.dataType !== 'custom') {
      _resolve()
      return
    }
    let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    let sql = SettingUtils.getDebugSql(verify, scripts, searches, Utils, timestamp)
    let param = {
src/templates/sharecomponent/settingcomponent/index.jsx
@@ -71,7 +71,6 @@
        loading: false
      })
      res.actionfixed = res.actionfixed === 'true'
      res.columnfixed = res.columnfixed === 'true'
      this.props.updatesetting({...config, setting: res})
src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
@@ -27,8 +27,6 @@
  state = {
    interType: 'system',
    procMode: 'script',
    requestMode: 'system',
    sysInterface: 'false',
    controlField: '',
    tableType: '',
@@ -66,8 +64,6 @@
    this.setState({
      interType: setting.interType || 'system',
      procMode: setting.procMode || 'script',
      requestMode: setting.requestMode || 'system',
      controlField: setting.controlField || '',
      sysInterface: setting.sysInterface || 'false',
      tableType: setting.tableType,
@@ -172,14 +168,6 @@
      this.setState({
        interType: value
      })
    } else if (key === 'procMode') {
      this.setState({
        procMode: value
      })
    } else if (key === 'requestMode') {
      this.setState({
        requestMode: value
      })
    } else if (key === 'sysInterface') {
      this.setState({
        sysInterface: value
@@ -204,7 +192,7 @@
  render() {
    const { setting, dict, menu, config, columns } = this.props
    const { getFieldDecorator } = this.props.form
    const { interType, funcRules, funcTooltip, procMode, requestMode, tableType, controlField, sysInterface } = this.state
    const { interType, funcRules, funcTooltip, tableType, controlField, sysInterface } = this.state
    const formItemLayout = {
      labelCol: {
@@ -232,6 +220,10 @@
                  {
                    max: 50,
                    message: '表名最长为50个字符!'
                  },
                  {
                    pattern: /^[a-zA-Z_]+$/,
                    message: '表名只可使用字母以及_'
                  }
                ]
              })(<Input placeholder={''} autoComplete="off" />)}
@@ -252,7 +244,6 @@
                <Radio value="system">系统</Radio>
                <Radio value="inner">内部</Radio>
                <Radio value="outer">外部</Radio>
                <Radio value="custom">自定义</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col>
@@ -286,47 +277,7 @@
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          {interType === 'custom' ? <Col span={8}>
            <Form.Item label="参数处理">
              {getFieldDecorator('procMode', {
                initialValue: procMode,
                rules: [
                  {
                    required: true,
                    message: dict['form.required.select'] + '参数处理方式!'
                  },
                ]
              })(
              <Radio.Group onChange={(e) => {this.onRadioChange(e, 'procMode')}}>
                <Radio value="script">前置脚本</Radio>
                <Radio value="inner">前置函数</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          {interType === 'custom' && procMode === 'inner' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title={funcTooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
                前置函数
              </Tooltip>
            }>
              {getFieldDecorator('prevFunc', {
                initialValue: setting.prevFunc || '',
                rules: [
                  {
                    required: true,
                    message: dict['form.required.input'] + '前置函数!'
                  },
                  {
                    max: formRule.func.max,
                    message: formRule.func.maxMessage
                  },
                  ...funcRules
                ]
              })(<Input placeholder={''} autoComplete="off" />)}
            </Form.Item>
          </Col> : null}
          {interType === 'outer' || interType === 'custom' ? <Col className="mk-through-line3" span={24}>
          {interType === 'outer' ? <Col className="mk-through-line3" span={24}>
            <Form.Item label="接口地址">
              {getFieldDecorator('interface', {
                initialValue: setting.interface || (interType === 'outer' && sysInterface === 'true' ? window.GLOB.mainSystemApi : ''),
@@ -339,7 +290,7 @@
              })(<TextArea rows={2} readOnly={interType === 'outer' && sysInterface === 'true'}/>)}
            </Form.Item>
          </Col> : null}
          {(interType === 'outer' && sysInterface !== 'true') || interType === 'custom' ? <Col className="mk-through-line3" span={24}>
          {interType === 'outer' && sysInterface !== 'true' ? <Col className="mk-through-line3" span={24}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="正式系统所使用的的接口地址。">
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -351,41 +302,7 @@
              })(<TextArea rows={2} />)}
            </Form.Item>
          </Col> : null}
          {interType === 'custom' ? <Col span={8}>
            <Form.Item label="请求方式">
              {getFieldDecorator('method', {
                initialValue: setting.method || 'post',
                rules: [
                  {
                    required: true,
                    message: dict['form.required.select'] + '请求方式!'
                  },
                ]
              })(
              <Radio.Group>
                <Radio value="get">GET</Radio>
                <Radio value="post">POST</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          {interType === 'custom' ? <Col span={8}>
            <Form.Item label="数据请求">
              {getFieldDecorator('requestMode', {
                initialValue: requestMode,
                rules: [
                  {
                    required: true,
                    message: dict['form.required.select'] + '数据请求方式!'
                  },
                ]
              })(
              <Radio.Group onChange={(e) => {this.onRadioChange(e, 'requestMode')}}>
                <Radio value="system">系统函数</Radio>
                <Radio value="inner">内部函数</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          {interType === 'inner' || (interType === 'custom' && requestMode === 'inner') ? <Col span={8}>
          {interType === 'inner' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title={funcTooltip}>
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -424,7 +341,7 @@
              })(<Input placeholder={''} autoComplete="off" />)}
            </Form.Item>
          </Col> : null}
          {interType === 'system' || (interType === 'custom' && requestMode === 'system') ? <Col span={24} className="mk-through-line3">
          {interType === 'system' ? <Col span={24} className="mk-through-line3">
            <Form.Item help={'数据ID:' + menu.MenuID} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } label={
              <Tooltip placement="topLeft" title={`使用系统函数时,需填写数据源。注:数据权限替换符 $@ -> /* 或 ''、 @$ -> */ 或 '';查询替换符 $select@ -> /* 或 ''、 @select$ -> */ 或 '';统计替换符 $sum@ -> /* 或 ''、 @sum$ -> */ 或 ''。`}>
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -436,7 +353,7 @@
              })(<CodeMirror />)}
            </Form.Item>
          </Col> : null}
          {interType === 'system' || (interType === 'custom' && requestMode === 'system') ? <Col span={8}>
          {interType === 'system' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title={'查询时,搜索条件以where条件拼接进入sql,统计时,将数据源中以“@+搜索字段+@”的内容,以搜索条件中的值进行替换后,提交查询,注:查询类型仅在使用系统函数时有效。'}>
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -452,7 +369,7 @@
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          {interType === 'system' || (interType === 'custom' && requestMode === 'system') ? <Col span={8}>
          {interType === 'system' ? <Col span={8}>
            <Form.Item label="默认sql">
              {getFieldDecorator('default', {
                initialValue: setting.default || 'true'
@@ -496,77 +413,6 @@
              })(<Input placeholder={'ID asc, UID desc'} autoComplete="off" />)}
            </Form.Item>
          </Col>
          {interType === 'custom' ? <Col span={8}>
            <Form.Item label="回调方式">
              {getFieldDecorator('callbackType', {
                initialValue: setting.callbackType || 'script'
              })(
              <Radio.Group onChange={(e) => {this.onRadioChange(e, 'callbackType')}}>
                <Radio value="default">默认脚本</Radio>
                <Radio value="script">自定义脚本</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          {interType === 'custom' ? <Col span={8}>
            <Form.Item label="回调表名">
              {getFieldDecorator('cbTable', {
                initialValue: setting.cbTable || '',
                rules: [
                  {
                    required: true,
                    message: dict['form.required.input'] + '回调表名!'
                  },
                  {
                    max: formRule.input.max,
                    message: formRule.input.message
                  }
                ]
              })(<Input placeholder={''} autoComplete="off" />)}
            </Form.Item>
          </Col> : null}
          {interType === 'custom' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title={'同步执行:外部接口调用成功后再请求数据;异步执行:外部接口调用与请求数据同时进行。'}>
                <QuestionCircleOutlined className="mk-form-tip" />
                执行方式
              </Tooltip>
            }>
              {getFieldDecorator('execType', {
                initialValue: setting.execType || 'sync'
              })(
              <Radio.Group>
                <Radio value="sync">同步</Radio>
                <Radio value="async">异步</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          {interType === 'custom' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title={'如果自定义接口不支持跨域请求,会通过当前系统转发。'}>
                <QuestionCircleOutlined className="mk-form-tip" />
                跨域请求
              </Tooltip>
            }>
              {getFieldDecorator('cross', {
                initialValue: setting.cross || 'true'
              })(
              <Radio.Group>
                <Radio value="true">支持</Radio>
                <Radio value="false">不支持</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          {interType === 'custom' ? <Col span={8}>
            <Form.Item label="执行次数">
              {getFieldDecorator('execTime', {
                initialValue: setting.execTime || 'once'
              })(
              <Radio.Group>
                <Radio value="always">始终</Radio>
                <Radio value="once">一次</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          <Col span={8}>
            <Form.Item label="是否分页">
              {getFieldDecorator('laypage', {
@@ -600,7 +446,7 @@
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          {config.Template === 'CommonTable' ? <Col span={8}>
          {/* {config.Template === 'CommonTable' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title={'含有合并列或表格出现横向滚动时会显示异常,请慎用!'}>
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -615,7 +461,7 @@
                <Radio value="false">{dict['model.false']}</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col> : null}
          </Col> : null} */}
          <Col span={8}>
            <Form.Item label="边框">
              {getFieldDecorator('bordered', {
@@ -688,22 +534,6 @@
              </Radio.Group>)}
            </Form.Item>
          </Col>
          {/* <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="在搜索条件存在时,是否显示搜索和重置按钮。">
                <QuestionCircleOutlined className="mk-form-tip" />
                搜索按钮
              </Tooltip>
            }>
              {getFieldDecorator('show', {
                initialValue: setting.show || 'true'
              })(
              <Radio.Group>
                <Radio value="true">显示</Radio>
                <Radio value="false">隐藏</Radio>
              </Radio.Group>)}
            </Form.Item>
          </Col> */}
          {tableType !== '' ? <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="当按钮执行完成并返回主键值时,默认选中主键值对应行。注:在启用无人值守功能时无效。">
@@ -733,18 +563,6 @@
              })(<InputNumber min={1} max={500} precision={0} />)}
            </Form.Item>
          </Col>
          {/* <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="高级搜索弹窗的宽度,注:当宽度值小于100时表示占窗口的百分比,大于100时表示宽度的绝对值。">
                <QuestionCircleOutlined className="mk-form-tip" />
                高级搜索
              </Tooltip>
            }>
              {getFieldDecorator('advanceWidth', {
                initialValue: setting.advanceWidth || 1000
              })(<InputNumber min={10} max={3000} precision={0}/>)}
            </Form.Item>
          </Col> */}
          <Col span={8}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="双击表格中行,触发的按钮。">
src/templates/sharecomponent/settingcomponent/settingform/index.jsx
@@ -17,7 +17,6 @@
const { Paragraph } = Typography
const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror'))
const CustomScript = asyncComponent(() => import('@/templates/zshare/customscript'))
const SimpleScript = asyncComponent(() => import('./simplescript'))
class SettingForm extends Component {
  static propTpyes = {
@@ -48,8 +47,6 @@
    let _setting = fromJS(config.setting).toJS()
    let _scripts = _setting.scripts || []
    let _preScripts = _setting.preScripts || []
    let _cbScripts = _setting.cbScripts || []
    _setting.default = _setting.default || 'true'            // 默认sql
    _setting.sysInterface = _setting.sysInterface || 'false' // 是否为系统接口
@@ -90,9 +87,6 @@
    _search = _search ? 'where ' + _search : ''
    let status = fromJS(_setting).toJS()
    status.requestMode = status.requestMode || 'system'
    status.procMode = status.procMode || 'script'
    status.callbackType = status.callbackType || 'script'
    let regoptions = this.getRegOptions(search)
    if (config.urlFields && config.urlFields.length > 0) {
@@ -111,12 +105,6 @@
        _scripts.forEach(item => {
          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
        })
        _preScripts.forEach(item => {
          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
        })
        _cbScripts.forEach(item => {
          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
        })
        if (_setting.dataresource) {
          _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`)
        }
@@ -130,8 +118,6 @@
      regoptions: regoptions, // 搜索条件,正则替换
      columns: columns,
      scripts: _scripts,
      preScripts: _preScripts,
      cbScripts: _cbScripts,
      status
    })
  }
@@ -241,18 +227,9 @@
  }
  handleConfirm = (trigger) => {
    const { activeKey, setting, scripts, preScripts, cbScripts } = this.state
    const { activeKey, setting, scripts } = this.state
    let _loading = false
    if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
      _loading = true
    } else if (this.preScriptsForm && this.preScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.preScriptsForm.props.form.getFieldValue('sql'))) {
      _loading = true
    } else if (this.cbScriptsForm && this.cbScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.cbScriptsForm.props.form.getFieldValue('sql'))) {
      _loading = true
    }
    if (_loading) {
      notification.warning({
        top: 92,
        message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!',
@@ -274,7 +251,7 @@
          }, () => {
            this.sqlverify(() => {
              this.setState({loading: false})
              resolve({...res, scripts, preScripts, cbScripts})
              resolve({...res, scripts})
            }, () => {
              this.setState({loading: false})
              reject()
@@ -289,7 +266,7 @@
      return new Promise((resolve, reject) => {
        this.sqlverify(() => {
          this.setState({loading: false})
          resolve({...setting, scripts, preScripts, cbScripts})
          resolve({...setting, scripts})
        }, () => {
          this.setState({loading: false})
          reject()
@@ -298,7 +275,7 @@
    } else {
      this.setState({loading: false})
      return new Promise((resolve) => {
        resolve({...setting, scripts, preScripts, cbScripts})
        resolve({...setting, scripts})
      })
    }
  }
@@ -306,7 +283,7 @@
  sqlverify = (_resolve, _reject, type, uscripts) => {
    const { setting, scripts, arr_field, regoptions, search } = this.state
    if (setting.interType !== 'system' && setting.requestMode !== 'system') { // 不使用系统接口时,不需要sql验证
    if (setting.interType !== 'system') { // 不使用系统接口时,不需要sql验证
      _resolve()
      return
    }
@@ -382,18 +359,9 @@
  // 标签切换
  changeTab = (val) => {
    const { activeKey, search, arr_field, setting } = this.state
    const { activeKey, search, arr_field } = this.state
    let _loading = false
    if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
      _loading = true
    } else if (this.preScriptsForm && this.preScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.preScriptsForm.props.form.getFieldValue('sql'))) {
      _loading = true
    } else if (this.cbScriptsForm && this.cbScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.cbScriptsForm.props.form.getFieldValue('sql'))) {
      _loading = true
    }
    if (_loading) {
      notification.warning({
        top: 92,
        message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!',
@@ -402,43 +370,9 @@
      return
    }
    if (activeKey !== 'setting') {
      if (setting.interType !== 'system' && setting.requestMode !== 'system' && val === 'scripts') {
        notification.warning({
          top: 92,
          message: '使用系统接口时,才可以设置自定义脚本!',
          duration: 5
        })
        return
      } else if (setting.interType !== 'custom' && (val === 'prescripts' || val === 'cbscripts')) {
        notification.warning({
          top: 92,
          message: '使用自定义接口时,才可以设置前置或回调脚本!',
          duration: 5
        })
        return
      }
    }
    if (activeKey === 'setting') {
      let _defaultSql = ''
      this.settingForm.handleConfirm().then(res => {
        if (res.interType !== 'system' && res.requestMode !== 'system' && val === 'scripts') {
          notification.warning({
            top: 92,
            message: '使用系统接口时,才可以设置自定义脚本!',
            duration: 5
          })
          return
        } else if (res.interType !== 'custom' && (val === 'prescripts' || val === 'cbscripts')) {
          notification.warning({
            top: 92,
            message: '使用自定义接口时,才可以设置前置或回调脚本!',
            duration: 5
          })
          return
        }
        if (res.dataresource) {
          let _dataresource = res.dataresource
@@ -534,16 +468,6 @@
  scriptsUpdate = (scripts) => {
    this.setState({scripts})
  }
  // 前置脚本更新
  preScriptsUpdate = (preScripts) => {
    this.setState({preScripts})
  }
  // 后置脚本更新
  cbScriptsUpdate = (cbScripts) => {
    this.setState({cbScripts})
  }
  handleDelete = (item) => {
    const { script, scripts } = this.state
@@ -573,7 +497,7 @@
  render() {
    const { config, menu, dict } = this.props
    const { loading, activeKey, setting, defaultSql, columns, scripts, preScripts, cbScripts, status, regoptions, visible, script, scriptValue } = this.state
    const { loading, activeKey, setting, defaultSql, columns, scripts, status, visible, script, scriptValue } = this.state
    return (
      <div className="model-table-setting-form-box">
@@ -596,7 +520,7 @@
              自定义脚本
              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
            </span>
          } disabled={!(status.interType === 'system' || (status.interType === 'custom' && status.requestMode === 'system'))} key="scripts" id="mk-setting-scripts">
          } disabled={status.interType !== 'system'} key="scripts" id="mk-setting-scripts">
            {scripts.length ? <BorderOutlined className="full-scripts" onClick={() => {
              if (this.scriptsForm && (this.scriptsForm.state.editItem || (this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))))) {
                notification.warning({
@@ -618,37 +542,6 @@
              scriptsChange={this.scriptsChange}
              scriptsUpdate={this.scriptsUpdate}
              wrappedComponentRef={(inst) => this.scriptsForm = inst}
            />
          </TabPane>
          <TabPane tab={
            <span>
              前置脚本
              {preScripts.length ? <span className="count-tip">{preScripts.length}</span> : null}
            </span>
          } disabled={status.interType !== 'custom' || status.procMode !== 'script'} key="prescripts">
            <SimpleScript
              dict={dict}
              setting={setting}
              scripts={preScripts}
              regoptions={regoptions}
              urlFields={config.urlFields}
              searches={this.props.search}
              scriptsUpdate={this.preScriptsUpdate}
              wrappedComponentRef={(inst) => this.preScriptsForm = inst}
            />
          </TabPane>
          <TabPane tab={
            <span>
              回调脚本
              {cbScripts.length ? <span className="count-tip">{cbScripts.length}</span> : null}
            </span>
          } disabled={status.interType !== 'custom' || status.callbackType !== 'script'} key="cbscripts">
            <SimpleScript
              dict={dict}
              setting={setting}
              scripts={cbScripts}
              scriptsUpdate={this.cbScriptsUpdate}
              wrappedComponentRef={(inst) => this.cbScriptsForm = inst}
            />
          </TabPane>
        </Tabs>
src/templates/sharecomponent/settingcomponent/settingform/index.scss
@@ -27,6 +27,13 @@
      }
    }
  }
  .mk-color-move {
    height: 40px;
    .color-sketch-block {
      position: relative;
      top: 7px;
    }
  }
  .operation-btn {
    display: inline-block;
    font-size: 16px;
src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
@@ -152,6 +152,13 @@
  }
  getsysScript = () => {
    if (sessionStorage.getItem('mk_sys_scripts')) {
      this.setState({
        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
      })
      return
    }
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
@@ -170,13 +177,14 @@
    Api.getSystemConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = res.data.map(item => {
          let _item = {
          return {
            name: item.funcname,
            value: window.decodeURIComponent(window.atob(item.longparam))
          }
          return _item
        })
        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
        this.setState({
          systemScripts: _scripts
        })
src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
@@ -157,7 +157,7 @@
        }
        scripts && scripts.forEach(script => {
          if (reg.test(script.sql)) {
            errors.push(`自定义脚本(${script.$index})存在未替换值${item}`)
            errors.push(`自定义脚本(${script.$index || ''})存在未替换值${item}`)
          }
        })
      })
src/templates/sharecomponent/tablecomponent/index.jsx
@@ -68,6 +68,8 @@
    Api.getSystemCacheConfig(param).then(res => {
      if (res.status) {
        let tbNames = res.data.map(item => item.TbName).join(',')
        sessionStorage.setItem('mk_tb_names', ',' + tbNames.toLowerCase() + ',')
        this.setState({
          tables: res.data
        })
@@ -82,7 +84,7 @@
  }
  gettableFields = () => {
    let deffers = this.state.selectedTables.map(item => {
    let deffers = this.state.selectedTables.map((item, i) => {
      return new Promise(resolve => {
        let param = {func: 'sPC_Get_FieldName', TBName: item.TbName}
        if (options.cloudServiceApi) { // 且存在云端地址
@@ -91,10 +93,12 @@
          param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
        }
        Api.getSystemCacheConfig(param).then(res => {
          res.TBName = item.TbName
          resolve(res)
        })
        setTimeout(() => {
          Api.getSystemCacheConfig(param).then(res => {
            res.TBName = item.TbName
            resolve(res)
          })
        }, (i + 1) * 100)
      })
    })
    Promise.all(deffers).then(response => {
src/templates/zshare/customscript/index.jsx
@@ -122,6 +122,12 @@
  }
  getsysScript = () => {
    if (sessionStorage.getItem('mk_sys_scripts')) {
      this.setState({
        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
      })
      return
    }
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
@@ -147,6 +153,8 @@
          return _item
        })
        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
        this.setState({
          systemScripts: _scripts
        })
src/templates/zshare/editTable/index.jsx
@@ -364,7 +364,47 @@
    let data = fromJS(this.state.data).toJS()
    this.pasteFormRef.handleConfirm().then(res => {
      if (res.key !== type) {
      if (res.copyType === 'columns' && type === 'datasourcefield') {
        res.type = 'array'
        res.data = []
        res.columns.forEach(col => {
          if (!col.field) return
          if (col.type === 'number') {
            let datatype = 'Int'
            if (col.decimal) {
              datatype = `Decimal(18,${col.decimal})`
            }
            res.data.push({
              $index: res.data.length + 1,
              datatype: datatype,
              field: col.field,
              decimal: col.decimal,
              label: col.label,
              type: 'number',
              uuid: Utils.getuuid()
            })
          } else {
            let datatype = 'Nvarchar(50)'
            let fieldlength = 50
            if (col.fieldlength && [10, 20, 50, 100, 256, 512, 1024, 2048].includes(col.fieldlength)) {
              fieldlength = col.fieldlength
              datatype = `Nvarchar(${fieldlength})`
            }
            res.data.push({
              $index: res.data.length + 1,
              datatype: datatype,
              field: col.field,
              fieldlength: fieldlength,
              label: col.label,
              type: 'text',
              uuid: Utils.getuuid()
            })
          }
        })
      } else if (res.key !== type) {
        message.warning('配置信息格式错误!')
        return
      }
src/templates/zshare/formconfig.jsx
@@ -3571,6 +3571,24 @@
      required: false
    },
    {
      type: 'radio',
      key: 'lenControl',
      label: '长度控制',
      initVal: card.lenControl || 'limit',
      tooltip: '在设置字段长度后,对长度的控制方式。',
      required: false,
      options: [{
        value: 'limit',
        text: '限制输入'
      }, {
        value: 'left',
        text: '左截'
      }, {
        value: 'right',
        text: '右截'
      }]
    },
    {
      type: 'number',
      key: 'span',
      min: 1,
@@ -3602,24 +3620,6 @@
      }, {
        value: 6,
        text: 6
      }]
    },
    {
      type: 'radio',
      key: 'lenControl',
      label: '长度控制',
      initVal: card.lenControl || 'limit',
      tooltip: '在设置字段长度后,对长度的控制方式。',
      required: false,
      options: [{
        value: 'limit',
        text: '限制输入'
      }, {
        value: 'left',
        text: '左截'
      }, {
        value: 'right',
        text: '右截'
      }]
    },
    {
@@ -3687,6 +3687,15 @@
    },
    {
      type: 'text',
      key: 'regularText',
      label: '正则提示',
      initVal: card.regularText || '',
      tooltip: '正则验证时的提示信息。',
      required: false,
      readonly: false
    },
    {
      type: 'text',
      key: 'tooltip',
      label: '悬浮提示',
      tooltip: '鼠标悬浮于提示文字上方时,显示提示信息。',
@@ -3722,7 +3731,7 @@
    {
      type: 'text',
      key: 'placeholder',
      label: '提示信息',
      label: '输入提示',
      tooltip: '字段预期值的提示信息。',
      initVal: card.placeholder || '',
      required: false
src/templates/zshare/modalform/index.jsx
@@ -41,7 +41,7 @@
  formula: ['label', 'type', 'marginTop', 'marginBottom', 'splitline', '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'],
  linkMain: ['readonly', 'required', 'hidden', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'interception', 'extra', 'marginTop', 'marginBottom']
  linkMain: ['readonly', 'required', 'hidden','declare', 'span', 'labelwidth', 'tooltip', 'interception', 'extra', 'marginTop', 'marginBottom']
}
class MainSearch extends Component {
@@ -140,6 +140,9 @@
      if (this.record.enter === 'tab' || this.record.enter === 'sub') {
        shows.push('tabField')
      }
      if (this.record.regular !== '') {
        shows.push('regularText')
      }
    } else if (type === 'number') {
      reTypes.initval = 'number'
      reRequired.initval = true
@@ -149,6 +152,12 @@
      if (sessionStorage.getItem('appType') === 'mob') { // 移动端右侧扩展信息
        shows.push('placeholder')
      }
    } else if (type === 'linkMain') {
      if (this.record.declare === 'nvarchar') {
        shows.push('fieldlength')
      } else if (this.record.declare === 'decimal') {
        shows.push('decimal')
      }
    } else if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(type)) {
      if (this.record.resourceType === '0') {        // 自定义资源
        shows.push('options')
src/templates/zshare/verifycard/baseform/index.jsx
@@ -29,7 +29,7 @@
    const { verify } = this.props
    let wxTemps = sessionStorage.getItem('wxTemplates')
    if (window.GLOB.WXAppID && !wxTemps) {
    if (window.GLOB.WXAppID && window.GLOB.nginx && !wxTemps) {
      Api.wxAccessToken().then(res => {
        let wxtoken = res.oa_access_token || ''
        // let minitoken = res.mini_access_token || ''
src/templates/zshare/verifycard/customscript/index.jsx
@@ -325,7 +325,7 @@
          </Col>
          <Col span={24} className="sql">
            <Form.Item label={
              <Tooltip placement="topLeft" title={'数据检查替换符 $check@ -> \'\'、 @check$ -> \'\',ErrorCode等于C时 $check@ -> /*、 @check$ -> */。注:1、需使用系统接口 2、行设置为“选择多行”时无效。'}>
              <Tooltip placement="topLeft" overlayStyle={{width: '320px', maxWidth: '320px'}} title={<><div>{'调试替换符 /*$breakpoint_begin_xxxx@ 、@breakpoint_end_xxxx$*/,在控制台中输入 window.debug = \'xxxx\' 会启用对应的调试语句,快捷键 ctrl+c 或在控制台中输入 window.debug = false 关闭调试。注:调试时字符 $breakpoint_proc@ 将被替换。'}</div><div style={{height: '5px'}}></div><div>{'数据检查替换符 $check@ -> \'\'、 @check$ -> \'\',ErrorCode等于C时 $check@ -> /*、 @check$ -> */。注:1、需使用系统接口 2、行设置为“选择多行”时无效。'}</div></>}>
                <QuestionCircleOutlined className="mk-form-tip" />
                sql
              </Tooltip>
src/templates/zshare/verifycard/index.jsx
@@ -1517,7 +1517,7 @@
    return (
      <div>
        {card.label ? <div className="mk-com-name">{card.label} - 验证信息</div> : null}
        <Tabs activeKey={activeKey} className="verify-card-box" onChange={this.changeTab}>
        <Tabs activeKey={activeKey} className="mk-verify-tabs" onChange={this.changeTab}>
          {verifyInter === 'system' || card.intertype === 'inner' ? <TabPane tab={
            <span>
              基础验证
src/templates/zshare/verifycard/index.scss
@@ -1,4 +1,7 @@
.verify-card-box {
.mk-verify-tabs {
  .ant-tabs-nav .ant-tabs-tab {
    margin-right: 25px;
  }
  .ant-tabs-nav-scroll {
    text-align: center;
  }
@@ -226,4 +229,13 @@
    color: #1890ff;
    border-top: 1px solid #e9e9e9;
  }
}
@media screen and (max-width: 1500px) {
  .mk-verify-tabs {
    .ant-tabs-nav .ant-tabs-tab {
      margin: 0 15px 0 0;
      padding: 12px 12px;
    }
  }
}
src/utils/utils-custom.js
@@ -590,7 +590,7 @@
      }
  
      if (item.btnlog) {
        item.btnlog = []
        item.btnlog = null
      }
  
      let oriUids = {}
@@ -870,7 +870,7 @@
    }
    if (item.btnlog) {
      item.btnlog = []
      item.btnlog = null
    }
    let oriUids = {}
@@ -970,4 +970,167 @@
  }
  
  return JSON.parse(_style)
}
/**
 * @description 获取表名
 */
export function getTables (config) {
  let tables = []
  let cuts = []
  let cutreg = /(from|update|insert\s+into)\s+(@db@)?[a-z_]+/ig
  let trimreg = /(from|update|insert\s+into)\s+(@db@)?/ig
  if (!config.wrap || !config.wrap.datatype || config.wrap.datatype === 'dynamic') {
    if (config.setting.interType === 'system') {
      if (config.setting.execute !== 'false') {
        let tbs = config.setting.dataresource.match(cutreg)
        tbs && cuts.push(...tbs)
      }
      config.scripts && config.scripts.forEach(script => {
        if (script.status === 'false') return
        let tbs = script.sql.match(cutreg)
        tbs && cuts.push(...tbs)
      })
    } else {
      let tb = config.setting.tableName.replace(/@db@|\s+/ig, '')
      if (/[a-z_]+/ig.test(tb)) {
        tables.push(tb)
      }
    }
  }
  let action = []
  if (config.type === 'form') {
    config.subcards.forEach(item => {
      action.push(item.subButton)
    })
  } else if (config.subcards) {
    config.subcards.forEach(item => {
      item.elements.forEach(cell => {
        if (cell.eleType === 'button' && ['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
          action.push(cell)
        }
      })
      if (item.backElements && item.setting.type === 'multi') {
        item.backElements.forEach(cell => {
          if (cell.eleType === 'button' && ['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
            action.push(cell)
          }
        })
      }
    })
  }
  config.cols && config.cols.forEach(col => {
    if (col.type === 'action') {
      col.elements.forEach(cell => {
        if (['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
          action.push(cell)
        }
      })
    }
  })
  config.elements && config.elements.forEach(cell => {
    if (cell.eleType === 'button' && ['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
      action.push(cell)
    }
  })
  config.action && config.action.forEach(cell => {
    if (['pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
      action.push(cell)
    }
  })
  action.forEach(btn => {
    if (btn.OpenType === 'excelIn') {
      if (!btn.verify) return
      if (btn.intertype !== 'system' || btn.verify.default !== 'false') {
        let tb = btn.sheet.replace(/@db@|\s+/ig, '')
        if (/[a-z_]+/ig.test(tb)) {
          tables.push(tb)
        }
      }
      if (btn.intertype === 'system' && btn.verify.scripts) {
        btn.verify.scripts.forEach(script => {
          if (script.status === 'false') return
          let tbs = script.sql.match(cutreg)
          tbs && cuts.push(...tbs)
        })
      }
    } else if (btn.OpenType === 'excelOut') {
      if (btn.intertype !== 'system' || !btn.verify) return
      if (btn.verify.dataType === 'custom') {
        if (btn.verify.defaultSql !== 'false') {
          let tbs = btn.verify.dataresource.match(cutreg)
          tbs && cuts.push(...tbs)
        }
        btn.verify.scripts && btn.verify.scripts.forEach(script => {
          if (script.status === 'false') return
          let tbs = script.sql.match(cutreg)
          tbs && cuts.push(...tbs)
        })
      }
      if (btn.verify.enable === 'true' && btn.verify.script) {
        let tbs = btn.verify.script.match(cutreg)
        tbs && cuts.push(...tbs)
      }
    } else {
      if (btn.intertype === 'inner') return
      if (btn.intertype === 'outer' || btn.intertype === 'custom') {
        if (btn.procMode === 'system' && btn.verify) {
          if (btn.verify.default !== 'false' && btn.sql) {
            let tb = btn.sql.replace(/@db@|\s+/ig, '')
            if (/[a-z_]+/ig.test(tb)) {
              tables.push(tb)
            }
          }
          btn.verify.customverifys && btn.verify.customverifys.forEach(script => {
            if (script.status === 'false') return
            let tbs = script.sql.match(cutreg)
            tbs && cuts.push(...tbs)
          })
          btn.verify.scripts && btn.verify.scripts.forEach(script => {
            if (script.status === 'false') return
            let tbs = script.sql.match(cutreg)
            tbs && cuts.push(...tbs)
          })
        }
        if (btn.callbackType === 'script' && btn.verify) {
          btn.verify.cbScripts && btn.verify.cbScripts.forEach(script => {
            if (script.status === 'false') return
            let tbs = script.sql.match(cutreg)
            tbs && cuts.push(...tbs)
          })
        }
      } else if (btn.verify) {
        if (btn.verify.default !== 'false' && btn.sql) {
          let tb = btn.sql.replace(/@db@|\s+/ig, '')
          if (/[a-z_]+/ig.test(tb)) {
            tables.push(tb)
          }
        }
        btn.verify.customverifys && btn.verify.customverifys.forEach(script => {
          if (script.status === 'false') return
          let tbs = script.sql.match(cutreg)
          tbs && cuts.push(...tbs)
        })
        btn.verify.scripts && btn.verify.scripts.forEach(script => {
          if (script.status === 'false') return
          let tbs = script.sql.match(cutreg)
          tbs && cuts.push(...tbs)
        })
      }
    }
  })
  cuts = cuts.map(item => item.replace(trimreg, ''))
  tables.push(...cuts)
  tables = tables.filter(Boolean)
  tables = Array.from(new Set(tables))
  return tables
}
src/utils/utils-datamanage.js
@@ -446,7 +446,6 @@
   */
  static getPrevQueryParams (setting, search = [], BID) {
    let param = null
    if (setting.procMode !== 'inner') {
      param = this.getDefaultPrevQueryParam(setting, search, BID)
    } else {
src/utils/utils.js
@@ -158,7 +158,7 @@
    let error = ''
    
    sql = sql.replace(/sys\.fn_sqlvarbasetostr\(HashBytes\('MD5'/ig, '') // 跳过MD5加密
    sql = sql.replace(/sys\.fn_/ig, '') // 跳过sys.fn_验证
    chars.forEach(char => {
      if (!error && char.reg.test(sql)) {
@@ -1374,7 +1374,7 @@
 */
export function getSysDefaultSql (btn, setting, formdata, param, data, columns, tab, retmsg = false, moduleParams, getOptions) {
  let primaryId = param.ID
  let BID = param.BID
  let BID = param.BID || ''
  let verify = btn.verify || {}
  let datavars = {}                 // 声明的变量,表单及显示列
  let _actionType = null
@@ -1434,14 +1434,11 @@
      if (form.type === 'number' || form.type === 'rate') {
        let val = form.value
        if (typeof(val) !== 'number') {
          val = parseFloat(val)
          if (isNaN(val)) {
            val = 0
          }
        if (isNaN(val)) {
          val = 0
        }
        _initFormfields.push(`@${_key}=${val}`)
      } else if (['date', 'datemonth', 'datetime'].includes(form.type)) {
      } else if (['date', 'datemonth'].includes(form.type)) {
        _initFormfields.push(`@${_key}='${form.value || '1949-10-01'}'`)
      } else {
        _initFormfields.push(`@${_key}='${form.value}'`)
@@ -1476,7 +1473,7 @@
  }
  // 添加数据中字段,表单值优先(按钮不选行或多行拼接时跳过)
  if (data && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce') {
  if (data && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce' && columns && columns.length > 0) {
    datavars = {...data, ...datavars}
    const setField = (col) => {
@@ -1518,17 +1515,15 @@
      }
    }
    if (columns && columns.length > 0) {
      columns.forEach(col => {
        if (col.type === 'colspan' || col.type === 'old_colspan') {
          col.subcols.forEach(cell => {
            setField(cell)
          })
        } else {
          setField(col)
        }
      })
    }
    columns.forEach(col => {
      if (col.type === 'colspan' || col.type === 'old_colspan') {
        col.subcols.forEach(cell => {
          setField(cell)
        })
      } else {
        setField(col)
      }
    })
  }
  // 变量声明
@@ -1560,7 +1555,7 @@
  // 初始化凭证及用户信息字段
  _sql += `
      /* 凭证及用户信息初始化赋值 */
      select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @BillCode='', @ModularDetailCode=''
      select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @bid='${BID}', @BillCode='', @ModularDetailCode=''
      `
  // 表单变量赋值
@@ -2069,6 +2064,20 @@
    _sql += _backCustomScript
  }
  if (window.GLOB.breakpoint) {
    let start = new RegExp('\\/\\*\\$breakpoint_begin_' + window.GLOB.breakpoint + '@', 'ig')
    let end = new RegExp('@breakpoint_end_' + window.GLOB.breakpoint + '\\$\\*\\/', 'ig')
    if (window.GLOB.breakpoint === 'all') {
      start = /\/\*\$breakpoint_begin_[0-9a-z_]+@/ig
      end = /@breakpoint_end_[0-9a-z_]+\$\*\//ig
    }
    _sql = _sql.replace(start, '').replace(end, '').replace(/\$breakpoint_proc@/ig, window.GLOB.breakpoint)
    _sql += `
      z_debug_end: select @ErrorCode='E',@retmsg='debug_end' goto aaa`
  }
  if (retmsg) {
    _sql += `
      aaa: if @ErrorCode!=''
@@ -2082,7 +2091,7 @@
  }
  _sql = _sql.replace(/@ID@/ig, `'${primaryId || ''}'`)
  _sql = _sql.replace(/@BID@/ig, `'${BID || ''}'`)
  _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') || ''}'`)
@@ -2095,7 +2104,7 @@
  if (retmsg) {
    _callbacksql = _callbacksql.replace(/@ID@/ig, `'${primaryId || ''}'`)
    _callbacksql = _callbacksql.replace(/@BID@/ig, `'${BID || ''}'`)
    _callbacksql = _callbacksql.replace(/@BID@/ig, `'${BID}'`)
    _callbacksql = _callbacksql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
    _callbacksql = _callbacksql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
    _callbacksql = _callbacksql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
src/views/appmanage/index.jsx
@@ -709,8 +709,9 @@
    if (item.typename === 'pc') {
      route = 'pcdesign'
    }
    let param = {...item, kei_no: selectApp.kei_no, remark: selectApp.remark, type: 'app'}
    window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify({...item, kei_no: selectApp.kei_no, remark: selectApp.remark, type: 'app'})))}`))
    window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify(param)))}`))
  }
  jumpMenu = (item) => {
src/views/design/sidemenu/editthdmenu/index.jsx
@@ -307,7 +307,6 @@
const mapStateToProps = (state) => {
  return {
    mainMenu: state.mainMenu,
    menuTree: state.menuTree
  }
}
src/views/imdesign/index.jsx
@@ -55,10 +55,9 @@
      if (param.type === 'app') {
        sessionStorage.setItem('appId', param.ID || '')
        sessionStorage.setItem('appName', param.remark || '')
        sessionStorage.setItem('lang', param.lang || 'zh-CN')
        sessionStorage.setItem('kei_no', param.kei_no || '')
        sessionStorage.setItem('role_type', param.role_type || 'true')
        sessionStorage.setItem('login_types', param.login_types || 'false')
        sessionStorage.setItem('typename', param.typename || 'mob')
        sessionStorage.setItem('adapter', param.adapter || '')
        sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
src/views/main/index.jsx
@@ -23,6 +23,21 @@
  componentDidMount () {
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    Object.defineProperty(window, 'debug', {
      set(value) {
        if (value + '' === 'false') {
          window.debugger = false
          window.GLOB.breakpoint = false
          sessionStorage.removeItem('breakpoint')
        } else {
          window.debugger = true
          window.GLOB.breakpoint = value + ''
          sessionStorage.setItem('breakpoint', value)
        }
        MKEmitter.emit('debugChange')
      }
    })
  }
  componentWillUnmount () {
src/views/menudesign/index.jsx
@@ -7,6 +7,7 @@
import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button, Typography } from 'antd'
import { DoubleLeftOutlined, DoubleRightOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
import html2canvas from 'html2canvas'
import md5 from 'md5'
import Api from '@/api'
import options from '@/store/options.js'
@@ -39,6 +40,7 @@
const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
const Versions = asyncComponent(() => import('@/menu/versions'))
const TableNodes = asyncComponent(() => import('@/menu/tablenodes'))
const SysInterface = asyncComponent(() => import('@/menu/sysinterface'))
const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent'))
const PictureController = asyncComponent(() => import('@/menu/picturecontroller'))
@@ -108,7 +110,6 @@
  componentDidMount () {
    MKEmitter.addListener('delButtons', this.delButtons)
    MKEmitter.addListener('modalStatus', this.modalStatus)
    // MKEmitter.addListener('thawButtons', this.thawButtons)
    MKEmitter.addListener('copyButtons', this.copyButtons)
    MKEmitter.addListener('changePopview', this.initPopview)
    MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
@@ -179,7 +180,6 @@
    }
    MKEmitter.removeListener('delButtons', this.delButtons)
    MKEmitter.removeListener('modalStatus', this.modalStatus)
    // MKEmitter.removeListener('thawButtons', this.thawButtons)
    MKEmitter.removeListener('copyButtons', this.copyButtons)
    MKEmitter.removeListener('changePopview', this.initPopview)
    MKEmitter.removeListener('triggerMenuSave', this.triggerMenuSave)
@@ -355,10 +355,6 @@
  copyButtons = (items) => {
    this.setState({copyButtons: [...this.state.copyButtons, ...items]})
  }
  // thawButtons = (item) => {
  //   this.setState({thawButtons: [...this.state.thawButtons, item]})
  // }
  initPopview = (card, btn) => {
    const { oriConfig, config } = this.state
@@ -483,13 +479,16 @@
    })
  }
  getMenuMessage = (delButtons) => {
  getMenuMessage = (delButtons, tbs) => {
    const { config } = this.state
    let buttons = []
    let _sort = 1
    let traversal = (components) => {
      components.forEach(item => {
        if (item.$tables) {
          tbs.push(...item.$tables)
        }
        if (item.type === 'tabs') {
          item.subtabs.forEach(tab => {
            traversal(tab.components)
@@ -621,6 +620,37 @@
        config.enabled = false
      }
      let tbs = []
      let delButtons = fromJS(this.state.delButtons).toJS()
      let btns = this.getMenuMessage(delButtons, tbs)
      let arr = []
      tbs = tbs.filter(tb => {
        let _tb = tb.toLowerCase()
        if (arr.includes(_tb)) return false
        arr.push(_tb)
        return true
      })
      tbs.sort()
      if (tbs.length && sessionStorage.getItem('mk_tb_names')) {
        let names = sessionStorage.getItem('mk_tb_names')
        tbs = tbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
      }
      tbs = tbs.map(tb => `'${tb}'`).join(';')
      let key = md5(config.uuid + tbs.toLowerCase())
      let url = ''
      if (config.tbkey === key) {
        key = ''
      } else {
        let urlparam = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
        urlparam.type = 'admin'
        url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
        config.tbkey = key
      }
      let param = {
        func: 'sPC_TrdMenu_AddUpt',
        FstID: config.fstMenuId || '',
@@ -632,10 +662,13 @@
        Template: 'CustomPage',
        MenuName: config.MenuName || '',
        PageParam: JSON.stringify({Template: 'CustomPage', OpenType: config.OpenType || 'newtab', hidden: config.hidden || 'false'}),
        LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config))),
        open_edition: config.open_edition,
        LText: '',
        LTexttb: ''
        LTexttb: '',
        debug_md5: key,
        debug_url: url,
        debug_list: window.btoa(tbs),
        LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config)))
      }
      param.LText = Utils.formatOptions(param.LText)
@@ -653,10 +686,9 @@
        LText: []
      }
      let delButtons = fromJS(this.state.delButtons).toJS()
      let btnIds = '' // 用于复制按钮的过滤
      if (MenuType !== 'billPrint') {
        btnParam.LText = this.getMenuMessage(delButtons)
        btnParam.LText = btns
        btnParam.LText = btnParam.LText.join(' union all ')
        btnIds = btnParam.LText
@@ -728,28 +760,6 @@
          }
          return Api.getSystemConfig(_param)
        }
      // }).then(res => { // 按钮解除冻结
      //   if (!res) return
      //   if (!res.status) {
      //     notification.warning({
      //       top: 92,
      //       message: res.message,
      //       duration: 5
      //     })
      //     return false
      //   }
      //   let ids = thawButtons.filter(item => btnIds.indexOf(item) !== -1)
      //   if (ids.length === 0) {
      //     return {
      //       status: true
      //     }
      //   } else {
      //     return Api.getSystemConfig({
      //       func: 'sPC_MainMenu_ReDel',
      //       MenuID: ids.join(',')
      //     })
      //   }
      }).then(res => { // 页面保存
        if (!res) return
@@ -1130,12 +1140,11 @@
                </Collapse>
              </div>
              <div className={'menu-view' + (menuloading ? ' saving' : '') + (eyeopen ? ' eye-open' : '')}>
                <Card title={
                  <div style={{paddingLeft: '15px'}}> {config && config.MenuName} </div>
                } bordered={false} extra={
                  <div>
                <Card title={config ? config.MenuName : ''} bordered={false} extra={
                  <div className="mk-opeartion-list">
                    <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 组件名</Button>
                    <Versions MenuId={MenuId} open_edition={config ? config.open_edition : ''}/>
                    <TableNodes config={config} />
                    <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                    <SysInterface config={config} updateConfig={this.updateConfig}/>
                    <PictureController/>
src/views/menudesign/index.scss
@@ -219,4 +219,16 @@
    background: transparent!important;
    border-radius: 0!important;
  }
}
@media screen and (max-width: 1500px) {
  .mk-opeartion-list .ant-btn {
    min-width: 65px;
    .anticon {
      display: none;
    }
    .anticon + span {
      margin-left: 0px;
    }
  }
}
src/views/mobdesign/index.jsx
@@ -2,16 +2,16 @@
import { DndProvider } from 'react-dnd'
import { withRouter } from 'react-router'
import { is, fromJS } from 'immutable'
import moment from 'moment'
import HTML5Backend from 'react-dnd-html5-backend'
import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, RedoOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import Utils, { setGLOBFuncs } from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
import antdEnUS from 'antd/es/locale/en_US'
import antdZhCN from 'antd/es/locale/zh_CN'
import MKEmitter from '@/utils/events.js'
import MenuUtils from '@/utils/utils-custom.js'
@@ -33,6 +33,7 @@
const ViewNodes = asyncComponent(() => import('@/menu/viewnodes'))
const SourceWrap = asyncComponent(() => import('@/mob/modulesource'))
const Modulecell = asyncComponent(() => import('@/menu/modulecell'))
const TableNodes = asyncComponent(() => import('@/menu/tablenodes'))
const BgController = asyncComponent(() => import('@/pc/bgcontroller'))
const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
const SysInterface = asyncComponent(() => import('@/menu/sysinterface'))
@@ -61,7 +62,6 @@
class MobDesign extends Component {
  state = {
    localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    loading: true,
    MenuId: '',
@@ -89,10 +89,9 @@
      if (param.type === 'app') {
        sessionStorage.setItem('appId', param.ID || '')
        sessionStorage.setItem('appName', param.remark || '')
        sessionStorage.setItem('lang', param.lang || 'zh-CN')
        sessionStorage.setItem('kei_no', param.kei_no || '')
        sessionStorage.setItem('role_type', param.role_type || 'true')
        sessionStorage.setItem('login_types', param.login_types || 'false')
        sessionStorage.setItem('typename', param.typename || 'mob')
        sessionStorage.setItem('adapter', param.adapter || '')
        sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
@@ -100,7 +99,6 @@
        sessionStorage.setItem('instantMessage', param.instantMessage || '')
        this.setState({
          localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
          dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
        })
        this.getAppMessage(param.MenuID)
@@ -664,7 +662,7 @@
            backElements: []
          }
        ],
        headerStyle: {}, parentId: '', width: 24, scripts: [], btnlog: [], pageable: false,
        headerStyle: {}, parentId: '', width: 24, scripts: [], pageable: false,
        wrap: {name: 'logo', width: 24, datatype: 'static', cardType: '', blacklist: []},
        name: 'logo', floor: 1, switchable: true,
        setting:{interType: 'system'}, tabId: '', style:{paddingTop: '8vh', paddingBottom: '10vh'}, dataName: Utils.getuuid(), format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
@@ -696,7 +694,7 @@
            backElements: []
          }
        ],
        headerStyle: {}, parentId: '', width: 24, scripts: [], btnlog: [], pageable: false,
        headerStyle: {}, parentId: '', width: 24, scripts: [], pageable: false,
        wrap: {name: 'Power', width: 24, datatype: 'static', cardType: '', blacklist: []},
        name: 'Power', floor: 1, switchable: true,
        setting:{interType: 'system'}, tabId: '', style:{}, dataName: Utils.getuuid(), format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
@@ -919,12 +917,16 @@
    })
  }
  getMenuMessage = () => {
  getMenuMessage = (tbs) => {
    const { config } = this.state
    
    let traversal = (components) => {
      let list = []
      components.forEach(item => {
        if (item.$tables) {
          tbs.push(...item.$tables)
        }
        let m = {
          key: item.uuid,
          title: item.name,
@@ -1320,10 +1322,50 @@
        config.enabled = false
      }
      let tbs = []
      let roleParam = {type: 'view', version: '1.0', key: config.uuid, title: config.MenuName, children: []}
      roleParam.children = this.getMenuMessage()
      roleParam.children = this.getMenuMessage(tbs)
      config.loginview = false
      config.tabview = false
      let arr = []
      tbs = tbs.filter(tb => {
        let _tb = tb.toLowerCase()
        if (arr.includes(_tb)) return false
        arr.push(_tb)
        return true
      })
      tbs.sort()
      if (tbs.length && sessionStorage.getItem('mk_tb_names')) {
        let names = sessionStorage.getItem('mk_tb_names')
        tbs = tbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
      }
      tbs = tbs.map(tb => `'${tb}'`).join(';')
      let key = md5(config.uuid + sessionStorage.getItem('kei_no') + sessionStorage.getItem('typename') + sessionStorage.getItem('lang') + tbs.toLowerCase())
      let url = ''
      if (config.tbkey === key) {
        key = ''
      } else {
        let urlparam = {
          type: 'app',
          MenuID: config.uuid,
          ID: sessionStorage.getItem('appId') || '',
          remark: sessionStorage.getItem('appName') || '',
          lang: sessionStorage.getItem('lang') || '',
          kei_no: sessionStorage.getItem('kei_no') || '',
          typename: sessionStorage.getItem('typename') || '',
          adapter: sessionStorage.getItem('adapter') || '',
          sysBgColor: sessionStorage.getItem('sysBgColor') || '',
          MenuName: config.MenuName || '',
        }
        url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
        config.tbkey = key
      }
      if (roleParam.children.length === 0) {
        roleParam.pass = true
@@ -1377,7 +1419,10 @@
        menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roleParam))),
        LText: '',
        LTexttb: '',
        menus_used_list
        menus_used_list,
        debug_md5: key,
        debug_url: url,
        debug_list: window.btoa(tbs)
      }
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -1921,10 +1966,10 @@
  render () {
    const { viewType, localedict, comloading, loading, settingshow, controlshow, activeKey, dict, MenuId, config, menuloading, customComponents, adapters, eyeopen } = this.state
    const { viewType, comloading, loading, settingshow, controlshow, activeKey, dict, MenuId, config, menuloading, customComponents, adapters, eyeopen } = this.state
    return (
      <ConfigProvider locale={localedict}>
      <ConfigProvider locale={antdZhCN}>
        <div className={'mk-mob-view ' + viewType} id="mk-mob-design-view">
          <Header changeView={this.changeView}/>
          {loading ? <Spin className="view-spin" size="large" /> : null}
@@ -1979,6 +2024,7 @@
                <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 组件名</Button>
                <CreateView resetmenu={this.getAppMenus} />
                <PasteController insert={this.insert} />
                <TableNodes config={config} />
                <ViewNodes config={config} MenuId={MenuId}/>
                <SysInterface config={config} updateConfig={this.updateConfig}/>
                <PictureController/>
src/views/pcdesign/index.jsx
@@ -2,16 +2,17 @@
import { DndProvider } from 'react-dnd'
import { withRouter } from 'react-router'
import { is, fromJS } from 'immutable'
import moment from 'moment'
import HTML5Backend from 'react-dnd-html5-backend'
import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, RedoOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import Utils, { setGLOBFuncs } from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
import antdEnUS from 'antd/es/locale/en_US'
// import antdEnUS from 'antd/es/locale/en_US'
import antdZhCN from 'antd/es/locale/zh_CN'
import MKEmitter from '@/utils/events.js'
import MenuUtils from '@/utils/utils-custom.js'
@@ -31,6 +32,7 @@
const ViewNodes = asyncComponent(() => import('@/menu/viewnodes'))
const SourceWrap = asyncComponent(() => import('@/pc/modulesource'))
const Modulecell = asyncComponent(() => import('@/menu/modulecell'))
const TableNodes = asyncComponent(() => import('@/menu/tablenodes'))
const CreateView = asyncComponent(() => import('@/pc/createview'))
const BgController = asyncComponent(() => import('@/pc/bgcontroller'))
const Quotecomponent = asyncComponent(() => import('@/pc/quotecomponent'))
@@ -55,7 +57,6 @@
class MenuDesign extends Component {
  state = {
    localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    loading: true,
    MenuId: '',
@@ -91,14 +92,12 @@
      if (param.type === 'app') {
        sessionStorage.setItem('appId', param.ID || '')
        sessionStorage.setItem('appName', param.remark || '')
        sessionStorage.setItem('lang', param.lang || 'zh-CN')
        sessionStorage.setItem('kei_no', param.kei_no || '')
        sessionStorage.setItem('role_type', param.role_type || 'true')
        sessionStorage.setItem('login_types', param.login_types || 'false')
        sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
        this.setState({
          localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
          dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
        })
        this.getAppMessage(param.MenuID)
@@ -869,7 +868,7 @@
    })
  }
  getMenuMessage = () => {
  getMenuMessage = (tbs) => {
    const { config } = this.state
    let nodes = {type: 'view', version: '1.0', key: config.uuid, title: config.MenuName, children: []}
    let popviews = []
@@ -877,6 +876,10 @@
    let traversal = (components) => {
      let list = []
      components.forEach(item => {
        if (item.$tables) {
          tbs.push(...item.$tables)
        }
        let m = {
          key: item.uuid,
          title: item.name,
@@ -1204,11 +1207,50 @@
        config.enabled = false
      }
      let roleParam = this.getMenuMessage()
      let tbs = []
      let roleParam = this.getMenuMessage(tbs)
      let subMenus = this.getSubMenus()
      let menus_used_list = subMenus.map(m => `'${config.uuid}','${config.MenuName || ''}','${config.MenuNo || ''}','${m.MenuID}','${m.MenuName}'`).join(';')
      menus_used_list = window.btoa(window.encodeURIComponent(menus_used_list || 'del'))
      let arr = []
      tbs = tbs.filter(tb => {
        let _tb = tb.toLowerCase()
        if (arr.includes(_tb)) return false
        arr.push(_tb)
        return true
      })
      tbs.sort()
      if (tbs.length && sessionStorage.getItem('mk_tb_names')) {
        let names = sessionStorage.getItem('mk_tb_names')
        tbs = tbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
      }
      tbs = tbs.map(tb => `'${tb}'`).join(';')
      let key = md5(config.uuid + sessionStorage.getItem('kei_no') + 'pc' + sessionStorage.getItem('lang') + tbs.toLowerCase())
      let url = ''
      if (config.tbkey === key) {
        key = ''
      } else {
        let urlparam = {
          type: 'app',
          MenuID: config.uuid,
          ID: sessionStorage.getItem('appId') || '',
          remark: sessionStorage.getItem('appName') || '',
          lang: sessionStorage.getItem('lang') || '',
          kei_no: sessionStorage.getItem('kei_no') || '',
          typename: 'pc',
          sysBgColor: sessionStorage.getItem('sysBgColor') || '',
          MenuName: config.MenuName || '',
        }
        url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
        config.tbkey = key
      }
      let param = {
        func: 'sPC_TrdMenu_AddUpt',
@@ -1227,7 +1269,10 @@
        open_edition: config.open_edition,
        LText: '',
        LTexttb: '',
        menus_used_list
        menus_used_list,
        debug_md5: key,
        debug_url: url,
        debug_list: window.btoa(tbs)
      }
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -1830,10 +1875,10 @@
  }
  render () {
    const { localedict, loading, comloading, activeKey, settingshow, controlshow, dict, MenuId, config, menuloading, customComponents, eyeopen } = this.state
    const { loading, comloading, activeKey, settingshow, controlshow, dict, MenuId, config, menuloading, customComponents, eyeopen } = this.state
    return (
      <ConfigProvider locale={localedict}>
      <ConfigProvider locale={antdZhCN}>
        <div className={'mk-pc-view '} id="mk-pc-design-view">
          {loading ? <Spin className="view-spin" size="large" /> : null}
          <DndProvider backend={HTML5Backend}>
@@ -1886,6 +1931,7 @@
                <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 组件名</Button>
                <CreateView resetmenu={this.getAppMenus} />
                <PasteController insert={this.insert} />
                <TableNodes config={config} />
                <ViewNodes config={config} MenuId={MenuId}/>
                <SysInterface config={config} updateConfig={this.updateConfig}/>
                <PictureController/>
src/views/systemfunc/header/index.jsx
@@ -32,13 +32,13 @@
      <header className="sys-header-container ant-menu-dark">
        <div className="header-logo"><img src={MainLogo} alt=""/></div>
        <div className="title">HS</div>
        <div className="close" onClick={() => window.close()}>关闭</div>
        <div className="header-setting">
          <img src={this.state.avatar} alt=""/>
          <span>
            <span className="username">{this.state.userName}</span>
          </span>
        </div>
        <div className="close" onClick={() => window.close()}>关闭</div>
      </header>
    )
  }
src/views/systemfunc/header/index.scss
@@ -31,11 +31,11 @@
  }
  .close {
    position: absolute;
    float: right;
    font-size: 16px;
    color: #ffffff;
    right: 90px;
    top: 12px;
    margin-top: 13px;
    margin-right: 15px;
    cursor: pointer;
  }