king
2020-03-26 a24beb36feaa46f39cbb26ce5277e84f91241ce8
2020-03-26
2 文件已重命名
26个文件已修改
3 文件已复制
7个文件已添加
3270 ■■■■ 已修改文件
src/assets/css/main.scss 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/config.js 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/main.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 202 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.scss 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/formtab/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/managetable/index.scss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtable/index.jsx 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtable/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtabtable/index.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/verupmanage/index.scss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/verupmanage/subtabtable/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/index.jsx 471 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/index.jsx 643 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/index.scss 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/actionform/index.jsx 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/actionform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/index.jsx 625 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/index.scss 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/printform/index.jsx 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/printform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/printtypeform/index.jsx 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/verifycard/tabcard/printtypeform/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.jsx 62 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/index.jsx 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/index.jsx 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/createinterface/index.jsx 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/createinterface/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycardprint/editable/index.jsx 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycardprint/editable/index.scss 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycardprint/index.jsx 68 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycardprint/index.scss 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/asyncLoadComponent.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.jsx 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/loginform.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss
@@ -222,3 +222,25 @@
    background: rgba(0, 0, 0, 0);
  }
}
.popview-modal {
  .ant-modal-body {
    min-height: 300px;
    max-height: calc(100vh - 160px);
    overflow-y: auto;
  }
  .ant-modal-body::-webkit-scrollbar {
    width: 7px;
  }
  .ant-modal-body::-webkit-scrollbar-thumb {
    border-radius: 5px;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
    background: rgba(0, 0, 0, 0.13);
  }
  .ant-modal-body::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
    border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(0, 0, 0, 0);
  }
}
src/components/header/index.jsx
@@ -229,6 +229,13 @@
      }
      this.props.initPermission(_permRoles, _permAction, _permFuncField)
      this.loadmenu()
    } else {
      notification.error({
        top: 92,
        message: result.message,
        duration: 15
      })
    }
  }
@@ -285,6 +292,7 @@
          sessionStorage.setItem('CloudSessionUid', Utils.getuuid())
          sessionStorage.setItem('CloudLoginUID', res.LoginUID)
          sessionStorage.setItem('CloudUserName', res.UserName)
          sessionStorage.setItem('CloudFullName', res.FullName)
          sessionStorage.setItem('CloudAvatar', res.icon)
          sessionStorage.setItem('isEditState', 'true')
@@ -359,15 +367,11 @@
      _avatar = Utils.getrealurl(_avatar) // 头像
      this.setState({avatar: _avatar})
    }
    this.loadmenu()
    this.getRolesMenu()
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
  componentDidMount () {
    this.getRolesMenu()
  }
  render () {
src/components/sidemenu/config.js
@@ -81,6 +81,38 @@
      MenuNo: 'KUNMainMOut_advanced',
      MenuName: '高阶查询',
      text: '高阶查询'
    }, {
      src: '',
      PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
      type: 'ManageTable',
      MenuID: '1584676379094iktph45fb8imhg96bql',
      MenuNo: 'KUNMainM_Out_usual',
      MenuName: '通用查询接口',
      text: '通用查询接口'
    }, {
      src: '',
      PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
      type: 'ManageTable',
      MenuID: '1584695125339vo5g7iqgfn01qmrd6s2',
      MenuNo: 'KUNMainM_In_usual',
      MenuName: '通用写入接口',
      text: '通用写入接口'
    }, {
      src: '',
      PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
      type: 'ManageTable',
      MenuID: '1584699661372vhmpp9dn9foo0eob722',
      MenuNo: 'KUNMainM_In',
      MenuName: '写入接口',
      text: '写入接口'
    }, {
      src: '',
      PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
      type: 'ManageTable',
      MenuID: '15848421131551gg04ie8sitsd3f7467',
      MenuNo: 'KUNOsMainM',
      MenuName: '外部接口',
      text: '外部接口'
    }]
  }]
}
src/locales/en-US/main.js
@@ -10,6 +10,7 @@
  'main.pagination.of': 'of',
  'main.pagination.items': 'items',
  'main.page.settingerror': '页面配置错误!',
  'main.datasource.settingerror': '数据源配置错误!',
  'main.action.settingerror': 'Button setting error!',
  'main.action.confirm.tip': 'Do you want to execute?',
  'main.action.confirm.success': 'Execute successfully!',
src/tabviews/commontable/index.jsx
@@ -13,12 +13,14 @@
import {refreshTabView, modifyTabview} from '@/store/action'
import MainTable from '@/tabviews/zshare/normalTable'
import MainAction from '@/tabviews/zshare/actionList'
import VerifyCard from '@/tabviews/zshare/verifycard'
// import MainAction from '@/tabviews/zshare/actionList'
// import VerifyCard from '@/tabviews/zshare/verifycard'
import MainSearch from '@/tabviews/zshare/topSearch'
import NotFount from '@/components/404'
import './index.scss'
const VerifyCard = asyncLoadComponent(() => import('@/tabviews/zshare/verifycard'))
const MainAction = asyncLoadComponent(() => import('@/tabviews/zshare/actionList'))
const SubTable = asyncLoadComponent(() => import('@/tabviews/subtable'))
const SubTabTable = asyncLoadComponent(() => import('@/tabviews/subtabtable'))
const FormTab = asyncLoadComponent(() => import('@/tabviews/formtab'))
@@ -42,6 +44,8 @@
    viewlost: false,      // 页面丢失:1、未获取到配置-页面丢失;2、页面未启用
    lostmsg: '',          // 页面丢失时的提示信息
    config: {},           // 页面配置信息,包括按钮、搜索、显示列、标签等
    userConfig: null,     // 用户自定义设置
    userParam: null,      // 保存用户编辑中的配置
    searchlist: null,     // 搜索条件
    actions: null,        // 按钮集
    columns: null,        // 显示列
@@ -65,7 +69,8 @@
    tabParam: null,       // 表单标签参数
    refreshtabs: null,    // 需要刷新的标签集
    confirmLoading: false,// 自定义设置模态框加载中
    settingVisible: false // 自定义设置模态框
    settingVisible: false,// 自定义设置模态框
    triggerBtn: null      // 点击表格中或快捷键触发的按钮
  }
  /**
@@ -82,7 +87,8 @@
    if (result.status) {
      let config = ''
      let userConfig = ''
      let userConfig = null
      let _curUserConfig = ''
      try { // 配置信息解析
        config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
@@ -94,9 +100,10 @@
      if (result.LongParamUser) {
        try { // 配置信息解析
          userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
          _curUserConfig = userConfig[this.props.MenuID]
        } catch (e) {
          console.warn('Parse Failure')
          userConfig = ''
          userConfig = null
        }
      }
@@ -156,16 +163,27 @@
        }
      })
      if (userConfig) {
        config.setting = {...config.setting, ...userConfig.setting}
        let _actions = {}
        userConfig.action.forEach(item => {
          _actions[item.uuid] = item
        })
      if (_curUserConfig) {
        config.setting = {...config.setting, ..._curUserConfig.setting}
        config.action = config.action.map(item => {
          if (_actions[item.uuid]) {
            item = {...item, ..._actions[item.uuid]}
          if (item.execMode) {
            item.OpenType = 'funcbutton'
          }
          if (_curUserConfig.action[item.uuid]) {
            item = {...item, ..._curUserConfig.action[item.uuid]}
          }
          if (item.OpenType === 'funcbutton' && item.funcType === 'print' && item.verify && item.printer) {
            item.verify.defaultPrinter = item.printer.defaultPrinter || ''
            if (item.verify.printerTypeList && item.printer.printerList) {
              item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
                cell.printer = item.printer.printerList[cell.Value] || ''
                return cell
              })
            }
          }
          return item
@@ -199,7 +217,6 @@
          operations: _operations
        })
      }
      // 1、筛选字段集,2、过滤隐藏列及合并列中的字段uuid
      config.columns.forEach(col => {
@@ -242,9 +259,24 @@
        }
      })
      if (_curUserConfig) {
        _columns = _columns.map(item => {
          if (_curUserConfig.columns[item.uuid]) {
            item = {...item, ..._curUserConfig.columns[item.uuid]}
          }
          return item
        })
        _columns.sort((pre, next) => {
          return pre.sort - next.sort
        })
      }
      this.setState({
        loadingview: false,
        config: config,
        userConfig: userConfig,
        setting: config.setting,
        searchlist: config.search,
        actions: _actions,
@@ -273,8 +305,8 @@
  }
  setShortcut = () => {
    const { actions } = this.state
    if (!actions) return
    const { actions, userConfig } = this.state
    if (!userConfig) return
    document.onkeydown = (event) => {
      let e = event || window.event
@@ -288,8 +320,11 @@
      } else if (e.altKey) {
        preKey = 'alt'
      }
      if (!preKey) return
      let istrigger = false
      actions.forEach(item => {
        if (!item.shortcut || typeof(item.shortcut) !== 'object' || item.shortcut.length === 0 || istrigger) return
@@ -297,8 +332,43 @@
          e.preventDefault()
          istrigger = true
          this.refs.mainButton.actionTrigger(item)
          this.setState({
            triggerBtn: {
              uuid: new Date().getTime(),
              parentId: this.props.MenuID,
              button: item,
              data: null
            }
          })
        }
      })
      if (istrigger) return
      Object.keys(userConfig).forEach(key => {
        if (key === this.props.MenuID || !userConfig[key].action || istrigger) return
        let _actions = userConfig[key].action
        Object.keys(_actions).forEach(btnkey => {
          let item = _actions[btnkey]
          if (!item.shortcut || typeof(item.shortcut) !== 'object' || item.shortcut.length === 0 || istrigger) return
          if (preKey === item.shortcut[0] && keyCode === item.shortcut[1]) {
            e.preventDefault()
            istrigger = true
            this.setState({
              triggerBtn: {
                uuid: new Date().getTime(),
                parentId: key,
                button: item,
                data: null
              }
            })
          }
        })
      })
    }
  }
@@ -624,6 +694,8 @@
      viewlost: false,
      lostmsg: '',
      config: {},
      userConfig: null,
      userParam: null,
      searchlist: null,
      actions: null,
      columns: null,
@@ -734,7 +806,14 @@
   * @description 表格中,按钮触发事件传递
   */
  buttonTrigger = (btn, record) => {
    this.refs.mainButton.actionTrigger(btn, record)
    this.setState({
      triggerBtn: {
        uuid: new Date().getTime(),
        parentId: this.props.MenuID,
        button: btn,
        data: record
      }
    })
  }
  /**
@@ -906,39 +985,53 @@
    })
  }
  settingSubmit = () => {
    this.verifyRef.handleConfirm().then(res => {
      let _LongParam = ''
  changeMenuParam = (param) => {
    this.setState({userParam: param})
  }
      try {
        _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(res)))
      } catch (e) {
  settingSubmit = () => {
    const { userParam } = this.state
    let _LongParam = ''
    try {
      _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(userParam)))
    } catch (e) {
      notification.warning({
        top: 92,
        message: '编译错误',
        duration: 10
      })
      return
    }
    let param = {
      func: 'sPC_TrdMenu_UserParam',
      MenuID: this.props.MenuID,
      LongParam: _LongParam
    }
    this.setState({
      confirmLoading: true
    })
    Api.getSystemConfig(param).then(result => {
      if (!result.status) {
        this.setState({
          confirmLoading: false
        })
        notification.warning({
          top: 92,
          message: '编译错误',
          message: result.message,
          duration: 10
        })
        return
      }
      let param = {
        func: 'sPC_TrdMenu_UserParam',
        MenuID: this.props.MenuID,
        LongParam: _LongParam
      }
      this.setState({
        confirmLoading: true
      })
      Api.getSystemConfig(param).then(result => {
        this.setState({
          settingVisible: false,
          confirmLoading: false
        }, () => {
          window.GLOB.CacheMap = new Map()
          this.reloadview()
        })
        settingVisible: false,
        confirmLoading: false
      }, () => {
        window.GLOB.CacheMap = new Map()
        this.reloadview()
      })
    })
  }
@@ -964,16 +1057,17 @@
  }
  /**
   * @description 组件销毁,清除state更新
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    document.onkeydown = () => {}
  }
  render() {
    const { view, setting, searchlist, actions, columns, loadingview, viewlost, pickup, config } = this.state
    const { view, setting, searchlist, actions, columns, loadingview, viewlost, pickup, config, triggerBtn, userConfig } = this.state
    return (
      <div>
@@ -990,12 +1084,12 @@
          {actions && setting.onload !== 'false' ?
            <div style={{minHeight: '25px'}}>
              <MainAction
                ref="mainButton"
                BID=""
                type="main"
                menuType="main"
                setting={setting}
                actions={actions}
                triggerBtn={triggerBtn}
                dict={this.state.dict}
                MenuID={this.props.MenuID}
                permRoles={this.props.permRoles}
@@ -1050,6 +1144,8 @@
                            Tab={_tab}
                            menuType="main"
                            MenuID={_tab.linkTab}
                            userConfig={userConfig ? userConfig[_tab.linkTab] : null}
                            triggerBtn={triggerBtn}
                            SupMenuID={this.props.MenuID}
                            refreshtabs={this.state.refreshtabs}
                            ContainerId={this.state.ContainerId}
@@ -1119,17 +1215,23 @@
            wrapClassName="common-table-custom-modal"
            title={'自定义设置'}
            maskClosable={false}
            width={850}
            width={950}
            visible={this.state.settingVisible}
            onOk={this.settingSubmit}
            onCancel={() => { this.setState({ settingVisible: false }) }}
            confirmLoading={this.state.confirmLoading}
            destroyOnClose
          >
            {this.state.config ?
            {this.state.settingVisible ?
              <VerifyCard
                MenuID={this.props.MenuID}
                MenuName={this.props.MenuName}
                permAction={this.props.permAction}
                permRoles={this.props.permRoles}
                config={this.state.config}
                wrappedComponentRef={(inst) => this.verifyRef = inst}
                userConfig={this.state.userConfig}
                columns={this.state.columns}
                handleParam={this.changeMenuParam}
              /> : null
            }
          </Modal>
src/tabviews/commontable/index.scss
@@ -21,6 +21,7 @@
  }
  > .ant-spin {
    position: fixed;
    z-index: 10;
    left: calc(50vw - 22px);
    top: calc(50vh - 70px);
  }
@@ -90,11 +91,6 @@
    padding-right: 140px;
  }
}
.popview-modal {
  .ant-modal-body {
    min-height: 300px;
  }
}
.menu-tree-modal {
  .ant-modal-body {
    min-height: 300px;
@@ -120,6 +116,7 @@
    padding-bottom: 5px;
    .ant-modal-body {
      max-height: calc(100vh - 190px);
      min-height: 250px;
      overflow-y: auto;
      .ant-empty {
        margin: 15vh 8px;
src/tabviews/formtab/index.scss
@@ -157,9 +157,3 @@
    }
  }
}
.popview-modal {
  .ant-modal-body {
    min-height: 300px;
  }
}
src/tabviews/managetable/index.scss
@@ -83,11 +83,7 @@
    padding-right: 140px;
  }
}
.popview-modal {
  .ant-modal-body {
    min-height: 300px;
  }
}
.menu-tree-modal {
  .ant-modal-body {
    min-height: 300px;
src/tabviews/subtable/index.jsx
@@ -12,13 +12,14 @@
import options from '@/store/options.js'
import SubTable from '@/tabviews/zshare/normalTable'
import SubAction from '@/tabviews/zshare/actionList'
// import SubAction from '@/tabviews/zshare/actionList'
import SubSearch from '@/tabviews/zshare/topSearch'
import asyncLoadComponent from '@/utils/asyncLoadComponent'
import NotFount from '@/components/404'
import './index.scss'
const SubAction = asyncLoadComponent(() => import('@/tabviews/zshare/actionList'))
const SubTabTable = asyncLoadComponent(() => import('@/tabviews/subtabtable'))
class SubTabViewTable extends Component {
@@ -32,7 +33,9 @@
    ContainerId: PropTypes.any,      // 三级菜单Container(html) ID
    handleTableId: PropTypes.func,   // 控制表格数据切换时,更新在主表中的id
    handleMainTable: PropTypes.func, // 刷新主表
    refreshtabs:PropTypes.any
    refreshtabs: PropTypes.any,      // 标签刷新控制
    userConfig: PropTypes.any,       // 用户自定义设置
    triggerBtn: PropTypes.any        // 快捷键或点击行按钮触发事件
  }
  state = {
@@ -58,7 +61,8 @@
    popAction: false,     // 弹框页面,按钮信息
    popData: false,       // 弹框页面,所选的表格数据
    visible: false,       // 弹框显示隐藏控制
    pickup: false,         // 子表数据隐藏显示切换
    pickup: false,        // 子表数据隐藏显示切换
    triggerBtn: null      // 按钮触发
  }
  /**
@@ -70,6 +74,10 @@
      this.loadmaindata(nextProps.BID, 'refresh')
    } else if (this.state.config && nextProps.refreshtabs && nextProps.refreshtabs.includes(this.props.Tab.uuid)) {
      this.reloadtable()
    } else if (nextProps.triggerBtn && !is(fromJS(this.props.triggerBtn), fromJS(nextProps.triggerBtn)) && nextProps.triggerBtn.parentId === this.props.MenuID) {
      this.setState({
        triggerBtn: nextProps.triggerBtn
      })
    }
  }
@@ -77,7 +85,7 @@
   * @description 获取页面配置信息
   */
  async loadconfig () {
    const { permAction, Tab, BID } = this.props
    const { permAction, Tab, BID, userConfig } = this.props
    let param = {
      func: 'sPC_Get_LongParam',
@@ -153,6 +161,33 @@
        })
      }
      if (userConfig) {
        config.setting.tableType = userConfig.setting.tableType
        config.action = config.action.map(item => {
          if (userConfig.action[item.uuid]) {
            item = {...item, ...userConfig.action[item.uuid]}
          }
          if (item.execMode) {
            item.OpenType = 'funcbutton'
          }
          if (item.OpenType === 'funcbutton' && item.funcType === 'print' && item.verify && item.printer) {
            item.verify.defaultPrinter = item.printer.defaultPrinter || ''
            if (item.verify.printerTypeList && item.printer.printerList) {
              item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
                cell.printer = item.printer.printerList[cell.Value] || ''
                return cell
              })
            }
          }
          return item
        })
      }
      // 1、筛选字段集,2、过滤隐藏列及合并列中的字段uuid
      config.columns.forEach(col => {
        if (col.field) {
@@ -215,6 +250,21 @@
          valid = false
        }
      })
      // 添加用户显示列设置
      if (userConfig) {
        _columns = _columns.map(item => {
          if (userConfig.columns[item.uuid]) {
            item = {...item, ...userConfig.columns[item.uuid]}
          }
          return item
        })
        _columns.sort((pre, next) => {
          return pre.sort - next.sort
        })
      }
      this.setState({
        loadingview: false,
@@ -640,7 +690,15 @@
   * @description 表格中,按钮触发事件传递
   */
  buttonTrigger = (btn, record) => {
    this.refs.subButton.actionTrigger(btn, record)
    this.setState({
      triggerBtn: {
        uuid: new Date().getTime(),
        parentId: this.props.MenuID,
        button: btn,
        data: record
      }
    })
    // this.refs.subButton.actionTrigger(btn, record)
  }
  /**
@@ -698,7 +756,7 @@
  }
  render() {
    const { setting, searchlist, actions, columns, loadingview, viewlost, pickup } = this.state
    const { setting, searchlist, actions, columns, loadingview, viewlost, pickup, triggerBtn } = this.state
    return (
      <div className="subtable" id={'subtable' + this.props.MenuID}>
@@ -713,9 +771,9 @@
        {actions ?
          <div className="sub-action">
            <SubAction
              ref="subButton"
              type="sub"
              menuType={this.props.menuType}
              triggerBtn={triggerBtn}
              setting={setting}
              actions={actions}
              Tab={this.props.Tab}
src/tabviews/subtable/index.scss
@@ -45,8 +45,3 @@
    }
  }
}
.popview-modal {
  .ant-modal-body {
    min-height: 300px;
  }
}
src/tabviews/subtabtable/index.jsx
@@ -98,6 +98,9 @@
      let _hideCol = []      // 隐藏及合并列中字段的uuid集
      let colMap = new Map()
      // 仅支持exec、prompt、pop 三种类型按钮
      config.action = config.action.filter(item => ['exec', 'prompt', 'pop'].includes(item.OpenType))
      // 权限过滤
      if (this.props.menuType !== 'HS') {
        config.action = config.action.filter(item => permAction[item.uuid])
src/tabviews/verupmanage/index.scss
@@ -89,11 +89,7 @@
    padding-right: 140px;
  }
}
.popview-modal {
  .ant-modal-body {
    min-height: 300px;
  }
}
.menu-tree-modal {
  .ant-modal-body {
    min-height: 300px;
src/tabviews/verupmanage/subtabtable/index.scss
@@ -45,8 +45,3 @@
    }
  }
}
.popview-modal {
  .ant-modal-body {
    min-height: 300px;
  }
}
src/tabviews/zshare/actionList/index.jsx
@@ -1,6 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import moment from 'moment'
import { is, fromJS } from 'immutable'
import { Button, Affix, Modal, notification, Spin, message } from 'antd'
import * as XLSX from 'xlsx'
import MutilForm from '@/tabviews/zshare/mutilform'
@@ -30,7 +31,8 @@
    triggerPopview: PropTypes.func,   // 弹窗标签页触发
    getexceloutparam: PropTypes.func, // 获取excel导出数据
    gettableselected: PropTypes.func, // 获取表格中数据
    permRoles: PropTypes.any          // 用户权限列表
    permRoles: PropTypes.any,         // 用户权限列表
    triggerBtn: PropTypes.any
  }
  state = {
@@ -41,7 +43,19 @@
    execAction: null,
    loadingUuid: '',
    btnloading: false,
    configMap: {}
    configMap: {},
    running: false
  }
  /**
   * @description 上级菜单id变化时,刷新数据
   */
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (nextProps.triggerBtn && !is(fromJS(this.props.triggerBtn), fromJS(nextProps.triggerBtn)) && nextProps.triggerBtn.parentId === this.props.MenuID) {
      if (!this.state.loadingUuid && !this.state.visible && !this.state.running) {
        this.actionTrigger(nextProps.triggerBtn.button, nextProps.triggerBtn.data)
      }
    }
  }
  refreshdata = (item, type) => {
@@ -97,6 +111,9 @@
    }
    if (item.OpenType === 'prompt') {
      this.setState({
        running: true
      })
      confirm({
        title: this.props.dict['main.action.confirm.tip'],
        onOk() {
@@ -104,7 +121,11 @@
            _this.execSubmit(item, data, resolve)
          })
        },
        onCancel() {}
        onCancel() {
          _this.setState({
            running: false
          })
        }
      })
    } else if (item.OpenType === 'exec') {
      this.setState({loadingUuid: item.uuid})
@@ -196,12 +217,19 @@
            this.improveAction(item)
          })
        } else if (item.execMode === 'prompt') {
          this.setState({
            running: true
          })
          confirm({
            title: this.props.dict['main.action.confirm.tip'],
            onOk() {
              _this.triggerPrint(item, data)
            },
            onCancel() {}
            onCancel() {
              _this.setState({
                running: false
              })
            }
          })
        } else {
          this.triggerPrint(item, data)
@@ -239,64 +267,54 @@
    }
    let printlist = []
    let templates = [btn.verify.Template || '']
    let templates = []
    let printCount = 1
    if (formdata.printCount && typeof(formdata.printCount) === 'number' && formdata.printCount >= 1) {
      printCount = formdata.printCount
      delete formdata.printCount
    }
    this.setState({loadingUuid: btn.uuid})
    new Promise(resolve => {
      if (btn.intertype === 'inner' && !btn.innerFunc) {
        formdata.TemplateID = btn.verify.Template
        let printcell = {}
        printcell.printType = formdata.printType || ''
        printcell.printCount = printCount
        printcell.templateID = btn.verify.Template || ''
        if (btn.Ot === 'notRequired') {
          for (let i = 0; i < printCount; i++) {
            printlist.push(JSON.parse(JSON.stringify(formdata)))
          }
          printcell.data = [formdata]
        } else {
          data.forEach(cell => {
            let _cell = {...cell, ...formdata}
            for (let i = 0; i < printCount; i++) {
              printlist.push(JSON.parse(JSON.stringify(_cell)))
            }
          printcell.data = data.map(cell => {
            return {...cell, ...formdata}
          })
        }
        if (btn.verify.printMode === 'custom') {
          this.execCustomPrint(btn, printlist)
        } else {
          resolve('getTemp')
        }
        templates.push(printcell.templateID)
        printlist.push(printcell)
        resolve(true)
      } else {
        this.getprintdata(btn, data, formdata, formlist).then(result => {
          if (result.next === 'getTemp') {
            result.list.forEach(item => {
              let _cell = item.data
              if (_cell.TemplateID) {
                templates.push(_cell.TemplateID)
              } else {
                _cell.TemplateID = btn.verify.Template
          if (result.next) {
            printlist = result.list.map(cell => {
              cell.templateID = cell.templateID || btn.verify.Template
              cell.printType = cell.printType || formdata.printType || ''
              let _printCount = printCount
              if (cell.printCount && typeof(cell.printCount) === 'number' && cell.printCount >= 1) {
                _printCount = cell.printCount
              }
              let _count = printCount
              if (item.count && typeof(item.count) === 'number' && item.count >= 1) {
                _count = item.count
              }
              for (let i = 0; i < _count; i++) {
                printlist.push({...formdata, ..._cell})
              }
              cell.printCount = _printCount
              templates.push(cell.templateID)
              return cell
            })
          } else if (result.next === 'customPrint') {
            this.execCustomPrint(btn, result.list)
          }
          
          resolve(result.next)
@@ -304,8 +322,13 @@
      }
    }).then(res => {
      // 获取打印模板 getTemp
      if (!res) return
      if (res !== 'getTemp') return false
      if (!res) return false
      if (btn.verify.printMode === 'custom') {
        this.execCustomPrint(btn, printlist, formdata)
        return false
      }
      templates = Array.from(new Set(templates)) // 去重
@@ -355,119 +378,33 @@
      })
      if (!errorMsg) {
        this.execPrint(btn, printlist, _temps)
        this.execPrint(btn, printlist, _temps, formdata)
      } else {
        this.execError(errorMsg, btn)
      }
    })
  }
  execCustomPrint = (item, printlist) => {
  execCustomPrint = (item, printlist, formdata) => {
    this.setState({loadingUuid: ''})
    if (!socket || socket.readyState !== 1 || socket.url !== 'ws://' + item.verify.linkUrl) {
      socket = new WebSocket('ws://' + item.verify.linkUrl)
    } else {
      if (!item.printer) {
        let request  = {
          requestID: '',
          version: '',
          cmd: 'getPrinters'
        }
        socket.send(JSON.stringify(request))
      } else {
        this.setState({loadingUuid: ''})
        try {
          // eslint-disable-next-line
          let func = new Function('socket', 'data', 'printer', 'notification', item.verify.printFunc)
          func(socket, printlist, item.printer, notification)
        } catch (e) {
          console.warn(e)
          notification.warning({
            top: 92,
            message: '自定义函数执行错误!',
            duration: 10
          })
        }
      }
    }
    // 打开Socket
    socket.onopen = () =>{
      if (!item.printer) {
        let request  = {
          requestID: '',
          version: '',
          cmd: 'getPrinters'
        }
        socket.send(JSON.stringify(request))
      } else {
        this.setState({loadingUuid: ''})
        try {
          // eslint-disable-next-line
          let func = new Function('socket', 'data', 'printer', 'notification', item.verify.printFunc)
          func(socket, printlist, item.printer, notification)
        } catch (e) {
          console.warn(e)
          notification.warning({
            top: 92,
            message: '自定义函数执行错误!',
            duration: 10
          })
        }
      }
    }
    // 监听消息
    socket.onmessage = (event) => {
      let data = ''
      if (event.data) {
        try {
          data = JSON.parse(event.data)
        } catch {
          data = ''
          notification.warning({
            top: 92,
            message: event.data,
            duration: 10
          })
          this.setState({loadingUuid: ''})
        }
      }
      if (data && data.cmd === 'getPrinters' && data.status) {
        this.setState({loadingUuid: ''})
        try {
          // eslint-disable-next-line
          let func = new Function('socket', 'data', 'printer', 'notification', item.verify.printFunc)
          func(socket, printlist, data.defaultPrinter, notification)
        } catch (e) {
          console.warn(e)
          notification.warning({
            top: 92,
            message: '自定义函数执行错误!',
            duration: 10
          })
        }
      } else if (data && data.message && !data.status) {
        notification.warning({
          top: 92,
          message: data.message,
          duration: 10
        })
        this.setState({loadingUuid: ''})
      }
    }
    socket.onerror = () => {
    try {
      // eslint-disable-next-line
      let func = new Function('data', 'form', 'printer', 'notification', item.verify.printFunc)
      func(printlist, formdata, item.verify, notification)
    } catch (e) {
      console.warn(e)
      notification.warning({
        top: 92,
        message: '无法连接到:' + item.verify.linkUrl,
        message: '自定义函数执行错误!',
        duration: 10
      })
      this.setState({loadingUuid: ''})
    }
  }
  /**
   * @description 获取打印数据
   */
  getprintdata = (btn, data, formdata, formlist) => {
    const { setting } = this.props
@@ -531,23 +468,15 @@
          Promise.all(deffers).then(result => {
            let errorMsg = ''
            result.forEach(res => {
              if (res.status) {
                if (btn.verify.printMode === 'custom') {
                  _list.push(res)
                } else {
                  res.data.forEach(_item => {
                    _list.push({data: _item, count: res.printCount})
                  })
                }
              } else {
              if (!res.status) {
                errorMsg = res
              }
            })
            if (!errorMsg) {
              resolve({next: btn.verify.printMode === 'custom' ? 'customPrint' : 'getTemp', list: _list})
              resolve({next: true, list: result})
            } else {
              this.execError(errorMsg, btn)
              resolve({next: false, list: _list})
              resolve({next: false, list: []})
            }
          })
        } else {
@@ -588,7 +517,7 @@
          } else {
            this.execError(res, btn)
            resolve(false)
            _resolve({next: false, list: _list})
            _resolve({next: false, list: []})
          }
        })
      } else {
@@ -632,45 +561,34 @@
        return Api.genericInterface(_callbackparam)
      } else if (response.status) {
        if (btn.verify.printMode === 'custom') {
          _list.push(response)
        } else {
          response.data.forEach(_item => {
            _list.push({data: _item, count: response.printCount})
          })
        }
        _list.push(response)
        // 一次请求成功,进行下一项请求
        if (params.length === 0) {
          _resolve({next: btn.verify.printMode === 'custom' ? 'customPrint' : 'getTemp', list: _list})
          _resolve({next: true, list: _list})
        } else {
          this.printOuterLoopRequest(params, btn, _list, _resolve)
        }
      } else {
        this.execError(response, btn)
        _resolve({next: false, list: _list})
        _resolve({next: false, list: []})
      }
    }).then(response => {
      if (!response) return
      if (response.status) {
        if (btn.verify.printMode === 'custom') {
          _list.push(response)
        } else {
          response.data.forEach(_item => {
            _list.push({data: _item, count: response.printCount})
          })
        }
        _list.push(response)
        // 一次请求成功,进行下一项请求
        if (params.length === 0) {
          _resolve({next: btn.verify.printMode === 'custom' ? 'customPrint' : 'getTemp', list: _list})
          _resolve({next: true, list: _list})
        } else {
          this.printOuterLoopRequest(params, btn, _list, _resolve)
        }
      } else {
        this.execError(response, btn)
        _resolve({next: false, list: _list})
        _resolve({next: false, list: []})
      }
    })
  }
@@ -683,22 +601,16 @@
    Api.genericInterface(param).then(res => {
      if (res.status) {
        if (btn.verify.printMode === 'custom') {
          _list.push(res)
        } else {
          res.data.forEach(_item => {
            _list.push({data: _item, count: res.printCount})
          })
        }
        _list.push(res)
        if (params.length === 0) {
          _resolve({next: btn.verify.printMode === 'custom' ? 'customPrint' : 'getTemp', list: _list})
          _resolve({next: true, list: _list})
        } else {
          this.printInnerLoopRequest(params, btn, _list, _resolve)
        }
      } else {
        this.execError(res, btn)
        _resolve({next: false, list: _list})
        _resolve({next: false, list: []})
      }
    })
  }
@@ -825,65 +737,104 @@
    }
  }
  execPrint = (item, list, template) => {
    let _documents = []
  execPrint = (item, list, template, formdata) => {
    let _errors = []
    Object.keys(template).forEach(key => {
      let _data = list.filter(cell => cell.TemplateID === key)
      if (_data.length > 0) {
        let _fields = Array.from(new Set(template[key].fields))
        let _nonEFields = Array.from(new Set(template[key].nonEFields))
        let lacks = []
        let emptys = []
        _data.forEach(d => {
          _fields.forEach(f => {
            if (!d.hasOwnProperty(f)) {
              lacks.push(f)
            } else if (_nonEFields.includes(f) && !d[f] && d[f] !== 0) {
              emptys.push(f)
            }
          })
        })
        let _cell = {
          documentID: Utils.getuuid(),
          contents: [
            {
              data: _data,
              templateURL: JSON.stringify(template[key].config)
            }
          ]
    let defaultPrinter = item.verify.defaultPrinter || 'lackprinter'
    let printers = {}
    if (item.verify.printerTypeList && item.verify.printerTypeList.length > 0) {
      item.verify.printerTypeList.forEach(cell => {
        if (cell.printer) {
          printers[cell.Value] = cell.printer
        }
      })
    }
        if (lacks.length > 0 || emptys.length > 0) {
          lacks = Array.from(new Set(lacks))
          emptys = Array.from(new Set(emptys))
    let printdata = {}
          _errors.push({
            title: template[key].config.Title,
            lacks: lacks,
            emptys: emptys
          })
        }
    list.forEach(res => {
      let _printer = defaultPrinter
        _documents.push(_cell)
      if (res.printType && printers[res.printType]) {
        _printer = printers[res.printType]
      }
      printdata[_printer] = printdata[_printer] || []
      printdata[_printer].push(res)
    })
    let printdata = {
      cmd: 'print',
      requestID: '',
      version: '',
      task: {
        taskID: Utils.getuuid(),
        preview: false,
        printer: item.printer,
        documents: _documents
    let printerList = []
    Object.keys(printdata).forEach(printer => {
      let _documents = []
      Object.keys(template).forEach(key => {
        let _datalist = printdata[printer].filter(cell => cell.templateID === key)
        if (_datalist.length > 0) {
          let _data = []
          _datalist.forEach(res => {
            res.data.forEach(_cell => {
              for (let i = 0; i < res.printCount; i++) {
                _data.push({...formdata, ..._cell})
              }
            })
          })
          let _fields = Array.from(new Set(template[key].fields))
          let _nonEFields = Array.from(new Set(template[key].nonEFields))
          let lacks = []
          let emptys = []
          _data.forEach(d => {
            _fields.forEach(f => {
              if (!d.hasOwnProperty(f)) {
                lacks.push(f)
              } else if (_nonEFields.includes(f) && !d[f] && d[f] !== 0) {
                emptys.push(f)
              }
            })
          })
          let _cell = {
            documentID: Utils.getuuid(),
            contents: [
              {
                data: _data,
                templateURL: JSON.stringify(template[key].config)
              }
            ]
          }
          if (lacks.length > 0 || emptys.length > 0) {
            lacks = Array.from(new Set(lacks))
            emptys = Array.from(new Set(emptys))
            _errors.push({
              title: template[key].config.Title,
              lacks: lacks,
              emptys: emptys
            })
          }
          _documents.push(_cell)
        }
      })
      if (_documents.length > 0) {
        printerList.push({
          cmd: 'print',
          requestID: Utils.getuuid(),
          version: Utils.getuuid(),
          task: {
            taskID: Utils.getuuid(),
            preview: false,
            printer: printer,
            documents: _documents
          }
        })
      }
    }
    })
    if (list.length === 0) {
      notification.warning({
@@ -896,6 +847,7 @@
    } else if (_errors.length > 0) {
      let lackerror = []
      let emptyerror = []
      _errors.forEach(err => {
        if (err.lacks.length > 0) {
          lackerror.push(`数据中未获取到模板(${err.title})${err.lacks.join('、')} 字段`)
@@ -923,10 +875,12 @@
      return
    }
    let lackItems = printerList.filter(cell => cell.task.printer === 'lackprinter')[0]
    if (!socket || socket.readyState !== 1 || socket.url !== 'ws://' + item.verify.linkUrl) {
      socket = new WebSocket('ws://' + item.verify.linkUrl)
    } else {
      if (!item.printer) {
      if (lackItems) {
        let request  = {
          requestID: '',
          version: '',
@@ -934,18 +888,21 @@
        }
        socket.send(JSON.stringify(request))
      } else {
        printerList.forEach(cell => {
          socket.send(JSON.stringify(cell))
        })
        this.setState({loadingUuid: ''})
        notification.success({
          top: 92,
          message: '打印请求已发出。',
          duration: 2
        })
        socket.send(JSON.stringify(printdata))
      }
    }
    // 打开Socket
    socket.onopen = () =>{
      if (!item.printer) {
      if (lackItems) {
        let request  = {
          requestID: '',
          version: '',
@@ -953,13 +910,16 @@
        }
        socket.send(JSON.stringify(request))
      } else {
        printerList.forEach(cell => {
          socket.send(JSON.stringify(cell))
        })
        this.setState({loadingUuid: ''})
        notification.success({
          top: 92,
          message: '打印请求已发出。',
          duration: 2
        })
        socket.send(JSON.stringify(printdata))
      }
    }
    // 监听消息
@@ -981,14 +941,19 @@
      }
      if (data && data.cmd === 'getPrinters' && data.status) {
        printdata.task.printer = data.defaultPrinter
        printerList.forEach(cell => {
          if (cell.task.printer === 'lackprinter') {
            cell.task.printer = data.defaultPrinter
          }
          socket.send(JSON.stringify(cell))
        })
        this.setState({loadingUuid: ''})
        notification.success({
          top: 92,
          message: '打印请求已发出。',
          duration: 2
        })
        socket.send(JSON.stringify(printdata))
      } else if (data && data.message && !data.status) {
        notification.warning({
          top: 92,
@@ -1014,6 +979,7 @@
   */
  changeUser = (btn, data) => {
    const { setting } = this.props
    let _this = this
    let param = {
      BID: this.props.BID,
@@ -1024,6 +990,9 @@
    param[setting.primaryKey] = data[0][setting.primaryKey]
    this.setState({
      running: true
    })
    confirm({
      title: this.props.dict['main.action.confirm.tip'],
      onOk() {
@@ -1036,6 +1005,7 @@
              sessionStorage.setItem('SessionUid', Utils.getuuid())
              sessionStorage.setItem('LoginUID', res.LoginUID)
              sessionStorage.setItem('User_Name', res.UserName)
              sessionStorage.setItem('Full_Name', res.FullName)
              
              window.location.reload()
            } else {
@@ -1048,7 +1018,11 @@
          })
        })
      },
      onCancel() {}
      onCancel() {
        _this.setState({
          running: false
        })
      }
    })
  }
@@ -1080,7 +1054,6 @@
        btn.Ot === 'notRequired' ||
        btn.Ot === 'requiredSgl' ||
        (btn.Ot === 'requiredOnce' && btn.OpenType !== 'pop')
        // (btn.OpenType === 'pop' && !btn.innerFunc && btn.sql && btn.sqlType === 'insert')
      ) {
        // 创建凭证时,需要选择行时
@@ -1135,12 +1108,14 @@
          } else if (btn.sql && btn.sqlType === 'insert') { // 系统函数添加时,生成uuid
            primaryId = ''
            if (formdata && setting.primaryKey) { // 表单中存在主键字段,主键值以表单中的值为准
              let _form = formdata.filter(_form => _form.key === setting.primaryKey)[0]
              if (_form) {
                primaryId = _form.value
              }
            }
            param.ID = primaryId || Utils.getguid()
            param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, formdata, param, data[0], logcolumns)) // 数据源
            param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
@@ -1499,7 +1474,8 @@
    }
    this.setState({
      loadingUuid: ''
      loadingUuid: '',
      running: false
    })
    this.refreshdata(btn, 'success')
@@ -1534,7 +1510,8 @@
    }
    
    this.setState({
      loadingUuid: ''
      loadingUuid: '',
      running: false
    })
    
    this.refreshdata(btn, 'error')
@@ -1544,6 +1521,9 @@
   * @description 按钮配置信息错误提示
   */
  actionSettingError = () => {
    this.setState({
      running: false
    })
    notification.warning({
      top: 92,
      message: this.props.dict['main.action.settingerror'],
@@ -2416,6 +2396,9 @@
        value: _initval
      }
    })
    this.setState({
      running: true
    })
    confirm({
      title: this.props.dict['main.action.confirm.tip'],
@@ -2424,7 +2407,11 @@
          _this.execSubmit(execAction, tabledata, resolve, result)
        })
      },
      onCancel() {}
      onCancel() {
        _this.setState({
          running: false
        })
      }
    })
  }
src/tabviews/zshare/normalTable/index.jsx
@@ -33,6 +33,8 @@
    let _columns = []
    
    columns.forEach(item => {
      if (item.hidden === 'true') return
      let cell = {
        align: item.Align,
        dataIndex: item.field || item.uuid,
@@ -43,6 +45,7 @@
          return this.getContent(item, record)
        }
      }
      _columns.push(cell)
    })
src/tabviews/zshare/verifycard/index.jsx
@@ -1,387 +1,346 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Tabs, Row, Col, Radio, Table, Icon, Select, notification } from 'antd'
import { Form, Tabs, notification, Spin, Icon } from 'antd'
import Utils from '@/utils/utils.js'
// import Utils from '@/utils/utils.js'
import Api from '@/api'
import ActionForm from './actionform'
import TabCard from './tabcard'
import './index.scss'
const { TabPane } = Tabs
const keycode = {
  65: 'A',
  66: 'B',
  67: 'C',
  68: 'D',
  69: 'E',
  70: 'F',
  71: 'G',
  72: 'H',
  73: 'I',
  74: 'J',
  75: 'K',
  76: 'L',
  77: 'M',
  78: 'N',
  79: 'O',
  80: 'P',
  81: 'Q',
  82: 'R',
  83: 'S',
  84: 'T',
  85: 'U',
  86: 'V',
  87: 'W',
  88: 'X',
  89: 'Y',
  90: 'Z'
}
class VerifyCard extends Component {
  static propTpyes = {
    config: PropTypes.object     // 页面配置
    MenuID: PropTypes.string,
    MenuName: PropTypes.string,
    permAction: PropTypes.object,
    permRoles: PropTypes.array,
    userConfig: PropTypes.object,
    columns: PropTypes.array,
    config: PropTypes.object,     // 页面配置
    handleParam: PropTypes.func   // 配置信息变化
  }
  state = {
    colColumns: [
      {
        title: '字段名',
        dataIndex: 'field',
        width: '35%'
      },
      {
        title: '操作',
        align: 'center',
        width: '25%',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record, 'column')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
            <span className="operation-btn" title="上移" onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
            <span className="operation-btn" title="下移" onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
            <span className="operation-btn" title="状态切换" onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
          </div>)
      }
    ],
    actionColumns: [
      {
        title: '名称',
        dataIndex: 'label',
        width: '25%'
      },
      {
        title: '快捷键',
        dataIndex: 'shortcut',
        width: '25%',
        render: (text, record) => {
          if (!record.shortcut || typeof(record.shortcut) !== 'object' || record.shortcut.length === 0) return ''
          let _text = keycode[record.shortcut[1]]
          return record.shortcut[0] + ' + ' + _text
        }
      },
      {
        title: '打印机',
        dataIndex: 'printer',
        width: '30%'
      },
      {
        title: '操作',
        align: 'center',
        width: '20%',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record, 'action')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
          </div>)
      }
    ]
    loading: true,
    menuParam: null,
    menuconfig: null
  }
  UNSAFE_componentWillMount() {
    const { config } = this.props
  UNSAFE_componentWillMount () {
    const { MenuID, MenuName, permAction, permRoles, config, userConfig, columns } = this.props
    let menuParam = []
    this.setState({
      config: JSON.parse(JSON.stringify(config))
      loadingview: true
    })
  }
  componentDidMount() {
    let printbtns = this.state.config.action.filter(item => item.OpenType === 'funcbutton' && item.funcType === 'print')
    printbtns.forEach(item => {
      if (!item.verify || !item.verify.linkUrl) {
        notification.warning({
          top: 92,
          message: '打印按钮《' + item.label + '》设置错误!',
          duration: 10
        })
      } else {
        let socket = null
        socket = new WebSocket('ws://' + item.verify.linkUrl)
        // 打开Socket
        socket.onopen = () =>{
          let request  = {
            requestID: '',
            version: '',
            cmd: 'getPrinters'
          }
          socket.send(JSON.stringify(request))
        }
        // 监听消息
        socket.onmessage = (event) => {
          let data = ''
          try {
            data = JSON.parse(event.data)
          } catch {
            data = ''
          }
          if (data && data.cmd === 'getPrinters' && data.status) {
            let printers = Array.from(new Set(data.printers))
            let _config = JSON.parse(JSON.stringify(this.state.config))
            _config.action = _config.action.map(cell => {
              if (item.uuid === cell.uuid) {
                cell.printer = cell.printer || data.defaultPrinter
                cell.printers = printers.map(print => {
                  return {
                    value: print,
                    text: print
                  }
                })
              }
              return cell
            })
            this.setState({
              config: _config
            })
          } else if (data && data.cmd === 'getPrinters' && !data.status) {
            notification.warning({
              top: 92,
              message: data.message,
              duration: 10
            })
          }
    menuParam.push({
      uuid: MenuID,
      type: 'main',
      label: MenuName + '(主表)',
      setting: {
        actionfixed: config.setting.actionfixed,
        columnfixed: config.setting.columnfixed,
        tableType: config.setting.tableType
      },
      action: config.action.map(item => {
        let _item = {
          uuid: item.uuid,
          label: item.label,
          shortcut: item.shortcut || ''
        }
        socket.onerror = () => {
        if (item.OpenType === 'funcbutton' && item.funcType === 'print') {
          _item.type = 'print'
          _item.verify = item.verify
          _item.printer = item.printer || ''
        }
        return _item
      }),
      columns: columns.map(item => {
        return {
          uuid: item.uuid,
          label: item.label,
          Width: item.Width,
          hidden: item.hidden || false,
          sort: item.sort || 0
        }
      })
    })
    let deffers = []
    config.tabgroups.forEach(groupId => {
      config[groupId].forEach(tab => {
        deffers.push(new Promise(resolve => {
          let param = {
            func: 'sPC_Get_LongParam',
            MenuID: tab.linkTab
          }
          Api.getSystemCacheConfig(param).then(res => {
            res.tab = tab
            resolve(res)
          })
        }))
      })
    })
    if (deffers.length > 0) {
      Promise.all(deffers).then(result => {
        let errors = result.filter(res => !res.status)
        if (errors.length > 0) {
          notification.warning({
            top: 92,
            message: '无法连接到:' + item.verify.linkUrl,
            message: errors[0].message,
            duration: 10
          })
          return
        }
      }
    })
  }
  columnChange = (values) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
        result.forEach(res => {
          if (!res.LongParam) return
    if (values.uuid) {
      verify.uniques = verify.uniques.map(item => {
        if (item.uuid === values.uuid) {
          return values
        } else {
          return item
        }
      })
    } else {
      values.uuid = Utils.getuuid()
      verify.uniques.push(values)
    }
          let subconfig = ''
          let subUserConfig = userConfig ? userConfig[res.tab.linkTab] : ''
    this.setState({
      verify: verify
    })
  }
          try {
            subconfig = JSON.parse(window.decodeURIComponent(window.atob(res.LongParam)))
          } catch (e) {
            console.warn('Parse Failure')
            errors.push('子标签《' + res.tab.label + '》参数解析错误!')
          }
  actionChange = (values) => {
    let config = JSON.parse(JSON.stringify(this.state.config))
          if (!subconfig || !subconfig.enabled) return
    config.action = config.action.map(item => {
      if (values.uuid === item.uuid) {
        item = {...item, ...values}
      }
          let _columns = []      // 显示列
          let _hideCol = []      // 隐藏及合并列中字段的uuid集
          let colMap = new Map()
      return item
    })
    this.setState({
      config: config
    })
  }
  handleEdit = (record, type) => {
    if (type === 'action') {
      this.actionForm.edit(record)
    } else if (type === 'column') {
      this.uniqueForm.edit(record)
    }
    let node = document.getElementById('verify-card-box-tab').parentNode
    if (node && node.scrollTop) {
      let inter = Math.ceil(node.scrollTop / 10)
      let timer = setInterval(() => {
        if (node.scrollTop - inter > 0) {
          node.scrollTop = node.scrollTop - inter
        } else {
          node.scrollTop = 0
          clearInterval(timer)
        }
      }, 10)
    }
  }
  handleStatus = (record) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    record.status = record.status === 'false' ? 'true' : 'false'
    verify.scripts = verify.scripts.map(item => {
      if (item.uuid === record.uuid) {
        return record
      } else {
        return item
      }
    })
    this.setState({
      verify: verify
    })
  }
  handleUpDown = (record, type, direction) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    let index = 0
    verify.customverifys = verify.customverifys.filter((item, i) => {
      if (item.uuid === record.uuid) {
        index = i
      }
      return item.uuid !== record.uuid
    })
    if ((index === 0 && direction === 'up') || (index === verify.customverifys.length && direction === 'down')) {
      return
    }
    if (direction === 'up') {
      verify.customverifys.splice(index - 1, 0, record)
    } else {
      verify.customverifys.splice(index + 1, 0, record)
    }
    this.setState({
      verify: verify
    })
  }
  handleConfirm = () => {
    const { config } = this.state
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _config = {}
          _config.setting = values
          _config.action = config.action.map(item => {
            return {
              uuid: item.uuid,
              shortcut: item.shortcut || '',
              shortcutkey: item.shortcutkey || '',
              printer: item.printer || ''
          // 权限过滤
          subconfig.action = subconfig.action.filter(item => permAction[item.uuid])
          subconfig.columns = subconfig.columns.filter(col => {
            if (!col.field || !col.blacklist || col.blacklist.length === 0 || subconfig.setting.primaryKey === col.field) return true
            let _black = col.blacklist.filter(v => {
              return permRoles.indexOf(v) !== -1
            })
            if (_black.length > 0) {
              return false
            } else {
              return true
            }
          })
          resolve(_config)
          if (subUserConfig) {
            subconfig.setting.tableType = subUserConfig.setting.tableType
            subconfig.action = subconfig.action.map(item => {
              if (subUserConfig.action[item.uuid]) {
                item = {...item, ...subUserConfig.action[item.uuid]}
              }
              if (item.execMode) {
                item.OpenType = 'funcbutton'
              }
              if (item.OpenType === 'funcbutton' && item.funcType === 'print' && item.verify && item.printer) {
                item.verify.defaultPrinter = item.printer.defaultPrinter || ''
                if (item.verify.printerTypeList && item.printer.printerList) {
                  item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
                    cell.printer = item.printer.printerList[cell.Value] || ''
                    return cell
                  })
                }
              }
              return item
            })
          } else {
            subconfig.action = subconfig.action.map(item => {
              if (item.execMode) {
                item.OpenType = 'funcbutton'
              }
              return item
            })
          }
          // 1、筛选字段集,2、过滤隐藏列及合并列中的字段uuid
          subconfig.columns.forEach(col => {
            if (col.type === 'colspan' && col.sublist) { // 筛选隐藏列
              _hideCol = _hideCol.concat(col.sublist)
            } else if (col.Hide === 'true') {
              _hideCol.push(col.uuid)
            }
            colMap.set(col.uuid, col)
          })
          // 生成显示列,处理合并列中的字段
          subconfig.columns.forEach(col => {
            if (_hideCol.includes(col.uuid)) return
            if (col.type === 'colspan' && col.sublist) {
              let _col = JSON.parse(JSON.stringify(col))
              let subColumn = []
              _col.sublist.forEach(sub => {
                if (colMap.has(sub)) {
                  subColumn.push(colMap.get(sub))
                }
              })
              _col.subColumn = subColumn
              _columns.push(_col)
            } else {
              _columns.push(col)
            }
          })
          let _operations = subconfig.action.filter(item => item.position === 'grid')
          if (subconfig.gridBtn && subconfig.gridBtn.display && _operations.length > 0) {
            _columns.push({
              ...subconfig.gridBtn,
              operations: _operations
            })
          }
          // 添加用户显示列设置
          if (subUserConfig) {
            _columns = _columns.map(item => {
              if (subUserConfig.columns[item.uuid]) {
                item = {...item, ...subUserConfig.columns[item.uuid]}
              }
              return item
            })
            _columns.sort((pre, next) => {
              return pre.sort - next.sort
            })
          }
          menuParam.push({
            uuid: res.tab.linkTab,
            label: res.tab.label,
            setting: {tableType: subconfig.setting.tableType},
            action: subconfig.action.map(item => {
              let _item = {
                uuid: item.uuid,
                label: item.label,
                shortcut: item.shortcut || ''
              }
              if (item.OpenType === 'funcbutton' && item.funcType === 'print') {
                _item.type = 'print'
                _item.verify = item.verify
                _item.printer = item.printer || ''
              }
              return _item
            }),
            columns: _columns.map(item => {
              return {
                uuid: item.uuid,
                label: item.label,
                Width: item.Width,
                hidden: item.hidden || false,
                sort: item.sort || 0
              }
            })
          })
        })
        if (errors.length > 0) {
          notification.warning({
            top: 92,
            message: errors[0],
            duration: 10
          })
          return
        }
        this.setState({
          loading: false,
          menuParam: menuParam
        }, () => {
          this.getInitParam()
        })
      })
    })
    } else {
      this.setState({
        loading: false
      })
    }
  }
  getInitParam = () => {
    let config = JSON.parse(JSON.stringify(this.state.menuParam))
    let _config = {}
    config.forEach(tab => {
      let _tab = {
        label: tab.label,
        setting: tab.setting,
        action: {},
        columns: {}
      }
      tab.action.forEach(item => {
        _tab.action[item.uuid] = {
          printer: item.printer || '',
          shortcut: item.shortcut
        }
      })
      tab.columns.forEach((item, index) => {
        _tab.columns[item.uuid] = {
          Width: item.Width,
          hidden: item.hidden,
          sort: index
        }
      })
      _config[tab.uuid] = _tab
    })
    this.setState({
      menuconfig: _config
    })
    this.props.handleParam(_config)
  }
  changeconfig = (uuid, param) => {
    let _menuconfig = JSON.parse(JSON.stringify(this.state.menuconfig))
    _menuconfig[uuid] = param
    this.setState({
      menuconfig: _menuconfig
    })
    this.props.handleParam(_menuconfig)
  }
  render() {
    const { getFieldDecorator } = this.props.form
    const { actionColumns, config } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    const { menuParam, loading } = this.state
    return (
      <div id="verify-card-box-tab">
        <Tabs defaultActiveKey="1" className="verify-card-box">
          <TabPane tab="基础设置" key="1">
            <Form {...formItemLayout}>
              <Row gutter={24}>
                <Col span={8}>
                  <Form.Item label="固定按钮">
                    {getFieldDecorator('actionfixed', {
                      initialValue: config.setting.actionfixed ? 'true' : 'false'
                    })(
                      <Radio.Group>
                        <Radio value="true">是</Radio>
                        <Radio value="false">否</Radio>
                      </Radio.Group>
                    )}
                  </Form.Item>
                </Col>
                <Col span={8}>
                  <Form.Item label="固定表头">
                    {getFieldDecorator('columnfixed', {
                      initialValue: config.setting.columnfixed ? 'true' : 'false'
                    })(
                      <Radio.Group>
                        <Radio value="true">是</Radio>
                        <Radio value="false">否</Radio>
                      </Radio.Group>
                    )}
                  </Form.Item>
                </Col>
                <Col span={8}>
                  <Form.Item label="表格属性">
                    {getFieldDecorator('tableType', {
                      initialValue: config.setting.tableType || 'checkbox'
                    })(
                      <Select>
                        <Select.Option value="">不可选</Select.Option>
                        <Select.Option value="radio">单选</Select.Option>
                        <Select.Option value="checkbox">多选</Select.Option>
                      </Select>
                    )}
                  </Form.Item>
                </Col>
              </Row>
            </Form>
          </TabPane>
          <TabPane tab="按钮设置" key="action">
            <ActionForm
              dict={this.props.dict}
              actionChange={this.actionChange}
              wrappedComponentRef={(inst) => this.actionForm = inst}
            />
            <Table
              bordered
              rowKey="uuid"
              className="custom-table"
              dataSource={config.action}
              columns={actionColumns}
              pagination={false}
            />
          </TabPane>
        </Tabs>
      <div id="verify-card-box-tab" className="verify-card-horizontal-box">
        {loading ? <Spin size="large" /> : null}
        {menuParam ? <Tabs defaultActiveKey={menuParam[0].uuid}>
          {menuParam.map(tab => {
            return (
              <TabPane tab={tab.label} key={tab.uuid}>
                <TabCard config={tab} handleconfig={this.changeconfig}/>
              </TabPane>
            )
          })}
        </Tabs> : null}
        {!loading && !menuParam ? <div className="message-fail"><Icon type="exclamation-circle" />信息获取失败</div> : null}
      </div>
    )
  }
src/tabviews/zshare/verifycard/index.scss
@@ -1,4 +1,11 @@
.verify-card-box {
.verify-card-horizontal-box {
  min-height: 250px;
  position: relative;
  > .ant-spin {
    position: absolute;
    left: calc(50% - 22px);
    top: 80px;
  }
  .ant-tabs-nav-scroll {
    text-align: center;
  }
@@ -33,9 +40,6 @@
        width: 89.5%;
      }
    }
    .add {
      padding-top: 0px;
    }
    .ant-input-disabled {
      color: rgba(0, 0, 0, 0.65);
      cursor: default;
@@ -44,14 +48,19 @@
  .custom-table .ant-empty {
    margin: 20px 8px!important;
  }
  .errorval {
    display: inline-block;
    width: 30px;
  }
  .operation-btn {
    display: inline-block;
    font-size: 16px;
    padding: 0 5px;
    cursor: pointer;
  }
  > .message-fail {
    text-align: center;
    padding-top: 50px;
    i {
      color: #ff4d4f;
      margin-right: 5px;
      font-size: 16px;
    }
  }
}
src/tabviews/zshare/verifycard/tabcard/actionform/index.jsx
File was renamed from src/tabviews/zshare/verifycard/actionform/index.jsx
@@ -1,6 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Select, Button, Input, Cascader } from 'antd'
import { Form, Row, Col, Button, Input, Cascader } from 'antd'
import './index.scss'
const shortkeycode = {
@@ -86,10 +86,6 @@
        shortcut: _shortcut
      }
      if (record.OpenType === 'funcbutton' && record.funcType === 'print') {
        item.printer = record.printer || ''
      }
      this.props.form.setFieldsValue(item)
    })
  }
@@ -105,11 +101,6 @@
        this.setState({
          editItem: null
        }, () => {
          this.props.form.setFieldsValue({
            shortcut: [],
            label: ''
          })
        })
      }
    })
@@ -129,11 +120,9 @@
      }
    }
    let hasprint = editItem && editItem.OpenType === 'funcbutton' && editItem.funcType === 'print'
    return (
      <Form {...formItemLayout} className="verify-form" id="verifycard1">
        <Row gutter={24}>
      <Form {...formItemLayout} className="verify-form">
        {editItem ? <Row gutter={24}>
          <Col span={10}>
            <Form.Item label={'名称'}>
              {getFieldDecorator('label', {
@@ -154,34 +143,18 @@
            </Form.Item>
          </Col>
          <Col span={4} className="add">
            <Form.Item label=" " colon={false} >
              <Button onClick={this.handleConfirm} type="primary" className="add-row">
                确定
              </Button>
            <Button onClick={this.handleConfirm} type="primary" className="add-row">
              确定
            </Button>
          </Col>
        </Row> : null}
        {!editItem ? <Row gutter={24} style={{height: '64px', paddingTop: '5px'}}>
          <Col span={24} className="print-tip">
            <Form.Item label={'提示'}>
              点击编辑图标可设置按钮对应的快捷键,注:快捷键设置重复时,会以排序在前的按钮为准。
            </Form.Item>
          </Col>
          {hasprint ?
            <Col span={10}>
              <Form.Item label={'打印机'}>
                {getFieldDecorator('printer', {
                  initialValue: '',
                  rules: [
                    {
                      required: true,
                      message: '请选择打印机!'
                    }
                  ]
                })(
                  <Select>
                    {editItem.printers && editItem.printers.map(option =>
                      <Select.Option id={option.value} title={option.text} key={option.value} value={option.value}>{option.text}</Select.Option>
                    )}
                  </Select>
                )}
              </Form.Item>
            </Col> : null
          }
        </Row>
        </Row> : null}
      </Form>
    )
  }
src/tabviews/zshare/verifycard/tabcard/actionform/index.scss
src/tabviews/zshare/verifycard/tabcard/index.jsx
New file
@@ -0,0 +1,625 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Tabs, Row, Col, Radio, Table, Icon, Select, notification } from 'antd'
// import Utils from '@/utils/utils.js'
import ActionForm from './actionform'
import PrintForm from './printform'
import PrintTypeForm from './printtypeform'
import './index.scss'
const { TabPane } = Tabs
const keycode = {
  65: 'A',
  66: 'B',
  67: 'C',
  68: 'D',
  69: 'E',
  70: 'F',
  71: 'G',
  72: 'H',
  73: 'I',
  74: 'J',
  75: 'K',
  76: 'L',
  77: 'M',
  78: 'N',
  79: 'O',
  80: 'P',
  81: 'Q',
  82: 'R',
  83: 'S',
  84: 'T',
  85: 'U',
  86: 'V',
  87: 'W',
  88: 'X',
  89: 'Y',
  90: 'Z'
}
class VerifyCard extends Component {
  static propTpyes = {
    config: PropTypes.object,        // 页面配置
    handleconfig: PropTypes.func     // 页面配置
  }
  state = {
    config: null,
    subconfig: null,
    printbtns: null,
    colColumns: [
      {
        title: '字段名',
        dataIndex: 'field',
        width: '35%'
      },
      {
        title: '列宽',
        dataIndex: 'Width',
        width: '35%'
      },
      {
        title: '字段名',
        dataIndex: 'field',
        width: '35%'
      },
      {
        title: '操作',
        align: 'center',
        width: '25%',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record, 'column')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
            <span className="operation-btn" title="上移" onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
            <span className="operation-btn" title="下移" onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
            <span className="operation-btn" title="状态切换" onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
          </div>)
      }
    ],
    printColumns: [
      {
        title: '名称',
        dataIndex: 'label',
        width: '25%'
      },
      {
        title: '默认打印机',
        dataIndex: 'print',
        width: '45%',
        render: (text, record) => {
          if (!record.verify) return ''
          return record.verify.defaultPrinter || ''
        }
      },
      {
        title: '操作',
        align: 'center',
        width: '20%',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record, 'print')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
          </div>)
      }
    ],
    printTypeColumns: [
      {
        title: '打印类型',
        dataIndex: 'Text',
        width: '25%'
      },
      {
        title: '打印机',
        dataIndex: 'printer',
        width: '45%'
      },
      {
        title: '操作',
        align: 'center',
        width: '20%',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record, 'printtype')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
          </div>)
      }
    ],
    actionColumns: [
      {
        title: '名称',
        dataIndex: 'label',
        width: '25%'
      },
      {
        title: '快捷键',
        dataIndex: 'shortcut',
        width: '25%',
        render: (text, record) => {
          if (!record.shortcut || typeof(record.shortcut) !== 'object' || record.shortcut.length === 0) return ''
          let _text = keycode[record.shortcut[1]]
          return record.shortcut[0] + ' + ' + _text
        }
      },
      {
        title: '操作',
        align: 'center',
        width: '20%',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record, 'action')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
          </div>)
      }
    ]
  }
  UNSAFE_componentWillMount() {
    let config = JSON.parse(JSON.stringify(this.props.config))
    let _subconfig = {
      label: config.label,
      setting: config.setting,
      action: {},
      columns: {}
    }
    config.action.forEach(item => {
      _subconfig.action[item.uuid] = {
        printer: item.printer || '',
        shortcut: item.shortcut
      }
    })
    config.columns.forEach((item, index) => {
      _subconfig.columns[item.uuid] = {
        Width: item.Width,
        hidden: item.hidden,
        sort: index
      }
    })
    this.setState({
      subconfig: _subconfig,
      config: config,
      printbtns: config.action.filter(item => item.type === 'print')
    })
  }
  componentDidMount() {
    const { printbtns } = this.state
    printbtns.forEach(item => {
      if (!item.verify || !item.verify.linkUrl) {
        notification.warning({
          top: 92,
          message: '打印按钮《' + item.label + '》设置错误!',
          duration: 10
        })
      } else {
        let socket = null
        socket = new WebSocket('ws://' + item.verify.linkUrl)
        // 打开Socket
        socket.onopen = () =>{
          let request  = {
            requestID: '',
            version: '',
            cmd: 'getPrinters'
          }
          socket.send(JSON.stringify(request))
        }
        // 监听消息
        socket.onmessage = (event) => {
          let data = ''
          try {
            data = JSON.parse(event.data)
          } catch {
            data = ''
          }
          if (data && data.cmd === 'getPrinters' && data.status) {
            let _printers = Array.from(new Set(data.printers))
            _printers = _printers.map(print => {
              return {
                value: print,
                text: print
              }
            })
            let _printparam = {
              defaultPrinter: data.defaultPrinter,
              printers: _printers
            }
            let _printbtns = JSON.parse(JSON.stringify(this.state.printbtns))
            _printbtns = _printbtns.map(cell => {
              if (item.uuid === cell.uuid) {
                cell.printparam = _printparam
              }
              return cell
            })
            this.setState({
              printbtns: _printbtns
            })
          } else if (data && data.cmd === 'getPrinters' && !data.status) {
            notification.warning({
              top: 92,
              message: data.message,
              duration: 10
            })
          }
        }
        socket.onerror = () => {
          notification.warning({
            top: 92,
            message: '无法连接到:' + item.verify.linkUrl,
            duration: 10
          })
        }
      }
    })
  }
  columnChange = (values) => {
    let _config = JSON.parse(JSON.stringify(this.state.config))
    let _subconfig = JSON.parse(JSON.stringify(this.state.subconfig))
    _config.action = _config.action.map(item => {
      if (values.uuid === item.uuid) {
        item = {...item, ...values}
      }
      _subconfig.action[item.uuid] = {
        printer: item.printer || '',
        shortcut: item.shortcut
      }
      return item
    })
    this.setState({
      config: _config,
      subconfig: _subconfig
    })
    this.props.handleconfig(_config.uuid, _subconfig)
  }
  actionChange = (values) => {
    let _config = JSON.parse(JSON.stringify(this.state.config))
    let _subconfig = JSON.parse(JSON.stringify(this.state.subconfig))
    _config.action = _config.action.map(item => {
      if (values.uuid === item.uuid) {
        item = {...item, ...values}
        _subconfig.action[item.uuid].shortcut = item.shortcut || ''
      }
      return item
    })
    this.setState({
      config: _config,
      subconfig: _subconfig
    })
    this.props.handleconfig(_config.uuid, _subconfig)
  }
  printChange = (values) => {
    const { config } = this.props
    let _printbtns = JSON.parse(JSON.stringify(this.state.printbtns))
    let _subconfig = JSON.parse(JSON.stringify(this.state.subconfig))
    _printbtns = _printbtns.map(item => {
      if (values.uuid === item.uuid) {
        item.verify = item.verify || {}
        item.verify.defaultPrinter = values.defaultPrinter || ''
        _subconfig.action[item.uuid].printer = _subconfig.action[item.uuid].printer || {}
        _subconfig.action[item.uuid].printer.defaultPrinter = values.defaultPrinter || ''
      }
      return item
    })
    this.setState({
      printbtns: _printbtns,
      subconfig: _subconfig
    })
    this.props.handleconfig(config.uuid, _subconfig)
  }
  printTypeChange = (record, values) => {
    const { config } = this.props
    let _printbtns = JSON.parse(JSON.stringify(this.state.printbtns))
    let _subconfig = JSON.parse(JSON.stringify(this.state.subconfig))
    _printbtns = _printbtns.map(item => {
      if (record.uuid === item.uuid) {
        item.verify.printerTypeList = item.verify.printerTypeList.map(cell => {
          if (cell.key === values.key) {
            cell.printer = values.printer
          }
          return cell
        })
        _subconfig.action[item.uuid].printer = _subconfig.action[item.uuid].printer || {}
        _subconfig.action[item.uuid].printer.printerList = _subconfig.action[item.uuid].printer.printerList || {}
        _subconfig.action[item.uuid].printer.printerList[values.Value] = values.printer
      }
      return item
    })
    this.setState({
      printbtns: _printbtns,
      subconfig: _subconfig
    })
    this.props.handleconfig(config.uuid, _subconfig)
  }
  handleEdit = (record, type) => {
    if (type === 'action') {
      this.actionForm.edit(record)
    } else if (type === 'print') {
      this.printForm.edit(record)
    } else if (type === 'printtype') {
      this.printTypeForm.edit(record)
    } else if (type === 'column') {
      this.uniqueForm.edit(record)
    }
    if (type === 'printtype') return
    let node = document.getElementById('verify-card-box-tab').parentNode
    if (node && node.scrollTop) {
      let inter = Math.ceil(node.scrollTop / 10)
      let timer = setInterval(() => {
        if (node.scrollTop - inter > 0) {
          node.scrollTop = node.scrollTop - inter
        } else {
          node.scrollTop = 0
          clearInterval(timer)
        }
      }, 10)
    }
  }
  handleStatus = (record) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    record.status = record.status === 'false' ? 'true' : 'false'
    verify.scripts = verify.scripts.map(item => {
      if (item.uuid === record.uuid) {
        return record
      } else {
        return item
      }
    })
    this.setState({
      verify: verify
    })
  }
  handleUpDown = (record, type, direction) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    let index = 0
    verify.customverifys = verify.customverifys.filter((item, i) => {
      if (item.uuid === record.uuid) {
        index = i
      }
      return item.uuid !== record.uuid
    })
    if ((index === 0 && direction === 'up') || (index === verify.customverifys.length && direction === 'down')) {
      return
    }
    if (direction === 'up') {
      verify.customverifys.splice(index - 1, 0, record)
    } else {
      verify.customverifys.splice(index + 1, 0, record)
    }
    this.setState({
      verify: verify
    })
  }
  handleConfirm = () => {
    const { config } = this.state
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _config = {}
          _config.setting = values
          _config.action = config.action.map(item => {
            return {
              uuid: item.uuid,
              shortcut: item.shortcut || '',
              printer: item.printer || ''
            }
          })
          resolve(_config)
        }
      })
    })
  }
  changebtnfix = (e) => {
    let val = e.target.value
    const { config } = this.props
    let subconfig = JSON.parse(JSON.stringify(this.state.subconfig))
    subconfig.setting.actionfixed = val === 'true'
    this.setState({
      subconfig: subconfig
    })
    this.props.handleconfig(config.uuid, subconfig)
  }
  changecolfix = (e) => {
    let val = e.target.value
    const { config } = this.props
    let subconfig = JSON.parse(JSON.stringify(this.state.subconfig))
    subconfig.setting.columnfixed = val === 'true'
    this.setState({
      subconfig: subconfig
    })
    this.props.handleconfig(config.uuid, subconfig)
  }
  changecheckbox = (val) => {
    const { config } = this.props
    let subconfig = JSON.parse(JSON.stringify(this.state.subconfig))
    subconfig.setting.tableType = val
    this.setState({
      subconfig: subconfig
    })
    this.props.handleconfig(config.uuid, subconfig)
  }
  render() {
    const { config } = this.props
    const { actionColumns, printColumns, printTypeColumns, printbtns } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <Tabs defaultActiveKey="1" tabPosition="left" className="verify-card-box-vertical-tab">
        <TabPane tab="基础设置" key="1">
          <Form {...formItemLayout}>
            <Row gutter={24}>
              {config.type === 'main' ? <Col span={8}>
                <Form.Item label="固定按钮">
                  <Radio.Group defaultValue={config.setting.actionfixed ? 'true' : 'false'} onChange={this.changebtnfix}>
                    <Radio value="true">是</Radio>
                    <Radio value="false">否</Radio>
                  </Radio.Group>
                </Form.Item>
              </Col> : null}
              {config.type === 'main' ? <Col span={8}>
                <Form.Item label="固定表头">
                  <Radio.Group defaultValue={config.setting.columnfixed ? 'true' : 'false'} onChange={this.changecolfix}>
                    <Radio value="true">是</Radio>
                    <Radio value="false">否</Radio>
                  </Radio.Group>
                </Form.Item>
              </Col> : null}
              <Col span={8}>
                <Form.Item label="表格属性">
                  <Select defaultValue={config.setting.tableType} onChange={this.changecheckbox}>
                    <Select.Option value="">不可选</Select.Option>
                    <Select.Option value="radio">单选</Select.Option>
                    <Select.Option value="checkbox">多选</Select.Option>
                  </Select>
                </Form.Item>
              </Col>
            </Row>
          </Form>
        </TabPane>
        <TabPane tab="按钮设置" key="action">
          <ActionForm
            dict={this.props.dict}
            actionChange={this.actionChange}
            wrappedComponentRef={(inst) => this.actionForm = inst}
          />
          <Table
            bordered
            rowKey="uuid"
            className="custom-table"
            dataSource={this.state.config.action}
            columns={actionColumns}
            pagination={false}
          />
        </TabPane>
        {/* <TabPane tab="显示列设置" key="column">
          <ActionForm
            dict={this.props.dict}
            actionChange={this.actionChange}
            wrappedComponentRef={(inst) => this.actionForm = inst}
          />
          <Table
            bordered
            rowKey="uuid"
            className="custom-table"
            dataSource={this.state.config.action}
            columns={actionColumns}
            pagination={false}
          />
        </TabPane> */}
        {printbtns && printbtns.length > 0 ? <TabPane tab="打印设置" key="print">
          <PrintForm
            dict={this.props.dict}
            actionChange={this.printChange}
            wrappedComponentRef={(inst) => this.printForm = inst}
          />
          <Table
            bordered
            rowKey="uuid"
            className="custom-table"
            dataSource={printbtns}
            columns={printColumns}
            expandedRowRender={record => <div style={{marginTop: '-5px'}}>
              {!record.verify || !record.verify.printerTypeList || record.verify.printerTypeList.length === 0 ?
                <p>此按钮未添加打印类型</p> : null
              }
              {record.verify && record.verify.printerTypeList && record.verify.printerTypeList.length > 0 ?
                <div>
                  <PrintTypeForm
                    dict={this.props.dict}
                    printers={record.printparam ? record.printparam.printers : []}
                    actionTypeChange={(values) => this.printTypeChange(record, values)}
                    wrappedComponentRef={(inst) => this.printTypeForm = inst}
                  />
                  <Table
                    bordered
                    rowKey="key"
                    className="custom-table"
                    dataSource={record.verify.printerTypeList}
                    columns={printTypeColumns}
                    pagination={false}
                  />
                </div> : null
              }
            </div>}
            pagination={false}
          />
        </TabPane> : null}
      </Tabs>
    )
  }
}
export default Form.create()(VerifyCard)
src/tabviews/zshare/verifycard/tabcard/index.scss
New file
@@ -0,0 +1,68 @@
.verify-card-box-vertical-tab {
  .ant-tabs-nav-scroll {
    text-align: center;
  }
  .ant-tabs-content {
    min-height: 40vh;
  }
  table tr td {
    word-wrap: break-word;
    word-break: break-word;
  }
  .verify-form {
    .ant-input-number {
      width: 100%;
    }
    .sql {
      .ant-col-sm-8 {
        width: 10.5%;
      }
      .ant-col-sm-16 {
        width: 89.5%;
        padding-top: 4px;
      }
    }
    .sqlfield {
      .ant-form-item {
        margin-bottom: 5px;
      }
      .ant-col-sm-8 {
        width: 10.5%;
      }
      .ant-col-sm-16 {
        width: 89.5%;
      }
    }
    .add {
      padding-top: 4px;
    }
    .ant-input-disabled {
      color: rgba(0, 0, 0, 0.65);
      cursor: default;
    }
    .print-tip {
      .ant-form-item {
        margin-bottom: 10px;
        .ant-form-item-label {
          width: 10.5%;
        }
        .ant-form-item-control-wrapper {
          width: 89.5%;
        }
      }
    }
  }
  .custom-table .ant-empty {
    margin: 20px 8px!important;
  }
  .errorval {
    display: inline-block;
    width: 30px;
  }
  .operation-btn {
    display: inline-block;
    font-size: 16px;
    padding: 0 5px;
    cursor: pointer;
  }
}
src/tabviews/zshare/verifycard/tabcard/printform/index.jsx
New file
@@ -0,0 +1,121 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Button, Input, Select } from 'antd'
import './index.scss'
class UniqueForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,       // 字典项
    actionChange: PropTypes.func  // 修改函数
  }
  state = {
    editItem: null, // 编辑元素
    shortcutOptions: null
  }
  UNSAFE_componentWillMount () {
  }
  edit = (record) => {
    this.setState({
      editItem: record
    }, () => {
      let _defaultPrinter = ''
      if (record.printer && typeof(record.printer) === 'object') {
        _defaultPrinter = record.printer.defaultPrinter || ''
      }
      let item = {
        label: record.label,
        defaultPrinter: _defaultPrinter
      }
      this.props.form.setFieldsValue(item)
    })
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
        this.props.actionChange(values)
        this.setState({
          editItem: null
        })
      }
    })
  }
  render() {
    const { getFieldDecorator } = this.props.form
    const { editItem } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    let printers = []
    if (editItem && editItem.printparam) {
      printers = editItem.printparam.printers
    }
    return (
      <Form {...formItemLayout} className="verify-form">
        {editItem ? <Row gutter={24}>
          <Col span={10}>
            <Form.Item label={'名称'}>
              {getFieldDecorator('label', {
                initialValue: '',
              })(<Input placeholder="" autoComplete="off" disabled />)}
            </Form.Item>
          </Col>
          <Col span={10}>
            <Form.Item label={'默认打印机'}>
              {getFieldDecorator('defaultPrinter', {
                initialValue: '',
                rules: [
                  {
                    required: true,
                    message: '请选择打印机!'
                  }
                ]
              })(
                <Select>
                  {printers.map(option =>
                    <Select.Option id={option.value} title={option.text} key={option.value} value={option.value}>{option.text}</Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
          <Col span={4} className="add">
            <Button onClick={this.handleConfirm} type="primary" className="add-row">
              确定
            </Button>
          </Col>
        </Row> : null}
        {!editItem ? <Row gutter={24} style={{height: '64px', paddingTop: '5px'}}>
          <Col span={24} className="print-tip">
            <Form.Item label={'提示'}>
              打印按钮需设置默认打印机,点击编辑图标可修改默认打印机。
            </Form.Item>
          </Col>
        </Row> : null}
      </Form>
    )
  }
}
export default Form.create()(UniqueForm)
src/tabviews/zshare/verifycard/tabcard/printform/index.scss
copy from src/tabviews/zshare/verifycard/actionform/index.scss copy to src/tabviews/zshare/verifycard/tabcard/printform/index.scss
src/tabviews/zshare/verifycard/tabcard/printtypeform/index.jsx
New file
@@ -0,0 +1,112 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Button, Input, Select } from 'antd'
import './index.scss'
class UniqueForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,       // 字典项
    printers: PropTypes.array,    // 打印机列表
    actionChange: PropTypes.func  // 修改函数
  }
  state = {
    editItem: null // 编辑元素
  }
  UNSAFE_componentWillMount () {
  }
  edit = (record) => {
    this.setState({
      editItem: record
    }, () => {
      let item = {
        Text: record.Text,
        printer: record.printer || ''
      }
      this.props.form.setFieldsValue(item)
    })
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        values.key = this.state.editItem ? this.state.editItem.key : ''
        values.Value = this.state.editItem ? this.state.editItem.Value : ''
        this.props.actionTypeChange(values)
        this.setState({
          editItem: null
        })
      }
    })
  }
  render() {
    const { getFieldDecorator } = this.props.form
    const { editItem } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <Form {...formItemLayout} className="verify-form">
        {editItem ? <Row gutter={24}>
          <Col span={10}>
            <Form.Item label={'打印类型'}>
              {getFieldDecorator('Text', {
                initialValue: '',
              })(<Input placeholder="" autoComplete="off" disabled />)}
            </Form.Item>
          </Col>
          <Col span={10}>
            <Form.Item label={'打印机'}>
              {getFieldDecorator('printer', {
                initialValue: '',
                rules: [
                  {
                    required: true,
                    message: '请选择打印机!'
                  }
                ]
              })(
                <Select>
                  {this.props.printers.map(option =>
                    <Select.Option id={option.value} title={option.text} key={option.value} value={option.value}>{option.text}</Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
          <Col span={4} className="add">
            <Button onClick={this.handleConfirm} type="primary" className="add-row">
              确定
            </Button>
          </Col>
        </Row> : null}
        {!editItem ? <Row gutter={24} style={{height: '64px', paddingTop: '5px'}}>
          <Col span={24} className="print-tip">
            <Form.Item label={'提示'}>
              点击编辑图标,可设置打印类型对应的打印机。
            </Form.Item>
          </Col>
        </Row> : null}
      </Form>
    )
  }
}
export default Form.create()(UniqueForm)
src/tabviews/zshare/verifycard/tabcard/printtypeform/index.scss
copy from src/tabviews/zshare/verifycard/actionform/index.scss copy to src/tabviews/zshare/verifycard/tabcard/printtypeform/index.scss
src/templates/comtableconfig/index.jsx
@@ -33,6 +33,7 @@
import TransferForm from '@/components/transferform'
import SourceElement from '@/templates/zshare/dragelement/source'
import CreateFunc from '@/templates/zshare/createfunc'
import CreateInterface from '@/templates/zshare/createinterface'
import Source from './source'
import './index.scss'
@@ -77,7 +78,8 @@
    optionLibs: null,        // 自定义下拉选项库
    thawBtnVisible: false,   // 解冻按钮弹窗
    thawbtnlist: null,       // 解冻按钮列表
    thawButtons: []          // 已选择要解冻的按钮
    thawButtons: [],         // 已选择要解冻的按钮
    activeKey: '0'           // 默认展开基本信息
  }
  /**
@@ -165,6 +167,7 @@
    this.setState({
      config: _config,
      activeKey: menu.activeKey || '0',
      optionLibs: optionLibs,
      originActions: _oriActions,
      originMenu: JSON.parse(JSON.stringify(menu)),
@@ -1047,10 +1050,10 @@
   */
  tableCreatFunc = () => {
    const { menu } = this.props
    let config = JSON.parse(JSON.stringify(this.state.config))
    const { config } = this.state
    this.settingRef.handleConfirm().then(res => {
      const setting = res
    this.settingRef.handleConfirm().then(setting => {
      if (!(setting.interType === 'inner') || !setting.innerFunc) {
        notification.warning({
          top: 92,
@@ -1074,16 +1077,51 @@
        Api.getLocalConfig(param)
      }
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, menu, config)) // 创建存储过程sql
      let _config = {...config, setting: setting}
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, menu, _config)) // 创建存储过程sql
      let DelText = Utils.formatOptions(Utils.dropfunc(setting.innerFunc))          // 删除存储过程sql
      this.refs.tableCreatFunc.exec(setting.innerFunc, newLText, DelText).then(result => {
        if (result === 'success') {
          this.setState({
            config: {...config, setting: setting}
            config: _config
          })
        }
      })
    })
  }
  /**
   * @description 创建表格接口
   */
  tableCreatInterface = () => {
    const { menu } = this.props
    const { config } = this.state
    this.settingRef.handleConfirm().then(setting => {
      if (/[^\s]+\s+[^\s]+/ig.test(setting.dataresource) && config.setting.dataresource !== setting.dataresource) {
        let param = {
          func: 's_DataSrc_Save',
          LText: setting.dataresource,
          MenuID: menu.MenuID
        }
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        Api.getLocalConfig(param)
      }
      // let _config = {...config, setting: setting}
      // this.refs.tableCreatInterface.exec(setting.innerFunc, newLText, DelText).then(result => {
      //   if (result === 'success') {
      //     this.setState({
      //       config: {...config, setting: setting}
      //     })
      //   }
      // })
    })
  }
@@ -2243,7 +2281,7 @@
   */
  setSubConfig = (item, type) => {
    const { menu } = this.props
    const { config, originMenu, optionLibs } = this.state
    const { config, originMenu, optionLibs, activeKey } = this.state
    if (!originMenu.MenuID) { // menuID不存在时,为新建菜单,提示菜单尚未保存
      notification.warning({
@@ -2294,6 +2332,9 @@
          uuid = item.linkTab
          isbutton = false
        }
        // 保存当前打开页签
        _originMenu.activeKey = activeKey
        let param = {
          optionLibs: optionLibs,
@@ -2618,7 +2659,7 @@
  }
  render () {
    const { modaltype } = this.state
    const { modaltype, activeKey } = this.state
    const configAction = this.state.config.action.filter(_action =>
      !_action.origin && (_action.OpenType === 'pop' || _action.OpenType === 'popview' || _action.OpenType === 'blank' || _action.OpenType === 'tab')
    )
@@ -2633,9 +2674,9 @@
        <DndProvider backend={HTML5Backend}>
          {/* 工具栏 */}
          <div className="tools">
            <Collapse accordion defaultActiveKey="0" bordered={false}>
            <Collapse accordion defaultActiveKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
              {/* 基本信息 */}
              <Panel header={this.state.dict['header.menu.basedata']} key="0" id="common-basedata">
              <Panel forceRender={true} header={this.state.dict['header.menu.basedata']} key="0" id="common-basedata">
                {/* 菜单信息 */}
                <MenuForm
                  dict={this.state.dict}
@@ -3051,6 +3092,7 @@
            })
          }}
          footer={[
            <CreateInterface key="interface" dict={this.state.dict} ref="tableCreatInterface" trigger={this.tableCreatInterface}/>,
            <CreateFunc key="create" dict={this.state.dict} ref="tableCreatFunc" trigger={this.tableCreatFunc}/>,
            <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>{this.state.dict['header.cancel']}</Button>,
            <Button key="confirm" type="primary" onClick={this.settingSave}>{this.state.dict['header.confirm']}</Button>
src/templates/formtabconfig/index.jsx
@@ -66,7 +66,8 @@
    profileVisible: false,   // 验证信息模态框
    editgroup: null,         // 当前编辑组
    groupVisible: false,     // 编辑组模态框
    optionLibs: null         // 自定义下拉选项库
    optionLibs: null,        // 自定义下拉选项库
    activeKey: '0'           // 默认展开基本信息
  }
  /**
@@ -125,6 +126,7 @@
    this.setState({
      config: _config,
      activeKey: btnTab.activeKey || '0',
      optionLibs: optionLibs,
      columns: columns,
      originMenu: JSON.parse(JSON.stringify(_config)),
@@ -845,10 +847,10 @@
   */
  tableCreatFunc = () => {
    const { menu } = this.props
    let config = JSON.parse(JSON.stringify(this.state.config))
    const { config } = this.state
    this.settingRef.handleConfirm().then(res => {
      const setting = res
    this.settingRef.handleConfirm().then(setting => {
      if (!(setting.interType === 'inner') || !setting.innerFunc) {
        notification.warning({
          top: 92,
@@ -872,13 +874,14 @@
        Api.getLocalConfig(param)
      }
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, menu, config)) // 创建存储过程sql
      let _config = {...config, setting: setting}
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, menu, _config)) // 创建存储过程sql
      let DelText = Utils.formatOptions(Utils.dropfunc(setting.innerFunc))          // 删除存储过程sql
      this.refs.tableCreatFunc.exec(setting.innerFunc, newLText, DelText).then(result => {
        if (result === 'success') {
          this.setState({
            config: {...config, setting: setting}
            config: _config
          })
        }
      })
@@ -1576,7 +1579,7 @@
   */
  setSubConfig = (btn) => {
    const {menu, btnTab} = this.props
    const { config, originMenu } = this.state
    const { config, originMenu, activeKey } = this.state
    if (config.isAdd) {
      notification.warning({
@@ -1598,6 +1601,9 @@
          this.setState({
            loading: true
          })
          // 保存当前打开页签
          btnTab.activeKey = activeKey
          let param = {
            editMenu: menu,
@@ -1857,7 +1863,7 @@
  }
  render () {
    const { config, modaltype } = this.state
    const { config, modaltype, activeKey } = this.state
    let _length = config.groups.length
    let configTabs = []
@@ -1870,9 +1876,9 @@
        <DndProvider backend={HTML5Backend}>
          {/* 工具栏 */}
          <div className="tools">
            <Collapse accordion defaultActiveKey="0" bordered={false}>
            <Collapse accordion defaultActiveKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
              {/* 基本信息 */}
              <Panel header={this.state.dict['header.menu.basedata']} key="0" id="common-basedata">
              <Panel forceRender={true} header={this.state.dict['header.menu.basedata']} key="0" id="common-basedata">
                {/* 菜单信息 */}
                <MenuForm
                  dict={this.state.dict}
src/templates/subtableconfig/index.jsx
@@ -82,7 +82,8 @@
    optionLibs: null,        // 自定义下拉选项库
    thawBtnVisible: false,   // 解冻按钮弹窗
    thawbtnlist: null,       // 解冻按钮列表
    thawButtons: []          // 已选择要解冻的按钮
    thawButtons: [],         // 已选择要解冻的按钮
    activeKey: '0'           // 默认展开基本信息
  }
  /**
@@ -138,10 +139,13 @@
      })
    }
    let _activeKey =  editSubTab ? editSubTab.activeKey : editTab.activeKey
    this.setState({
      originActions: _oriActions,
      optionLibs: optionLibs,
      config: _config,
      activeKey: _activeKey || '0',
      originConfig: _config,
      selectedTables: _config.tables || [],
      menuformlist: [
@@ -813,10 +817,10 @@
   * @description 创建表格存储过程
   */
  tableCreatFunc = () => {
    let config = JSON.parse(JSON.stringify(this.state.config))
    const { config } = this.state
    this.settingRef.handleConfirm().then(res => {
      const setting = res
    this.settingRef.handleConfirm().then(setting => {
      if (!(setting.interType === 'inner') || !setting.innerFunc) {
        notification.warning({
          top: 92,
@@ -840,13 +844,14 @@
        Api.getLocalConfig(param)
      }
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, {MenuID: config.uuid, MenuName: config.tabName, MenuNo: config.tabNo}, config)) // 创建存储过程sql
      let _config = {...config, setting: setting}
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, {MenuID: _config.uuid, MenuName: _config.tabName, MenuNo: _config.tabNo}, _config)) // 创建存储过程sql
      let DelText = Utils.formatOptions(Utils.dropfunc(setting.innerFunc))          // 删除存储过程sql
      
      this.refs.tableCreatFunc.exec(setting.innerFunc, newLText, DelText).then(result => {
        if (result === 'success') {
          this.setState({
            config: {...config, setting: setting}
            config: _config
          })
        }
      })
@@ -1773,7 +1778,7 @@
   */
  setSubConfig = (btn) => {
    const {menu, editTab, tabConfig, editSubTab, btnTab, btnTabConfig} = this.props
    const { config, originConfig } = this.state
    const { config, originConfig, activeKey } = this.state
    if (originConfig.isAdd) {
      notification.warning({
@@ -1805,6 +1810,12 @@
          } else if (btn.OpenType === 'popview') {
            _view = btn.tabType        // 新弹窗标签模板
            _subtab = btn
          }
          if (editSubTab) {
            editSubTab.activeKey = activeKey
          } else {
            editTab.activeKey = activeKey
          }
          let param = {
@@ -2028,7 +2039,7 @@
  }
  render () {
    const { modaltype } = this.state
    const { modaltype, activeKey } = this.state
    const configAction = this.state.config.action.filter(_action =>
      !_action.origin && (_action.OpenType === 'pop' || _action.OpenType === 'popview' || _action.OpenType === 'blank' || _action.OpenType === 'tab')
    )
@@ -2038,9 +2049,9 @@
        <DndProvider backend={HTML5Backend}>
          {/* 工具栏 */}
          <div className="tools">
            <Collapse accordion defaultActiveKey="0" bordered={false}>
            <Collapse accordion defaultActiveKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
              {/* 基本信息 */}
              <Panel header={'标签基本信息'} key="0" id="common-basedata">
              <Panel forceRender={true} header={'标签基本信息'} key="0" id="common-basedata">
                {/* 菜单信息 */}
                <MenuForm
                  dict={this.state.dict}
src/templates/zshare/createinterface/index.jsx
New file
@@ -0,0 +1,222 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Button, notification } from 'antd'
import moment from 'moment'
import Utils from '@/utils/utils.js'
import Api from '@/api'
import './index.scss'
class CreateFunc extends Component {
  static propTypes = {
    dict: PropTypes.object,  // 字典项
    trigger: PropTypes.func
  }
  state = {
    loading: false,
  }
  exec = (innerFunc, newLText, DelText) => {
    this.setState({
      loading: true
    })
    return new Promise(resolve => {
      this.createExec(resolve, innerFunc, newLText, DelText)
    })
  }
  createExec = (_resolve, innerFunc, newLText, DelText) => {
    let isExist = false // 存储过程是否存在
    let cloudText = ''  // 云端存储结果
    let localfunc = ''  // 本地存储过程
    new Promise(resolve => {
      // 获取云端存储过程信息
      Api.getSystemConfig({
        func: 'sPC_Get_TVP',
        TVPName: innerFunc
      }).then(result => {
        if (!result.status) {
          notification.warning({
            top: 92,
            message: result.message,
            duration: 10
          })
          resolve(false)
        } else {
          cloudText = result.TVPText
          resolve(true)
        }
      })
    }).then(res => {
      if (!res) return res
      // 获取本地存储过程信息
      let _param = {
        func: 's_get_userproc',
        LText: innerFunc
      }
      _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
      _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
      return Api.getLocalConfig(_param)
    }).then(res => {
      if (!res) return res
      // 处理本地结果
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
        return false
      } else {
        isExist = true
        localfunc = Utils.formatOptions(res.Ltext)
        return true
      }
    }).then(res => {
      if (!res) return res
      // 根据本地及远端结果判断执行动作
      if ((newLText === localfunc) && (newLText === cloudText)) {
        return 'drop'
      } else if (!localfunc || (cloudText === localfunc)) {
        // 本地存储过程不存在,或云端和本地存储过程一致时,将新的存储过程更新至云端
        return Api.getSystemConfig({
          func: 'sPC_TVP_InUp',
          TVPName: innerFunc,
          TVPText: newLText,
          TypeName: 'P'
        })
      } else {
        return new Promise(resolve => {
          Api.getSystemConfig({ // 添加现有的本地存储过程至云端
            func: 'sPC_TVP_InUp',
            TVPName: innerFunc,
            TVPText: localfunc,
            TypeName: 'P'
          }).then(result => {
            if (result.status) {
              Api.getSystemConfig({
                func: 'sPC_TVP_InUp', // 添加最新的存储过程至云端
                TVPName: innerFunc,
                TVPText: newLText,
                TypeName: 'P'
              }).then(response => {
                resolve(response)
              })
            } else {
              resolve(result)
            }
          })
        })
      }
    }).then(res => {
      if (!res || res === 'drop') return res
      // 处理云端更新结果
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
        return false
      } else if (isExist) {
        return 'drop'
      } else {
        return 'create'
      }
    }).then(res => {
      if (!res || res === 'create') return res
      // 删除存储过程
      let _param = {
        func: 'sPC_TableData_InUpDe',
        LText: DelText,
        TypeCharOne: 'proc' // 删除或创建存储过程标志
      }
      _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
      _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
      return Api.getLocalConfig(_param)
    }).then(res => {
      if (!res || res === 'create') return res
      // 删除结果处理
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
        return false
      } else {
        return true
      }
    }).then(res => {
      if (!res) return res
      // 新建存储过程
      let _param = {
        func: 'sPC_TableData_InUpDe',
        LText: newLText,
        TypeCharOne: 'proc'
      }
      _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
      _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
      return Api.getLocalConfig(_param)
    }).then(res => {
      if (!res) return res
      // 处理新建结果
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 10
        })
        return false
      } else {
        notification.success({
          top: 92,
          message: '创建成功',
          duration: 2
        })
        return true
      }
    }).then(res => {
      // 结果处理
      if (!res) {
        _resolve('error')
      } else {
        _resolve('success')
      }
      this.setState({
        loading: false
      })
    })
  }
  render() {
    return (
      <Button
        className="mk-btn mk-purple"
        onClick={this.props.trigger}
        loading={this.state.loading}
      >
        {this.props.dict['header.menu.func.create']}
      </Button>
    )
  }
}
export default CreateFunc
src/templates/zshare/createinterface/index.scss
copy from src/tabviews/zshare/verifycard/actionform/index.scss copy to src/templates/zshare/createinterface/index.scss
src/templates/zshare/verifycardprint/editable/index.jsx
New file
@@ -0,0 +1,241 @@
import React, {Component} from 'react'
import { Table, Input, Button, Popconfirm, Form, Icon } from 'antd'
import Utils from '@/utils/utils.js'
import './index.scss'
const EditableContext = React.createContext()
const EditableRow = ({ form, index, ...props }) => (
  <EditableContext.Provider value={form}>
    <tr {...props} />
  </EditableContext.Provider>
)
const EditableFormRow = Form.create()(EditableRow)
class EditableCell extends Component {
  state = {
    editing: false
  }
  toggleEdit = () => {
    const editing = !this.state.editing
    this.setState({ editing }, () => {
      if (editing && this.input && this.input.select) {
        this.input.select()
      } else if (editing && this.input && this.input.focus) {
        this.input.focus()
      }
    })
  }
  save = e => {
    const { record, handleSave } = this.props
    this.form.validateFields((error, values) => {
      handleSave({ ...record, ...values })
      if (error && error[e.currentTarget.id]) {
        return
      }
      this.toggleEdit()
    })
  }
  renderCell = form => {
    this.form = form
    const { children, dataIndex, record } = this.props
    const { editing } = this.state
    return editing ? (
      <Form.Item style={{ margin: 0 }}>
        {form.getFieldDecorator(dataIndex, {
          rules: [
            {
              required: true,
              message: 'NOT NULL.',
            },
          ],
          initialValue: record[dataIndex]
        })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)}
      </Form.Item>
    ) : (
      <div
        className="editable-cell-value-wrap"
        onClick={this.toggleEdit}
      >
        {children}
      </div>
    )
  }
  render() {
    const {
      editable,
      dataIndex,
      title,
      record,
      index,
      handleSave,
      children,
      ...restProps
    } = this.props
    return (
      <td {...restProps}>
        {editable ? (
          <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer>
        ) : (
          children
        )}
      </td>
    )
  }
}
class EditTable extends Component {
  constructor(props) {
    super(props)
    let columns = [
      {
        title: 'Value',
        dataIndex: 'Value',
        width: '40%',
        editable: true
      },
      {
        title: 'Text',
        dataIndex: 'Text',
        width: '40%',
        editable: true
      },
      {
        title: '操作',
        align: 'center',
        dataIndex: 'operation',
        render: (text, record) =>
          this.state.dataSource.length >= 1 ? (
            <div>
              <span className="operation-btn" title={props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
              <span className="operation-btn" title={props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
              <Popconfirm
                title={props.dict['header.form.query.delete']}
                okText={props.dict['header.confirm']}
                cancelText={props.dict['header.cancel']}
                onConfirm={() => this.handleDelete(record.key)
              }>
                <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
              </Popconfirm>
            </div>
          ) : null,
      }
    ]
    this.state = {
      columns: columns,
      dataSource: props.data,
      count: props.data.length,
      linkSubFields: props.linkSubFields
    }
  }
  handleUpDown = (record, direction) => {
    const { dataSource } = this.state
    let index = 0
    let _data = dataSource.filter((item, i) => {
      if (item.key === record.key) {
        index = i
      }
      return item.key !== record.key
    })
    if ((index === 0 && direction === 'up') || (index === dataSource.length - 1 && direction === 'down')) {
      return
    }
    if (direction === 'up') {
      _data.splice(index - 1, 0, record)
    } else {
      _data.splice(index + 1, 0, record)
    }
    this.setState({
      dataSource: _data
    })
  }
  handleDelete = key => {
    const dataSource = [...this.state.dataSource]
    this.setState({ dataSource: dataSource.filter(item => item.key !== key) })
  }
  handleAdd = () => {
    const { count, dataSource } = this.state
    const newData = {
      key: Utils.getuuid(),
      Value: `${count}`,
      Text: `${count}`
    }
    this.setState({
      dataSource: [...dataSource, newData],
      count: count + 1
    })
  }
  handleSave = row => {
    const newData = [...this.state.dataSource]
    const index = newData.findIndex(item => row.key === item.key)
    const item = newData[index]
    newData.splice(index, 1, {
      ...item,
      ...row
    })
    this.setState({ dataSource: newData })
  }
  UNSAFE_componentWillReceiveProps () {
  }
  render() {
    const { dataSource } = this.state
    const components = {
      body: {
        row: EditableFormRow,
        cell: EditableCell
      }
    }
    const columns = this.state.columns.map(col => {
      if (!col.editable) {
        return col
      }
      return {
        ...col,
        onCell: record => ({
          record,
          editable: col.editable,
          dataIndex: col.dataIndex,
          title: col.title,
          handleSave: this.handleSave,
        })
      }
    })
    return (
      <div className="print-verify-edit-table">
        <Button onClick={this.handleAdd} type="primary" className="add-row">
          添加
        </Button>
        <Table
          components={components}
          rowClassName={() => 'editable-row'}
          bordered
          dataSource={dataSource}
          columns={columns}
          pagination={false}
        />
      </div>
    )
  }
}
export default EditTable
src/templates/zshare/verifycardprint/editable/index.scss
New file
@@ -0,0 +1,48 @@
.print-verify-edit-table {
  margin: 10px 20px;
  .add-row {
    position: absolute;
    z-index: 1;
    right: 32px;
    top: -40px;
  }
  .ant-table-thead > tr > th {
    padding: 10px 16px;
  }
  .ant-table-tbody > tr > td {
    padding: 0px 16px;
  }
  .editable-cell-value-wrap {
    cursor: pointer;
    height: 40px;
    width: 500px;
    display: table-cell;
    vertical-align: middle;
    word-wrap: break-word;
    word-break: break-word;
    .ant-input {
      height: 30px;
      padding: 0 11px;
    }
  }
  .ant-form-item-control-wrapper {
    width: 100%;
  }
  .ant-table-placeholder {
    padding: 5px 16px;
    .ant-empty-normal {
      margin: 0;
    }
  }
  .operation-btn {
    margin-right: 10px;
    cursor: pointer;
  }
  .ant-table-content {
    .ant-table-placeholder {
      .ant-empty.ant-empty-normal {
        margin: 50px 8px;
      }
    }
  }
}
src/templates/zshare/verifycardprint/index.jsx
@@ -7,6 +7,7 @@
import Api from '@/api'
import Utils from '@/utils/utils.js'
import EditTable from './editable'
import 'codemirror/lib/codemirror.css'
// import 'codemirror/theme/solarized.css'
@@ -15,7 +16,7 @@
import './index.scss'
const { TabPane } = Tabs
let _printFunc = null
let _printFunc = null // antd 无法获取 codemirror 内容,手动控制
class VerifyCard extends Component {
  static propTpyes = {
@@ -37,14 +38,16 @@
  UNSAFE_componentWillMount() {
    let _verify = this.props.card.verify || {}
    _verify.Template = _verify.Template || ''
    _verify.printerTypeList = _verify.printerTypeList || []
    _verify.linkType = _verify.linkType || 'system'
    _verify.printMode = _verify.printMode || 'normal'
    this.setState({
      verify: {
        ..._verify,
        Template: _verify.Template || ''
      },
      linkType: _verify.linkType || 'system',
      printMode: _verify.printMode || 'normal',
      printFunc: _verify.printFunc || '// Function(socket, data, printer, notification) socket-WebSocket 对象,data-打印数据列表,printer-打印机,notification-信息提示控件'
      verify: _verify,
      linkType: _verify.linkType,
      printMode: _verify.printMode,
      printFunc: _verify.printFunc || '// Function(data, form, printer, notification) data-打印数据列表,form-表单信息(不存在时为{}),printer-打印设置,notification-信息提示控件'
    })
    _printFunc = _verify.printFunc || ''
@@ -166,6 +169,40 @@
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _verify = {...verify, ...values, printFunc: _printFunc}
          if (this.refs.editTable && this.refs.editTable.state) {
            let printTypes = this.refs.editTable.state.dataSource
            let emptys = printTypes.filter(item => !item.Value || !item.Text)
            let valMap = new Map()
            let isvalid = true
            printTypes.forEach(item => {
              if (valMap.has(item.Value)) {
                isvalid = false
              } else {
                valMap.set(item.Value, item.Text)
              }
            })
            if (emptys.length > 0) {
              notification.warning({
                top: 92,
                message: '打印类型表格中Value、Text字段不可为空!',
                duration: 10
              })
              return
            } else if (!isvalid) {
              notification.warning({
                top: 92,
                message: '打印类型表格中Value字段不可重复!',
                duration: 10
              })
              return
            }
            _verify.printerTypeList = printTypes
          }
          resolve(_verify)
        } else {
@@ -313,6 +350,21 @@
              </Row>
            </Form>
          </TabPane>
          <TabPane tab="打印类型" key="2">
            <Form {...formItemLayout}>
              <Row gutter={24}>
                <Col span={24} className="print-tip">
                  <Form.Item label={'提示'}>
                    如果此按钮的打印功能涉及多种打印类型,且不同类型需要设置不同的打印机时,可以添加打印类型控制信息,
                    设置完成后,用户可针对不同的类型设置对应的打印机。注:在返回数据顶层结构中添加 printType、printCount、templateID 字段,可分别控制打印类型、打印数量和打印模板。
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <EditTable data={verify.printerTypeList} dict={this.props.dict} ref="editTable"/>
                </Col>
              </Row>
            </Form>
          </TabPane>
          <TabPane tab="信息提示" key="7">
            <Form {...formItemLayout}>
              <Row gutter={24}>
src/templates/zshare/verifycardprint/index.scss
@@ -44,4 +44,17 @@
      height: calc(100vh - 360px);
    }
  }
  .print-tip {
    margin-bottom: 25px;
    .ant-form-item-label {
      width: 10.5%;
      line-height: 25px;
    }
    .ant-form-item-control-wrapper {
      width: 89.5%;
      .ant-form-item-children {
        line-height: 25px;
      }
    }
  }
}
src/utils/asyncLoadComponent.jsx
@@ -26,7 +26,7 @@
      return C ?
        <C {...this.props} /> :
        <Spin style={{position: 'fixed', left: 'calc(50vw - 22px)', top: 'calc(50vh - 70px)'}} size="large" />
        <Spin style={{position: 'fixed', left: 'calc(50vw - 22px)', top: 'calc(50vh - 70px)', zIndex: 10}} size="large" />
    }
  }
}
src/utils/utils.js
@@ -634,7 +634,6 @@
    let _formFieldValue = {}
    // 需要声明的变量集
    // let _vars = ['tbid', 'ErrorCode', 'retmsg', 'BillCode', 'BVoucher', 'FIBVoucherDate', 'FiYear', 'UserName', 'FullName', 'ID', 'BID', 'LoginUID', 'SessionUid', 'UserID', 'Appkey']
    // let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'id', 'bid', 'loginuid', 'sessionuid', 'userid', 'appkey']
    let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode']
    // 主键字段
@@ -645,7 +644,6 @@
      `
    // let _initvars = ['ID', 'BID', 'LoginUID', 'SessionUid', 'UserID', 'Appkey'] // 已赋值字段集
    // let _initvars = ['id', 'bid', 'loginuid', 'sessionuid', 'userid', 'appkey'] // 已赋值字段集
    let _initvars = [] // 已赋值字段集
    let _initfields = []
    let _declarefields = []
@@ -734,11 +732,6 @@
        `
    }
    // 添加时主键为空 改为前台生成
    // if (btn.sqlType === 'insert') {
    //   primaryId = ''
    // }
    // 去除禁用的验证
    if (verify.contrasts) {
      verify.contrasts = verify.contrasts.filter(item => item.status !== 'false')
@@ -756,8 +749,16 @@
      verify.scripts = verify.scripts.filter(item => item.status !== 'false')
    }
    // 初始化凭证字段
    _sql += `select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg=''
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    if (sessionStorage.getItem('isEditState') === 'true') {
      userName = sessionStorage.getItem('CloudUserName') || ''
      fullName = sessionStorage.getItem('CloudFullName') || ''
    }
    // 初始化凭证及用户信息字段
    _sql += `select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}'
      `
    // 启用账期验证
@@ -926,10 +927,6 @@
        `
    }
    // 用于取用户信息
    let _user = `select @UserName=UserName,@FullName=FullName from SUsers where UID=@UserID@
      `
    let primaryKeyName = ['id', 'bid', 'loginuid', 'sessionuid', 'userid', 'appkey'].includes(primaryKey.toLowerCase()) ? primaryKey + '@' : primaryKey
    let _actionType = null
@@ -979,7 +976,6 @@
      keys = keys.join(',')
      values = values.join(',')
      _sql += _user
      _sql += `insert into ${btn.sql} (${keys}) select ${values};`
    } else if (_actionType === 'update') {
      let _form = []
@@ -1031,7 +1027,6 @@
          }
        })
      }
      _sql += _user
      _sql += `insert into snote (remark,createuserid,CreateUser,CreateStaff) select '删除表:${btn.sql} 数据: ${_msg}${primaryKey}='+@${primaryKeyName},@userid@,@username,@fullname delete ${btn.sql} where ${primaryKey}=@${primaryKeyName};`
    }
src/views/login/index.jsx
@@ -8,11 +8,13 @@
import options from '@/store/options.js'
import Utils from '@/utils/utils.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncLoadComponent from '@/utils/asyncLoadComponent'
import logourl from '@/assets/img/login-logo.png'
import loginbg from '@/assets/img/loginbg.jpg'
import './index.scss'
const LoginForm = asyncComponent(() => import('./loginform'))
const LoginForm = asyncLoadComponent(() => import('./loginform'))
const Action = asyncComponent(() => import('@/tabviews/zshare/actionList'))
const iszhCN = !localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN'
class Login extends Component {
@@ -28,7 +30,8 @@
    ICP: window.GLOB.icp || 'ICP备案: 京ICP备12007830号',
    bgColor: window.GLOB.bgColor || '#000000',
    lineColor: window.GLOB.lineColor || '#1890ff',
    website: window.GLOB.website || (!window.GLOB.copyRight && 'http://minkesoft.com')
    website: window.GLOB.website || (!window.GLOB.copyRight && 'http://minkesoft.com'),
    loaded: false
  }
  changelang (item) {
@@ -61,6 +64,7 @@
      sessionStorage.setItem('SessionUid', Utils.getuuid())
      sessionStorage.setItem('LoginUID', res.LoginUID)
      sessionStorage.setItem('User_Name', res.UserName)
      sessionStorage.setItem('Full_Name', res.FullName)
      sessionStorage.setItem('avatar', res.icon || '')
      
      localStorage.setItem('lang', param.lang)
@@ -142,6 +146,7 @@
            isDisabled={this.state.isDisabled}
            changelang={(value) => this.changelang(value)}
            handleSubmit={() => this.handleSubmit()}
            handleloaded={() => {this.setState({loaded: true})}}
            wrappedComponentRef={(inst) => this.loginformRef = inst}
          />
        </div>
@@ -152,6 +157,25 @@
          }
          <p dangerouslySetInnerHTML={{ __html: this.state.ICP.replace(/\s/ig, '&nbsp;') }}></p>
        </div>
        {this.state.loaded ? <div style={{position: 'fixed', bottom: '-300px'}}>
          <Action
            BID=""
            type=""
            menuType=""
            setting={{}}
            actions={[]}
            triggerBtn={{}}
            dict={{}}
            MenuID=""
            permRoles={{}}
            logcolumns={[]}
            ContainerId=""
            refreshdata={() => {}}
            triggerPopview={() => {}}
            getexceloutparam={() => {}}
            gettableselected={() => {}}
          />
        </div> : null}
      </div>
    )
  }
src/views/login/loginform.jsx
@@ -10,6 +10,7 @@
    isDisabled: PropTypes.bool,
    changelang: PropTypes.func,
    handleSubmit: PropTypes.func,
    handleloaded: PropTypes.func,
    dict: PropTypes.object,
    auth: PropTypes.bool,
    lang: PropTypes.string,
@@ -96,6 +97,7 @@
        input.focus()
      }
    }
    this.props.handleloaded()
  }
  render() {