king
2023-01-05 876a5e6657d67df66bb525d02dd6d147ba81cae5
2023-01-05
130个文件已修改
10个文件已添加
5466 ■■■■ 已修改文件
src/api/index.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/viewstyle.scss 339 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/account.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/voucher.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.scss 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/keyInterface/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/index.scss 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tabview/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/card.jsx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/dragaction/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/elementform/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/formconfig.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcellcomponent/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/index.scss 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardsimplecomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardsimplecomponent/index.scss 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/options.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/prop-card/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/table-card/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/data-card/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/carousel/prop-card/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-G6/index.jsx 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/formaction/formconfig.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/simple-form/index.scss 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/step-form/index.scss 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/tab-form/index.scss 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/iframe/index.scss 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/iframe/options.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/account/index.jsx 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/account/index.scss 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/account/options.jsx 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/voucher/index.jsx 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/voucher/index.scss 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/voucher/options.jsx 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/voucher/voucherTable/index.jsx 362 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/module/voucher/voucherTable/index.scss 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/search/main-search/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/search/main-search/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/actionform/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/formconfig.jsx 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/searchcomponent/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/index.jsx 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/index.jsx 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/options.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/options.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/options.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/timeline/normal-timeline/index.scss 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modulecell/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modulesource/option.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/tablenodes/index.jsx 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/tablenodes/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/common-menubar/index.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/menubar/normal-menubar/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/header/index.jsx 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/mobshell/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/index.scss 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/loginform.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/options.jsx 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/signform.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/navbar/normal-navbar/index.scss 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/menushell/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.jsx 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/cardcellList/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/prop-card/index.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-G6/index.jsx 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/iframe/index.jsx 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/iframe/index.scss 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/account/index.jsx 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/account/index.scss 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/index.jsx 81 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/index.scss 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/voucherTable/index.jsx 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/module/voucher/voucherTable/index.scss 100 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/normalTable/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/base-table/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/edit-table/normalTable/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/table/normal-table/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/exceloutbutton/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/index.jsx 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/index.scss 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/printbutton/index.jsx 620 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/cardcomponent/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkCheckCard/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/tablenodes/index.jsx 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/tablenodes/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/topSearch/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/updatetable/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/checkCard/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/actionform/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx 190 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx 559 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyprint/index.scss 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searchform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/datatable/index.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/modalform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-custom.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/submutilform/index.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/index.scss 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.scss 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/main/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/main/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/index.jsx 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobdesign/menuform/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/index.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/index.scss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemproc/proc/index.jsx 363 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemproc/proc/index.scss 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js
@@ -12,7 +12,7 @@
window.GLOB.WebSql = null
window.GLOB.IndexDB = null
window.GLOB.OuterToken = {}
const systemMenuKeys = `1581067625930haged11ieaivpavv77k,1581734956310scks442ul2d955g9tu5,1583991994144ndddg0bhh0is6shi0v1,1583979633842550imkchl4qt4qppsiv,1578900109100np8aqd0a77q3na46oas,
const systemMenuKeys = `1581067625930haged11ieaivpavv77k,1581734956310scks442ul2d955g9tu5,1583991994144ndddg0bhh0is6shi0v1,1583979633842550imkchl4qt4qppsiv,
  1585192949946f3et2ts8tn82krmumdf,15855615451212m12ip23vpcm79kloro,1587005717541lov40vg61q7l1rbveon,1590458676585agbbr63t6ihighg2i1g,1602315375262ikd33ii0nii34pt861o,1582771068837vsv54a089lgp45migbg,
  1582777675954ifu05upurs465omoth7,158294809668898cklbv6c5bou8e1fpu,1584676379094iktph45fb8imhg96bql,1584695125339vo5g7iqgfn01qmrd6s2,1584699661372vhmpp9dn9foo0eob722,15848421131551gg04ie8sitsd3f7467,
  1589782279158ngr675kk3oksin35sul,1589788042787ffdt9hle4s45k9r1nvs,1594095599055qicg2eb642v5qglhnuo,1577972969199lei1g0qkvlh4tkc908m,16044812935562g807p3p12huk8kokmb,
src/assets/css/main.scss
@@ -36,11 +36,9 @@
/*背景色*/
html, body {
  --mk-sys-color: #1890ff;
  width: 100%;
  font-size: 14px;
  // .ant-table, .ant-dropdown {
  //   color: rgba(0, 0, 0, 0.85);
  // }
}
#root {
  height: 100%;
@@ -180,9 +178,9 @@
  z-index: 1090!important;
}
.ant-dropdown {
  z-index: 1090!important;
}
// .ant-dropdown {
//   z-index: 1090!important;
// }
.mk-normal-dropdown {
  .ant-dropdown-menu {
@@ -472,4 +470,22 @@
  .video-react .video-react-poster {
    background-size: cover;
  }
}
.table-vertical-top {
  table td {
    vertical-align: top;
  }
}
.table-vertical-bottom {
  table td {
    vertical-align: bottom;
  }
}
// 系统色设置
.mk-main-view {
  display: flex;
  flex: auto;
  min-height: 100%;
}
src/assets/css/viewstyle.scss
@@ -1,6 +1,3 @@
// bg1     主背景色
// bg2     次背景色
// font1   主字体颜色
// color1  1阶色 - 底色
// color2  2阶色
// color3  3阶色
@@ -11,142 +8,8 @@
// color8  8阶色
// color9  9阶色
// color10 10阶色
@mixin viewstyle($bg1, $bg2, $font1, $font2, $color1, $color2, $color3, $color4, $color5, $color6, $color7, $color8, $color9, $color10) {
  .login-container {
    background-color: $bg1;
    .logo {
      border-color: $color6;
      .plat-name {
        color: $font1;
      }
    }
    .login-middle {
      border-color: $color6;
      .login-form-button {
        background-color: $color6;
        border-color: $color6;
      }
      .login-form-button[disabled] {
        background-color: $color5;
        border-color: $color5;
      }
      button.vercode {
        color: $color6;
      }
      .login-way-wrap {
        .login-way.active, .login-way:hover {
          color: $color6;
        }
      }
      .anticon-eye {
        color: $color6;
      }
    }
    .login-bottom {
      color: $font1;
      a {
        color: $font1;
      }
    }
  }
  .menu-board {
    .menu-wrap {
      .title {
        color: $color6;
      }
      .menu-detail {
        div:hover {
          color: $color5;
        }
      }
    }
  }
@mixin viewstyle($color1, $color2, $color3, $color4, $color5, $color6, $color7) {
  #root > .mk-main-view {
    > .header-container {
      background: $bg1;
      color: $font1;
      box-shadow: 0 1px 1px #d9d9d9;
      .header-setting span {
        color: $font1;
      }
      > .header-collapse .anticon {
        color: $font1;
      }
      > .header-menu {
        li {
          span {
            color: $font1;
          }
          &:hover {
            span {
              color: $color6;
              border-bottom: 4px solid $color6;
            }
          }
          &.active {
            span {
              color: $color6;
              border-bottom: 4px solid $color6;
            }
          }
        }
      }
    }
    > .mk-side-menu {
      border-right: 1px solid #d9d9d9;
      background: $bg1;
      > .ant-menu {
        background: $bg1;
        > .ant-menu-submenu {
          color: $font1;
          background: transparent;
          > .ant-menu-submenu-title {
            &:hover {
              color: $font1;
            }
            > .ant-menu-submenu-arrow:before {
              background: $font1;
            }
            > .ant-menu-submenu-arrow:after {
              background: $font1;
            }
          }
          > .ant-menu-sub {
            background: transparent;
            box-shadow: none;
            .ant-menu-item {
              a {
                color: $font2;
              }
            }
          }
        }
        > .ant-menu-submenu.ant-menu-submenu-open {
          > .ant-menu-submenu-title {
            background: $bg2;
          }
        }
      }
    }
    > .mk-side-menu:not(.edit) {
      > .ant-menu {
        > .ant-menu-submenu {
          > .ant-menu-sub {
            .ant-menu-item.ant-menu-item-active, .ant-menu-item.ant-menu-item-selected {
              background: $color5;
              color: #ffffff;
              a {
                color: #ffffff;
              }
            }
          }
        }
      }
    }
    >.mk-tabview-wrap {
      >.content-header {
        >.ant-tabs {
@@ -444,11 +307,7 @@
  .system-color {
    color: $color6;
  }
  .system-background {
    background: $color6;
    border-color: $color6;
    color: #ffffff;
  }
  .ant-timeline.system {
    .ant-timeline-item-tail {
      border-color: $color2;
@@ -497,6 +356,11 @@
      }
    }
  }
  .ant-spin {
    .ant-spin-dot-item {
      background-color: $color6;
    }
  }
}
body.hidden-split-line #root { // 去除登录页分割线
@@ -510,152 +374,99 @@
  }
}
@mixin bgblack() {
  #root > .mk-main-view {
    > .header-container {
      box-shadow: none;
      > .header-menu {
        li {
          &:hover, &.active {
            span {
              color: #ffffff;
            }
          }
        }
      }
      .header-menu::-webkit-scrollbar-track {
        box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.05);
        border: 1px solid rgba(255, 255, 255, 0.07);
        background: rgba(255, 255, 255, 255);
        border-radius: 3px;
      }
    }
  }
// 皮肤背景与字体颜色
body[class*='-black'] {
  --mk-sys-background: #000000;
  --mk-sys-light-background: #434343;
  --mk-sys-font-color: rgba(255, 255, 255, 0.85);
  --mk-sys-light-font-color: rgba(255, 255, 255, 0.65);
}
body[class*='-white'] {
  --mk-sys-background: #ffffff;
  --mk-sys-light-background: #ffffff;
  --mk-sys-font-color: rgba(0, 0, 0, 0.85);
  --mk-sys-light-font-color: rgba(0, 0, 0, 0.65);
}
body[class*='mk-blue-'] {
  --mk-sys-color: #1890ff;
  --mk-sys-color5: #40a9ff;
  @include viewstyle(#e6f7ff, #bae7ff, #91d5ff, #69c0ff, #40a9ff, #1890ff, #096dd9);
}
body.mk-blue-black {
  --mk-sys-color: #1890ff;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65), #e6f7ff, #bae7ff, #91d5ff, #69c0ff, #40a9ff, #1890ff, #096dd9, #0050b3, #003a8c, #002766);
  @include bgblack();
}
body.mk-blue-white {
  --mk-sys-color: #1890ff;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #e6f7ff, #bae7ff, #91d5ff, #69c0ff, #40a9ff, #1890ff, #096dd9, #0050b3, #003a8c, #002766);
}
body.mk-red-black {
body[class*='mk-red-'] {
  --mk-sys-color: #f5222d;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65), #fff1f0, #ffccc7, #ffa39e, #ff7875, #ff4d4f, #f5222d, #cf1322, #a8071a, #820014, #5c0011);
  @include bgblack();
  --mk-sys-color5: #ff4d4f;
  @include viewstyle(#fff1f0, #ffccc7, #ffa39e, #ff7875, #ff4d4f, #f5222d, #cf1322);
}
body.mk-red-white {
  --mk-sys-color: #f5222d;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #fff1f0, #ffccc7, #ffa39e, #ff7875, #ff4d4f, #f5222d, #cf1322, #a8071a, #820014, #5c0011);
}
body.mk-orange-red-black {
body[class*='mk-orange-red-'] {
  --mk-sys-color: #fa541c;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65), #fff2e8, #ffd8bf, #ffbb96, #ff9c6e, #ff7a45, #fa541c, #d4380d, #ad2102, #871400, #610b00);
  @include bgblack();
  --mk-sys-color5: #ff7a45;
  @include viewstyle(#fff2e8, #ffd8bf, #ffbb96, #ff9c6e, #ff7a45, #fa541c, #d4380d);
}
body.mk-orange-red-white {
  --mk-sys-color: #fa541c;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #fff2e8, #ffd8bf, #ffbb96, #ff9c6e, #ff7a45, #fa541c, #d4380d, #ad2102, #871400, #610b00);
}
body.mk-orange-black {
body[class*='mk-orange-'] {
  --mk-sys-color: #fa8c16;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65), #fff7e6, #ffe7ba, #ffd591, #ffc069, #ffa940, #fa8c16, #d46b08, #ad4e00, #873800, #612500);
  @include bgblack();
  --mk-sys-color5: #ffa940;
  @include viewstyle(#fff7e6, #ffe7ba, #ffd591, #ffc069, #ffa940, #fa8c16, #d46b08);
}
body.mk-orange-white {
  --mk-sys-color: #fa8c16;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #fff7e6, #ffe7ba, #ffd591, #ffc069, #ffa940, #fa8c16, #d46b08, #ad4e00, #873800, #612500);
}
body.mk-orange-yellow-black {
body[class*='mk-orange-yellow-'] {
  --mk-sys-color: #faad14;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#fffbe6, #fff1b8, #ffe58f, #ffd666, #ffc53d, #faad14, #d48806, #ad6800, #874d00, #613400);
  @include bgblack();
  --mk-sys-color5: #ffc53d;
  @include viewstyle(#fffbe6, #fff1b8, #ffe58f, #ffd666, #ffc53d, #faad14, #d48806);
}
body.mk-orange-yellow-white {
  --mk-sys-color: #faad14;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #fffbe6, #fff1b8, #ffe58f, #ffd666, #ffc53d, #faad14, #d48806, #ad6800, #874d00, #613400);
}
body.mk-yellow-black {
body[class*='mk-yellow-'] {
  --mk-sys-color: #fadb14;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#feffe6, #ffffb8, #fffb8f, #fff566, #ffec3d, #fadb14, #d4b106, #ad8b00, #876800, #614700);
  @include bgblack();
  --mk-sys-color5: #ffec3d;
  @include viewstyle(#feffe6, #ffffb8, #fffb8f, #fff566, #ffec3d, #fadb14, #d4b106);
}
body.mk-yellow-white {
  --mk-sys-color: #fadb14;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #feffe6, #ffffb8, #fffb8f, #fff566, #ffec3d, #fadb14, #d4b106, #ad8b00, #876800, #614700);
}
body.mk-yellow-green-black {
body[class*='mk-yellow-green-'] {
  --mk-sys-color: #a0d911;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#fcffe6, #f4ffb8, #eaff8f, #d3f261, #bae637, #a0d911, #7cb305, #5b8c00, #3f6600, #254000);
  @include bgblack();
  --mk-sys-color5: #bae637;
  @include viewstyle(#fcffe6, #f4ffb8, #eaff8f, #d3f261, #bae637, #a0d911, #7cb305);
}
body.mk-yellow-green-white {
  --mk-sys-color: #a0d911;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #fcffe6, #f4ffb8, #eaff8f, #d3f261, #bae637, #a0d911, #7cb305, #5b8c00, #3f6600, #254000);
}
body.mk-green-black {
body[class*='mk-green-'] {
  --mk-sys-color: #52c41a;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#f6ffed, #d9f7be, #b7eb8f, #95de64, #73d13d, #52c41a, #389e0d, #237804, #135200, #092b00);
  @include bgblack();
  --mk-sys-color5: #73d13d;
  @include viewstyle(#f6ffed, #d9f7be, #b7eb8f, #95de64, #73d13d, #52c41a, #389e0d);
}
body.mk-green-white {
  --mk-sys-color: #52c41a;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #f6ffed, #d9f7be, #b7eb8f, #95de64, #73d13d, #52c41a, #389e0d, #237804, #135200, #092b00);
}
body.mk-cyan-black {
body[class*='mk-cyan-'] {
  --mk-sys-color: #13c2c2;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#e6fffb, #b5f5ec, #87e8de, #5cdbd3, #36cfc9, #13c2c2, #08979c, #006d75, #00474f, #002329);
  @include bgblack();
  --mk-sys-color5: #36cfc9;
  @include viewstyle(#e6fffb, #b5f5ec, #87e8de, #5cdbd3, #36cfc9, #13c2c2, #08979c);
}
body.mk-cyan-white {
  --mk-sys-color: #13c2c2;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #e6fffb, #b5f5ec, #87e8de, #5cdbd3, #36cfc9, #13c2c2, #08979c, #006d75, #00474f, #002329);
}
body.mk-blue-purple-black {
body[class*='mk-blue-purple-'] {
  --mk-sys-color: #2f54eb;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#f0f5ff, #d6e4ff, #adc6ff, #85a5ff, #597ef7, #2f54eb, #1d39c4, #10239e, #061178, #030852);
  @include bgblack();
  --mk-sys-color5: #597ef7;
  @include viewstyle(#f0f5ff, #d6e4ff, #adc6ff, #85a5ff, #597ef7, #2f54eb, #1d39c4);
}
body.mk-blue-purple-white {
  --mk-sys-color: #2f54eb;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #f0f5ff, #d6e4ff, #adc6ff, #85a5ff, #597ef7, #2f54eb, #1d39c4, #10239e, #061178, #030852);
}
body.mk-purple-black {
body[class*='mk-purple-'] {
  --mk-sys-color: #722ed1;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#f9f0ff, #efdbff, #d3adf7, #b37feb, #9254de, #722ed1, #531dab, #391085, #22075e, #120338);
  @include bgblack();
  --mk-sys-color5: #9254de;
  @include viewstyle(#f9f0ff, #efdbff, #d3adf7, #b37feb, #9254de, #722ed1, #531dab);
}
body.mk-purple-white {
  --mk-sys-color: #722ed1;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #f9f0ff, #efdbff, #d3adf7, #b37feb, #9254de, #722ed1, #531dab, #391085, #22075e, #120338);
}
body.mk-magenta-black {
body[class*='mk-magenta-'] {
  --mk-sys-color: #eb2f96;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#fff0f6, #ffd6e7, #ffadd2, #ff85c0, #f759ab, #eb2f96, #c41d7f, #9e1068, #780650, #520339);
  @include bgblack();
  --mk-sys-color5: #f759ab;
  @include viewstyle(#fff0f6, #ffd6e7, #ffadd2, #ff85c0, #f759ab, #eb2f96, #c41d7f);
}
body.mk-magenta-white {
  --mk-sys-color: #eb2f96;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #fff0f6, #ffd6e7, #ffadd2, #ff85c0, #f759ab, #eb2f96, #c41d7f, #9e1068, #780650, #520339);
}
body.mk-grass-green-black {
body[class*='mk-grass-green-'] {
  --mk-sys-color: #aeb303;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#f2efda, #e6de97, #d9d26c, #ccc845, #bfbf22, #aeb303, #838c00, #5c6600, #374000, #151a00);
  @include bgblack();
  --mk-sys-color5: #bfbf22;
  @include viewstyle(#f2efda, #e6de97, #d9d26c, #ccc845, #bfbf22, #aeb303, #838c00);
}
body.mk-grass-green-white {
  --mk-sys-color: #aeb303;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #f2efda, #e6de97, #d9d26c, #ccc845, #bfbf22, #aeb303, #838c00, #5c6600, #374000, #151a00);
}
body.mk-deep-red-black {
body[class*='mk-deep-red-'] {
  --mk-sys-color: #c32539;
  @include viewstyle(#000000, #434343,rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.65),#fff0f0, #f5cbcb, #e89b9e, #db7077, #cf4856, #c32539, #9c162c, #750b20, #4f0315, #29010c);
  @include bgblack();
}
body.mk-deep-red-white {
  --mk-sys-color: #c32539;
  @include viewstyle(#ffffff, #ffffff, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.65), #fff0f0, #f5cbcb, #e89b9e, #db7077, #cf4856, #c32539, #9c162c, #750b20, #4f0315, #29010c);
  --mk-sys-color5: #cf4856;
  @include viewstyle(#fff0f0, #f5cbcb, #e89b9e, #db7077, #cf4856, #c32539, #9c162c);
}
src/assets/mobimg/account.png
src/assets/mobimg/voucher.png
src/components/header/index.scss
@@ -7,6 +7,8 @@
  width: 100%;
  height: 48px;
  display: flex;
  background: var(--mk-sys-background);
  color: var(--mk-sys-font-color);
  .header-logo {
    width: 180px;
@@ -39,7 +41,7 @@
      position: relative;
      top: 3px;
      font-size: 20px;
      color: #ffffff;
      color: var(--mk-sys-font-color);
    }
  }
  .header-collapse.collapse {
@@ -62,18 +64,21 @@
        padding: 0 10px;
        height: 42px;
        display: inline-block;
        color: var(--mk-sys-font-color);
      }
      &:hover {
        color: #eeeeee;
        span {
          border-bottom: 4px solid #fafcfb;
          color: var(--mk-sys-color);
          border-bottom: 4px solid var(--mk-sys-color);
        }
      }
      &.active {
        color: #ffffff;
        span {
          border-bottom: 4px solid #1890ff;
          color: var(--mk-sys-color);
          border-bottom: 4px solid var(--mk-sys-color);
        }
      }
    }
@@ -95,9 +100,9 @@
    border-radius: 5px;
  }
  .header-menu::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(0, 0, 0, 0);
    box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.07);
    background: rgba(255, 255, 255, 255);
    border-radius: 3px;
  }
@@ -111,7 +116,7 @@
      margin-right: 7px;
    }
    span {
      color: #ffffff;
      color: var(--mk-sys-font-color);
      font-size: 0.95rem;
      .username {
        vertical-align: middle;
@@ -216,7 +221,7 @@
  // left: 11.8%;
  .menu-wrap {
    .title {
      color: #1890ff;
      color: var(--mk-sys-color);
      font-size: 15px;
      font-weight: 600;
    }
@@ -224,18 +229,14 @@
      max-width: 60vw;
      padding: 5px 0 5px 15px;
      div {
        // float: left;
        display: inline-block;
        vertical-align: top;
        margin-bottom: 8px;
        width: 120px;
        // overflow: hidden;
        // white-space: nowrap;
        // text-overflow: ellipsis;
        cursor: pointer;
      }
      div:hover {
        color: #40a9ff;
        color: var(--mk-sys-color5);
      }
      div:not(:last-child) {
        margin-right: 15px;
@@ -247,4 +248,30 @@
      clear: both;
    }
  }
}
body[class*='-white'] {
  .header-container {
    box-shadow: 0 1px 1px #d9d9d9;
    .header-menu::-webkit-scrollbar-track {
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
      border: 1px solid rgba(0, 0, 0, 0.07);
      background: rgba(0, 0, 0, 0);
      border-radius: 3px;
    }
  }
}
body[class*='-black'] {
  .header-container {
    .header-menu {
      li {
        &:hover, &.active {
          span {
            color: #ffffff;
          }
        }
      }
    }
  }
}
src/components/keyInterface/index.jsx
@@ -57,7 +57,7 @@
      }
    }
    this.setState({visible: true, setting: _setting || {}})
    this.setState({visible: true, setting: _setting || {ssoInterface: 'http://sso.mk9h.cn/cloud/webapi/dostars'}})
  }
  decrypt = (token, value) => {
@@ -193,7 +193,7 @@
            <Form>
              <Form.Item label="接口地址">
                {getFieldDecorator('interface', {
                  initialValue: setting.interface,
                  initialValue: setting.interface || 'http://******/webapi/dostars',
                  rules: [
                    {
                      required: true,
@@ -204,7 +204,7 @@
                      message: '只可使用英文、数字以及:_./'
                    }
                  ]
                })(<TextArea rows={2}/>)}
                })(<TextArea placeholder="http://******/webapi/dostars" rows={2}/>)}
              </Form.Item>
              <Form.Item label="sso地址">
                {getFieldDecorator('ssoInterface', {
@@ -215,7 +215,7 @@
                      message: '只可使用英文、数字以及:_./'
                    }
                  ]
                })(<TextArea rows={2}/>)}
                })(<TextArea placeholder="http://sso.mk9h.cn/cloud/webapi/dostars" rows={2}/>)}
              </Form.Item>
              <Form.Item label="appkey">
                {getFieldDecorator('appkey', {
src/components/sidemenu/index.scss
@@ -1,10 +1,12 @@
@import '../../assets/css/iconfont.css';
// @import '../../assets/css/iconfont.css';
.mk-side-menu {
  flex: 0 0 235px;
  width: 235px;
  padding: 48px 0 40px;
  transition: width 0.2s, flex 0.2s;
  border-right: 1px solid #d9d9d9;
  background: var(--mk-sys-background);
  .ant-menu-item {
    padding-left: 0!important;
    cursor: default;
@@ -29,12 +31,6 @@
    .edit-check {
      top: -5px;
    }
  }
  .ant-menu-sub.ant-menu-inline > .ant-menu-item.ant-menu-item-active {
    background: #06b4f7;
  }
  .ant-menu-sub.ant-menu-inline > .ant-menu-item.ant-menu-item-selected {
    background: #06b4f7;
  }
  .ant-menu-inline .ant-menu-item {
    font-size: 1.1rem;
@@ -92,6 +88,46 @@
    width: 48px;
    left: 187px;
  }
  > .ant-menu {
    background: var(--mk-sys-background);
    > .ant-menu-submenu {
      color: var(--mk-sys-font-color);
      background: transparent;
      > .ant-menu-submenu-title {
        &:hover {
          color: var(--mk-sys-font-color);
        }
        > .ant-menu-submenu-arrow:before {
          background: var(--mk-sys-font-color);
        }
        > .ant-menu-submenu-arrow:after {
          background: var(--mk-sys-font-color);
        }
      }
      > .ant-menu-sub {
        background: transparent;
        box-shadow: none;
        .ant-menu-item {
          a {
            color: var(--mk-sys-light-font-color);
          }
        }
        .ant-menu-item.ant-menu-item-active, .ant-menu-item.ant-menu-item-selected {
          background: var(--mk-sys-color5);
          color: #ffffff;
          a {
            color: #ffffff;
          }
        }
      }
    }
    > .ant-menu-submenu.ant-menu-submenu-open {
      > .ant-menu-submenu-title {
        background: var(--mk-sys-light-background);
      }
    }
  }
}
// .mk-side-menu.mk-iframe { // tab页中为iframe时
src/components/tabview/index.jsx
@@ -264,11 +264,11 @@
    const { tabviews, activeId } = this.state
    return (
      <section id="mk-tabview-wrap" className={'mk-tabview-wrap' + (this.props.collapse ? ' collapsed' : '') + (tabviews && tabviews.length > 0 ? ' hastab' : '')}>
      <section className={'mk-tabview-wrap' + (this.props.collapse ? ' collapsed' : '')}>
        <div className="content-header">
          {tabviews && tabviews.length > 0 &&
            <Tabs activeKey={activeId}>
              {tabviews.map((view, index) => {
              {tabviews.map(view => {
                return (
                  <Tabs.TabPane
                    tab={
@@ -292,7 +292,6 @@
                        </div>
                      </div>
                    </BackTop>
                    {/* {options.sysType === 'local' && window.GLOB.systemType !== 'production' ? <div className="mk-water-mark">测试系统</div> : null} */}
                  </Tabs.TabPane>
                )
              })}
src/index.js
@@ -8,7 +8,7 @@
import options, { styles } from '@/store/options.js'
import '@/assets/css/main.scss'
import '@/assets/css/action.scss'
import '@/assets/css/minkeicon.css'
// import '@/assets/css/minkeicon.css'
import '@/assets/css/viewstyle.scss'
if (window.location.href.indexOf('#/design') > -1) { // 编辑页面刷新时,跳转至主页
@@ -156,6 +156,7 @@
    let _systemMsg = localStorage.getItem(_href + 'system')
    GLOB.navBar = 'shutter' // 默认为百叶窗
    let className = 'mk-blue-black'
    if (_systemMsg) {
      try {
@@ -184,13 +185,15 @@
          document.getElementsByTagName('head')[0].appendChild(link)
        }
        if (GLOB.style && styles[GLOB.style]) {
          document.body.className = styles[GLOB.style] + ' ' + (GLOB.showline === 'false' ? 'hidden-split-line' : '')
          className = styles[GLOB.style] + ' ' + (GLOB.showline === 'false' ? 'hidden-split-line' : '')
        }
      } catch (e) {
        console.warn('Parse Failure')
      }
    }
    document.body.className = className
    if (/^https/.test(window.location.protocol) || (process.env.NODE_ENV !== 'production' && /^https/.test(config.host))) { // https转换
      let meta = document.createElement('meta')
      meta.content = 'upgrade-insecure-requests'
src/menu/components/card/balcony/index.scss
@@ -17,17 +17,7 @@
  .model-menu-card-cell-list {
    flex: 1;
  }
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -180,6 +180,19 @@
          {val}
        </div>
      )
    } else if (card.eleType === 'color') {
      _style.overflow = 'hidden'
      let _bgstyle = {backgroundColor: card.value || '#1890ff'}
      if (PicRadio[card.lenWidRadio]) {
        _bgstyle.paddingTop = PicRadio[card.lenWidRadio]
      } else {
        _bgstyle.paddingTop = '100%'
      }
      return (
        <div style={_bgstyle}></div>
      )
    }
  }
@@ -191,7 +204,7 @@
  }
  let able = true
  if ((appType === 'mob' || appType === 'pc') && (parent.setting.click === 'menu' || parent.setting.click === 'menus')) {
  if ((appType === 'mob' || appType === 'pc') && parent.setting && (parent.setting.click === 'menu' || parent.setting.click === 'menus')) {
    able = false
  }
src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -140,4 +140,10 @@
    width: 26px;
    height: 26px;
  }
  .card-cell > div {
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
  }
}
src/menu/components/card/cardcellcomponent/elementform/index.jsx
@@ -26,6 +26,7 @@
  qrcode: ['eleType', 'datatype', 'width', 'qrWidth', 'color', 'url', 'noValue'],
  currentDate: ['eleType', 'width', 'dateFormat', 'prefix', 'postfix', 'fixStyle'],
  formula: ['eleType', 'width', 'height', 'prefix', 'postfix', 'eval', 'formula', 'noValue', 'fixStyle'],
  color: ['eleType', 'datatype', 'width', 'lenWidRadio', 'noValue', 'copyable'],
}
class MainSearch extends Component {
@@ -104,7 +105,7 @@
  getOptions = (eleType, datatype, link, showType, showInfo, fixStyle, posterType) => {
    let _options = fromJS(cardTypeOptions[eleType]).toJS() // 选项列表
    
    if (['text', 'number', 'picture', 'slider', 'barcode', 'qrcode', 'video'].includes(eleType)) {
    if (['text', 'number', 'picture', 'slider', 'barcode', 'qrcode', 'video', 'color'].includes(eleType)) {
      if (datatype === 'dynamic') {
        _options.push('field')
        if (eleType === 'number') {
src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -18,6 +18,7 @@
    { value: 'qrcode', text: '二维码'},
    { value: 'currentDate', text: '当前时间'},
    { value: 'formula', text: '公式'},
    { value: 'color', text: '颜色'},
  ]
  let anchors = []
src/menu/components/card/cardcellcomponent/index.jsx
@@ -155,6 +155,8 @@
      }
    } else if (element.eleType === 'picture') {
      options = ['border', 'margin']
    } else if (element.eleType === 'color') {
      options = ['border', 'margin', 'padding']
    } else if (element.eleType === 'text') {
      options[0] = 'font2'
      options.push('display')
src/menu/components/card/cardcomponent/index.scss
@@ -45,4 +45,20 @@
      }
    }
  }
}
}
.card-control {
  position: absolute;
  top: 0px;
  left: 0px;
  .anticon-tool {
    position: absolute;
    left: 1px;
    top: 1px;
    padding: 1px;
    z-index: 2;
    font-size: 16px;
    cursor: pointer;
    background: rgba(255, 255, 255, 0.55);
  }
}
src/menu/components/card/cardsimplecomponent/index.jsx
@@ -10,7 +10,7 @@
import { getTableSetting, getCarouselSetting } from './options'
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
// import './index.scss'
import './index.scss'
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const NodesWrap = asyncComponent(() => import('./node-wrap'))
src/menu/components/card/cardsimplecomponent/index.scss
@@ -0,0 +1,15 @@
.card-control {
  position: absolute;
  top: 0px;
  left: 0px;
  .anticon-tool {
    position: absolute;
    left: 1px;
    top: 1px;
    padding: 1px;
    z-index: 2;
    font-size: 16px;
    cursor: pointer;
    background: rgba(255, 255, 255, 0.55);
  }
}
src/menu/components/card/data-card/index.scss
@@ -8,17 +8,7 @@
  min-height: 20px;
  overflow-y: auto;
  
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/components/card/data-card/options.jsx
@@ -303,15 +303,15 @@
    {
      type: 'radio',
      field: 'goback',
      label: '空值返回',
      label: appType === 'mob' ? '空值返回' : '空值关闭',
      initval: wrap.goback || 'false',
      tooltip: '当查询数据为空时,返回上一界面。',
      tooltip: appType === 'mob' ? '当查询数据为空时,返回上一界面。' : '当查询数据为空时,关闭当前标签页。',
      required: false,
      options: [
        {value: 'true', label: '是'},
        {value: 'false', label: '否'},
        {value: 'true', label: '是'},
      ],
      forbid: subtype !== 'propcard' || appType !== 'mob'
      forbid: subtype !== 'propcard' || appType === 'pc'
    },
    {
      type: 'radio',
src/menu/components/card/prop-card/index.scss
@@ -7,17 +7,7 @@
  background-size: cover;
  min-height: 20px;
  
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/components/card/table-card/index.scss
@@ -24,17 +24,7 @@
      z-index: 1;
    }
  }
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/components/carousel/data-card/index.scss
@@ -7,17 +7,7 @@
  background-size: cover;
  min-height: 30px;
  
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/components/carousel/prop-card/index.scss
@@ -7,17 +7,7 @@
  background-size: cover;
  min-height: 30px;
  
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
@@ -218,7 +218,7 @@
      controlFields: [
        {field: 'dirField', values: ['mindmap']},
        {field: 'nodeColor', values: ['mindmap']},
        {field: 'collapsed', values: ['indentTree', 'kapmap']},
        // {field: 'collapsed', values: ['indentTree', 'kapmap']},
      ]
    },
    {
src/menu/components/chart/antv-G6/index.jsx
@@ -93,29 +93,7 @@
  },
  'single-node',
)
G6.registerNode(
  'dice-mind-map-sub', {
    jsx: (cfg) => {
      const width = Util.getTextSize(cfg.label, 14)[0] + 24
      return `
        <group>
          <rect style={{width: ${width}, height: 22, cursor: pointer}}>
            <text style={{ fontSize: 14, fill: ${cfg.selected ? systemColor : '#000000'}, marginLeft: 12, marginTop: 6, cursor: pointer }}>${cfg.label}</text>
          </rect>
          <rect style={{ fill: ${cfg.color}, width: ${width}, height: 2, x: 0, y: 22, cursor: pointer }} />
        </group>
      `
    },
    getAnchorPoints() {
      return [
        [0, 0.965],
        [1, 0.965]
      ]
    }
  },
  'single-node',
)
G6.registerNode(
  'dice-mind-map-leaf', {
    jsx: (cfg) => {
@@ -203,38 +181,6 @@
    ev.preventDefault()
  }
})
const dataMapTransform = (data) => {
  const changeData = (d, level = 0, color) => {
    const data = { ...d }
    switch (level) {
      case 0:
        data.type = 'dice-mind-map-root'
        break
      case 1:
        data.type = 'dice-mind-map-sub'
        break
      default:
        data.type = 'dice-mind-map-leaf'
        break
    }
    if (color) {
      data.color = color
    }
    if (level === 1 && !d.direction) {
      data.direction = 'right'
    }
    if (d.children) {
      data.children = d.children.map((child) => changeData(child, level + 1, data.color))
    }
    return data
  }
  return changeData(data)
}
// 缩进文件树
G6.registerNode('indentedRoot', {
@@ -1137,9 +1083,27 @@
        if (item.direction === 'left') {
          item.color = card.plot.leftColor || '#26C281'
        } else {
          item.direction = 'right'
          item.color = card.plot.nodeColor || '#1890ff'
        }
      })
      data.collapsed = false
      data.type = 'dice-mind-map-root'
      const collapse = (item) => {
        if (!item.children) return
        item.children.forEach(cell => {
          cell.collapsed = card.plot.collapsed === 'true'
          cell.direction = cell.direction || 'right'
          cell.type = 'dice-mind-map-leaf'
          cell.color = cell.color || item.color
          collapse(cell)
        })
      }
      collapse(data)
    } else if (card.plot.subtype === 'indentTree') {
      data.isRoot = true
      data.collapsed = false
@@ -1184,11 +1148,12 @@
    const { card } = this.state
    const plot = card.plot
    const data = this.getdata()
    const height = getHeight(plot.height)
    const graph = new G6.TreeGraph({
      container: card.uuid + 'canvas',
      width: this.wrap.scrollWidth - 30,
      height: getHeight(plot.height),
      height: height,
      modes: {
        default: [
          {
@@ -1235,6 +1200,10 @@
    graph.data(data)
    graph.render()
    graph.fitView()
    if (plot.collapsed === 'true') {
      graph.zoomTo(1, { x: 0, y: height / 2 })
    }
  }
  indentrender = () => {
@@ -1306,11 +1275,18 @@
    const { card } = this.state
    const plot = card.plot
    const data = this.getdata()
    const width = this.wrap.scrollWidth - 30
    const height = getHeight(plot.height)
    let modes = ['drag-canvas', 'zoom-canvas', 'dice-mindmap']
    if (plot.collapsed === 'true') {
      modes = [{ type: 'collapse-expand' },'drag-canvas', 'zoom-canvas', 'dice-mindmap']
    }
    const tree = new G6.TreeGraph({
      container: card.uuid + 'canvas',
      width: this.wrap.scrollWidth - 30,
      height: getHeight(plot.height),
      width: width,
      height: height,
      fitView: true,
      layout: {
        type: 'mindmap',
@@ -1341,13 +1317,19 @@
      },
      minZoom: 0.5,
      modes: {
        default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap']
        default: modes
      }
    })
    tree.data(dataMapTransform(data))
    tree.data(data)
    tree.render()
    if (plot.collapsed === 'true' && plot.dirField) {
      tree.zoomTo(1, { x: width / 2, y: height / 2 })
    } else if (plot.collapsed === 'true') {
      tree.zoomTo(1, { x: 0, y: height / 2 })
    }
  }
  updateComponent = (card) => {
src/menu/components/form/formaction/formconfig.jsx
@@ -97,6 +97,7 @@
      key: 'procMode',
      label: '参数处理',
      initVal: card.procMode || 'system',
      tooltip: '当返回值存在 mk_ex_invoke 且值为 false 时,不会调用外部接口。',
      required: true,
      options: [{
        value: 'system',
src/menu/components/form/simple-form/index.scss
@@ -6,18 +6,8 @@
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 30px;
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/components/form/step-form/index.scss
@@ -6,18 +6,8 @@
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 30px;
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/components/form/tab-form/index.scss
@@ -6,18 +6,8 @@
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 30px;
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/components/iframe/index.scss
@@ -25,8 +25,7 @@
    height: 45px;
    padding-top: 5px;
    .ant-input-group-wrapper {
      width: 40%;
      max-width: 400px;
      width: 65%;
      float: right;
    }
  }
src/menu/components/iframe/options.jsx
@@ -79,9 +79,22 @@
      ],
      controlFields: [
        {field: 'linkUrl', values: ['fixed']},
        {field: 'focus', values: ['input']},
      ]
    },
    {
      type: 'radio',
      field: 'focus',
      label: '自动聚焦',
      initval: wrap.focus || 'true',
      required: false,
      options: [
        {value: 'true', label: '是'},
        {value: 'false', label: '否'},
      ],
      forbid: appType === 'mob'
    },
    {
      type: 'textarea',
      field: 'linkUrl',
      label: '地址链接',
src/menu/components/module/account/index.jsx
New file
@@ -0,0 +1,147 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover } from 'antd'
import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, CaretDownOutlined } from '@ant-design/icons'
import moment from 'moment'
import asyncIconComponent from '@/utils/asyncIconComponent'
import MKEmitter from '@/utils/events.js'
import getWrapForm from './options'
import './index.scss'
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
class Account extends Component {
  static propTpyes = {
    card: PropTypes.object,
    deletecomponent: PropTypes.func,
    updateConfig: PropTypes.func,
  }
  state = {
    card: null,
    date: moment().format('YYYY年MM月')
  }
  UNSAFE_componentWillMount () {
    const { card } = this.props
    if (card.isNew) {
      let _card = {
        uuid: card.uuid,
        type: card.type,
        format: 'array',    // 组件属性 - 数据格式
        pageable: false,    // 组件属性 - 是否可分页
        switchable: true,   // 组件属性 - 数据是否可切换
        width: card.width || 24,
        name: '账套',
        subtype: card.subtype,
        wrap: { name: '账套', width: card.width || 24 },
        style: { paddingLeft: '20px', paddingRight: '20px', paddingTop: '10px', paddingBottom: '10px' },
      }
      this.updateComponent(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
      })
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  /**
   * @description 卡片行外层信息更新(数据源,样式等)
   */
  updateComponent = (card) => {
    card.width = card.wrap.width
    card.name = card.wrap.name
    this.setState({
      card: card
    })
    this.props.updateConfig(card)
  }
  changeStyle = () => {
    const { card } = this.state
    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear'], card.style, this.getStyle)
  }
  getStyle = (style) => {
    let _card = {...this.state.card, style}
    this.updateComponent(_card)
  }
  getWrapForms = () => {
    const { card } = this.state
    return getWrapForm(card.wrap)
  }
  updateWrap = (res) => {
    if (res.linkmenu) {
      let list = null
      try {
        list = JSON.parse(sessionStorage.getItem('thdMenuList')) || []
      } catch (e) {
        list = []
      }
      let id = res.linkmenu[res.linkmenu.length - 1]
      res.MenuID = id
      list.forEach(item => {
        if (item.MenuID === id) {
          res.MenuName = item.MenuName
          res.MenuNo = item.MenuNo
          res.tabType = item.type
        }
      })
    }
    this.updateComponent({...this.state.card, wrap: res})
  }
  render() {
    const { card, date } = this.state
    return (
      <div className="menu-account-box" style={card.style} id={card.uuid}>
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <NormalForm title="基本设置" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
              <EditOutlined style={{color: '#1890ff'}} title="编辑"/>
            </NormalForm>
            <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/>
            <DeleteOutlined className="close" title="删除组件" onClick={() => this.props.deletecomponent(card.uuid)} />
          </div>
        } trigger="hover">
          <ToolOutlined />
        </Popover>
        <div className="account-box">
          <div className="company">北京明科普华信息技术有限公司 <CaretDownOutlined /></div>
          <div className="date">{date}</div>
        </div>
      </div>
    )
  }
}
export default Account
src/menu/components/module/account/index.scss
New file
@@ -0,0 +1,52 @@
.menu-account-box {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  color: #000000;
  .anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
    right: 1px;
    top: 1px;
    cursor: pointer;
    padding: 5px;
    background: rgba(255, 255, 255, 0.55);
  }
  .account-box {
    display: flex;
    .company {
      border: 1px solid #d9d9d9;
      padding: 3px 10px 3px 5px;
      border-radius: 4px;
      margin-right: 15px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      .anticon-caret-down {
        margin-left: 20px;
      }
    }
    .date {
      padding-top: 3px;
      flex: 1;
    }
  }
}
.menu-account-box::after {
  display: block;
  content: ' ';
  clear: both;
}
.menu-account-box:hover {
  z-index: 1;
  box-shadow: 0px 0px 4px #1890ff;
}
src/menu/components/module/account/options.jsx
New file
@@ -0,0 +1,61 @@
/**
 * @description Wrap表单配置信息
 */
export default function (wrap) {
  let menulist = sessionStorage.getItem('fstMenuList')
  if (menulist) {
    try {
      menulist = JSON.parse(menulist)
    } catch (e) {
      menulist = []
    }
  } else {
    menulist = []
  }
  const wrapForm = [
    {
      type: 'text',
      field: 'name',
      label: '组件名称',
      initval: wrap.name || '',
      tooltip: '用于组件间的区分。',
      required: true
    },
    {
      type: 'number',
      field: 'width',
      label: '宽度',
      initval: wrap.width || 24,
      tooltip: '栅格布局,每行等分为24列。',
      min: 1,
      max: 24,
      precision: 0,
      required: true
    },
    {
      type: 'radio',
      field: 'addable',
      label: '可新增',
      initval: wrap.addable || 'false',
      required: true,
      options: [
        {value: 'true', label: '是'},
        {value: 'false', label: '否'},
      ],
      controlFields: [
        {field: 'linkmenu', values: ['true']},
      ],
    },
    {
      type: 'cascader',
      field: 'linkmenu',
      label: '关联菜单',
      initVal: wrap.linkmenu || [],
      required: true,
      options: menulist
    },
  ]
  return wrapForm
}
src/menu/components/module/voucher/index.jsx
@@ -1,18 +1,17 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Popover } from 'antd'
import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import { Popover, Button } from 'antd'
import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, DownOutlined, CalendarOutlined } from '@ant-design/icons'
// import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
import MKEmitter from '@/utils/events.js'
import getWrapForm from './options'
import VoucherTable from './voucherTable'
import './index.scss'
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
// const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
class Voucher extends Component {
  static propTpyes = {
@@ -39,9 +38,9 @@
        width: card.width || 12,
        name: '凭证',
        subtype: card.subtype,
        setting: { interType: 'system' },
        // setting: { interType: 'system' },
        wrap: { name: '凭证', title: '', width: card.width || 12, type: 'edit' },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px', paddingBottom: '20px' },
        headerStyle: {},
        columns: [],
        scripts: [],
@@ -112,7 +111,6 @@
    return (
      <div className="menu-voucher-box" style={card.style} id={card.uuid}>
        {/* <NormalHeader config={card} updateComponent={this.updateComponent}/> */}
        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <NormalForm title="基本设置" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
@@ -125,7 +123,31 @@
          <ToolOutlined />
        </Popover>
        <div className="voucher-box">
          jjj
          <div className="voucher-header">
            <Button className="add-background header-btn">新增</Button>
            <Button className="add-background header-btn">保存</Button>
            <Button className="print-background header-btn">打印</Button>
            <Button className="system-background header-btn">导入</Button>
            <Button className="out-background header-btn">导出</Button>
          </div>
          <div className="voucher-body">
          <div className="pre-wrap">
            <div className="voucher-code">
              <div>记<DownOutlined/></div>
              <div>1</div>
              号
            </div>
            <div className="voucher-date">
              日期:<div>请选择日期 <CalendarOutlined /></div>
            </div>
            <div className="voucher-affix">
              附单据 <div>2</div> 张
              <Button type="link" className="">附件</Button>
              <Button type="link" className="">备注</Button>
            </div>
          </div>
          <VoucherTable config={card}/>
        </div>
        </div>
      </div>
    )
src/menu/components/module/voucher/index.scss
@@ -18,12 +18,97 @@
    padding: 5px;
    background: rgba(255, 255, 255, 0.55);
  }
  .empty-content {
    text-align: center;
    font-size: 30px;
    margin: 0;
    line-height: 90px;
    color: #bcbcbc;
  .voucher-header {
    padding: 10px;
    border-bottom: 1px solid #eeeeee;
    .header-btn {
      height: 28px;
      min-width: 80px;
      margin-right: 10px;
    }
  }
  .voucher-body {
    padding: 0 15px;
    .voucher-code {
      display: inline-block;
      width: 160px;
      margin-right: 15px;
      div {
        display: inline-block;
        min-width: 50px;
        margin-right: 10px;
        border: 1px solid #d9d9d9;
        padding: 4px 10px;
        border-radius: 4px;
        .anticon-down {
          position: relative;
          left: 3px;
          color: #c8c8c8;
          font-size: 12px;
          margin-left: 5px;
        }
      }
    }
    .pre-wrap {
      padding: 10px 0px;
    }
    .voucher-date {
      display: inline-block;
      div {
        display: inline-block;
        min-width: 50px;
        margin-right: 10px;
        border: 1px solid #d9d9d9;
        padding: 4px 10px;
        border-radius: 4px;
        color: #c8c8c8;
        .anticon {
          position: relative;
          left: 3px;
          color: #c8c8c8;
          margin-left: 5px;
        }
      }
    }
    .voucher-affix {
      float: right;
      width: 250px;
      div {
        display: inline-block;
        min-width: 50px;
        margin-right: 10px;
        border: 1px solid #d9d9d9;
        padding: 4px 10px;
        border-radius: 4px;
      }
    }
  }
  .add-background {
    background: #26C281;
    border-color: #26C281;
    color: #ffffff;
  }
  .print-background {
    background-color: #8E44AD;
    border-color: #8E44AD;
    color: #ffffff;
  }
  .out-background {
    background-color: rgb(50, 197, 210);
    border-color: rgb(50, 197, 210);
    color: #ffffff;
  }
  .system-background {
    background: #1890ff;
    border-color: #1890ff;
    color: #ffffff;
  }
}
.menu-voucher-box::after {
src/menu/components/module/voucher/options.jsx
@@ -4,21 +4,21 @@
 * @description Wrap表单配置信息
 */
export default function (wrap, id) {
  let roleList = sessionStorage.getItem('sysRoles')
  let appType = sessionStorage.getItem('appType')
  let menu = window.GLOB.customMenu
  let modules = MenuUtils.getSupModules(menu.components, id, menu.interfaces)
  if (roleList) {
    try {
      roleList = JSON.parse(roleList)
    } catch (e) {
      roleList = []
  let books = []
  let bookids = []
  menu.components.forEach(item => {
    if (item.subtype === 'account') {
      books.push({
        value: item.uuid,
        label: item.name
      })
      bookids.push(item.uuid)
    }
  } else {
    roleList = []
  }
  })
  modules = modules.filter(item => !bookids.includes(item.value))
  const wrapForm = [
    // {
@@ -59,6 +59,15 @@
      required: true
    },
    {
      type: 'select',
      field: 'supBook',
      label: '账套',
      initval: wrap.supBook || '',
      required: true,
      options: books,
      allowClear: true
    },
    {
      type: 'cascader',
      field: 'supModule',
      label: '上级组件',
@@ -66,15 +75,6 @@
      required: false,
      options: modules,
      allowClear: true,
    },
    {
      type: 'multiselect',
      field: 'blacklist',
      label: '黑名单',
      initval: wrap.blacklist || [],
      required: false,
      options: roleList,
      forbid: !!appType
    },
  ]
src/menu/components/module/voucher/voucherTable/index.jsx
New file
@@ -0,0 +1,362 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Table } from 'antd'
import Utils from '@/utils/utils.js'
import '@/assets/css/table.scss'
import './index.scss'
class BodyRow extends React.Component {
  render() {
    let { data, ...resProps } = this.props
    let style = {}
    let className = ''
    return <tr {...resProps} className={className} style={style}/>
  }
}
class BodyCell extends React.Component {
  state = {}
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  render() {
    let { col, record, className } = this.props
    let children = null
    let colSpan = 1
    if (col.field === 'remark') {
      let val = record.remark || ''
      if (record.type === 'total') {
        children = <div className="content-wrap" style={{lineHeight: '60px'}}>合计: {val}</div>
        colSpan = 2
      } else {
        children = <div className="content-wrap">{val}</div>
      }
    } else if (col.field === 'subject') {
      if (record.type === 'total') {
        colSpan = 0
      } else {
        let val = record.subject || ''
        children = <div className="content-wrap">{val}</div>
      }
    } else if (col.field === 'debtor') {
      let val = record.debtor
      let down = false
      let vals = []
      if (typeof(val) === 'number') {
        if (val < 0) {
          down = true
          val = Math.abs(val)
        }
        vals = (val * 100).toFixed(0).split('').reverse()
      }
      children = <div className={'money-uint' + (down ? ' down' : '')}>
        <span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
        <span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
      </div>
    } else if (col.field === 'creditor') {
      let val = record.creditor
      let down = false
      let vals = []
      if (typeof(val) === 'number') {
        if (val < 0) {
          down = true
          val = Math.abs(val)
        }
        vals = (val * 100).toFixed(0).split('').reverse()
      }
      children = <div className={'money-uint' + (down ? ' down' : '')}>
        <span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
        <span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
      </div>
    }
    if (!colSpan) return null
    return (<td colSpan={colSpan} className={className}>{children}</td>)
  }
}
class VoucherTable extends Component {
  static propTpyes = {
    config: PropTypes.object,        // 菜单Id
    BID: PropTypes.any,              // 主表ID
    total: PropTypes.any,            // 总数
    loading: PropTypes.bool,         // 表格加载中
    refreshdata: PropTypes.func,     // 表格中排序列、页码的变化时刷新
  }
  state = {
    data: [],
    edData: [],
    edColumns: [],
    tableId: '',          // 表格ID
    pageSize: 10,         // 每页数据条数
    columns: null,        // 显示列
    loading: false,
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    let data = [
      {remark: '提现', subject: '1001 库存现金', debtor: 124, creditor: ''},
      {remark: '购入固定资产', subject: '1001 库存现金', debtor: '', creditor: 124},
      {remark: '转结销售成本', subject: '1001 库存现金', debtor: -524, creditor: ''},
      {remark: '提现', subject: '1001 库存现金', debtor: 34, creditor: ''},
    ]
    data = this.initData(data)
    data.push(this.getTotalLine(data))
    let columns = [
      {
        title: '摘要',
        dataIndex: 'remark',
        key: 'remark',
        width: '22%',
        onCell: record => ({
          record,
          col: {uuid: 'remark', field: 'remark', tableId: config.uuid},
        })
      },
      {
        title: '会计科目',
        dataIndex: 'subject',
        key: 'subject',
        width: '34%',
        onCell: record => ({
          record,
          col: {uuid: 'subject', field: 'subject', tableId: config.uuid},
        })
      },
      {
        title: () => (<>
          <div className="money-title">借方金额</div>
          <div className="money-uint">
            <span>亿</span> <span>千</span> <span>百</span> <span>十</span> <span>万</span> <span>千</span>
            <span>百</span> <span>十</span> <span>元</span> <span>角</span> <span className="last">分</span>
          </div>
        </>),
        dataIndex: 'debtor',
        key: 'debtor',
        width: '22%',
        onCell: record => ({
          record,
          col: {uuid: 'debtor', field: 'debtor', tableId: config.uuid},
        })
      },
      {
        title: () => (<>
          <div className="money-title">贷方金额</div>
          <div className="money-uint">
            <span>亿</span> <span>千</span> <span>百</span> <span>十</span> <span>万</span> <span>千</span>
            <span>百</span> <span>十</span> <span>元</span> <span>角</span> <span className="last">分</span>
          </div>
        </>),
        dataIndex: 'creditor',
        key: 'creditor',
        width: '22%',
        onCell: record => ({
          record,
          col: {uuid: 'creditor', field: 'creditor', tableId: config.uuid},
        })
      }
    ]
    this.setState({
      data: data,
      edData: fromJS(data).toJS(),
      columns,
      tableId: config.uuid
    })
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  initData = (data) => {
    let _data = data.map((item, i) => {
      item.uuid = Utils.getuuid()
      item.index = i
      return item
    })
    if (_data.length < 4) {
      for (let i = _data.length - 1; i < 4; i++) {
        _data.push({uuid: Utils.getuuid(), index: i + 1, remark: '', subject: '', debtor: '', creditor: ''})
      }
    }
    return _data
  }
  getTotalLine = (data) => {
    let totalLine = {uuid: Utils.getuuid(), type: 'total'}
    let debtor = ''
    let creditor = ''
    data.forEach(item => {
      if (typeof(item.debtor) === 'number') {
        if (debtor === '') {
          debtor = 0
        }
        debtor += item.debtor
      } else if (typeof(item.creditor) === 'number') {
        if (debtor === '') {
          debtor = 0
        }
        if (creditor === '') {
          creditor = 0
        }
        creditor += item.creditor
      }
    })
    totalLine.debtor = debtor
    totalLine.creditor = creditor
    totalLine.remark = this.changeMoneyToChinese(debtor)
    return totalLine
  }
  changeMoneyToChinese = (money) => {
    let cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
    let cnIntRadice = ['', '拾', '佰', '仟']
    let cnIntUnits = ['', '万', '亿', '兆']
    let cnDecUnits = ['角', '分', '毫', '厘']
    let cnInteger = '整'
    let cnIntLast = '元'
    let maxNum = 999999999999999.9999 // 最大处理的数字
    let IntegerNum = null
    let DecimalNum = null
    let ChineseStr = ''
    let parts = null // 分离金额后用的数组,预定义
    let Symbol = ''  // 正负值标记
    if (money === '') return ''
    if (money >= maxNum) return '超出最大处理数字'
    if (money === 0) {
      ChineseStr = cnNums[0] + cnIntLast + cnInteger;
      return ChineseStr
    }
    if(money < 0) {
      money = -money
      Symbol = '负'
    }
    money = money.toString() // 转换为字符串
    if (money.indexOf('.') === -1) {
      IntegerNum = money
      DecimalNum = ''
    } else {
      parts = money.split('.')
      IntegerNum = parts[0]
      DecimalNum = parts[1].substr(0, 4)
    }
    if (parseInt(IntegerNum, 10) > 0) { // 获取整型部分转换
      let zeroCount = 0
      let IntLen = IntegerNum.length
      for (let i = 0; i < IntLen; i++) {
        let n = IntegerNum.substr(i, 1)
        let p = IntLen - i - 1
        let q = p / 4
        let m = p % 4
        if (n === '0') {
          zeroCount++
        } else {
          if (zeroCount > 0) {
            ChineseStr += cnNums[0]
          }
          zeroCount = 0 // 归零
          ChineseStr += cnNums[parseInt(n)] + cnIntRadice[m]
        }
        if (m === 0 && zeroCount < 4) {
          ChineseStr += cnIntUnits[q]
        }
      }
      ChineseStr += cnIntLast
    }
    if (DecimalNum !== '') { // 小数部分
      let decLen = DecimalNum.length
      for (let i = 0; i < decLen; i++) {
        let n = DecimalNum.substr(i, 1)
        if (n !== '0') {
          ChineseStr += cnNums[Number(n)] + cnDecUnits[i]
        }
      }
    }
    if (ChineseStr === '') {
      ChineseStr += cnNums[0] + cnIntLast + cnInteger
    } else if (DecimalNum === '') {
      ChineseStr += cnInteger
    }
    ChineseStr = Symbol + ChineseStr
    return ChineseStr
  }
  render() {
    const { edData, columns} = this.state
    const components = {
      body: {
        row: BodyRow,
        cell: BodyCell
      }
    }
    return (
      <div className="voucher-table-wrap">
        <Table
          rowKey="uuid"
          components={components}
          columns={columns}
          dataSource={edData}
          bordered={true}
          onRow={(record, index) => {
            return {
              data: record
            }
          }}
          pagination={false}
        />
      </div>
    )
  }
}
export default VoucherTable
src/menu/components/module/voucher/voucherTable/index.scss
New file
@@ -0,0 +1,259 @@
.voucher-table-wrap {
  position: relative;
  padding: 0px;
  .normal-table-footer {
    padding: 10px 0px;
    color: rgba(0, 0, 0, 0.65);
  }
  .normal-table-footer.pagination {
    position: absolute;
    bottom: 10px;
  }
  >.ant-table-wrapper {
    position: relative;
    z-index: 1;
  }
  .ant-table {
    color: inherit;
    font-size: inherit;
  }
  .money-uint {
    display: flex;
    span {
      display: inline-block;
      flex: 1;
      text-align: center;
      font-size: 12px;
    }
    span:not(.last) {
      border-right: 1px solid #e9e9e9;
    }
    span:nth-child(3), span:nth-child(6) {
      border-color: #91d5ff;
    }
    span:nth-child(9) {
      border-color: #ffa39e;
    }
  }
  table {
    max-width: 100%;
    width: 100%;
    .ant-table-thead {
      tr {
        th {
          position: relative;
          background-color: transparent;
          padding: 0;
          height: 60px;
          line-height: 60px;
          text-align: center;
          .ant-table-header-column {
            display: block;
            width: 100%;
            height: 100%;
            .ant-table-column-title {
              display: block;
              width: 100%;
              height: 100%;
              font-weight: bold;
              font-size: 13px;
            }
          }
          .money-title {
            line-height: 30px;
            font-weight: bold;
            font-size: 13px;
          }
          .money-uint {
            line-height: 30px;
            border-top: 1px solid #dadada;
          }
        }
      }
    }
    .ant-table-selection-column {
      width: 60px;
      min-width: 60px;
      max-width: 60px;
    }
    .ant-table-tbody {
      tr td {
        position: relative;
        background-color: transparent;
        padding: 0;
        height: 60px;
        vertical-align: top;
        .content-wrap {
          padding: 5px;
          height: 100%;
          font-size: 13px;
          font-weight: bold;
        }
        .money-uint {
          height: 100%;
          line-height: 60px;
          span {
            font-size: 14px;
            font-weight: bold;
          }
        }
        .money-uint.down {
          span {
            color: #ff4d4f;
          }
        }
      }
    }
  }
  .ant-input {
    height: 60px;
    border-radius: 0;
    resize: none;
  }
  .ant-input-number {
    height: 60px;
    border-radius: 0;
    .ant-input-number-handler-wrap {
      display: none;
    }
    .ant-input-number-input {
      border-radius: 0;
      height: 60px;
    }
  }
  .editing_table_cell {
    .ant-input {
      padding: 0px;
      position: absolute;
      top: 0px;
      left: 0px;
      right: 0px;
      bottom: 0px;
      border: 1px solid #1890ff;
    }
    .ant-input-number-input {
      position: absolute;
      top: 0px;
      left: 0px;
      right: 0px;
      bottom: 0px;
      border: 1px solid #1890ff;
    }
    .anticon {
      color: #ff4d4f;
      position: absolute;
      right: 3px;
      top: calc(50% - 8px);
    }
  }
  td.pointer {
    position: relative;
  }
  td.pointer {
    .mk-mask {
      display: none;
      cursor: pointer;
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
    }
  }
}
.edit-custom-table.editable {
  td {
    background-color: #ffffff!important;
  }
  td.pointer .mk-mask {
    display: block;
  }
  .mk-operation {
    display: none;
  }
  .ant-table-placeholder {
    display: none;
  }
}
.edit-custom-table:not(.fixed-height) {
  .ant-table-body::-webkit-scrollbar {
    width: 8px;
    height: 10px;
  }
  ::-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);
  }
  ::-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);
  }
}
.edit-custom-table.fixed-height {
  .ant-table-body {
    border-bottom: 1px solid rgba(0, 0, 0, .05);
    .ant-table-fixed {
      border-bottom: 0;
    }
  }
}
.edit-custom-table.hidden {
  thead {
    display: none;
  }
}
.edit-custom-table.ghost {
  .ant-table-thead > tr {
    > th {
      color: inherit;
      background: transparent;
      .ant-table-column-sorter .ant-table-column-sorter-inner {
        color: inherit;
      }
    }
    > th:hover {
      background: transparent;
    }
  }
  .ant-table-body {
    overflow-x: auto;
    tr {
      td {
        background: transparent!important;
      }
    }
    tr:hover td {
      background: transparent!important;
    }
  }
}
.image-scale-modal {
  width: 70vw;
  min-height: 80vh;
  top: 10vh;
  .ant-modal-body {
    min-height: calc(80vh - 110px);
    line-height: calc(80vh - 160px);
    text-align: center;
  }
  .ant-modal-footer {
    text-align: center;
    span {
      display: inline-block;
      color: #1890ff;
      padding: 5px 15px;
      cursor: pointer;
    }
  }
}
src/menu/components/search/main-search/index.jsx
@@ -207,7 +207,6 @@
    this.searchFormRef.handleConfirm().then(res => {
      let fieldrepet = false // 字段重复
      let labelrepet = false // 提示文字重复
      card.search = card.search.map(item => { // 数据更新及重复检测
        if (item.uuid !== res.uuid && res.field && item.field) {
@@ -233,8 +232,6 @@
          if (setFields.length < itemFields.length + resFields.length && (res.type !== 'date' || item.type !== 'date')) {
            fieldrepet = true
          } else if (item.label === res.label) {
            labelrepet = true
          }
        }
@@ -249,13 +246,6 @@
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 5
        })
        return
      } else if (labelrepet) {
        notification.warning({
          top: 92,
          message: '名称已存在!',
          duration: 5
        })
        return
src/menu/components/search/main-search/index.scss
@@ -102,6 +102,9 @@
    }
  }
  .mk-search-item-wrap.action {
    .ant-form-item {
      white-space: nowrap;
    }
    .ant-form-item-label, .ant-form-item-control-wrapper {
      display: inline-block;
    }
src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -420,6 +420,9 @@
        if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
          shows.push('resetPageIndex')
        }
        if (this.record.execMode === 'pop' || this.record.execMode === 'prompt') {
          shows.push('position')
        }
      } else if (_funcType === 'mkBinding' || _funcType === 'mkUnBinding') {
        shows.push('execSuccess', 'execError')
      } else if (_funcType === 'closetab') {
@@ -549,14 +552,13 @@
      } else if (value === 'excelIn') {
        _fieldval.intertype = 'system'
        _fieldval.Ot = 'notRequired'
        _fieldval.execSuccess = 'grid'
        _fieldval.label = '导入Excel'
        _fieldval.class = 'dgreen'
        this.record.Ot = 'notRequired'
        this.record.label = '导入Excel'
        this.record.class = 'dgreen'
        this.record.execSuccess = 'grid'
      } else if (value === 'excelOut') {
        _fieldval.intertype = 'system'
        _fieldval.label = '导出Excel'
src/menu/components/share/actioncomponent/formconfig.jsx
@@ -128,6 +128,7 @@
  if (appType === 'mob') {
    opentypes = opentypes.filter(item => ['pop', 'prompt', 'exec', 'excelOut', 'innerpage', 'funcbutton'].includes(item.value))
    funTypes = [
      { value: 'print', text: '标签打印' },
      { value: 'scan', text: '扫码' },
      { value: 'pay', text: '支付' },
      { value: 'refund', text: '退款' },
@@ -147,7 +148,7 @@
  } else if (appType === 'pc') {
    opentypes = opentypes.filter(item => item.value !== 'tab')
    funTypes = [
      { value: 'refund', text: '退款' },
      { value: 'print', text: '标签打印' },
      { value: 'changeuser', text: '切换用户' },
    ]
    pageTemps = [
@@ -311,6 +312,7 @@
      key: 'procMode',
      label: '参数处理',
      initVal: card.procMode || (card.innerFunc ? 'inner' : 'system'),
      tooltip: '当返回值存在 mk_ex_invoke 且值为 false 时,不会调用外部接口。',
      required: true,
      options: [{
        value: 'system',
@@ -1211,6 +1213,7 @@
      key: 'procMode',
      label: '参数处理',
      initVal: card.procMode || (card.innerFunc ? 'inner' : 'system'),
      tooltip: '当返回值存在 mk_ex_invoke 且值为 false 时,不会调用外部接口。',
      required: true,
      options: [{
        value: 'system',
src/menu/components/share/searchcomponent/index.jsx
@@ -153,7 +153,6 @@
    this.searchFormRef.handleConfirm().then(res => {
      let fieldrepet = false // 字段重复
      let labelrepet = false // 提示文字重复
      _searchlist = _searchlist.filter(item => !item.origin || item.uuid === res.uuid) // 去除系统项
@@ -181,8 +180,6 @@
          if (setFields.length < itemFields.length + resFields.length && (res.type !== 'date' || item.type !== 'date')) {
            fieldrepet = true
          } else if (item.label === res.label) {
            labelrepet = true
          }
        }
@@ -197,13 +194,6 @@
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 5
        })
        return
      } else if (labelrepet) {
        notification.warning({
          top: 92,
          message: '名称已存在!',
          duration: 5
        })
        return
src/menu/components/table/base-table/columns/index.jsx
@@ -3,7 +3,7 @@
import { is, fromJS } from 'immutable'
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
import { Table, Popover, Modal, message, notification } from 'antd'
import { PlusOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
import { PlusOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined, InfoOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -68,7 +68,7 @@
              }
              <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
              {column && column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column && column.type === 'custom' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              {column && (column.type === 'custom' || column.type === 'action') ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            </div>
@@ -140,6 +140,34 @@
  }))(HeaderCol),
)
class HeaderEmptyCol extends Component {
  render() {
    const { connectDragSource, connectDropTarget } = this.props
    return connectDragSource(
      connectDropTarget(<div style={{border: '1px solid #e8e8e8', textAlign: 'center', height: '100px', lineHeight: '100px', color: '#bcbcbc'}}>请添加显示列</div>)
    )
  }
}
const ColEmptyTarget = {
  drop(props, monitor) {
    const item = monitor.getItem()
    if (item.$init) {
      props.dropCol(item, 0)
    }
  }
}
const DragableEmptyCol = DropTarget('col', ColEmptyTarget, connect => ({
  connectDropTarget: connect.dropTarget()
}))(
  DragSource('col', rowSource, connect => ({
    connectDragSource: connect.dragSource(),
  }))(HeaderEmptyCol)
)
class EditableColumnCell extends Component {
  updateCard = (vals, btn) => {
    const { column } = this.props
@@ -167,7 +195,7 @@
      )
    } else if (column && column.type === 'action') {
      return (
        <td style={{padding: '0 5px', textAlign: column.Align}} className={'action-column ' + className}>
        <td style={{padding: 0, textAlign: column.Align, ...(column.style || {})}} className={'action-column ' + className}>
          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
        </td>
      )
@@ -396,8 +424,10 @@
    if (col.type === 'colspan') {
      col.subcols = card.subcols || []
    } else if (col.type === 'custom') {
      col.style = card.style || {}
      col.elements = card.type === 'custom' ? (card.elements || []) : []
    } else if (col.type === 'action') {
      col.style = card.style || {}
      col.elements = card.type === 'action' ? (card.elements || []) : []
    }
@@ -560,6 +590,27 @@
    })
  }
  copyFields = () => {
    const { config } = this.props
    let m = []
    let n = []
    config.columns.forEach(col => {
      m.push(`${col.field}(${col.label})`)
      n.push(col.field)
    })
    let oInput = document.createElement('input')
    oInput.value = `/*${m.join(',')}*/
      ${n.join(',')}`
    document.body.appendChild(oInput)
    oInput.select()
    document.execCommand('Copy')
    document.body.removeChild(oInput)
    message.success('复制成功。')
  }
  componentDidMount () {
    MKEmitter.addListener('plusColumns', this.plusColumns)
  }
@@ -599,11 +650,12 @@
    }
    return (
      <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType} ${config.wrap.mode || ''}`} id={tableId}>
      <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType} ${config.wrap.mode || ''} table-vertical-${config.wrap.vertical || ''}`} id={tableId}>
        <div className="col-control">
          <FieldsComponent config={config} type="columns" />
          <CopyOutlined title="复制显示列" onClick={this.copycolumn} />
          <MarkColumn columns={fields} type="line" marks={lineMarks} onSubmit={this.updateLineMarks} />
          <InfoOutlined title="复制字段" style={{color: 'orange'}} onClick={this.copyFields}/>
        </div>
        <DndProvider>
          {groups ? groups.map((group, i) => {
@@ -626,7 +678,7 @@
              } : false}
            />
          }) :
          <Table
          (columns.length === 0 ? <DragableEmptyCol dropCol={this.dropCol}/> : <Table
            rowKey="uuid"
            size={config.wrap.size || 'middle'}
            bordered={config.wrap.bordered !== 'false'}
@@ -642,7 +694,7 @@
              total: 58,
              showTotal: (total, range) => `${range[0]}-${range[1]} 共 ${total} 条`
            }}
          />}
          />)}
        </DndProvider>
        <EditColumn column={card} fields={fields} submitCol={this.submitCol} cancelCol={this.cancelCol}/>
      </div>
src/menu/components/table/base-table/columns/index.scss
@@ -105,16 +105,17 @@
  }
  table tr {
    th .ant-table-column-title {
      // color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
    }
    td {
      color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
    }
  }
  table tbody tr {
    color: var(--mk-table-color);
  }
}
.normal-table-columns.false {
  .ant-pagination {
src/menu/components/table/base-table/index.jsx
@@ -99,6 +99,39 @@
    MKEmitter.removeListener('completeSave', this.completeSave)
  }
  // updateFix = (card) => {
  //   let fixs = {}
  //   card.cols.forEach(col => {
  //     if (!col.field) return
  //     if (col.postfix || col.prefix) {
  //       fixs[col.field] = col
  //     }
  //   })
  //   card.cols.forEach(col => {
  //     if (col.type === 'custom') {
  //       col.elements.forEach(cell => {
  //         if (cell.datatype === 'dynamic') {
  //           cell.height = ''
  //           cell.innerHeight = 'auto'
  //           if (fixs[cell.field]) {
  //             if (!cell.prefix && fixs[cell.field].prefix) {
  //               cell.prefix = fixs[cell.field].prefix
  //             }
  //             if (!cell.postfix && fixs[cell.field].postfix) {
  //               cell.postfix = fixs[cell.field].postfix
  //             }
  //           }
  //         }
  //       })
  //     }
  //   })
  //   return card
  // }
  completeSave = () => {
    const { card } = this.state
src/menu/components/table/base-table/options.jsx
@@ -100,6 +100,30 @@
      required: false
    },
    {
      type: 'radio',
      field: 'vertical',
      label: '垂直对齐',
      initval: wrap.vertical || 'middle',
      tooltip: '单元格的垂直对齐方式。',
      required: false,
      options: [
        {value: 'top', label: '向上'},
        {value: 'middle', label: '居中'},
        {value: 'bottom', label: '向下'},
      ]
    },
    {
      type: 'number',
      field: 'btnlimit',
      label: '按钮限制',
      initval: wrap.btnlimit || '',
      tooltip: '按钮数量限制,超出的按钮会在更多中下拉显示,注:更多中的按钮不要绑定双击事件。',
      min: 3,
      max: 3000,
      precision: 0,
      required: false
    },
    {
      type: 'number',
      field: 'height',
      label: '表格高度',
src/menu/components/table/edit-table/columns/index.jsx
@@ -75,7 +75,7 @@
            <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
            {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
            {column.type === 'action' ? <PasteComponent options={['action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
            {column.type === 'custom' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
            {column.type === 'custom' || column.type === 'action' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
            <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
            {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
          </div>
@@ -148,7 +148,7 @@
      )
    } else if (column && column.type === 'action') {
      return (
        <td style={{padding: '0 5px', textAlign: column.Align}} className={'action-column ' + className}>
        <td style={{padding: 0, textAlign: column.Align, ...(column.style || {})}} className={'action-column ' + className}>
          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
        </td>
      )
@@ -359,8 +359,10 @@
    const { card } = this.state
    
    if (col.type === 'custom') {
      col.style = card.style || {}
      col.elements = card.type === 'custom' ? (card.elements || []) : []
    } else if (col.type === 'action') {
      col.style = card.style || {}
      col.elements = card.type === 'action' ? (card.elements || []) : []
    }
@@ -592,7 +594,7 @@
    })
    return (
      <div className={`edit-table-columns ${config.setting.laypage} ${config.wrap.mode || ''}`} id={tableId}>
      <div className={`edit-table-columns ${config.setting.laypage} ${config.wrap.mode || ''} table-vertical-${config.wrap.vertical || ''}`} id={tableId}>
        <div className="col-control">
          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
            <div className="mk-popover-control">
src/menu/components/table/edit-table/columns/index.scss
@@ -32,6 +32,7 @@
        .col-copy {
          margin-bottom: 0;
          display: inline-block;
          color: inherit;
          .ant-typography-copy {
            position: absolute;
            left: 2px;
@@ -132,16 +133,17 @@
  }
  table tr {
    th .ant-table-column-title, th .ant-table-column-title > span {
      // color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
    }
    td {
      color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
    }
  }
  table tbody tr {
    color: var(--mk-table-color);
  }
}
.edit-table-columns.false {
  .ant-pagination {
src/menu/components/table/edit-table/options.jsx
@@ -225,6 +225,19 @@
      tooltip: '默认值 #e8e8e8。',
      required: false
    },
    {
      type: 'radio',
      field: 'vertical',
      label: '垂直对齐',
      initval: wrap.vertical || 'middle',
      tooltip: '单元格的垂直对齐方式。',
      required: false,
      options: [
        {value: 'top', label: '向上'},
        {value: 'middle', label: '居中'},
        {value: 'bottom', label: '向下'},
      ]
    },
    // {
    //   type: 'color',
    //   field: 'color',
src/menu/components/table/normal-table/columns/index.jsx
@@ -70,7 +70,7 @@
              <EditOutlined className="edit" title="编辑" onClick={() => this.props.editColumn(column)} />
              {column && column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column && column.type === 'action' ? <PasteComponent options={['action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
              {column && column.type === 'custom' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              {column && (column.type === 'custom' || column.type === 'action') ? <FontColorsOutlined className="style" title="调整样式" onClick={() => this.props.changeStyle(column)}/> : null}
              <DeleteOutlined className="close" title="删除" onClick={this.deleteCol} />
              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
            </div>
@@ -170,7 +170,7 @@
      )
    } else if (column && column.type === 'action') {
      return (
        <td style={{padding: '0 5px', textAlign: column.Align}} className={'action-column ' + className}>
        <td style={{padding: 0, textAlign: column.Align, ...(column.style || {})}} className={'action-column ' + className}>
          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
        </td>
      )
@@ -400,8 +400,10 @@
    if (col.type === 'colspan') {
      col.subcols = card.subcols || []
    } else if (col.type === 'custom') {
      col.style = card.style || {}
      col.elements = card.type === 'custom' ? (card.elements || []) : []
    } else if (col.type === 'action') {
      col.style = card.style || {}
      col.elements = card.type === 'action' ? (card.elements || []) : []
    }
@@ -605,7 +607,7 @@
    const columns = this.handlecolumns(this.state.columns, fields, config)
    return (
      <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType} ${config.wrap.mode || ''}`} id={tableId}>
      <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType} ${config.wrap.mode || ''} table-vertical-${config.wrap.vertical || ''}`} id={tableId}>
        <div className="col-control">
          <CopyOutlined title="复制显示列" onClick={this.copycolumn} />
          <MarkColumn columns={fields} type="line" marks={lineMarks} onSubmit={this.updateLineMarks} />
src/menu/components/table/normal-table/columns/index.scss
@@ -23,6 +23,7 @@
        .col-copy {
          margin-bottom: 0;
          display: inline-block;
          color: inherit;
          .ant-typography-copy {
            position: absolute;
            left: 2px;
@@ -124,16 +125,17 @@
  }
  table tr {
    th .ant-table-column-title {
      // color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
    }
    td {
      color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
    }
  }
  table tbody tr {
    color: var(--mk-table-color);
  }
}
.normal-table-columns.false {
  .ant-pagination {
src/menu/components/table/normal-table/options.jsx
@@ -161,6 +161,19 @@
      tooltip: '默认值 #e8e8e8。',
      required: false
    },
    {
      type: 'radio',
      field: 'vertical',
      label: '垂直对齐',
      initval: wrap.vertical || 'middle',
      tooltip: '单元格的垂直对齐方式。',
      required: false,
      options: [
        {value: 'top', label: '向上'},
        {value: 'middle', label: '居中'},
        {value: 'bottom', label: '向下'},
      ]
    },
    // {
    //   type: 'color',
    //   field: 'color',
@@ -192,6 +205,18 @@
    //   forbid: appType === 'mob'
    // },
    {
      type: 'number',
      field: 'btnlimit',
      label: '按钮限制',
      initval: wrap.btnlimit || '',
      tooltip: '按钮数量限制,超出的按钮会在更多中下拉显示,注:更多中的按钮不要绑定双击事件。',
      min: 3,
      max: 3000,
      precision: 0,
      required: false,
      forbid: appType !== ''
    },
    {
      type: 'select',
      field: 'doubleClick',
      label: '双击事件',
src/menu/components/timeline/normal-timeline/index.scss
@@ -10,17 +10,8 @@
  .model-menu-card-cell-list {
    flex: 1;
  }
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/menu/menushell/card.jsx
@@ -28,6 +28,7 @@
const CustomChart = asyncComponent(() => import('@/menu/components/chart/chart-custom'))
const Timeline = asyncComponent(() => import('@/menu/components/timeline/normal-timeline'))
const Voucher = asyncComponent(() => import('@/menu/components/module/voucher'))
const Account = asyncComponent(() => import('@/menu/components/module/account'))
const Iframe = asyncComponent(() => import('@/menu/components/iframe'))
const AntvG6 = asyncComponent(() => import('@/menu/components/chart/antv-G6'))
@@ -121,6 +122,8 @@
      return (<AntvG6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'module' && card.subtype === 'voucher') {
      return (<Voucher card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'module' && card.subtype === 'account') {
      return (<Account card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
  return (
src/menu/menushell/index.jsx
@@ -100,6 +100,7 @@
        timeline: '时间轴',
        antvG6: '树图',
        iframe: 'iframe',
        module: '模块',
        card: '卡片'
      }
      let i = 1
src/menu/modulecell/index.jsx
@@ -22,6 +22,7 @@
          { value: 'qrcode', text: '二维码', type: 'action', class: 'element', $init: true},
          { value: 'currentDate', text: '当前时间', type: 'action', class: 'element', $init: true},
          { value: 'formula', text: '公式', type: 'action', class: 'element', $init: true},
          { value: 'color', text: '颜色', type: 'action', class: 'element', $init: true},
          { value: 'sequence', text: '序号', type: 'action', class: 'element', $init: true }
        ]
      },
src/menu/modulesource/option.jsx
@@ -30,7 +30,8 @@
import mindmap from '@/assets/mobimg/mindmap.png'
import indent from '@/assets/mobimg/indent.jfif'
import kapmap from '@/assets/mobimg/kapmap.jfif'
// import Voucher from '@/assets/mobimg/voucher.jpg'
import Voucher from '@/assets/mobimg/voucher.png'
import Account from '@/assets/mobimg/account.png'
// 组件配置信息
export const menuOptions = [
@@ -68,5 +69,6 @@
  { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '自定义', width: 24 },
  { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '分组', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: Iframe, component: 'iframe', subtype: 'iframe', title: 'iframe', width: 24, forbid: ['billPrint'] },
  // { type: 'menu', url: Voucher, component: 'module', subtype: 'voucher', title: '凭证', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: Account, component: 'module', subtype: 'account', title: '账套', width: 24, forbid: ['billPrint'] },
  { type: 'menu', url: Voucher, component: 'module', subtype: 'voucher', title: '凭证', width: 24, forbid: ['billPrint'] },
]
src/menu/tablenodes/index.jsx
@@ -173,6 +173,7 @@
        if (result.tb_list) {
          result.tb_list.sort((a, b) => a.tbname > b.tbname ? 1 : -1)
          let length = result.tb_list.length
          result.tb_list.forEach((item, i) => {
            let cell = {
              label: item.tbname,
@@ -180,6 +181,8 @@
              id: 'table' + i,
              direction: 'right',
              color: '#1890ff',
              collapsed: false,
              collable: true,
              children: []
            }
@@ -198,10 +201,17 @@
                    id: item.tbname + 'menu' + i,
                    direction: 'right',
                    color: '#1890ff',
                    type: 'dice-mind-map-leaf',
                    param: _param
                  })
                }
              })
            }
            if (cell.children.length > 5 && length > 1) {
              cell.collapsed = true
            } else if (cell.children.length === 0) {
              cell.collable = false
            }
            data.children.push(cell)
@@ -284,12 +294,12 @@
          const stroke = cfg.style.stroke || '#096dd9';
    
          return `
          <group>
            <rect draggable="true" style={{width: ${width}, height: 30, stroke: ${stroke}, radius: 4}} keyshape>
              <text style={{ fontSize: 14, marginLeft: 6, marginTop: 6 }}>${cfg.label}</text>
            </rect>
          </group>
        `;
            <group>
              <rect draggable="true" style={{width: ${width}, height: 30, stroke: ${stroke}, radius: 4}} keyshape>
                <text style={{ fontSize: 14, marginLeft: 6, marginTop: 6 }}>${cfg.label}</text>
              </rect>
            </group>
          `;
        },
        getAnchorPoints() {
          return [
@@ -308,13 +318,13 @@
          const color = cfg.color;
    
          return `
          <group>
            <rect draggable="true" style={{width: ${width}, height: 26, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, fill: 'transparent' }}>
              <text style={{ fontSize: 12, fill: ${cfg.fontcolor ? cfg.fontcolor : 'black'}, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, marginLeft: 12, marginTop: 6 }}>${cfg.label}</text>
            </rect>
            <rect style={{ fill: ${color}, width: ${width}, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, height: 2, x: 0, y: 32 }} />
          </group>
        `;
            <group>
              <rect draggable="true" style={{width: ${width}, height: 26, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, fill: 'transparent' }}>
                <text style={{ fontSize: 12, fill: ${cfg.fontcolor ? cfg.fontcolor : 'black'}, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, marginLeft: 12, marginTop: 6 }}>${cfg.label} ${cfg.collable ? '+' : ''}</text>
              </rect>
              <rect style={{ fill: ${color}, width: ${width}, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, height: 2, x: 0, y: 32 }} />
            </group>
          `;
        },
        getAnchorPoints() {
          return [
@@ -406,7 +416,7 @@
          data.color = color;
        }
    
        if (d.children) {
        if (d.children && !d.collapsed) {
          data.children = d.children.map((child) => changeData(child, level + 1, data.color));
        }
        return data;
@@ -447,9 +457,21 @@
          lineWidth: 2,
        },
      },
      minZoom: 0.5,
      minZoom: 0.3,
      modes: {
        default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap'],
        default: [
          {
            type: 'collapse-expand',
            trigger: 'click',
            shouldBegin: (e, self) => {
              if (e.item && e.item.getModel().collable) return true;
              return false;
            },
          },
          'drag-canvas',
          'zoom-canvas',
          'dice-mindmap'
        ],
      },
    });
    
@@ -483,6 +505,7 @@
          </div>
          <div className="footer">
            <Button key="cancel" onClick={() => { this.setState({ visible: false })}}>关闭</Button>
            <span className="tip">注:点击表名可展开/收起菜单</span>
          </div>
        </Modal>
      </div>
src/menu/tablenodes/index.scss
@@ -42,7 +42,16 @@
  }
  .footer {
    position: relative;
    text-align: center;
    .tip {
      position: absolute;
      font-size: 12px;
      color: #1890ff;
      right: 10px;
      top: 20px;
    }
  }
  .tb-search {
    position: absolute;
src/mob/components/menubar/common-menubar/index.scss
@@ -6,17 +6,7 @@
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 20px;
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  >.anticon-tool {
    position: absolute;
    z-index: 2;
src/mob/components/menubar/normal-menubar/index.scss
@@ -7,16 +7,6 @@
  background-size: cover;
  min-height: 20px;
  
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  >.anticon-tool {
    position: absolute;
    z-index: 2;
src/mob/header/index.jsx
@@ -1,5 +1,4 @@
import React, {Component} from 'react'
import { Radio } from 'antd'
import avatar from '@/assets/img/avatar.jpg'
import MainLogo from '@/assets/img/main-logo.png'
@@ -8,26 +7,13 @@
class MobHeader extends Component {
  state = {
    avatar: sessionStorage.getItem('CloudAvatar') || avatar,
    userName: sessionStorage.getItem('CloudUserName'),
    typename: sessionStorage.getItem('typename')
  }
  changeView = (e) => {
    let val = e.target.value
    this.props.changeView(val)
    userName: sessionStorage.getItem('CloudUserName')
  }
  render () {
    const { typename } = this.state
    return (
      <header className="mob-header-container">
        <div className="header-logo"><img src={MainLogo} alt=""/></div>
        {typename === 'pad' ? <div className="change-view">
          <Radio.Group defaultValue="vertical" onChange={this.changeView}>
            <Radio value="vertical">竖屏</Radio>
            <Radio value="horizontal">横屏</Radio>
          </Radio.Group>
        </div> : null}
        <div className="header-user">
          <img src={this.state.avatar} alt=""/>
          <span>
src/mob/mobshell/index.jsx
@@ -143,6 +143,7 @@
        timeline: '时间轴',
        officialAccount: '关注公众号',
        sharecode: '分享码',
        iframe: 'iframe',
        login: '登录'
      }
      let i = 1
src/pc/components/login/normal-login/index.scss
@@ -8,18 +8,8 @@
  background-size: cover;
  min-height: 100px;
  max-width: 100%;
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/pc/components/login/normal-login/loginform.jsx
@@ -139,9 +139,14 @@
    const { wrap } = this.props
    const { activeWay, loginWays, scanWay } = this.state
    let style = {}
    if (wrap.borderRadius) {
      style.borderRadius = wrap.borderRadius
    }
    return (
      <Form className="login-edit-form">
        <div className="login-way-title">{activeWay.label}</div>
        {wrap.topTip !== 'hidden' ? <div className="login-way-title">{activeWay.label}</div> : null}
        {scanWay && activeWay.type !== 'app_scan' ? <div className="scan-icon" onClick={() => this.onChangeTab(scanWay)}><QrcodeOutlined /></div> : null}
        {activeWay.type === 'uname_pwd' ? <div className={'form-item-wrap ' + (activeWay.shortcut === 'none' ? 'no-short' : '')}>
          <Form.Item>
@@ -161,7 +166,7 @@
            <Checkbox>自动登录</Checkbox>
          </Form.Item> : null}
          <Form.Item className="btn-login">
            <Button type="primary" onDoubleClick={() => this.changeMenu()} className="login-form-button">
            <Button type="primary" style={style} onDoubleClick={() => this.changeMenu()} className="login-form-button">
              登录
            </Button>
          </Form.Item>
@@ -185,7 +190,7 @@
            />
          </Form.Item>
          <Form.Item className="btn-login">
            <Button type="primary" onDoubleClick={() => this.changeMenu()} className="login-form-button">
            <Button type="primary" style={style} onDoubleClick={() => this.changeMenu()} className="login-form-button">
              登录
            </Button>
          </Form.Item>
src/pc/components/login/normal-login/options.jsx
@@ -81,6 +81,27 @@
    },
    {
      type: 'radio',
      field: 'topTip',
      label: '顶部提示',
      initval: wrap.topTip || 'show',
      tooltip: '登录或注册方式提示信息。',
      required: false,
      options: [
        {value: 'show', label: '显示'},
        {value: 'hidden', label: '隐藏'}
      ]
    },
    {
      type: 'styleInput',
      field: 'borderRadius',
      label: '圆角',
      initval: wrap.borderRadius || '',
      tooltip: '登录或注册时,确定按钮的圆角。',
      required: false,
      options: ['px', 'vh', 'vw', '%']
    },
    {
      type: 'radio',
      field: 'classify',
      label: '组件类型',
      initval: wrap.classify || 'login',
src/pc/components/login/normal-login/signform.jsx
@@ -133,9 +133,14 @@
    const { wrap } = this.props
    const { activeWay, signWays, appType } = this.state
    let style = {}
    if (wrap.borderRadius) {
      style.borderRadius = wrap.borderRadius
    }
    return (
      <Form className="login-edit-form">
        {appType === 'pc' ? <div className="login-way-title">{activeWay.label}</div> : null}
        {appType === 'pc' && wrap.topTip !== 'hidden' ? <div className="login-way-title">{activeWay.label}</div> : null}
        {activeWay.type === 'uname_pwd' ? <div className="form-item-wrap">
          <Form.Item>
            <Input
@@ -151,7 +156,7 @@
            <Checkbox>{wrap.tip}</Checkbox>{wrap.groups.map((item, i) => (<span><span className="protocol" key={i}>《{item.label}》</span>{wrap.groups.length > i + 1 ? (wrap.groups.length > i + 2 ? '、' : '和') : null}</span>))}
          </div> : null}
          <Form.Item className="btn-login">
            <Button type="primary" onDoubleClick={() => this.changeMenu()} className="sign-form-button">
            <Button type="primary" style={style} onDoubleClick={() => this.changeMenu()} className="sign-form-button">
            注册
            </Button>
          </Form.Item>
@@ -178,7 +183,7 @@
            <Checkbox>{wrap.tip}</Checkbox>{wrap.groups.map((item, i) => (<span><span className="protocol" key={i}>《{item.label}》</span>{wrap.groups.length > i + 1 ? (wrap.groups.length > i + 2 ? '、' : '和') : null}</span>))}
          </div> : null}
          <Form.Item className="btn-login">
            <Button type="primary" onDoubleClick={() => this.changeMenu()} className="sign-form-button">
            <Button type="primary" style={style} onDoubleClick={() => this.changeMenu()} className="sign-form-button">
              注册
            </Button>
          </Form.Item>
src/pc/components/navbar/normal-navbar/index.scss
@@ -58,17 +58,8 @@
      }
    }
  }
  .card-control {
    position: absolute;
    top: 0px;
    left: 0px;
    .anticon-tool {
      right: auto;
      left: 1px;
      padding: 1px;
    }
  }
  .anticon-tool {
  >.anticon-tool {
    position: absolute;
    z-index: 2;
    font-size: 16px;
src/pc/menushell/index.jsx
@@ -114,7 +114,8 @@
        balcony: '浮动卡',
        timeline: '时间轴',
        antvG6: '树图',
        login: '登录'
        login: '登录',
        iframe: 'iframe'
      }
      let i = 1
      
src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Col, Tooltip, notification, Typography } from 'antd'
import { Col, Tooltip, notification, Typography, message } from 'antd'
import moment from 'moment'
import Api from '@/api'
@@ -768,6 +768,51 @@
            </div>
          </Col>
        )
      } else if (card.eleType === 'color') {
        let color = ''
        if (card.datatype === 'static') {
          color = card.value
        } else {
          color = data[card.field] || ''
        }
        if (color === '' && card.noValue === 'hide') { // 空值隐藏
          return null
        }
        let _bgstyle = {backgroundColor: color}
        if (PicRadio[card.lenWidRadio]) {
          _bgstyle.paddingTop = PicRadio[card.lenWidRadio]
        } else {
          _bgstyle.paddingTop = '100%'
        }
        if (card.copyable === 'true') {
          _bgstyle.cursor = 'pointer'
        }
        contents.push(
          <Col key={card.uuid} style={_style_} span={card.width}>
            <div className="ant-mk-color" style={card.style}>
              <div style={_bgstyle} onClick={(e) => {
                if (card.copyable === 'true') {
                  e.stopPropagation()
                  let oInput = document.createElement('input')
                  oInput.value = color
                  document.body.appendChild(oInput)
                  oInput.select()
                  document.execCommand('Copy')
                  document.body.removeChild(oInput)
                  message.success('复制成功。')
                }
              }}></div>
            </div>
          </Col>
        )
      } else if (card.eleType === 'button') {
        let _disabled = data.$disabled
        if (card.control === 'hidden') {
@@ -896,6 +941,7 @@
                  BData={data.$$BData || ''}
                  disabled={_disabled}
                  setting={cards.setting}
                  columns={cards.columns}
                  selectedData={_data}
                />
              </Col>
src/tabviews/custom/components/card/cardcellList/index.scss
@@ -77,6 +77,11 @@
  .line10 {
    -webkit-line-clamp: 10;
  }
  .ant-col:not(.mk-cell-btn) > div {
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
  }
  .mk-cell-btn {
    > div {width: 100%;max-width: 100%;}
    button:not(.ant-switch) {
@@ -158,6 +163,9 @@
    vertical-align: top;
    line-height: inherit;
  }
  .ant-mk-color {
    overflow: hidden;
  }
  .ant-switch-large {
    min-width: 60px;
    height: 30px;
src/tabviews/custom/components/card/prop-card/index.jsx
@@ -397,12 +397,18 @@
        data: _data,
        loading: false
      }, () => {
        if (selected !== 'false') {
          this.checkTopLine()
        if (config.wrap.goback === 'true' && _data.$$empty) {
          this.timer && this.timer.stop()
          MKEmitter.emit('closeTabView', config.$pageId)
        } else {
          this.transferLine()
          if (selected !== 'false') {
            this.checkTopLine()
          } else {
            this.transferLine()
          }
          this.autoExec()
        }
        this.autoExec()
      })
      if (config.timer && config.clearField) {
src/tabviews/custom/components/chart/antv-G6/index.jsx
@@ -60,29 +60,7 @@
  },
  'single-node',
)
G6.registerNode(
  'dice-mind-map-sub', {
    jsx: (cfg) => {
      const width = Util.getTextSize(cfg.label, 14)[0] + 24
      return `
        <group>
          <rect style={{width: ${width}, height: 22, cursor: pointer}}>
            <text style={{ fontSize: 14, fill: ${cfg.selected ? systemColor : '#000000'}, marginLeft: 12, marginTop: 6, cursor: pointer }}>${cfg.label}</text>
          </rect>
          <rect style={{ fill: ${cfg.color}, width: ${width}, height: 2, x: 0, y: 22, cursor: pointer }} />
        </group>
      `
    },
    getAnchorPoints() {
      return [
        [0, 0.965],
        [1, 0.965]
      ]
    }
  },
  'single-node',
)
G6.registerNode(
  'dice-mind-map-leaf', {
    jsx: (cfg) => {
@@ -139,38 +117,6 @@
    ev.preventDefault()
  }
})
const dataMapTransform = (data) => {
  const changeData = (d, level = 0, color) => {
    const data = { ...d }
    switch (level) {
      case 0:
        data.type = 'dice-mind-map-root'
        break
      case 1:
        data.type = 'dice-mind-map-sub'
        break
      default:
        data.type = 'dice-mind-map-leaf'
        break
    }
    if (color) {
      data.color = color
    }
    if (level === 1 && !d.direction) {
      data.direction = 'right'
    }
    if (d.children) {
      data.children = d.children.map((child) => changeData(child, level + 1, data.color))
    }
    return data
  }
  return changeData(data)
}
// 缩进文件树
G6.registerNode('indentedRoot', {
@@ -1223,6 +1169,8 @@
    root.children = root.children || []
    if (plot.subtype === 'mindmap') {
      root.type = 'dice-mind-map-root'
      if (plot.dirField) {
        root.children = root.children.map(item => {
          item.direction = item[plot.dirField] === plot.dirSign ? 'left' : 'right'
@@ -1235,9 +1183,24 @@
        if (item.direction === 'left') {
          item.color = plot.leftColor || '#26C281'
        } else {
          item.direction = 'right'
          item.color = plot.nodeColor || '#1890ff'
        }
      })
      const collapse = (item) => {
        if (!item.children) return
        item.children.forEach(cell => {
          cell.collapsed = plot.collapsed === 'true'
          cell.direction = cell.direction || 'right'
          cell.type = 'dice-mind-map-leaf'
          cell.color = cell.color || item.color
          collapse(cell)
        })
      }
      collapse(root)
    } else if (plot.subtype === 'indentTree') {
      root.isRoot = true
      root.collapsed = false
@@ -1368,6 +1331,10 @@
    graph.data(data)
    graph.render()
    graph.fitView()
    if (plot.collapsed === 'true') {
      graph.zoomTo(1, { x: 0, y: plot.height / 2 })
    }
  }
  indentrender = () => {
@@ -1437,10 +1404,16 @@
  ponitrender = () => {
    const { config, plot, chartId } = this.state
    const data = this.getdata()
    const width = this.wrap.scrollWidth - 30
    let modes = ['drag-canvas', 'zoom-canvas', config.uuid]
    if (plot.collapsed === 'true') {
      modes = [{ type: 'collapse-expand' }, 'drag-canvas', 'zoom-canvas', config.uuid]
    }
    const tree = new G6.TreeGraph({
      container: chartId,
      width: this.wrap.scrollWidth - 30,
      width: width,
      height: plot.height,
      fitView: true,
      layout: {
@@ -1472,13 +1445,19 @@
      },
      minZoom: 0.5,
      modes: {
        default: ['drag-canvas', 'zoom-canvas', config.uuid]
        default: modes
      }
    })
    tree.data(dataMapTransform(data))
    tree.data(data)
    tree.render()
    if (plot.collapsed === 'true' && plot.dirField) {
      tree.zoomTo(1, { x: width / 2, y: plot.height / 2 })
    } else if (plot.collapsed === 'true') {
      tree.zoomTo(1, { x: 0, y: plot.height / 2 })
    }
  }
  handleClick = (data = null) => {
src/tabviews/custom/components/iframe/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Input, Modal, notification, Empty } from 'antd'
import { Input, Modal, notification, Empty, Spin } from 'antd'
import Api from '@/api'
import UtilsDM from '@/utils/utils-datamanage.js'
@@ -82,8 +82,17 @@
  }
  componentDidMount () {
    const { config } = this.state
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    if (config.wrap.linkType === 'input' && config.wrap.focus !== 'false') {
      setTimeout(() => {
        let node = document.getElementById(config.uuid)
        node && node.select && node.select()
      }, 200)
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -183,13 +192,9 @@
      this.setState({
        linkUrl: _data[config.wrap.linkField] || '',
        data: _data,
        loading: false
        data: _data
      })
    } else {
      this.setState({
        loading: false
      })
      if (result.ErrCode === 'N') {
        Modal.error({
          title: result.message,
@@ -215,30 +220,43 @@
    }
    if (submit) {
      this.setState({linkUrl: val}, () => {
        let node = document.getElementById(this.state.config.uuid)
        node && node.select && node.select()
      this.setState({linkUrl: '', loading: true}, () => {
        this.setState({linkUrl: val})
      })
      setTimeout(() => {
        this.setState({loading: false}, () => {
          let node = document.getElementById(this.state.config.uuid)
          node && node.select && node.select()
        })
      }, 500)
    }
  }
  enterUrl = (val) => {
    this.setState({linkUrl: val}, () => {
      let node = document.getElementById(this.state.config.uuid)
      node && node.select && node.select()
    this.setState({linkUrl: '', loading: true}, () => {
      this.setState({linkUrl: val})
    })
    setTimeout(() => {
      this.setState({loading: false}, () => {
        let node = document.getElementById(this.state.config.uuid)
        node && node.select && node.select()
      })
    }, 500)
  }
  render() {
    const { config, linkUrl } = this.state
    const { config, linkUrl, loading } = this.state
    return (
      <div className="menu-iframe-box" style={config.style}>
        {config.wrap.title || config.wrap.linkType === 'input' ? <div className="iframe-header" style={config.headerStyle}>
          <span className="title">{config.wrap.title}</span>
          {config.wrap.linkType === 'input' ? <Search id={config.uuid} placeholder="请输入地址" onChange={this.inputUrl} onSearch={this.enterUrl} enterButton="确定"/> : null}
          {config.wrap.linkType === 'input' ? <Search id={config.uuid} disabled={loading} placeholder="请输入地址" onChange={this.inputUrl} onSearch={this.enterUrl} enterButton="确定"/> : null}
        </div> : null}
        <div className="iframe-wrap" style={{height: config.wrap.height}}>
          {loading ? <div className="mask"><Spin size="large" /></div> : null}
          {linkUrl ? <iframe title="mk" className="iframe" src={linkUrl} frameBorder="0"></iframe> : <Empty description={false}/>}
        </div>
      </div>
src/tabviews/custom/components/iframe/index.scss
@@ -33,9 +33,15 @@
    .ant-input-search {
      margin-top: 5px;
      width: 40%;
      max-width: 400px;
      width: 65%;
      float: right;
      .ant-btn[disabled] {
        background-color: var(--mk-sys-color)!important;
        border-color: var(--mk-sys-color)!important;
        color: #ffffff!important;
        opacity: 0.5;
      }
    }
  }
@@ -57,5 +63,21 @@
      vertical-align: top;
      margin-top: 0px;
    }
    .mask {
      position: absolute;
      width: 100%;
      height: 100%;
      left: 0px;
      top: 0px;
      background: #ffffff;
      z-index: 1;
      .ant-spin {
        position: absolute;
        left: calc(50% - 16px);
        top: calc(50% - 16px);
      }
    }
  }
}
src/tabviews/custom/components/module/account/index.jsx
New file
@@ -0,0 +1,148 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { notification, Select, Divider } from 'antd'
import { PlusOutlined } from '@ant-design/icons'
import Api from '@/api'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const { Option } = Select
class AccountModule extends Component {
  static propTpyes = {
    config: PropTypes.object
  }
  state = {
    activeItem: null,
    books: []
  }
  componentDidMount () {
    this.loadData()
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  loadData = () => {
    let param = {
      func: 's_get_fcc_book_data'
    }
    Api.genericInterface(param).then(res => {
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        return
      }
      let books = res.book || []
      let activeItem = null
      let map = new Map()
      books = books.filter(item => {
        if (!item.id) return false
        if (map.has(item.id)) return false
        map.set(item.id, true)
        if (item.selected === 'true' && !activeItem) {
          activeItem = item
        }
        if (item.months) {
          item.date = item.months.replace('-', '年') + '月'
        }
        return true
      })
      if (!activeItem && books.length > 0) {
        activeItem = books[0]
      }
      this.setState({books, activeItem})
      if (activeItem) {
        MKEmitter.emit('resetSelectLine', this.props.config.uuid, activeItem.id, activeItem)
      }
    })
  }
  changeBook = (value) => {
    const { books } = this.state
    let activeItem = books.filter(item => item.id === value)[0]
    this.setState({activeItem})
    if (activeItem) {
      MKEmitter.emit('resetSelectLine', this.props.config.uuid, activeItem.id, activeItem)
    }
  }
  addBook = () => {
    const { config } = this.props
    let menuId = config.wrap.MenuID
    let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
    if (!menu && config.wrap.MenuNo) {
      menu = {
        MenuID: menuId,
        MenuName: config.wrap.MenuName,
        MenuNo: config.wrap.MenuNo || '',
        type: config.wrap.tabType
      }
    }
    let newtab = {
      ...menu,
      param: {}
    }
    MKEmitter.emit('modifyTabs', newtab, true)
  }
  render() {
    const { config } = this.props
    const { activeItem, books } = this.state
    return (
      <div className="menu-account-wrap" style={config.style}>
        {config.wrap.MenuID ? <Select value={activeItem ? activeItem.id : ''} placeholder="请选择账套" onChange={this.changeBook} dropdownRender={menu => (
          <div>
            {menu}
            <Divider style={{ margin: '4px 0' }} />
            <div className="mk-add-book" onMouseDown={this.addBook}>
              <PlusOutlined /> 点击新增账套
            </div>
          </div>
        )}>
          {books.map(item => (
            <Option key={item.id}>{item.account_name}</Option>
          ))}
        </Select> : <Select value={activeItem ? activeItem.id : ''} placeholder="请选择账套" onChange={this.changeBook}>
          {books.map(item => (
            <Option key={item.id}>{item.account_name}</Option>
          ))}
        </Select>}
        {activeItem ? <span className="date">{activeItem.date}</span> : null}
      </div>
    )
  }
}
export default AccountModule
src/tabviews/custom/components/module/account/index.scss
New file
@@ -0,0 +1,27 @@
.menu-account-wrap {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  color: #000000;
  .ant-select {
    min-width: 250px;
    max-width: 300px;
    color: #000000;
  }
  .date {
    margin-left: 15px;
  }
}
.mk-add-book {
  padding: 4px 8px 10px;
  cursor: pointer;
  text-align: center;
  color: var(--mk-sys-color);
}
src/tabviews/custom/components/module/voucher/index.jsx
@@ -1,11 +1,12 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Button, Select, Input, DatePicker } from 'antd'
// import { EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
import { Button, Select, Input, DatePicker, notification } from 'antd'
import moment from 'moment'
import Api from '@/api'
import asyncComponent from '@/utils/asyncComponent'
// import MKEmitter from '@/utils/events.js'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const VoucherTable = asyncComponent(() => import('./voucherTable'))
@@ -17,14 +18,13 @@
  state = {
    BID: '',
    type: '',
    config: null,
    loading: false,
    data: null,
    searchkey: null,
    disableAdd: true,
    disableSave: true,
    typeOptions: []
    disableAdd: false,
    disableSave: false,
    typeOptions: [],
    book: null
  }
  UNSAFE_componentWillMount () {
@@ -33,8 +33,8 @@
    let BID = ''
    let BData = ''
    if (config.setting.supModule) {
      BData = window.GLOB.CacheData.get(config.setting.supModule)
    if (config.wrap.supModule) {
      BData = window.GLOB.CacheData.get(config.wrap.supModule)
    } else {
      BData = window.GLOB.CacheData.get(config.$pageId)
    }
@@ -45,14 +45,14 @@
    this.setState({
      config: fromJS(config).toJS(),
      BID: BID || '',
      type: config.wrap.type
      book: window.GLOB.CacheData.get(config.wrap.supBook) || null
    }, () => {
      this.loadData()
    })
  }
  componentDidMount () {
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -66,10 +66,51 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
  }
  resetParentParam = (MenuID, id, data) => {
    const { config } = this.state
    if (config.wrap.supBook === MenuID) {
      this.setState({ book: data }, () => {
        this.loadData()
      })
      return
    }
    if (!config.wrap.supModule || config.wrap.supModule !== MenuID) return
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id, BData: data }, () => {
        this.loadData()
      })
    }
  }
  loadData = () => {
    const { book } = this.state
    if (!book) return
    let param = {
      func: 's_get_fcc_account_data',
      account_code: book.account_code || '',
      fcc_date: book.months ? book.months + '-01' : moment().format('YYYY-MM-DD')
    }
    Api.genericInterface(param).then(res => {
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        return
      }
    })
  }
  triggeradd = () => {
@@ -85,21 +126,21 @@
  }
  render() {
    const { config, disableSave, disableAdd, typeOptions, data, type } = this.state
    const { config, disableSave, disableAdd, typeOptions, data } = this.state
    return (
      <div className="menu-voucher-wrap" style={config.style}>
        <div className="voucher-header">
          <Button className="system-background header-btn" disabled={disableAdd} onClick={this.triggeradd}>新增</Button>
          <Button className="system-background header-btn" disabled={disableSave} onClick={this.triggersave}>保存</Button>
          <Button className="system-background header-btn" disabled={disableSave} onClick={this.triggerprint}>打印</Button>
          <Button className="add-background header-btn" disabled={disableAdd} onClick={this.triggeradd}>新增</Button>
          <Button className="add-background header-btn" disabled={disableSave} onClick={this.triggersave}>保存</Button>
          <Button className="print-background header-btn" disabled={disableSave} onClick={this.triggerprint}>打印</Button>
          <Button className="system-background header-btn" disabled={disableSave} onClick={this.triggerprint}>导入</Button>
          <Button className="system-background header-btn" disabled={disableSave} onClick={this.triggerprint}>导出</Button>
          <Button className="out-background header-btn" disabled={disableSave} onClick={this.triggerprint}>导出</Button>
        </div>
        {type === 'edit' ? <div className="voucher-body">
        {config.wrap.type === 'edit' ? <div className="voucher-body">
          <div className="pre-wrap">
            <div className="voucher-code">
              <Select>
              <Select dropdownClassName="mk-vcode-dropdown">
                {typeOptions.map(option =>
                  <Select.Option value={option.value}>{option.label}</Select.Option>
                )}
@@ -117,7 +158,7 @@
          </div>
          <VoucherTable config={config} data={data}/>
        </div> : null}
        {type === 'check' ? <div className="voucher-body">
        {config.wrap.type === 'check' ? <div className="voucher-body">
          <div className="pre-wrap">
            <div className="voucher-code">
              记 1 号
src/tabviews/custom/components/module/voucher/index.scss
@@ -51,6 +51,35 @@
      }
    }
  }
  .add-background {
    background: #26C281;
    border-color: #26C281;
    color: #ffffff;
  }
  .print-background {
    background-color: #8E44AD;
    border-color: #8E44AD;
    color: #ffffff;
  }
  .out-background {
    background-color: rgb(50, 197, 210);
    border-color: rgb(50, 197, 210);
    color: #ffffff;
  }
  .system-background {
    background: var(--mk-sys-color);
    border-color: var(--mk-sys-color);
    color: #ffffff;
  }
}
.mk-vcode-dropdown {
  .ant-empty-image svg {
    max-width: 100%;
  }
  .ant-empty-description {
    display: none;
  }
}
src/tabviews/custom/components/module/voucher/voucherTable/index.jsx
@@ -1,8 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Table, Modal, Input, InputNumber, notification, message } from 'antd'
// import { EditOutlined } from '@ant-design/icons'
import { Table, Modal, Input, InputNumber, notification, message, AutoComplete } from 'antd'
import Api from '@/api'
import Utils from '@/utils/utils.js'
@@ -120,6 +119,10 @@
    this.setState({value: val})
  }
  complete = (key, option) => {
    this.setState({value: option.props.value})
  }
  render() {
    let { col, record, className } = this.props
    const { editing } = this.state
@@ -135,7 +138,19 @@
        colSpan = 2
      } else {
        if (editing) {
          children = <Input.TextArea id={col.uuid + record.uuid} autoSize={false} defaultValue={val} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
          let options = ['现金', '发票']
          children = <AutoComplete
            dataSource={options.map((cell, i) => <AutoComplete.Option value={cell} key={i}>
              {cell}
            </AutoComplete.Option>)}
            filterOption={(input, option) => option.props.children.indexOf(input) > -1}
            onSelect={this.complete}
            defaultValue={val}
            onChange={(val) => this.onChange(val)}
            defaultOpen={true}
          >
            <Input.TextArea id={col.uuid + record.uuid} autoSize={false} defaultValue={val} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
          </AutoComplete>
        } else {
          children = <div className="content-wrap" onClick={this.focus}>{val}</div>
        }
src/tabviews/custom/components/module/voucher/voucherTable/index.scss
@@ -112,6 +112,18 @@
      }
    }
  }
  .ant-select-auto-complete {
    width: 100%;
    .ant-input {
      height: 60px;
      border-radius: 0;
      resize: none;
    }
    .ant-select-selection {
      height: 60px;
    }
  }
  .ant-input {
    height: 60px;
    border-radius: 0;
@@ -169,91 +181,3 @@
    }
  }
}
.edit-custom-table.editable {
  td {
    background-color: #ffffff!important;
  }
  td.pointer .mk-mask {
    display: block;
  }
  .mk-operation {
    display: none;
  }
  .ant-table-placeholder {
    display: none;
  }
}
.edit-custom-table:not(.fixed-height) {
  .ant-table-body::-webkit-scrollbar {
    width: 8px;
    height: 10px;
  }
  ::-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);
  }
  ::-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);
  }
}
.edit-custom-table.fixed-height {
  .ant-table-body {
    border-bottom: 1px solid rgba(0, 0, 0, .05);
    .ant-table-fixed {
      border-bottom: 0;
    }
  }
}
.edit-custom-table.hidden {
  thead {
    display: none;
  }
}
.edit-custom-table.ghost {
  .ant-table-thead > tr {
    > th {
      color: inherit;
      background: transparent;
      .ant-table-column-sorter .ant-table-column-sorter-inner {
        color: inherit;
      }
    }
    > th:hover {
      background: transparent;
    }
  }
  .ant-table-body {
    overflow-x: auto;
    tr {
      td {
        background: transparent!important;
      }
    }
    tr:hover td {
      background: transparent!important;
    }
  }
}
.image-scale-modal {
  width: 70vw;
  min-height: 80vh;
  top: 10vh;
  .ant-modal-body {
    min-height: calc(80vh - 110px);
    line-height: calc(80vh - 160px);
    text-align: center;
  }
  .ant-modal-footer {
    text-align: center;
    span {
      display: inline-block;
      color: #1890ff;
      padding: 5px 15px;
      cursor: pointer;
    }
  }
}
src/tabviews/custom/components/share/normalTable/index.jsx
@@ -385,7 +385,10 @@
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
    } else if (col.type === 'action') {
      style.padding = '0px 5px'
      style.padding = '0px'
      if (col.style) {
        style = {...style, ...col.style}
      }
      resProps.children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
@@ -960,7 +963,7 @@
    let height = setting.height || false
    return (
      <div className={`normal-custom-table ${setting.tableHeader || ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''}`} id={tableId}>
      <div className={`normal-custom-table ${setting.tableHeader || ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || ''}`} id={tableId}>
        {(setting.tableType === 'radio' || setting.tableType === 'checkbox') && data && data.length > 0 ?
          <Switch title="收起" className="main-pickup" checkedChildren="开" unCheckedChildren="关" checked={pickup} onChange={this.pickupChange} /> : null
        }
src/tabviews/custom/components/share/normalTable/index.scss
@@ -94,7 +94,7 @@
        // vertical-align: top;
        .card-cell-list {
          color: rgba(0, 0, 0, 0.85);
          color: inherit;
        }
        .ant-mk-picture {
          position: relative;
@@ -204,12 +204,10 @@
  }
  table tr {
    th .ant-table-column-title {
      // color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
    }
    td {
      color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
@@ -218,6 +216,9 @@
      }
    }
  }
  table tbody tr {
    color: var(--mk-table-color);
  }
}
.normal-custom-table:not(.fixed-height) {
  .ant-table-body::-webkit-scrollbar {
src/tabviews/custom/components/table/base-table/index.scss
@@ -7,6 +7,7 @@
  }
  .top-search {
    border-bottom: 1px solid #efefef;
    padding-top: 10px;
  }
  >.button-list.toolbar-button {
    min-height: 60px;
src/tabviews/custom/components/table/edit-table/index.scss
@@ -7,6 +7,7 @@
  }
  .top-search {
    border-bottom: 1px solid #efefef;
    padding-top: 10px;
  }
  >.button-list.toolbar-button {
    padding: 0;
src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -507,7 +507,10 @@
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
    } else if (col.type === 'action') {
      style.padding = '0px 5px'
      style.padding = '0px'
      if (col.style) {
        style = {...style, ...col.style}
      }
      children = (
        <CardCellComponent data={record} cards={config} elements={col.elements}/>
      )
@@ -1988,7 +1991,7 @@
          {!submit.hasAction && pickup ? <Button style={submit.style} onClick={() => setTimeout(() => {this.checkData()}, 10)} loading={loading} className="submit-table" type="link">提交</Button> : null}
          <Switch title="编辑" className="main-pickup" checkedChildren="开" unCheckedChildren="关" disabled={loading || this.props.loading} checked={pickup} onChange={this.pickupChange} />
        </div>
        <div className={`edit-custom-table ${pickup ? 'editable' : ''} ${setting.tableHeader || ''} ${setting.operType || ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''}`} id={tableId}>
        <div className={`edit-custom-table ${pickup ? 'editable' : ''} ${setting.tableHeader || ''} ${setting.operType || ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || ''}`} id={tableId}>
          <Table
            rowKey="$$uuid"
            components={components}
src/tabviews/custom/components/table/edit-table/normalTable/index.scss
@@ -72,7 +72,7 @@
        // vertical-align: top;
        .card-cell-list {
          color: rgba(0, 0, 0, 0.85);
          color: inherit;
        }
        .action-col {
          .ant-btn > .anticon + span {
@@ -292,12 +292,10 @@
  }
  table tr {
    th .ant-table-column-title, th .ant-table-column-title span:not(.anticon) {
      // color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
    }
    td {
      color: var(--mk-table-color)!important;
      font-size: var(--mk-table-font-size)!important;
      font-weight: var(--mk-table-font-weight)!important;
@@ -306,6 +304,9 @@
      }
    }
  }
  table tbody tr {
    color: var(--mk-table-color);
  }
}
.edit-custom-table.buoyMode {
  .ant-table-scroll {
src/tabviews/custom/components/table/normal-table/index.scss
@@ -7,6 +7,7 @@
  }
  .top-search {
    border-bottom: 1px solid #efefef;
    padding-top: 10px;
  }
  >.button-list.toolbar-button {
    min-height: 60px;
src/tabviews/custom/index.jsx
@@ -40,6 +40,7 @@
const TimeLine = asyncComponent(() => import('./components/timeline/normal-timeline'))
const AntvG6 = asyncComponent(() => import('./components/chart/antv-G6'))
const Voucher = asyncComponent(() => import('./components/module/voucher'))
const Account = asyncComponent(() => import('./components/module/account'))
const Iframe = asyncComponent(() => import('./components/iframe'))
const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
const TableNodes = asyncComponent(() => import('@/tabviews/zshare/tablenodes'))
@@ -838,6 +839,10 @@
      component.setting.useMSearch = component.setting.useMSearch === 'true'
      if (component.wrap && component.wrap.goback === 'true') {
        component.setting.sync = 'false'
      }
      if (component.setting.interType !== 'system') { // 不使用系统函数时
        component.setting.sync = 'false'
        component.setting.laypage = component.setting.laypage === 'true'
@@ -1272,6 +1277,12 @@
            <Voucher config={item}/>
          </Col>
        )
      } else if (item.type === 'module' && item.subtype === 'account') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>
            <Account config={item}/>
          </Col>
        )
      } else if (item.type === 'iframe') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>
src/tabviews/zshare/actionList/exceloutbutton/index.jsx
@@ -195,7 +195,7 @@
        })
        viewParam.arr_field = viewParam.arr_field.join(',')
        viewParam.orderBy = btn.verify.order || viewParam.orderBy
        viewParam.orderBy = btn.verify.order || ''
      }
    }
    if (btn.intertype === 'system' && btn.verify.enable === 'true') {
src/tabviews/zshare/actionList/index.jsx
@@ -1,7 +1,8 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Affix } from 'antd'
import { Affix, Dropdown } from 'antd'
import { DownOutlined } from '@ant-design/icons'
import asyncComponent from './asyncButtonComponent'
import './index.scss'
@@ -29,7 +30,25 @@
    setting: PropTypes.any,           // 页面通用设置
  }
  state = {}
  state = {
    actions: [],
    mores: null
  }
  UNSAFE_componentWillMount() {
    const { setting, actions } = this.props
    if (!setting.btnlimit || setting.btnlimit >= actions.length) {
      this.setState({actions: actions})
    } else {
      let mores = fromJS(actions).toJS()
      this.setState({
        actions: mores.splice(0, setting.btnlimit),
        mores
      })
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
@@ -139,6 +158,7 @@
              btn={item}
              BData={BData}
              setting={setting}
              columns={columns}
              selectedData={selectedData}
            />
          )
@@ -173,7 +193,8 @@
  }
  render() {
    const { setting, MenuID, actions } = this.props
    const { setting, MenuID } = this.props
    const { actions, mores } = this.state
    let fixed = setting.actionfixed && setting.tabType === 'main' // 按钮是否固定在头部
    if (fixed && MenuID) {
@@ -181,6 +202,9 @@
        <Affix offsetTop={48}>
          <div className="button-list toolbar-button" id={fixed ? MenuID + 'mainaction' : ''}>
            {this.getButtonList(actions)}
            {mores ? <Dropdown overlay={<div className="mk-button-dropdown-wrap">{this.getButtonList(mores)}</div>} trigger={['hover']}>
              <div className="mk-more">更多<DownOutlined/></div>
            </Dropdown> : null}
          </div>
        </Affix>
      )
@@ -188,6 +212,9 @@
      return (
        <div className="button-list toolbar-button" id={fixed ? MenuID + 'mainaction' : ''}>
          {this.getButtonList(actions)}
          {mores ? <Dropdown overlay={<div className="mk-button-dropdown-wrap">{this.getButtonList(mores)}</div>} trigger={['hover']}>
            <div className="mk-more">更多<DownOutlined/></div>
          </Dropdown> : null}
        </div>
      )
    }
src/tabviews/zshare/actionList/index.scss
@@ -26,3 +26,34 @@
    display: none;
  }
}
.mk-more {
  display: inline-block;
  height: 28px;
  border: 1px solid #d8d8d8;
  line-height: 28px;
  padding: 0 10px 0px 20px;
  border-radius: 4px;
  cursor: pointer;
  .anticon-down {
    margin-left: 3px;
  }
}
.mk-button-dropdown-wrap {
  box-shadow: 0 0 2px #bcbcbc;
  background: #ffffff;
  min-width: 85px;
  button {
    display: block;
    margin: 0!important;
    width: 100%;
    height: 34px;
    border-radius: 0px;
    padding-left: 15px!important;
    .anticon {
      display: none;
    }
    .anticon + span {
      margin-left: 0px;
    }
  }
}
src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -27,6 +27,7 @@
    MenuID: PropTypes.string,         // 菜单ID
    btn: PropTypes.object,            // 按钮
    setting: PropTypes.any,           // 页面通用设置
    columns: PropTypes.array,
    disabled: PropTypes.any,          // 行按钮禁用
  }
@@ -190,6 +191,13 @@
        duration: 5
      })
      return
    } else if (btn.intertype === 'system' && btn.verify.dataType === 'custom' && (!btn.verify.setting || btn.verify.columns.length === 0)) {
      notification.warning({
        top: 92,
        message: '自定义打印数据请设置数据源!',
        duration: 5
      })
      return
    }
    this.setState({
@@ -244,70 +252,52 @@
  triggerNormalPrint = (data, formlist) => {
    const { btn } = this.props
    let formdata = {}
    let baseCount = 1
    let baseType = ''
    let baseTemp = btn.verify.Template || ''
    
    formlist.forEach(_data => {
      formdata[_data.key] = _data.value
      if (!_data.value) return
      if (_data.key.toLowerCase() === 'printcount') {
        baseCount = +_data.value
      } else if (_data.key.toLowerCase() === 'printtype') {
        baseType = _data.value
      } else if (_data.key.toLowerCase() === 'templateid') {
        baseTemp = _data.value
      }
      let _key = _data.key.toLowerCase()
      formdata[_key] = _data.value
    })
    let printlist = []
    let templates = []
    if (isNaN(baseCount) || baseCount < 1) {
      baseCount = 1
    }
    new Promise(resolve => {
      if (btn.intertype === 'system') { // 使用系统时,直接从表格或表单中选取数据
      if (btn.intertype === 'system' && btn.verify.dataType !== 'custom') { // 使用系统时,直接从表格或表单中选取数据
        if (btn.Ot === 'notRequired') {
          let printcell = {}
  
          printcell.printType = baseType
          printcell.printCount = baseCount
          printcell.templateID = baseTemp
          printcell.printType = formdata.printtype || ''
          printcell.printCount = +(formdata.printcount || 1)
          printcell.templateID = formdata.templateid || btn.verify.Template || ''
          printcell.data = [formdata]
          if (isNaN(printcell.printCount) || printcell.printCount < 1) {
            printcell.printCount = 1
          }
          templates.push(printcell.templateID)
          printlist.push(printcell)
        } else {
          data.forEach(cell => {
            let _cell = {...cell, ...formdata}
            let _cell = {}
            Object.keys(cell).forEach(key => {
              let _key = key.toLowerCase()
              _cell[_key] = cell[key]
            })
            _cell = {..._cell, ...formdata}
            
            let printcell = {data: [_cell]}
  
            printcell.templateID = baseTemp
            printcell.printType = baseType
            printcell.printCount = 0
            Object.keys(_cell).forEach(key => {
              if (!_cell[key]) return
              let _key = key.toLowerCase()
              if (_key === 'templateid') {
                printcell.templateID = _cell[key]
              } else if (_key === 'printtype') {
                printcell.printType = _cell[key]
              } else if (_key === 'printcount') {
                printcell.printCount = +_cell[key]
              }
            })
            printcell.printType = _cell.printtype || ''
            printcell.printCount = +(_cell.printcount || 1)
            printcell.templateID = _cell.templateid || btn.verify.Template || ''
            if (isNaN(printcell.printCount) || printcell.printCount < 1) {
              printcell.printCount = baseCount
              printcell.printCount = 1
            }
            templates.push(printcell.templateID)
@@ -316,58 +306,71 @@
          })
        }
        resolve(true)
        if (btn.verify.printMode === 'custom') {
          this.execCustomPrint(printlist, formdata)
          resolve(false)
        } else {
          resolve(true)
        }
      } else {
        this.getprintdata(btn, data, formdata, formlist).then(result => {
          if (result.next) {
            result.list.forEach(cell => {
              // 系统打印数据,校验data字段
              if (btn.verify.printMode !== 'custom' && (!cell.data || cell.data.length === 0)) return
          if (!result.next) {
            resolve(false)
            return
          }
              let templateID = baseTemp
              let printType = baseType
              let printCount = 0
          // 自定义打印
          if (btn.verify.printMode === 'custom') {
            this.execCustomPrint(result.list, formdata)
            resolve(false)
            return
          }
              Object.keys(cell).forEach(key => {
                if (!cell[key]) return
          result.list.forEach(cell => {
            // 系统打印数据,校验data字段
            if (!cell.data || cell.data.length === 0) return
            Object.keys(cell).forEach(key => {
              let _key = key.toLowerCase()
              if (['templateid', 'printtype', 'printcount'].includes(_key)) {
                cell[_key] = cell[key]
              }
            })
            cell.data.forEach(item => {
              let _item = {...formdata}
              _item.printtype = cell.printtype || ''
              _item.printcount = cell.printcount || 1
              _item.templateid = cell.templateid || ''
              Object.keys(item).forEach(key => {
                let _key = key.toLowerCase()
                if (_key === 'templateid') {
                  templateID = cell[key]
                } else if (_key === 'printtype') {
                  printType = cell[key]
                } else if (_key === 'printcount') {
                  printCount = +cell[key]
                }
                _item[_key] = item[key]
              })
              cell.templateID = templateID
              cell.printType = printType
              cell.printCount = printCount
              let printcell = {data: [_item]}
              printcell.printType = _item.printtype || ''
              printcell.printCount = +(_item.printcount || 1)
              printcell.templateID = _item.templateid || btn.verify.Template || ''
              if (isNaN(cell.printCount) || cell.printCount < 1) {
                cell.printCount = baseCount
              if (isNaN(printcell.printCount) || printcell.printCount < 1) {
                printcell.printCount = 1
              }
              templates.push(cell.templateID)
              templates.push(printcell.templateID)
              printlist.push(cell)
              printlist.push(printcell)
            })
          }
          })
          
          resolve(result.next)
          resolve(true)
        })
      }
    }).then(res => {
      // 获取打印模板 getTemp
      if (!res) return false
      if (btn.verify.printMode === 'custom') {
        this.execCustomPrint(printlist, formdata)
        return false
      }
      templates = Array.from(new Set(templates)) // 去重
@@ -447,10 +450,10 @@
              })
            }
            this.execPrint(printlist, _temps, formdata)
            this.execPrint(printlist, _temps)
          }, 500)
        } else {
          this.execPrint(printlist, _temps, formdata)
          this.execPrint(printlist, _temps)
        }
      } else {
        this.execError(errorMsg)
@@ -471,7 +474,7 @@
    })
    new Promise(resolve => {
      if (btn.intertype === 'system') { // 使用系统时,直接从表格或表单中选取数据
      if (btn.intertype === 'system' && btn.verify.dataType !== 'custom') { // 使用系统时,直接从表格或表单中选取数据
        if (btn.Ot === 'notRequired') {
          if (formlist.length > 0) {
            list = [formdata]
@@ -792,72 +795,124 @@
   * @description 获取打印数据
   */
  getprintdata = (btn, data, formdata, formlist) => {
    const { setting } = this.props
    const { setting, BID } = this.props
    let _list = []
    return new Promise(resolve => {
      let params = []
      let param = {}
      if (this.props.BID) {
        param.BID = this.props.BID
      }
      if (btn.Ot === 'notRequired') {
        let _param = { ...param, ...formdata }
        params.push(_param)
      } else if (btn.Ot === 'requiredSgl') {
        if (setting.primaryKey) {
          param[setting.primaryKey] = data[0][setting.primaryKey]
        }
        let _param = { ...param, ...formdata }
        params.push(_param)
      } else if (btn.Ot === 'requiredOnce') {
        if (setting.primaryKey) {
          let ids = data.map(d => { return d[setting.primaryKey]})
          ids = ids.filter(Boolean)
          ids = ids.join(',')
      if (btn.intertype === 'system' && btn.verify.dataType === 'custom') {
        if (btn.Ot === 'notRequired') {
          let _param = this.getDefaultSql(formlist, null, '')
  
          param[setting.primaryKey] = ids
        }
        let _param = { ...param, ...formdata }
        params.push(_param)
      } else if (btn.Ot === 'required') {
        params = data.map((cell, index) => {
          let _param = { ...param }
          params.push(_param)
        } else if (btn.Ot === 'requiredSgl') {
          let ID = ''
          if (setting.primaryKey) {
            _param[setting.primaryKey] = cell[setting.primaryKey]
            ID = data[0][setting.primaryKey] || ''
          }
          let _cell = {}
          if (index !== 0) {
            Object.keys(cell).forEach(key => {
              _cell[key.toLowerCase()] = cell[key]
            })
          let _param = this.getDefaultSql(formlist, data[0], ID)
          params.push(_param)
        } else if (btn.Ot === 'requiredOnce') {
          let ID = ''
          if (setting.primaryKey) {
            let ids = data.map(d => { return d[setting.primaryKey]})
            ids = ids.filter(Boolean)
            ID = ids.join(',')
          }
          formlist.forEach(_data => {
            if (index !== 0 && _data.readin && _cell.hasOwnProperty(_data.key.toLowerCase())) {
              _param[_data.key] = _cell[_data.key.toLowerCase()]
            } else {
              _param[_data.key] = _data.value
          let _param = this.getDefaultSql(formlist, data[0], ID)
          params.push(_param)
        } else if (btn.Ot === 'required') {
          params = data.map(cell => {
            let ID = ''
            if (setting.primaryKey) {
              ID = cell[setting.primaryKey] || ''
            }
            return this.getDefaultSql(formlist, cell, ID)
          })
          return _param
        })
        }
      } else {
        if (btn.Ot === 'notRequired') {
          let _param = { ...formdata }
          if (BID) {
            _param.BID = BID
          }
          params.push(_param)
        } else if (btn.Ot === 'requiredSgl') {
          let _param = { ...formdata }
          if (setting.primaryKey) {
            _param[setting.primaryKey] = data[0][setting.primaryKey]
          }
          if (BID) {
            _param.BID = BID
          }
          params.push(_param)
        } else if (btn.Ot === 'requiredOnce') {
          let _param = { ...formdata }
          if (setting.primaryKey) {
            let ids = data.map(d => { return d[setting.primaryKey]})
            ids = ids.filter(Boolean)
            ids = ids.join(',')
            _param[setting.primaryKey] = ids
          }
          if (BID) {
            _param.BID = BID
          }
          params.push(_param)
        } else if (btn.Ot === 'required') {
          params = data.map((cell, index) => {
            let _param = {}
            if (setting.primaryKey) {
              _param[setting.primaryKey] = cell[setting.primaryKey]
            }
            if (BID) {
              _param.BID = BID
            }
            let _cell = {}
            if (index !== 0) {
              Object.keys(cell).forEach(key => {
                _cell[key.toLowerCase()] = cell[key]
              })
            }
            formlist.forEach(_data => {
              if (index !== 0 && _data.readin && _cell.hasOwnProperty(_data.key.toLowerCase())) {
                _param[_data.key] = _cell[_data.key.toLowerCase()]
              } else {
                _param[_data.key] = _data.value
              }
            })
            return _param
          })
        }
      }
      if (btn.intertype === 'inner') {
        params = params.map(_param => {
          _param.func = btn.innerFunc
          return _param
        })
      if (btn.intertype === 'inner' || btn.intertype === 'system') {
        if (btn.intertype === 'inner') {
          params = params.map(_param => {
            _param.func = btn.innerFunc
            return _param
          })
        }
        if (params.length <= 20) {
          let deffers = params.map(par => {
@@ -888,6 +943,233 @@
        this.printOuterLoopRequest(params, btn, _list, resolve)
      }
    })
  }
  /**
   * @description 获取默认存储过程请求参数
   */
  getDefaultSql = (formlist, data, ID) => {
    const { BID, btn, columns } = this.props
    let arrFields = btn.verify.columns.map(col => col.field).join(',')
    let param = {
      func: 'sPC_Get_TableData',
      obj_name: 'data',
      exec_type: 'y',
      arr_field: arrFields,
      default_sql: btn.verify.setting.defaultSql
    }
    if (BID) {
      param.BID = BID
    }
    if (ID) {
      param.ID = ID
    }
    let userName = sessionStorage.getItem('User_Name') || ''
    let fullName = sessionStorage.getItem('Full_Name') || ''
    let RoleID = sessionStorage.getItem('role_id') || ''
    let departmentcode = sessionStorage.getItem('departmentcode') || ''
    let organization = sessionStorage.getItem('organization') || ''
    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
    let nation = sessionStorage.getItem('nation') || ''
    let province = sessionStorage.getItem('province') || ''
    let city = sessionStorage.getItem('city') || ''
    let district = sessionStorage.getItem('district') || ''
    let address = sessionStorage.getItem('address') || ''
    let _dataresource = btn.verify.setting.dataresource
    let _customScript = ''
    btn.verify.scripts && btn.verify.scripts.forEach(script => {
      if (script.status !== 'false') {
        _customScript += `
        ${script.sql}
        `
      }
    })
    if (btn.verify.setting.defaultSql === 'false') {
      _dataresource = ''
    }
    if (/\s/.test(_dataresource)) {
      _dataresource = '(' + _dataresource + ') tb'
    }
    if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
      _dataresource = _dataresource.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
      _dataresource = _dataresource.replace(/@\$/ig, '*/')
      _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
      _customScript = _customScript.replace(/@\$/ig, '*/')
    } else {
      _dataresource = _dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
      _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
    }
    let initsql = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
      Select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
    `
    let _vars = []
    let _initvars = []
    let _declare = []
    // 获取字段键值对
    formlist.forEach(form => {
      let _key = form.key.toLowerCase()
      if (_vars.includes(_key)) return
      _vars.push(_key)
      if (form.type === 'number' || form.type === 'rate') {
        let val = form.value
        if (isNaN(val)) {
          val = 0
        }
        _initvars.push(`@${_key}=${val}`)
      } else if (['date', 'datemonth'].includes(form.type)) {
        _initvars.push(`@${_key}='${form.value || '1949-10-01'}'`)
      } else {
        _initvars.push(`@${_key}='${form.value}'`)
      }
      if (form.fieldlen && form.fieldlen > 2048) {
        form.fieldlen = 'max'
      }
      let _type = `nvarchar(${form.fieldlen})`
      if (form.type.match(/date/ig)) {
        _type = 'datetime'
      } else if (form.type === 'number') {
        _type = `decimal(18,${form.fieldlen})`
      } else if (form.type === 'rate') {
        _type = `decimal(18,2)`
      }
      _declare.push(`@${_key} ${_type}`)
    })
    if (_declare.length > 0) {
      initsql += `/* 表单变量 */
        Declare ${_declare.join(',')}
        select ${_initvars.join(',')}
      `
      _declare = []
      _initvars = []
    }
    if (data && columns && columns.length > 0) {
      let datavars = {}
      Object.keys(data).forEach(key => {
        datavars[key.toLowerCase()] = data[key]
      })
      columns.forEach(col => {
        if (!col.field || !col.datatype) return
        let _key = col.field.toLowerCase()
        if (_vars.includes(_key)) return
        let _val = datavars.hasOwnProperty(_key) ? datavars[_key] : ''
        if (/^date/ig.test(col.datatype) && !_val) {
          _val = '1949-10-01'
        }
        _initvars.push(`@${_key}='${_val}'`)
        _declare.push(`@${_key} ${col.datatype}`)
      })
    }
    if (_declare.length > 0) {
      initsql += `/* 显示列变量 */
        Declare ${_declare.join(',')}
        select ${_initvars.join(',')}
      `
    }
    if (_customScript) {
      _customScript = `${initsql}
        ${_customScript}
      `
    }
    _dataresource = _dataresource.replace(/@select\$|\$select@/ig, '')
    _customScript = _customScript.replace(/@select\$|\$select@/ig, '')
    _dataresource = _dataresource.replace(/\$sum@/ig, '/*')
    _dataresource = _dataresource.replace(/@sum\$/ig, '*/')
    _customScript = _customScript.replace(/\$sum@/ig, '/*')
    _customScript = _customScript.replace(/@sum\$/ig, '*/')
    _dataresource = _dataresource.replace(/@ID@/ig, `'${ID}'`)
    _customScript = _customScript.replace(/@ID@/ig, `'${ID}'`)
    _dataresource = _dataresource.replace(/@BID@/ig, `'${BID || ''}'`)
    _customScript = _customScript.replace(/@BID@/ig, `'${BID || ''}'`)
    _dataresource = _dataresource.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
    _customScript = _customScript.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
    _dataresource = _dataresource.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
    _customScript = _customScript.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
    _dataresource = _dataresource.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
    _customScript = _customScript.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
    _dataresource = _dataresource.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
    _customScript = _customScript.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
    let LText = ''
    if (_dataresource) {
      LText = `/*system_query*/select ${arrFields} from (select ${arrFields} ,ROW_NUMBER() over(order by ${btn.verify.setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows `
    }
    if (_customScript) {
      if (LText) {
        LText = `${LText}
          aaa:
          if @ErrorCode!=''
            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
        `
      } else {
        _customScript = `${_customScript}
          aaa:
          if @ErrorCode!=''
            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
        `
      }
    } else {
      LText = `${initsql}
        ${LText}
      `
    }
    // 测试系统打印查询语句
    if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
      _customScript && console.info(`${btn.logLabel ? `/*${btn.logLabel} 自定义脚本*/\n` : ''}${LText ? '' : '/*不执行默认sql*/\n'}${_customScript}`)
      LText && console.info(`${btn.logLabel ? `/*${btn.logLabel} 数据源*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
    }
    if (btn.logLabel) {
      param.menuname = btn.logLabel
    }
    param.custom_script = Utils.formatOptions(_customScript)
    param.LText = Utils.formatOptions(LText)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt('', param.timestamp)
    if (window.GLOB.probation) {
      param.s_debug_type = 'Y'
    }
    return param
  }
  /**
@@ -986,7 +1268,6 @@
        return Api.genericInterface(_callbackparam)
      } else if (response.status) {
        _list.push(response)
        // 一次请求成功,进行下一项请求
@@ -1072,7 +1353,7 @@
        }
        configParam.elements.forEach(element => {
          let _field = element.field
          let _field = element.field || ''
          if (_field === 'other_field') {
            _field = element.cusfield || ''
@@ -1082,7 +1363,7 @@
            Name: element.name || '',
            Type: element.type,
            Value: element.value || '',
            Field: _field,
            Field: _field.toLowerCase(),
            Left: element.left + offsetLeft,
            Top: element.top + offsetTop,
            Width: element.width,
@@ -1119,11 +1400,13 @@
            item.ImageWidth = element.imgWidth
            item.ImageHeight = element.imgHeight
            item.Trimming = ''
            if (element.productValue && window.GLOB.systemType === 'production') {
              item.Value = element.productValue
              imgs.push(item.Value)
            } else if (item.Value) {
              imgs.push(item.Value)
            if (!item.Field) {
              if (element.productValue && window.GLOB.systemType === 'production') {
                item.Value = element.productValue
                imgs.push(item.Value)
              } else if (item.Value) {
                imgs.push(item.Value)
              }
            }
          } else if (item.Type === 'text') {
            item.FontFamily = element.fontFamily
@@ -1190,8 +1473,8 @@
    return {
      error: error,
      config: _configparam,
      fields: fields,
      nonEFields: nonEFields,
      fields: Array.from(new Set(fields)),
      nonEFields: Array.from(new Set(nonEFields)),
      imgs: imgs
    }
  }
@@ -1339,7 +1622,7 @@
    })
  }
  execPrint = (list, template, formdata) => {
  execPrint = (list, template) => {
    const { btn } = this.props
    let _errors = []
@@ -1379,30 +1662,25 @@
        _datalist.forEach(res => {
          res.data.forEach(_cell => {
            for (let i = 0; i < res.printCount; i++) {
              _data.push({...formdata, ..._cell})
              _data.push(_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 => {
          template[key].fields.forEach(f => {
            if (!d.hasOwnProperty(f)) {
              lacks.push(f)
            } else if (_nonEFields.includes(f) && !d[f] && d[f] !== 0) {
            } else if (template[key].nonEFields.includes(f) && !d[f] && d[f] !== 0) {
              emptys.push(f)
            }
          })
        })
        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,
@@ -1490,49 +1768,29 @@
      return
    }
    // let lackItems = printerList.filter(cell => cell.task.printer === 'lackprinter')[0]
    if (!socket || socket.readyState !== 1 || socket.url !== 'ws://' + btn.verify.linkUrl) {
      socket = new WebSocket('ws://' + btn.verify.linkUrl)
    } else {
      // if (lackItems) {
      //   let request  = {
      //     requestID: '',
      //     version: '',
      //     cmd: 'getPrinters'
      //   }
      //   socket.send(JSON.stringify(request))
      // } else {
        this.syncMessageSend(printerList)
      this.syncMessageSend(printerList)
        this.execSuccess({
          ErrCode: 'S',
          message: '',
          ErrMesg: '打印请求已发出。',
          status: true
        })
      // }
      this.execSuccess({
        ErrCode: 'S',
        message: '',
        ErrMesg: '打印请求已发出。',
        status: true
      })
    }
    // 打开Socket
    socket.onopen = () =>{
      // if (lackItems) {
      //   let request  = {
      //     requestID: '',
      //     version: '',
      //     cmd: 'getPrinters'
      //   }
      //   socket.send(JSON.stringify(request))
      // } else {
        this.syncMessageSend(printerList)
      this.syncMessageSend(printerList)
        this.execSuccess({
          ErrCode: 'S',
          message: '',
          ErrMesg: '打印请求已发出。',
          status: true
        })
      // }
      this.execSuccess({
        ErrCode: 'S',
        message: '',
        ErrMesg: '打印请求已发出。',
        status: true
      })
    }
    // 监听消息
    socket.onmessage = (event) => {
src/tabviews/zshare/cardcomponent/index.jsx
@@ -208,6 +208,7 @@
              btn={item}
              BData={BData}
              setting={setting}
              columns={columns}
              selectedData={[data]}
            />
          )
src/tabviews/zshare/mutilform/index.jsx
@@ -301,7 +301,7 @@
            })
          } else if (item.regular === 'email') {
            _rules.push({
              pattern: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/,
              pattern: /^([a-zA-Z0-9._-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/,
              message: item.regularText || '请正确输入邮箱地址'
            })
          }
@@ -732,6 +732,12 @@
            _cell.$value = cell[item.cardValField]
            _cell = {..._cell, ...cell}
            if (item.urlField) {
              _cell.$url = cell[item.urlField] || ''
            } else if (item.colorField) {
              _cell.$color = cell[item.colorField] || ''
            }
            if (map.has(_cell.ParentID + _cell.$value)) return
            
            map.set(_cell.ParentID + _cell.$value, 0)
src/tabviews/zshare/mutilform/mkCheckCard/index.jsx
@@ -191,7 +191,7 @@
        }
        return <Col span={width} key={item.key}>
          <div className={'card-color-cell' + (_active ? ' active' : '') + (item.$disabled ? ' disabled' : '')} style={{background: item.$value}} onClick={() => this.changeCard(item)}>
          <div className={'card-color-cell' + (_active ? ' active' : '') + (item.$disabled ? ' disabled' : '')} style={{background: item.$color}} onClick={() => this.changeCard(item)}>
            {fields.map(col => {
              return <span className="content-line" key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span>
            })}
src/tabviews/zshare/tablenodes/index.jsx
@@ -155,11 +155,8 @@
        let { tbs, ptbs } = this.getTbs(config)
        ptbs = Array.from(new Set(ptbs))
        ptbs = ptbs.filter(tb => tb.length > 1 && tb !== 'dbo')
        ptbs.sort()
        if (ptbs.length && sessionStorage.getItem('mk_tb_names')) {
          let names = sessionStorage.getItem('mk_tb_names')
          ptbs = ptbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
        }
        if (ptbs.length) {
          ptbs.forEach((item, i) => {
@@ -184,6 +181,7 @@
        if (result.tb_list) {
          result.tb_list.sort((a, b) => a.tbname > b.tbname ? 1 : -1)
          let length = result.tb_list.length
          result.tb_list.forEach((item, i) => {
            let cell = {
              label: item.tbname,
@@ -191,6 +189,8 @@
              id: 'table' + i,
              direction: 'right',
              color: '#1890ff',
              collapsed: false,
              collable: true,
              children: []
            }
@@ -209,10 +209,17 @@
                    id: item.tbname + 'menu' + i,
                    direction: 'right',
                    color: '#1890ff',
                    type: 'dice-mind-map-leaf',
                    param: _param
                  })
                }
              })
            }
            if (cell.children.length > 5 && length > 1) {
              cell.collapsed = true
            } else if (cell.children.length === 0) {
              cell.collable = false
            }
            data.children.push(cell)
@@ -261,12 +268,12 @@
          const stroke = cfg.style.stroke || '#096dd9';
    
          return `
          <group>
            <rect draggable="true" style={{width: ${width}, height: 30, stroke: ${stroke}, radius: 4}} keyshape>
              <text style={{ fontSize: 14, marginLeft: 6, marginTop: 6 }}>${cfg.label}</text>
            </rect>
          </group>
        `;
            <group>
              <rect draggable="true" style={{width: ${width}, height: 30, stroke: ${stroke}, radius: 4}} keyshape>
                <text style={{ fontSize: 14, marginLeft: 6, marginTop: 6 }}>${cfg.label}</text>
              </rect>
            </group>
          `;
        },
        getAnchorPoints() {
          return [
@@ -285,13 +292,13 @@
          const color = cfg.color;
    
          return `
          <group>
            <rect draggable="true" style={{width: ${width}, height: 26, fill: 'transparent' }}>
              <text style={{ fontSize: 12, fill: ${cfg.fontcolor ? cfg.fontcolor : 'black'}, marginLeft: 12, marginTop: 6 }}>${cfg.label}</text>
            </rect>
            <rect style={{ fill: ${color}, width: ${width}, height: 2, x: 0, y: 32 }} />
          </group>
        `;
            <group>
              <rect draggable="true" style={{width: ${width}, cursor: ${cfg.collable ? 'pointer' : 'default'}, height: 26, fill: 'transparent' }}>
                <text style={{ fontSize: 12, fill: ${cfg.fontcolor ? cfg.fontcolor : 'black'}, cursor: ${cfg.collable ? 'pointer' : 'default'}, marginLeft: 12, marginTop: 6 }}>${cfg.label} ${cfg.collable ? '+' : ''}</text>
              </rect>
              <rect style={{ fill: ${color}, width: ${width}, cursor: ${cfg.collable ? 'pointer' : 'default'}, height: 2, x: 0, y: 32 }} />
            </group>
          `;
        },
        getAnchorPoints() {
          return [
@@ -302,6 +309,7 @@
      },
      'single-node',
    );
    G6.registerBehavior('scroll-canvas', {
      getEvents: function getEvents() {
        return {
@@ -358,9 +366,10 @@
          data.color = color;
        }
    
        if (d.children) {
        if (d.children && !d.collapsed) {
          data.children = d.children.map((child) => changeData(child, level + 1, data.color));
        }
        return data;
      };
      return changeData(data);
@@ -399,9 +408,20 @@
          lineWidth: 2,
        },
      },
      minZoom: 0.5,
      minZoom: 0.3,
      modes: {
        default: ['drag-canvas', 'zoom-canvas'],
        default: [
          {
            type: 'collapse-expand',
            trigger: 'click',
            shouldBegin: (e, self) => {
              if (e.item && e.item.getModel().collable) return true;
              return false;
            },
          },
          'drag-canvas',
          'zoom-canvas'
        ],
      },
    });
    
@@ -441,6 +461,7 @@
          </div>
          <div className="footer">
            <Button key="cancel" onClick={() => { this.setState({ visible: false })}}>关闭</Button>
            <span className="tip">注:点击表名可展开/收起菜单</span>
          </div>
        </Modal>
      </div>
src/tabviews/zshare/tablenodes/index.scss
@@ -62,7 +62,16 @@
  }
  .footer {
    position: relative;
    text-align: center;
    .tip {
      position: absolute;
      font-size: 12px;
      color: var(--mk-sys-color);
      right: 10px;
      top: 20px;
    }
  }
  .tb-search {
    position: absolute;
src/tabviews/zshare/topSearch/index.jsx
@@ -423,6 +423,12 @@
            _item.$value = cell[item.cardValField]
            _item = {..._item, ...cell}
            if (item.urlField) {
              _item.$url = cell[item.urlField] || ''
            } else if (item.colorField) {
              _item.$color = cell[item.colorField] || ''
            }
            if (map.has(_item.ParentID + _item.$value)) return
            
            map.set(_item.ParentID + _item.$value, 0)
src/templates/comtableconfig/updatetable/index.jsx
@@ -897,10 +897,12 @@
                datatype: 'dynamic',
                eleType: _cols[sub].type !== 'number' ? 'text' : 'number',
                field: sub,
                height: 1,
                innerHeight: 21,
                height: '',
                innerHeight: 'auto',
                marks: _cols[sub].marks || null,
                noValue: 'show',
                prefix: _cols[sub].prefix || '',
                postfix: _cols[sub].postfix || '',
                style: {},
                width: 24,
                uuid: Utils.getuuid()
src/templates/modalconfig/checkCard/index.jsx
@@ -66,7 +66,7 @@
      }
      return _options.map(item => {
        return <Col span={width} key={item.key}>
          <div className={'card-color-cell ' + cls} style={{background: item.$value}}>
          <div className={'card-color-cell ' + cls} style={{background: item.$color}}>
            {_fields.map(col => {
              return <span className="content-line" key={col.key} style={{color: col.color, fontSize: col.fontSize + 'px', height: col.fontSize * 1.5 + 'px', textAlign: col.align}}>{item[col.field]}</span>
            })}
src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -383,9 +383,11 @@
        
        _fieldval.label = '导入Excel'
        _fieldval.class = 'dgreen'
        _fieldval.execSuccess = 'grid'
        this.record.Ot = 'notRequired'
        this.record.label = '导入Excel'
        this.record.class = 'dgreen'
        this.record.execSuccess = 'grid'
      } else if (value === 'excelOut') {
        _fieldval.intertype = 'system'
        _fieldval.label = '导出Excel'
src/templates/sharecomponent/actioncomponent/index.jsx
@@ -878,7 +878,8 @@
    } else if (card.OpenType === 'funcbutton' && card.funcType === 'print') {
      return <VerifyPrint
        card={card}
        columns={config.columns}
        columns={[]}
        // columns={config.columns}
        wrappedComponentRef={(inst) => this.verifyRef = inst}
      />
    } else if (card.OpenType === 'funcbutton' && card.funcType === 'megvii') {
src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -239,8 +239,10 @@
  UNSAFE_componentWillMount() {
    const { card } = this.props
    let _verify = fromJS(card.verify || {range: 1}).toJS()
    let _verify = fromJS(card.verify || {}).toJS()
    let _columns = _verify.columns || []
    delete _verify.dataresource
    // 旧数据兼容
    _columns = _columns.map(col => {
@@ -260,6 +262,10 @@
      return col
    })
    if (!_verify.hasOwnProperty('range')) {
      _verify.range = 1
    }
    this.setState({
      verify: {
        ..._verify,
src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
@@ -1,8 +1,7 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Form, Row, Col, Button, notification, Modal, Tooltip, Radio, Select } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import { Form, Row, Col, Button, notification, Tooltip, Select } from 'antd'
import moment from 'moment'
import Api from '@/api'
@@ -12,39 +11,100 @@
class CustomForm extends Component {
  static propTpyes = {
    scripts: PropTypes.array,       // 自定义脚本列表
    usefulfields: PropTypes.any,    // 可用字段
    systemScripts: PropTypes.array, // 系统脚本
    scriptsChange: PropTypes.func   // 表单
    searches: PropTypes.any,        // 搜索条件
    linefields: PropTypes.any,
    scriptsChange: PropTypes.func
  }
  state = {
    editItem: null,
    systemScripts: [],
    usefulfields: null,
    loading: false,
    verifySql: ''
  }
  UNSAFE_componentWillMount () {
    this.resetfield(this.props.usefulfields)
    this.resetfield(this.props.searches)
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (nextProps.usefulfields && !is(fromJS(this.props.usefulfields), fromJS(nextProps.usefulfields))) {
      this.resetfield(nextProps.usefulfields)
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (!is(fromJS(this.props.searches), fromJS(nextProps.searches))) {
      this.resetfield(nextProps.searches)
    }
  }
  resetfield = (columns) => {
    columns = columns.filter(item => item.Column !== '$Index')
    let fields = columns.map(item => item.Column)
  componentDidMount () {
    this.getsysScript()
  }
    let _sql = `Declare @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@ErrorCode nvarchar(50), @retmsg nvarchar(4000)
    `
  getsysScript = () => {
    if (sessionStorage.getItem('mk_sys_scripts')) {
      this.setState({
        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
      })
      return
    }
    
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
    let _sParam = {
      func: 'sPC_Get_SelectedList',
      LText: _scriptSql,
      obj_name: 'data',
      arr_field: 'funcname,longparam'
    }
    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
    _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 云端数据验证
    Api.getSystemConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = res.data.map(item => {
          return {
            name: item.funcname,
            value: window.decodeURIComponent(window.atob(item.longparam))
          }
        })
        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
        this.setState({
          systemScripts: _scripts
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
      }
    })
  }
  resetfield = (searches) => {
    let _usefulFields = []
    searches.forEach(item => {
      if (!item.field) return
      if (item.type === 'group') {
        _usefulFields.push(item.field)
        _usefulFields.push(item.datefield)
        _usefulFields.push(item.datefield + '1')
      } else if (['dateweek', 'datemonth', 'daterange'].includes(item.type)) {
        _usefulFields.push(item.field)
        _usefulFields.push(item.field + '1')
      } else if (item.type === 'date' && _usefulFields.includes(item.field)) {
        _usefulFields.push(item.field + '1')
      } else {
        _usefulFields.push(item.field)
      }
    })
    this.setState({
      verifySql: _sql,
      usefulfields: fields.join(', ')
      usefulfields: _usefulFields.join(', ')
    })
  }
@@ -116,89 +176,22 @@
          return
        }
        let tail = `
          aaa:
        `
        let _initCustomScript = '' // 初始化脚本
        let _prevCustomScript = '' // 默认sql前执行脚本
        let _backCustomScript = '' // 默认sql后执行脚本
        this.props.scripts.forEach(item => {
          if (item.status === 'false') return
          if (item.position === 'init') {
            _initCustomScript += `
            /* 初始化脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          } else if (item.position === 'front') {
            _prevCustomScript += `
            /* 默认sql前脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          } else {
            _backCustomScript += `
            /* 默认sql后脚本 */
            ${values.uuid === item.uuid ? values.sql : item.sql}
            `
          }
        this.setState({
          loading: true
        })
        if (!values.uuid) {
          if (values.position === 'init') {
            _initCustomScript += `
            /* 初始化脚本 */
            ${values.sql}
            `
          } else if (values.position === 'front') {
            _prevCustomScript += `
            /* 默认sql前脚本 */
            ${values.sql}
            `
          } else {
            _backCustomScript += `
            /* 默认sql后脚本 */
            ${values.sql}
            `
          }
        }
        let param = {
          func: 's_debug_sql',
          exec_type: 'y',
          LText: this.state.verifySql + _initCustomScript + _prevCustomScript + _backCustomScript + tail
        }
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        param.LText = param.LText.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${param.timestamp}'`)
        param.LText = param.LText.replace(/\n/g, ' ')
        // 外联数据库替换
        if (window.GLOB.externalDatabase !== null) {
          param.LText = param.LText.replace(/@db@/ig, window.GLOB.externalDatabase)
        }
        param.LText = Utils.formatOptions(param.LText)
        param.secretkey = Utils.encrypt('', param.timestamp)
        this.setState({loading: true})
        Api.genericInterface(param).then(res => {
          if (res.status) {
        this.props.scriptsChange(values, (status) => {
          if (status) {
            this.setState({
              loading: false,
              editItem: null
            }, () => {
              this.props.scriptsChange(values)
            })
            this.props.form.setFieldsValue({
              sql: ''
            })
          } else {
            this.setState({loading: false})
            Modal.error({
              title: res.message
            this.setState({
              loading: false
            })
          }
        })
@@ -250,8 +243,8 @@
  }
  render() {
    const { systemScripts, sheet } = this.props
    const { usefulfields } = this.state
    const { sheet, linefields } = this.props
    const { usefulfields, systemScripts } = this.state
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
@@ -280,11 +273,12 @@
          <Col span={24} className="sqlfield">
            <Form.Item label={'可用字段'}>
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'公共值,请按照@xxx@格式使用。'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id</span></Tooltip>,&nbsp;
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'系统变量,系统会定义变量并赋值。'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
              {usefulfields}
              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'系统变量,系统会定义变量并赋值。'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>
              {usefulfields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'搜索条件,请按照@xxx@格式使用。'}>,&nbsp;{usefulfields}</Tooltip> : null}
              {linefields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'表单及行变量,系统会定义变量并赋值。'}>,&nbsp;{linefields}</Tooltip> : null}
            </Form.Item>
          </Col>
          <Col span={8} style={{whiteSpace: 'nowrap'}}>
          {/* <Col span={8} style={{whiteSpace: 'nowrap'}}>
            <Form.Item style={{marginBottom: 0}} label={
              <Tooltip placement="bottomLeft" title={'自定义脚本与默认sql位置关系。'}>
                <QuestionCircleOutlined className="mk-form-tip" />
@@ -301,8 +295,8 @@
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
          <Col span={10}>
          </Col> */}
          <Col span={8}>
            <Form.Item style={{marginBottom: 0}} label={'快捷添加'}>
              <Select
                showSearch
src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
@@ -11,6 +11,7 @@
class SettingForm extends Component {
  static propTpyes = {
    btnType: PropTypes.any,
    setting: PropTypes.object,    // 数据源配置
  }
@@ -20,10 +21,10 @@
  }
  UNSAFE_componentWillMount () {
    const { setting } = this.props
    const { setting, btnType } = this.props
    this.setState({
      dataType: setting.dataType,
      dataType: btnType === 'print' ? 'custom' : setting.dataType,
      defaultSql: setting.defaultSql || 'true'
    })
  }
@@ -104,7 +105,7 @@
  }
  render() {
    const { setting } = this.props
    const { setting, btnType } = this.props
    const { getFieldDecorator } = this.props.form
    const { dataType, defaultSql } = this.state
@@ -123,7 +124,7 @@
      <div className="excelout-datasource-wrap">
        <Form {...formItemLayout}>
          <Row gutter={24}>
            <Col span={8}>
            {btnType !== 'print' ? <Col span={8}>
              <Form.Item label="导出数据">
                {getFieldDecorator('dataType', {
                  initialValue: setting.dataType
@@ -134,7 +135,7 @@
                  </Radio.Group>
                )}
              </Form.Item>
            </Col>
            </Col> : null}
            {dataType === 'custom' ? <Col className="short-label" span={8}>
              <Form.Item label="表名">
                {getFieldDecorator('tableName', {
@@ -198,12 +199,7 @@
              </Form.Item>
            </Col> : null}
            {dataType === 'custom' && defaultSql === 'true' ? <Col className="short-label" span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="排序方式为空时,使用表格或组件中的排序方式。">
                  <QuestionCircleOutlined className="mk-form-tip" />
                  排序方式
                </Tooltip>
              }>
              <Form.Item label="排序方式">
                {getFieldDecorator('order', {
                  initialValue: setting.order || '',
                  rules: [
@@ -215,9 +211,9 @@
                })(<Input placeholder={'ID asc, UID desc'} autoComplete="off" />)}
              </Form.Item>
            </Col> : null}
            {dataType === 'custom' ? <Col span={8}>
            {dataType === 'custom' && btnType !== 'print' ? <Col span={8}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="不使用搜索条件时,不会进行搜索条件的拼接与相关统计字段的替换。注:自定义数据来源时,只使用内部搜索。">
                <Tooltip placement="topLeft" title="不使用搜索条件时,不会进行搜索条件的拼接与相关统计字段的替换。">
                  <QuestionCircleOutlined className="mk-form-tip" />
                  搜索条件
                </Tooltip>
src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -29,7 +29,6 @@
  state = {
    verify: {},
    activeKey: 'setting',
    systemScripts: [],
    defaultscript: '', // 自定义脚本
    excelColumns: [
      {
@@ -353,57 +352,6 @@
      searches: searches,
      activeKey: card.intertype === 'system' && _verify.dataType === 'custom' ? 'setting' : 'columns',
      defaultscript: defaultscript
    })
  }
  componentDidMount () {
    this.getsysScript()
  }
  getsysScript = () => {
    if (sessionStorage.getItem('mk_sys_scripts')) {
      this.setState({
        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
      })
      return
    }
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
    let _sParam = {
      func: 'sPC_Get_SelectedList',
      LText: _scriptSql,
      obj_name: 'data',
      arr_field: 'funcname,longparam'
    }
    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
    _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 云端数据验证
    Api.getSystemConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = res.data.map(item => {
          return {
            name: item.funcname,
            value: window.decodeURIComponent(window.atob(item.longparam))
          }
        })
        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
        this.setState({
          systemScripts: _scripts
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
      }
    })
  }
@@ -945,7 +893,7 @@
    }
  }
  scriptsChange = (values) => {
  scriptsChange = (values, callback) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    if (values.uuid) {
@@ -968,10 +916,12 @@
        loading: false,
        verify: verify
      })
      callback(true)
    }, () => {             // 验证失败
      this.setState({
        loading: false
      })
      callback(false)
    }, verify.scripts)
  }
@@ -984,7 +934,7 @@
    }
    let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    let sql = SettingUtils.getDebugSql(verify, scripts, searches, Utils, timestamp)
    let sql = SettingUtils.getDebugSql(verify, scripts, (verify.useSearch === 'true' ? searches : []), Utils, timestamp)
    let param = {
      func: 's_debug_sql',
      exec_type: 'y',
@@ -1012,7 +962,7 @@
  render() {
    const { card } = this.props
    const { verify, excelColumns, defaultscript, scriptsColumns, activeKey, loading } = this.state
    const { verify, excelColumns, defaultscript, scriptsColumns, activeKey, loading, searches } = this.state
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
@@ -1058,9 +1008,7 @@
            <CustomScript
              btn={card}
              sheet={verify.tableName}
              usefulfields={verify.columns}
              scripts={verify.scripts}
              systemScripts={this.state.systemScripts}
              searches={verify.useSearch === 'true' ? searches : []}
              scriptsChange={this.scriptsChange}
              wrappedComponentRef={(inst) => this.scriptsForm = inst}
            />
src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
@@ -23,6 +23,10 @@
    })
    arr_field = arr_field.join(',')
    if (!arr_field) {
      arr_field = '*'
    }
    let _customScript = ''
    scripts && scripts.forEach(script => {
      if (script.status === 'false') return
@@ -39,14 +43,6 @@
    if (verify.defaultSql === 'false') {
      _dataresource = ''
    }
    if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
      window.GLOB.funcs.forEach(item => {
        let reg = new RegExp('\\$ex@' + item.func_code + '@ex\\$', 'ig')
        _dataresource = _dataresource.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
        _customScript = _customScript.replace(reg, `/*$ex@${item.func_code}-begin*/\n${item.key_sql}\n/*@ex$-end*/`)
      })
    }
    
    _dataresource = _dataresource.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${timestamp}'`)
@@ -105,15 +101,15 @@
    }
    // 数据源处理, 存在显示列时 
    if (arr_field && _dataresource) {
    if (_dataresource) {
      if (/\s/.test(_dataresource)) {
        _dataresource = '(' + _dataresource + ') tb'
      }
      if (verify.order) {
        _dataresource = `select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${verify.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows`
        _dataresource = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${verify.order}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows`
      } else {
        _dataresource = `select ${arr_field} from ${_dataresource} ${_search}`
        _dataresource = `/*system_query*/select ${arr_field} from ${_dataresource} ${_search}`
      }
    }
src/templates/sharecomponent/actioncomponent/verifyprint/editable/index.jsx
@@ -1,4 +1,5 @@
import React, {Component} from 'react'
import { fromJS } from 'immutable'
import { Table, Input, Popconfirm, Form } from 'antd'
import { ArrowUpOutlined, ArrowDownOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons'
import Utils from '@/utils/utils.js'
@@ -160,11 +161,14 @@
    this.setState({
      dataSource: _data
    })
    this.props.onChange(fromJS(_data).toJS())
  }
  handleDelete = key => {
    const dataSource = [...this.state.dataSource]
    this.setState({ dataSource: dataSource.filter(item => item.key !== key) })
    const dataSource = [...this.state.dataSource].filter(item => item.key !== key)
    this.setState({ dataSource: dataSource })
    this.props.onChange(fromJS(dataSource).toJS())
  }
  handleAdd = () => {
@@ -174,11 +178,13 @@
      Value: `${count}`,
      Text: `${count}`
    }
    let list = [...dataSource, newData]
    this.setState({
      dataSource: [...dataSource, newData],
      dataSource: list,
      count: count + 1
    })
    this.props.onChange(fromJS(list).toJS())
  }
  handleSave = row => {
@@ -190,10 +196,7 @@
      ...row
    })
    this.setState({ dataSource: newData })
  }
  UNSAFE_componentWillReceiveProps () {
    this.props.onChange(fromJS(newData).toJS())
  }
  render() {
src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -1,16 +1,25 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Tabs, Row, Col, Button, notification, Modal, message, InputNumber, Input, Select, Radio, Tooltip } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import { fromJS } from 'immutable'
import { Form, Tabs, Row, Col, Button, notification, Modal, message, InputNumber, Input, Select, Radio, Tooltip, Typography, Popconfirm, Spin } from 'antd'
import { QuestionCircleOutlined, EditOutlined, StopOutlined, CheckCircleOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import SettingUtils from './utils.jsx'
import CodeMirror from '@/templates/zshare/codemirror'
import DataSource from '../verifyexcelout/datasource'
import CustomScript from '../verifyexcelout/customscript'
import asyncComponent from '@/utils/asyncComponent'
import ColForm from '@/menu/datasource/verifycard/columnform'
import EditTable from './editable'
import './index.scss'
const EditMTable = asyncComponent(() => import('@/templates/zshare/editTable'))
const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
const { Paragraph } = Typography
const { TabPane } = Tabs
class VerifyCard extends Component {
@@ -25,20 +34,239 @@
  state = {
    verify: {},
    templates: [],
    loading: false,
    activeKey: 'base',
    selectimg: '',
    printMode: 'normal'
    dataType: 'line',
    printMode: 'normal',
    usefulfields: '',
    declareSql: '',
    scriptsColumns: [
      {
        title: 'SQL',
        dataIndex: 'sql',
        width: '60%',
        render: (text) => {
          let title = text.match(/^\s*\/\*.+\*\//)
          title = title && title[0] ? title[0] : ''
          let _text = title ? text.replace(title, '') : text
          return (
            <div>
              {title ? <span style={{color: '#a50'}}>{title}<span style={{fontSize: '12px', marginLeft: '5px'}}>{_text.length}</span></span> : null}
              <Paragraph copyable={{ text: text }} ellipsis={{ rows: 4, expandable: true }}>{_text}</Paragraph>
            </div>
          )
        }
      },
      {
        title: '执行位置',
        dataIndex: 'position',
        width: '10%',
        render: (text, record) => {
          if (record.position === 'init') {
            return <span style={{color: 'orange'}}>初始化</span>
          } else if (record.position === 'front') {
            return <span style={{color: '#26C281'}}>sql前</span>
          } else {
            return <span style={{color: '#1890ff'}}>sql后</span>
          }
        }
      },
      {
        title: '状态',
        dataIndex: 'status',
        width: '10%',
        render: (text, record) => record.status === 'false' ?
          (
            <div style={{color: '#ff4d4f'}}>
              禁用
              <StopOutlined style={{marginLeft: '5px'}} />
            </div>
          ) :
          (
            <div style={{color: '#26C281'}}>
              启用
              <CheckCircleOutlined style={{marginLeft: '5px'}}/>
            </div>
          )
      },
      {
        title: '操作',
        align: 'center',
        width: '140px',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div style={{textAlign: 'center'}}>
            <span className="operation-btn" title="编辑" onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><EditOutlined /></span>
            <span className="operation-btn" title="状态切换" onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
            <Popconfirm
              overlayClassName="popover-confirm"
              title="确定删除吗?"
              onConfirm={() => this.handleDelete(record, 'scripts')
            }>
              <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
            </Popconfirm>
          </div>)
      }
    ],
    colColumns: [
      {
        title: '名称',
        dataIndex: 'label',
        inputType: 'input',
        editable: true,
        width: '28%'
      },
      {
        title: '字段',
        dataIndex: 'field',
        inputType: 'input',
        editable: true,
        unique: true,
        copy: true,
        rules: [{
          pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
          message: '字段名只允许包含数字、字母、汉字以及_'
        }],
        width: '28%'
      },
      {
        title: '数据类型',
        dataIndex: 'datatype',
        inputType: 'select',
        options: [
          { value: 'Nvarchar(10)', text: 'Nvarchar(10)' },
          { value: 'Nvarchar(20)', text: 'Nvarchar(20)' },
          { value: 'Nvarchar(50)', text: 'Nvarchar(50)' },
          { value: 'Nvarchar(100)', text: 'Nvarchar(100)' },
          { value: 'Nvarchar(256)', text: 'Nvarchar(256)' },
          { value: 'Nvarchar(512)', text: 'Nvarchar(512)' },
          { value: 'Nvarchar(1024)', text: 'Nvarchar(1024)' },
          { value: 'Nvarchar(2048)', text: 'Nvarchar(2048)' },
          { value: 'Nvarchar(max)', text: 'Nvarchar(max)' },
          { value: 'Int', text: 'Int' },
          { value: 'Decimal(18,0)', text: 'Decimal(18,0)' },
          { value: 'Decimal(18,1)', text: 'Decimal(18,1)' },
          { value: 'Decimal(18,2)', text: 'Decimal(18,2)' },
          { value: 'Decimal(18,3)', text: 'Decimal(18,3)' },
          { value: 'Decimal(18,4)', text: 'Decimal(18,4)' },
          { value: 'Decimal(18,5)', text: 'Decimal(18,5)' },
          { value: 'Decimal(18,6)', text: 'Decimal(18,6)' },
          { value: 'Decimal(18,7)', text: 'Decimal(18,7)' },
          { value: 'Decimal(18,8)', text: 'Decimal(18,8)' },
          { value: 'Decimal(18,9)', text: 'Decimal(18,9)' },
          { value: 'Decimal(18,10)', text: 'Decimal(18,10)' },
          { value: 'Decimal(18,11)', text: 'Decimal(18,11)' },
          { value: 'Decimal(18,12)', text: 'Decimal(18,12)' },
          { value: 'Decimal(18,13)', text: 'Decimal(18,13)' },
          { value: 'Decimal(18,14)', text: 'Decimal(18,14)' },
          { value: 'Decimal(18,15)', text: 'Decimal(18,15)' },
          { value: 'Decimal(18,16)', text: 'Decimal(18,16)' },
          { value: 'Decimal(18,17)', text: 'Decimal(18,17)' },
          { value: 'Decimal(18,18)', text: 'Decimal(18,18)' },
          { value: 'date', text: 'date' },
          { value: 'datetime', text: 'datetime' },
        ],
        editable: true,
        width: '25%',
      }
    ]
  }
  UNSAFE_componentWillMount() {
    let _verify = this.props.card.verify || {}
    const { columns, card } = this.props
    let _verify = fromJS(card.verify || {}).toJS()
    _verify.Template = _verify.Template || ''
    _verify.printerTypeList = _verify.printerTypeList || []
    _verify.linkType = _verify.linkType || 'system'
    _verify.printMode = _verify.printMode || 'normal'
    _verify.scripts = _verify.scripts || []
    _verify.columns = _verify.columns || []
    let _usefulfields = []
    let _declare = []
    let _select = []
    let fieldArr = []
    let _sql = ''
    if (card.execMode === 'pop' && card.modal && card.modal.fields) {
      card.modal.fields.forEach(_f => {
        if (!_f.field || fieldArr.includes(_f.field.toLowerCase())) return
        fieldArr.push(_f.field.toLowerCase())
        _usefulfields.push(_f.field)
        let _fieldlen = _f.fieldlength || 50
        if (_f.type === 'number') {
          _fieldlen = _f.decimal ? _f.decimal : 0
        }
        if (_fieldlen > 2048) {
          _fieldlen = 'max'
        }
        let _type = `nvarchar(${_fieldlen})`
        if (_f.type.match(/date/ig)) {
          _type = 'datetime'
          _select.push(`@${_f.field}='1949-10-01'`)
        } else if (_f.type === 'number') {
          _type = `decimal(18,${_fieldlen})`
          _select.push(`@${_f.field}=0`)
        } else if (_f.type === 'rate') {
          _type = `decimal(18,2)`
          _select.push(`@${_f.field}=0`)
        } else {
          _select.push(`@${_f.field}=''`)
        }
        _declare.push(`@${_f.field} ${_type}`)
      })
      if (_declare.length > 0) {
        _sql = `/* 表单变量 */
          Declare ${_declare.join(', ')}
          Select ${_select.join(', ')}
        `
      }
      _declare = []
      _select = []
    }
    if (columns && columns.length > 0 && card.Ot !== 'notRequired') {
      columns.forEach(_f => {
        if (!_f.field || fieldArr.includes(_f.field.toLowerCase()) || !_f.datatype) return
        fieldArr.push(_f.field.toLowerCase())
        _usefulfields.push(_f.field)
        if (/decimal/ig.test(_f.datatype)) {
          _select.push(`@${_f.field}=0`)
        } else {
          _select.push(`@${_f.field}=''`)
        }
        _declare.push(`@${_f.field} ${_f.datatype}`)
      })
      if (_declare.length > 0) {
        _sql += `/* 显示列变量 */
          Declare ${_declare.join(', ')}
          Select ${_select.join(', ')}
        `
      }
    }
    this.setState({
      verify: _verify,
      declareSql: _sql,
      usefulfields: _usefulfields.join(', '),
      dataType: _verify.dataType || 'line',
      linkType: _verify.linkType,
      printMode: _verify.printMode,
      printFunc: _verify.printFunc || '// Function(data, form, printer, notification) data-打印数据列表,form-表单信息(不存在时为{}),printer-打印设置,notification-信息提示控件'
@@ -157,56 +385,67 @@
  }
  handleConfirm = () => {
    const { verify } = this.state
    const { verify, activeKey } = this.state
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          let _verify = {...verify, ...values}
          if (this.refs.editTable && this.refs.editTable.state) {
            let printTypes = this.refs.editTable.state.dataSource
      if (activeKey === 'base') {
        this.props.form.validateFieldsAndScroll((err, values) => {
          if (err) return
  
            let emptys = printTypes.filter(item => !item.Value || !item.Text)
            let valMap = new Map()
            let isvalid = true
          resolve({...verify, ...values})
        })
      } else if (activeKey === 'print') {
        if (verify.printerTypeList.length > 0) {
          let printTypes = verify.printerTypeList.map(item => item.Value)
          printTypes = Array.from(new Set(printTypes))
  
            printTypes.forEach(item => {
              if (valMap.has(item.Value)) {
                isvalid = false
              } else {
                valMap.set(item.Value, item.Text)
              }
          if (verify.printerTypeList.length > printTypes.length) {
            notification.warning({
              top: 92,
              message: '打印类型中Value字段不可重复!',
              duration: 5
            })
            if (emptys.length > 0) {
              notification.warning({
                top: 92,
                message: '打印类型表格中Value、Text字段不可为空!',
                duration: 5
              })
              return
            } else if (!isvalid) {
              notification.warning({
                top: 92,
                message: '打印类型表格中Value字段不可重复!',
                duration: 5
              })
              return
            }
            _verify.printerTypeList = printTypes
            return
          }
          resolve(_verify)
        } else {
        }
        resolve(verify)
      } else if (activeKey === 'setting') {
        this.settingForm.handleConfirm().then(res => {
          let _verify = {...verify, setting: res}
          this.setState({
            verify: _verify
          }, () => {
            this.setState({loading: true})
            this.sqlverify(() => { // 验证成功
              resolve(_verify)
            }, () => {             // 验证失败
              this.setState({
                loading: false
              })
            }, _verify.scripts)
          })
        })
      } else if (activeKey === 'scripts') {
        if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
          notification.warning({
            top: 92,
            message: '链接地址与打印模板不可为空!',
            message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!',
            duration: 5
          })
          return
        }
      })
        this.setState({loading: true})
        this.sqlverify(() => { // 验证成功
          resolve(verify)
        }, () => {             // 验证失败
          this.setState({
            loading: false
          })
        }, verify.scripts)
      } else {
        resolve(verify)
      }
    })
  }
@@ -254,10 +493,182 @@
    })
  }
  changeDataType = (e) => {
    let value = e.target.value
    this.setState({
      dataType: value
    })
  }
  // 标签切换
  tabchange = (val) => {
    const { activeKey, verify } = this.state
    if (activeKey === 'base') {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (err) return
        this.setState({
          verify: {...verify, ...values},
          activeKey: val
        })
      })
    } else if (activeKey === 'print') {
      if (verify.printerTypeList.length > 0) {
        let printTypes = verify.printerTypeList.map(item => item.Value)
        printTypes = Array.from(new Set(printTypes))
        if (verify.printerTypeList.length > printTypes.length) {
          notification.warning({
            top: 92,
            message: '打印类型中Value字段不可重复!',
            duration: 5
          })
          return
        }
      }
      this.setState({
        activeKey: val
      })
    } else if (activeKey === 'setting') {
      this.settingForm.handleConfirm().then(res => {
        this.setState({
          verify: {...verify, setting: res}
        }, () => {
          this.setState({loading: true})
          this.sqlverify(() => { // 验证成功
            this.setState({
              activeKey: val,
              loading: false
            })
          }, () => {             // 验证失败
            this.setState({
              activeKey: val,
              loading: false
            })
          }, verify.scripts)
        })
      })
    } else if (activeKey === 'scripts') {
      if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
        notification.warning({
          top: 92,
          message: '存在未保存脚本,请点击确定保存,或点击取消放弃修改!',
          duration: 5
        })
        return
      }
      this.setState({loading: true})
      this.sqlverify(() => { // 验证成功
        this.setState({
          activeKey: val,
          loading: false
        })
      }, () => {             // 验证失败
        this.setState({
          activeKey: val,
          loading: false
        })
      }, verify.scripts)
    } else {
      this.setState({
        activeKey: val
      })
    }
  }
  scriptsChange = (values, callback) => {
    let verify = JSON.parse(JSON.stringify(this.state.verify))
    if (values.uuid) {
      verify.scripts = verify.scripts.map(item => {
        if (item.uuid === values.uuid) {
          return values
        } else {
          return item
        }
      })
    } else {
      values.uuid = Utils.getuuid()
      verify.scripts.push(values)
    }
    this.setState({loading: true})
    this.sqlverify(() => { // 验证成功
      this.setState({
        loading: false,
        verify: verify
      })
      callback(true)
    }, () => {             // 验证失败
      this.setState({
        loading: false
      })
      callback(false)
    }, verify.scripts)
  }
  sqlverify = (_resolve, _reject, scripts) => {
    const { verify, declareSql } = this.state
    let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    let sql = SettingUtils.getDebugSql(verify.setting || {}, verify.columns, scripts, declareSql, timestamp)
    let param = {
      func: 's_debug_sql',
      exec_type: 'y',
      LText: sql
    }
    param.LText = Utils.formatOptions(param.LText)
    param.timestamp = timestamp
    param.secretkey = Utils.encrypt('', timestamp)
    Api.genericInterface(param).then(result => {
      if (result.status) {
        _resolve()
      } else {
        _reject()
        Modal.error({
          title: result.message
        })
      }
    })
  }
  columnChange = (values, resolve) => {
    let verify = fromJS(this.state.verify).toJS()
    let fields = verify.columns.map(item => item.field.toLowerCase())
    if (fields.includes(values.field.toLowerCase())) {
      notification.warning({
        top: 92,
        message: '字段已存在!',
        duration: 5
      })
      return
    }
    resolve()
    values.uuid = Utils.getuuid()
    verify.columns.push(values)
    this.setState({verify})
  }
  updatefields = (columns) => {
    let verify = fromJS(this.state.verify).toJS()
    verify.columns = columns
    this.setState({verify})
  }
  render() {
    const { card } = this.props
    const { getFieldDecorator } = this.props.form
    const { verify, linkType, printMode, printFunc } = this.state
    const { verify, linkType, printMode, printFunc, scriptsColumns, dataType, loading, activeKey, usefulfields, colColumns } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
@@ -270,10 +681,11 @@
    }
    return (
      <div>
      <div className="verify-card-print-box">
        {card.label ? <div className="mk-com-name">{card.label} - 验证信息</div> : null}
        <Tabs defaultActiveKey="1" className="verify-card-print-box" onChange={this.tabchange}>
          <TabPane tab="打印验证" key="1">
        {loading && <Spin size="large" />}
        <Tabs activeKey={activeKey} onChange={this.tabchange}>
          <TabPane tab="打印验证" key="base">
            <Form {...formItemLayout}>
              <Row gutter={24}>
                <Col span={8}>
@@ -339,6 +751,18 @@
                    })(<Input placeholder="" autoComplete="off" />)}
                  </Form.Item>
                </Col>}
                {card.intertype === 'system' ? <Col span={8}>
                  <Form.Item label="数据类型">
                    {getFieldDecorator('dataType', {
                      initialValue: dataType || 'line'
                    })(
                      <Radio.Group onChange={this.changeDataType}>
                        <Radio value="line">行数据</Radio>
                        <Radio value="custom">自定义</Radio>
                      </Radio.Group>
                    )}
                  </Form.Item>
                </Col> : null}
                {printMode === 'custom' ? <Col span={24}>
                  <Form.Item label={'处理函数'} className="printFunc">
                    {getFieldDecorator('printFunc', {
@@ -433,7 +857,7 @@
                    )}
                  </Form.Item>
                </Col> : null}
                {printMode !== 'custom' ? <Col span={8} offset={printMode === 'RFID' ? 16 : 0}>
                {printMode !== 'custom' ? <Col span={8} offset={16}>
                  <img className="legend" src={this.state.selectimg} alt=""/>
                </Col> : null }
              </Row>
@@ -444,7 +868,7 @@
              打印类型
              {verify.printerTypeList.length ? <span className="count-tip">{verify.printerTypeList.length}</span> : null}
            </span>
          } disabled={printMode === 'RFID'} key="2">
          } disabled={printMode === 'RFID'} key="print">
            <Form {...formItemLayout}>
              <Row gutter={24}>
                <Col span={24} className="print-tip">
@@ -455,12 +879,45 @@
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <EditTable data={verify.printerTypeList} ref="editTable"/>
                  <EditTable data={verify.printerTypeList} onChange={(list) => this.setState({verify: {...verify, printerTypeList: list}})}/>
                </Col>
              </Row>
            </Form>
          </TabPane>
          <TabPane tab="信息提示" key="7">
          {card.intertype === 'system' ? <TabPane tab="数据源" disabled={dataType !== 'custom'} key="setting">
            <DataSource setting={verify.setting || {}} btnType="print" wrappedComponentRef={(inst) => this.settingForm = inst}/>
          </TabPane> : null}
          {card.intertype === 'system' ? <TabPane tab={
            <span>
              字段集
              {verify.columns.length ? <span className="count-tip">{verify.columns.length}</span> : null}
            </span>
          } disabled={dataType !== 'custom'} key="columns">
            <ColForm columnChange={this.columnChange}/>
            <FieldsComponent
              config={verify}
              type="fields"
              updatefield={this.updatefields}
            />
            <EditMTable actions={['edit', 'move', 'copy', 'del', 'clear']} type="datasourcefield" data={verify.columns} columns={colColumns} onChange={(columns) => this.setState({verify: {...verify, columns}})}/>
          </TabPane> : null}
          {card.intertype === 'system' ? <TabPane tab={
            <span>
              自定义脚本
              {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
            </span>
          } key="scripts" disabled={dataType !== 'custom'} id="mk-exout-script">
            <CustomScript
              btn={card}
              sheet={verify.setting ? verify.setting.tableName : ''}
              searches={[]}
              linefields={usefulfields}
              scriptsChange={this.scriptsChange}
              wrappedComponentRef={(inst) => this.scriptsForm = inst}
            />
            <EditMTable actions={['move']} data={verify.scripts} columns={scriptsColumns} onChange={(scripts) => {this.setState({verify: {...verify, scripts}})}}/>
          </TabPane> : null}
          <TabPane tab="信息提示" key="message">
            <div style={{textAlign: 'center', fontSize: '13px', marginBottom: '10px'}}>打印信息中如果存在网络资源(图片),请确保资源可以正常访问,资源不存在时会报数据异常。</div>
            <Form {...formItemLayout}>
              <Row gutter={24}>
src/templates/sharecomponent/actioncomponent/verifyprint/index.scss
@@ -1,4 +1,5 @@
.verify-card-print-box {
  position: relative;
  .ant-tabs-nav-scroll {
    text-align: center;
  }
@@ -60,6 +61,56 @@
    color: #1890ff;
    font-size: 12px;
  }
  .verify-form {
    .sql {
      .ant-col-sm-8 {
        width: 10.5%;
      }
      .ant-col-sm-16 {
        width: 89.5%;
        padding-top: 4px;
      }
      .CodeMirror {
        height: 350px;
      }
    }
    .sqlfield {
      .ant-form-item {
        margin-bottom: 5px;
      }
      .ant-form-item-control {
        line-height: 24px;
      }
      .ant-form-item-label {
        line-height: 25px;
      }
      .ant-form-item-children {
        line-height: 22px;
      }
      .ant-col-sm-8 {
        width: 10.5%;
      }
      .ant-col-sm-16 {
        width: 89.5%;
      }
    }
    .add {
      padding-top: 4px;
    }
  }
  .ant-spin {
    position: absolute;
    top: calc(50% - 16px);
    left: calc(50% - 16px);
    z-index: 1;
  }
  .quickly-add {
    position: absolute;
    width: 100px;
    right: 24px;
    top: 5px;
    z-index: 2;
  }
}
.print-template-setting {
  .ant-select-dropdown-menu-item {
src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
New file
@@ -0,0 +1,77 @@
export default class SettingUtils {
  static getDebugSql (setting, columns, scripts, declareSql, timestamp) {
    let sql = ''
    let _dataresource = setting.dataresource || ''
    let _customScript = ''
    scripts && scripts.forEach(script => {
      if (script.status === 'false') return
      _customScript += `
      ${script.sql}
      `
    })
    if (_customScript) {
      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
        ${declareSql}
        ${_customScript}
      `
    }
    if (setting.defaultSql === 'false') {
      _dataresource = ''
    }
    _dataresource = _dataresource.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${timestamp}'`)
    _customScript = _customScript.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${timestamp}'`)
    _dataresource = _dataresource.replace(/@\$|\$@/ig, '')
    _customScript = _customScript.replace(/@\$|\$@/ig, '')
    // 外联数据库替换
    if (window.GLOB.externalDatabase !== null) {
      _dataresource = _dataresource.replace(/@db@/ig, window.GLOB.externalDatabase)
      _customScript = _customScript.replace(/@db@/ig, window.GLOB.externalDatabase)
    }
    let arr_field = columns.map(col => col.field)
    arr_field = arr_field.join(',')
    if (!arr_field) {
      arr_field = '*'
    }
    // 数据源处理, 存在显示列时
    if (_dataresource) {
      if (/\s/.test(_dataresource)) {
        _dataresource = '(' + _dataresource + ') tb'
      }
      if (setting.order) {
        _dataresource = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows`
      } else {
        _dataresource = `/*system_query*/select ${arr_field} from ${_dataresource}`
      }
    }
    if (_customScript) {
      sql = `/* sql 验证 */
        ${_customScript}
        ${_dataresource}
        aaa:
        if @ErrorCode!=''
          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
      `
    } else {
      sql = `/* sql 验证 */
        declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
        ${declareSql}
        ${_dataresource}`
    }
    sql = sql.replace(/\n\s{8}/ig, '\n')
    console.info(sql)
    sql = sql.replace(/\n/g, ' ')
    return sql
  }
}
src/templates/sharecomponent/searchcomponent/index.jsx
@@ -160,7 +160,6 @@
    this.searchFormRef.handleConfirm().then(res => {
      let fieldrepet = false // 字段重复
      let labelrepet = false // 提示文字重复
      _searchlist = _searchlist.filter(item => !item.origin || item.uuid === res.uuid) // 去除系统项
@@ -188,8 +187,6 @@
          if (setFields.length < itemFields.length + resFields.length && (res.type !== 'date' || item.type !== 'date')) {
            fieldrepet = true
          } else if (item.label === res.label) {
            labelrepet = true
          }
        }
@@ -204,13 +201,6 @@
        notification.warning({
          top: 92,
          message: '字段已存在!',
          duration: 5
        })
        return
      } else if (labelrepet) {
        notification.warning({
          top: 92,
          message: '名称已存在!',
          duration: 5
        })
        return
src/templates/sharecomponent/searchcomponent/index.scss
@@ -26,6 +26,9 @@
    vertical-align: top;
  }
  .mk-search-item-wrap.action {
    .ant-form-item {
      white-space: nowrap;
    }
    .ant-form-item-label, .ant-form-item-control-wrapper {
      display: inline-block;
    }
src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -198,7 +198,7 @@
        if (this.record.resourceType === '0') {        // 自定义资源
          shows.push('options', 'fields')
        } else if (this.record.resourceType === '1') { // 数据源
          shows.push('dataSource', 'cardValField', 'fields', 'orderBy', 'orderType', 'database')
          shows.push('dataSource', 'cardValField', 'colorField', 'fields', 'orderBy', 'orderType', 'database')
        }
      } else {
        reRequired.fields = true
src/templates/zshare/formconfig.jsx
@@ -489,6 +489,13 @@
      required: true
    },
    {
      type: 'text',
      key: 'colorField',
      label: '色值字段',
      initVal: card.colorField || '',
      required: true
    },
    {
      type: 'radio',
      key: 'picratio',
      label: '图片比例',
@@ -2693,6 +2700,13 @@
      readonly: false
    },
    {
      type: 'text',
      key: 'colorField',
      label: '色值字段',
      initVal: card.colorField || '',
      required: true
    },
    {
      type: 'radio',
      key: 'picratio',
      label: '图片比例',
src/templates/zshare/modalform/datatable/index.jsx
@@ -201,6 +201,17 @@
          return <span style={{display: 'block', width: '70px', height: '70px'}}><img style={{width: '100%', height: '100%'}} src={text} alt="" /></span>
        }
      })
    } else if (display === 'color') {
      columns.push({
        title: 'Color',
        dataIndex: '$color',
        inputType: 'text',
        editable: true,
        render: (text) => {
          if (!text) return ''
          return <div style={{height: '20px', background: text}}></div>
        }
      })
    }
    fields.forEach(item => {
@@ -371,6 +382,8 @@
    if (display === 'picture') {
      item.$url = ''
    } else if (display === 'color') {
      item.$color = ''
    }
    fields.forEach(f => {
src/templates/zshare/modalform/index.jsx
@@ -193,7 +193,7 @@
        if (this.record.resourceType === '0') {        // 自定义资源
          shows.push('options', 'fields')
        } else if (this.record.resourceType === '1') { // 数据源
          shows.push('dataSource', 'cardValField', 'fields', 'orderBy', 'orderType', 'database')
          shows.push('dataSource', 'cardValField', 'colorField', 'fields', 'orderBy', 'orderType', 'database')
        }
      } else {
        reRequired.fields = true
src/templates/zshare/verifycard/index.jsx
@@ -626,7 +626,7 @@
          _fields.push(...group.sublist)
        })
        resolve(_fields)
      } else if (card.modal) {
      } else if (card.modal && (card.OpenType === 'pop' || !card.OpenType)) {
        _fields = card.modal.fields || []
        resolve(_fields)
      } else if (card.OpenType === 'pop') {
@@ -840,10 +840,10 @@
        let _arr = []
        _fields.forEach(item => {
          if (!item.field || item.writein === 'false') return
          if (!item.field || item.writein === 'false' || item.uuid === 'BID') return
          _arr.push(item.field.toLowerCase())
          if (item.field.toLowerCase() === 'bid' && item.uuid === 'BID') {
          if (item.field.toLowerCase() === 'bid') {
            _form.push(item.field + '=@BID@')
          } else {
            _form.push(item.field + '=@' + item.field)
src/utils/utils-custom.js
@@ -896,7 +896,7 @@
export function getTables (config, pops) {
  let tables = []
  let cuts = []
  let cutreg = /(from|update|insert\s+into)\s+(@db@)?[a-z_]+/ig
  let cutreg = /(from|update|insert\s+into)\s+(@db@)?[a-z0-9_]+/ig
  let trimreg = /(from|update|insert\s+into)\s+(@db@)?/ig
  if (config.setting && (!config.wrap || !config.wrap.datatype || config.wrap.datatype === 'dynamic')) {
@@ -943,6 +943,8 @@
        if (cell.eleType !== 'button') return
        if (['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
          action.push(cell)
        } else if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) {
          action.push(cell)
        } else if (cell.OpenType === 'popview') {
          if (pops) {
            pops.push({...cell, parentId: config.uuid})
@@ -956,6 +958,8 @@
        item.backElements.forEach(cell => {
          if (cell.eleType !== 'button') return
          if (['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
            action.push(cell)
          } else if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) {
            action.push(cell)
          } else if (cell.OpenType === 'popview') {
            if (pops) {
@@ -974,6 +978,8 @@
      col.elements.forEach(cell => {
        if (['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
          action.push(cell)
        } else if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) {
          action.push(cell)
        } else if (cell.OpenType === 'popview') {
          if (pops) {
            pops.push({...cell, parentId: config.uuid})
@@ -989,6 +995,8 @@
    if (cell.eleType !== 'button') return
    if (['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
      action.push(cell)
    } else if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) {
      action.push(cell)
    } else if (cell.OpenType === 'popview') {
      if (pops) {
        pops.push({...cell, parentId: config.uuid})
@@ -1000,6 +1008,8 @@
  config.action && config.action.forEach(cell => {
    if (['pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
      action.push(cell)
    } else if (cell.OpenType === 'funcbutton' && cell.funcType === 'print' && cell.verify) {
      action.push(cell)
    } else if (cell.OpenType === 'popview') {
      if (pops) {
@@ -1021,6 +1031,19 @@
      }
      if (btn.intertype === 'system' && btn.verify.scripts) {
        btn.verify.scripts.forEach(script => {
          if (script.status === 'false') return
          let tbs = script.sql.match(cutreg)
          tbs && cuts.push(...tbs)
        })
      }
    } else if (btn.OpenType === 'funcbutton') {
      if (btn.intertype !== 'system' || !btn.verify || !btn.verify.setting) return
      if (btn.verify.dataType === 'custom') {
        if (btn.verify.setting.defaultSql !== 'false') {
          let tbs = btn.verify.setting.dataresource.match(cutreg)
          tbs && cuts.push(...tbs)
        }
        btn.verify.scripts && btn.verify.scripts.forEach(script => {
          if (script.status === 'false') return
          let tbs = script.sql.match(cutreg)
          tbs && cuts.push(...tbs)
@@ -1102,7 +1125,7 @@
  cuts = cuts.map(item => item.replace(trimreg, ''))
  tables.push(...cuts)
  tables = tables.filter(Boolean)
  tables = tables.filter(tb => tb && tb !== 'dbo' && tb.length > 1)
  tables = Array.from(new Set(tables))
  return tables
src/utils/utils.js
@@ -783,6 +783,8 @@
      arrfield.push(item.cardValField)
      if (item.urlField) {
        arrfield.push(item.urlField)
      } else if (item.colorField) {
        arrfield.push(item.colorField)
      }
    }
@@ -2566,9 +2568,9 @@
        @ErrorSeverity=ERROR_SEVERITY(),
        @ErrorState=ERROR_STATE();
        
      RAISERROR(@ErrorMessage, /*-- Message text.*/
        @ErrorSeverity, /*-- Severity.*/
        @ErrorState  /*-- State.*/
      RAISERROR(@ErrorMessage, /* Message text.*/
        @ErrorSeverity, /* Severity.*/
        @ErrorState  /* State.*/
      );
    END CATCH
    
@@ -2707,9 +2709,9 @@
        @ErrorSeverity=ERROR_SEVERITY(),
        @ErrorState=ERROR_STATE();
        
      RAISERROR(@ErrorMessage, /*-- Message text.*/
        @ErrorSeverity, /*-- Severity.*/
        @ErrorState  /*-- State.*/
      RAISERROR(@ErrorMessage, /* Message text.*/
        @ErrorSeverity, /* Severity.*/
        @ErrorState  /* State.*/
      );
    END CATCH
    
src/views/appmanage/index.jsx
@@ -466,6 +466,7 @@
              cell.delay = _param.delay || 0
              cell.statusBarColor = _param.statusBarColor || 'black'
              cell.sysBgColor = _param.sysBgColor || '#ffffff'
              cell.direction = _param.direction || 'vertical'
              cell.adapter = _param.adapter || ''
              cell.share = _param.share || 'false' // 分享
              cell.share_des = _param.share_des || '' // 分享描述
@@ -650,7 +651,7 @@
    })
    // 子应用ID、typename、应用ID、CloudUserID、appkey、login_types(是否需要登录,已弃用)、link_type(是否使用短连接,已弃用)、role_type(是否使用角色管理)、lang、css(皮肤)、title(标题)、favicon(图标)、user_binding(用户绑定)、sms_id(短信模板ID)、自定义
    param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
    param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', direction: item.direction || 'vertical', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
    param.LText = param.LText.join(' union all ')
    param.LText = Utils.formatOptions(param.LText)
    
@@ -896,7 +897,7 @@
          return item
        })
        param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
        param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', direction: item.direction || 'vertical', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
        param.LText = param.LText.join(' union all ')
        param.LText = Utils.formatOptions(param.LText)
      }
@@ -989,7 +990,7 @@
        return item
      })
      param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
      param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', direction: item.direction || 'vertical', adapter: item.adapter || '', share: item.share || '', share_des: item.share_des || '', share_url: item.share_url || '', share_link: item.share_link || ''})))}'`)
      param.LText = param.LText.join(' union all ')
      param.LText = Utils.formatOptions(param.LText)
src/views/appmanage/submutilform/index.jsx
@@ -322,6 +322,23 @@
              )}
            </Form.Item>
          </Col>
          {typename === 'pad' ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="系统默认屏幕方向,单个页面方向请在页面中配置。">
                <QuestionCircleOutlined className="mk-form-tip" />
                屏幕方向
              </Tooltip>
            }>
              {getFieldDecorator('direction', {
                initialValue: card ? card.direction || 'vertical' : 'vertical'
              })(
                <Radio.Group>
                  <Radio value="vertical">竖屏</Radio>
                  <Radio value="horizontal">横屏</Radio>
                </Radio.Group>
              )}
            </Form.Item>
          </Col> : null}
        </Row>
      </Form>
    )
src/views/design/index.jsx
@@ -23,7 +23,7 @@
  
  render () {
    return (
      <div className="mk-main-view mk-design-view">
      <div className="mk-main-view">
        <ConfigProvider locale={_locale}>
          <Sidemenu key="sidemenu"/>
          <Header key="header"/>
src/views/design/index.scss
@@ -1,24 +1,6 @@
.mk-main-view {
  display: flex;
  flex: auto;
  min-height: 100%;
  .mk-save-menu[disabled] {
    background: #ffffff!important;
  }
}
.mk-design-view {
  #mk-tabview-wrap {
    z-index: unset;
    >.content-header {
      >.ant-tabs {
        z-index: 21;
        background: #ffffff;
      }
    }
  }
  #mk-tabview-wrap.hastab + .sys-header-container .app-prod-entrance {
    display: none;
  }
}
.mk-popover-control-wrap {
src/views/design/sidemenu/index.scss
@@ -1,4 +1,4 @@
@import '../../../assets/css/iconfont.css';
// @import '../../../assets/css/iconfont.css';
.mk-sys-side-menu {
  flex: 0 0 235px;
src/views/login/index.scss
@@ -1,7 +1,7 @@
.login-container {
  height: 100vh;
  min-height: 600px;
  background-color: #000000;
  background-color: var(--mk-sys-background);
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center center;
@@ -10,13 +10,13 @@
    height: 100px;
    padding-top: 30px;
    line-height: 80px;
    border-bottom: 2px solid #1890ff;
    border-bottom: 2px solid var(--mk-sys-color);
    img {
      max-height: 100%;
    }
    .plat-name {
      position: absolute;
      color: #ffffff;
      color: var(--mk-sys-font-color);
      line-height: 30px;
      font-size: 30px;
      font-weight: 600;
@@ -32,7 +32,22 @@
    min-height: 420px;
    background-size: cover;
    background-position: center center;
    border-bottom: 2px solid #1890ff;
    border-bottom: 2px solid var(--mk-sys-color);
    .login-form-button {
      background-color: var(--mk-sys-color);
      border-color: var(--mk-sys-color);
    }
    .login-form-button[disabled] {
      background-color: var(--mk-sys-color5);
      border-color: var(--mk-sys-color5);
    }
    .login-way-wrap {
      .login-way.active, .login-way:hover {
        color: var(--mk-sys-color);
      }
    }
    .login-form {
      position: relative;
@@ -167,6 +182,7 @@
      }
      button.vercode {
        border: 0;
        color: var(--mk-sys-color);
      }
      button:not(.vercode) {
        width: 100%;
@@ -198,7 +214,7 @@
        font-size: 18px;
      }
      .anticon-eye {
        color: #1890ff;
        color: var(--mk-sys-color);
      }
    }
    .login-sync-button {
@@ -209,7 +225,7 @@
  }
  .login-bottom {
    text-align: center;
    color: #ffffff;
    color: var(--mk-sys-font-color);
    padding-top: 20px;
    p span.split {
      margin-right: 15px;
@@ -217,7 +233,7 @@
    a {
      display: inline-block;
      margin-bottom: 5px;
      color: #ffffff;
      color: var(--mk-sys-font-color);
    }
  }
  .ant-btn-primary[disabled] {
src/views/main/index.jsx
@@ -10,7 +10,7 @@
import QueryLog from '@/components/querylog'
import ImgScale from '@/components/imgScale'
import './index.scss'
// import './index.scss'
const Tabview = asyncComponent(() => import('@/components/tabview'))
const Breadview = asyncComponent(() => import('@/components/breadview'))
src/views/main/index.scss
@@ -1,5 +0,0 @@
.mk-main-view {
  display: flex;
  flex: auto;
  min-height: 100%;
}
src/views/menudesign/index.jsx
@@ -1043,7 +1043,8 @@
      }
      let subforbid = {
        editable: '可编辑表格',
        voucher: '凭证'
        voucher: '凭证',
        account: '账套'
      }
      config.components.forEach(item => {
src/views/mobdesign/index.jsx
@@ -68,7 +68,6 @@
    menuloading: false,
    oriConfig: null,
    config: null,
    direction: 'vertical',
    settingshow: true,
    controlshow: true,
    comloading: false,
@@ -91,6 +90,7 @@
        sessionStorage.setItem('typename', param.typename || 'mob')
        sessionStorage.setItem('adapter', param.adapter || '')
        sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
        sessionStorage.setItem('direction', param.direction || 'vertical')
        sessionStorage.setItem('userbind', param.userbind || '')
        sessionStorage.setItem('instantMessage', param.instantMessage || '')
@@ -100,13 +100,6 @@
        window.GLOB.winHeight = 738
        window.GLOB.shellWidth = 376
        window.GLOB.shellHeight = 680
        if (sessionStorage.getItem('typename') === 'pad') {
          window.GLOB.winWidth = 736
          window.GLOB.winHeight = 945
          window.GLOB.shellWidth = 640
          window.GLOB.shellHeight = 853
        }
        let adapters = sessionStorage.getItem('adapter')
        if (adapters) {
@@ -498,7 +491,22 @@
        config.uuid = MenuId
        config.MenuID = MenuId
        config.open_edition = result.open_edition || ''
        config.direction = config.direction || sessionStorage.getItem('direction') || 'vertical'
        window.GLOB.urlFields = config.urlFields || []
        if (sessionStorage.getItem('typename') === 'pad') {
          if (config.direction !== 'vertical') {
            window.GLOB.winWidth = 992
            window.GLOB.winHeight = 690
            window.GLOB.shellWidth = 853
            window.GLOB.shellHeight = 640
          } else {
            window.GLOB.winWidth = 736
            window.GLOB.winHeight = 945
            window.GLOB.shellWidth = 640
            window.GLOB.shellHeight = 853
          }
        }
        if (config.version !== 2.0) {
          config.components = this.collectTB(config.components)
@@ -739,6 +747,21 @@
      config.MenuName = urlParam.MenuName || ''
      // config.MenuNo = urlParam.MenuNo || ''
      config.MenuNo = ''
      config.direction = config.direction || sessionStorage.getItem('direction') || 'vertical'
      if (sessionStorage.getItem('typename') === 'pad') {
        if (config.direction !== 'vertical') {
          window.GLOB.winWidth = 992
          window.GLOB.winHeight = 690
          window.GLOB.shellWidth = 853
          window.GLOB.shellHeight = 640
        } else {
          window.GLOB.winWidth = 736
          window.GLOB.winHeight = 945
          window.GLOB.shellWidth = 640
          window.GLOB.shellHeight = 853
        }
      }
      let navItem = null
      config.components.forEach(item => {
@@ -1809,6 +1832,8 @@
  }
  changeView = (val) => {
    if (sessionStorage.getItem('typename') !== 'pad') return
    if (val !== 'vertical') {
      window.GLOB.winWidth = 992
      window.GLOB.winHeight = 690
@@ -1822,7 +1847,6 @@
    }
    this.setState({
      direction: val,
      comloading: true
    }, () => {
      this.setState({ comloading: false })
@@ -1849,7 +1873,7 @@
    return (
      <ConfigProvider locale={antdZhCN}>
        <div className={'mk-mob-view ' + viewType} id="mk-mob-design-view">
          <Header changeView={this.changeView}/>
          <Header/>
          {loading ? <Spin className="view-spin" size="large" /> : null}
          <DndProvider backend={HTML5Backend}>
            <div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}>
@@ -1866,12 +1890,18 @@
                      config={config}
                      MenuId={MenuId}
                      adapters={adapters}
                      updateConfig={this.updateConfig}
                      updateConfig={(con) => {
                        this.updateConfig(con)
                        if (con.direction !== config.direction) {
                          this.changeView(con.direction)
                        }
                      }}
                    /> : null}
                    {config ? <UrlFieldComponent config={config} updateConfig={this.updateConfig}/> : null}
                    {/* 表名添加 */}
                    {config ? <TableComponent config={config} updatetable={this.updateConfig}/> : null}
                    {config ? <Paragraph style={{padding: '15px 0px 0px 18px'}} copyable={{ text: MenuId }}>菜单ID</Paragraph> : null}
                    {config ? <Paragraph style={{padding: '10px 0px 0px 18px'}} copyable={{ text:  `${window.GLOB.baseurl}mob/index.html#/index/${sessionStorage.getItem('kei_no')}/${sessionStorage.getItem('typename')}/${sessionStorage.getItem('lang')}/${MenuId}/@BID@` }}>菜单链接</Paragraph> : null}
                  </Panel>
                  {/* 组件添加 */}
                  <Panel header="组件" className="component" key="component">
src/views/mobdesign/menuform/index.jsx
@@ -185,6 +185,18 @@
              )}
            </Form.Item>
          </Col>
          <Col span={24}>
            <Form.Item label="屏幕方向">
              {getFieldDecorator('direction', {
                initialValue: config.direction || 'vertical'
              })(
                <Radio.Group onChange={(e) => {this.selectChange('direction', e.target.value)}}>
                  <Radio value="vertical">竖屏</Radio>
                  <Radio value="horizontal">横屏</Radio>
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
          {adapters.includes('app') || adapters.includes('wxmini') ? <Col span={24}>
            <Form.Item className="status-bar" label={
              <Tooltip placement="topLeft" title="在明科云APP或小程序中,状态栏的背景色。">
src/views/systemfunc/index.jsx
@@ -6,12 +6,13 @@
import Header from './header'
import Sidemenu from './sidemenu'
import './index.scss'
// import './index.scss'
const Tabview = asyncComponent(() => import('@/components/tabview'))
class Design extends Component {
  UNSAFE_componentWillMount() {
    document.body.className = 'mk-blue-black'
    sessionStorage.setItem('isEditState', 'true')
    window.GLOB.mkHS = true
@@ -27,7 +28,7 @@
  
  render () {
    return (
      <div className="mk-hs-view">
      <div className="mk-main-view">
        <ConfigProvider locale={zhCN}>
          <Sidemenu key="sidemenu"/>
          <Tabview key="tabview"/>
src/views/systemfunc/index.scss
@@ -1,5 +1 @@
.mk-hs-view {
  display: flex;
  flex: auto;
  min-height: 100%;
}
src/views/systemproc/proc/index.jsx
@@ -1,5 +1,6 @@
import React, {Component} from 'react'
import { Input, notification } from 'antd'
import { Input, notification, Button, Form, Modal, Empty } from 'antd'
import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons'
import moment from 'moment'
import Utils from '@/utils/utils.js'
@@ -7,17 +8,52 @@
import CodeMirror from '@/templates/zshare/codemirror'
import './index.scss'
const { confirm } = Modal
const { Search } = Input
class ProcControl extends Component {
  state = {
    procName: '',
    content: null,
    loading: false
    content: '',
    loading: false,
    visible: false,
    searchable: false,
    inputing: false,
    procList: [],
    permFuncs: []
  }
  componentDidMount () {
    if (sessionStorage.getItem('permFuncField')) {
      this.setState({permFuncs: JSON.parse(sessionStorage.getItem('permFuncField'))})
    } else {
      Api.getCloudConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
        if (res.status) {
          let _permFuncs = []
          if (res.sModular && res.sModular.length > 0) {
            res.sModular.forEach(field => {
              if (field.ModularNo) {
                _permFuncs.push(field.ModularNo)
              }
            })
            _permFuncs = _permFuncs.sort()
          }
          if (_permFuncs.length) {
            this.setState({permFuncs: _permFuncs})
    
            sessionStorage.setItem('permFuncField', JSON.stringify(_permFuncs))
          }
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 5
          })
        }
      })
    }
  }
  search = (value) => {
@@ -47,31 +83,330 @@
        })
        this.setState({content: '', procName: '', loading: false})
        return
      } else if (!res.Ltext) {
        this.setState({content: '', procName: '', loading: false})
      } else {
        this.setState({content: res.Ltext.replace(/mchr13k/ig, '\n'), procName: proc, loading: false})
      }
    })
  }
  save = (type) => {
    const { content, procName, permFuncs } = this.state
    let value = content.replace(/^(\s*)|(\s*)$/ig, '')
    if (!value) {
      notification.warning({
        top: 92,
        message: '存储过程不可为空',
        duration: 5
      })
      return
    } else {
      let chars = [
        {key: 'drop', reg: /(^|\s)drop\s/ig},
        {key: 'alter', reg: /(^|\s)alter\s/ig},
        {key: 'object', reg: /(^|\s)object(\s|\()/ig},
        {key: 'kill', reg: /(^|\s)kill\s/ig},
        {key: '--', reg: /--/ig}
      ]
      let error = ''
      if (!/create(\s+)proc/ig.test(value)) {
        error = '脚本中必须使用create proc'
      }
      chars.forEach(char => {
        if (!error && char.reg.test(value)) {
          error = '不可使用' + char.key
        }
      })
      if (error) {
        notification.warning({
          top: 92,
          message: error,
          duration: 5
        })
        return
      }
    }
    if (!procName) {
      if (permFuncs.length > 0) {
        this.setState({visible: true})
      } else {
        notification.warning({
          top: 92,
          message: '未获取到授权编码不可新建!',
          duration: 5
        })
      }
      return
    }
    let dropfunc = `IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('${procName}') AND type in (N'P', N'PC'))  mdrpk PROCEDURE ${procName}`
    let createfunc = value.replace(/\n/ig, 'mchr13k')
    let dropParam = {
      func: 'sPC_TableData_InUpDe',
      LText: Utils.formatOptions(dropfunc),
      TypeCharOne: 'proc' // 删除存储过程
    }
    dropParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    dropParam.secretkey = Utils.encrypt(dropParam.LText, dropParam.timestamp)
    dropParam.open_key = Utils.encryptOpenKey(dropParam.secretkey, dropParam.timestamp)
    let createParam = {
      func: 'sPC_TableData_InUpDe',
      LText: Utils.formatOptions(createfunc),
      TypeCharOne: 'proc' // 创建存储过程
    }
    createParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    createParam.secretkey = Utils.encrypt(createParam.LText, createParam.timestamp)
    createParam.open_key = Utils.encryptOpenKey(createParam.secretkey, createParam.timestamp)
    let saveParam = {
      func: 's_proc_save',
      sql_script: window.btoa(window.encodeURIComponent(createfunc)),
      proc_name: procName,
      save_type: type !== 'prev' ? 'auto' : '' // 'auto' 时 会清y的数据
    }
    this.setState({loading: true})
    Api.genericInterface(dropParam).then(res => {
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        this.setState({loading: false})
        return
      }
      this.setState({content: res.Ltext.replace(/mchr13k/ig, '\n'), procName: proc, loading: false})
      Api.genericInterface(createParam).then(result => {
        if (!result.status) {
          notification.warning({
            top: 92,
            message: result.message,
            duration: 5
          })
          this.setState({loading: false})
          return
        }
        Api.genericInterface(saveParam).then(response => {
          this.setState({loading: false})
          if (!response.status) {
            notification.warning({
              top: 92,
              message: response.message,
              duration: 5
            })
          } else {
            notification.success({
              top: 92,
              message: '保存成功。',
              duration: 5
            })
          }
        })
      })
    })
  }
  prev = () => {
    const { procName } = this.state
    const that = this
    let saveParam = {
      func: 's_proc_ctrl_z',
      proc_name: procName
    }
    confirm({
      title: '确定切换上一版本吗?',
      content: '',
      onOk() {
        that.setState({loading: true})
        Api.genericInterface(saveParam).then(res => {
          that.setState({loading: false})
          if (!res.status || !res.Ltext) {
            notification.warning({
              top: 92,
              message: !res.status ? res.message : '没有可以后退的版本',
              duration: 5
            })
            return
          }
          let value = window.decodeURIComponent(window.atob(res.Ltext))
          value  = value.replace(/mchr13k/ig, '\n')
          that.setState({content: value}, () => {
            that.save('prev')
          })
        })
      },
      onCancel() {}
    })
  }
  next = () => {
    const { procName } = this.state
    const that = this
    let saveParam = {
      func: 's_proc_ctrl_y',
      proc_name: procName
    }
    confirm({
      title: '确定切换下一版本吗?',
      content: '',
      onOk() {
        that.setState({loading: true})
        Api.genericInterface(saveParam).then(res => {
          that.setState({loading: false})
          if (!res.status || !res.Ltext) {
            notification.warning({
              top: 92,
              message: !res.status ? res.message : '没有可以撤销后退的版本',
              duration: 5
            })
            return
          }
          let value = window.decodeURIComponent(window.atob(res.Ltext))
          value  = value.replace(/mchr13k/ig, '\n')
          that.setState({content: value}, () => {
            that.save()
          })
        })
      },
      onCancel() {}
    })
  }
  handleConfirm = () => {
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (err) return
      this.setState({procName: values.name}, () => {
        this.save()
      })
    })
  }
  searchAll = (value) => {
    let param = {
      func: 's_proc_search',
      proc_name: value || ''
    }
    this.setState({loading: true})
    Api.genericInterface(param).then(res => {
      this.setState({loading: false})
      if (!res.status) {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        return
      }
      this.setState({procList: res.data || []})
    })
  }
  changeProc = (name) => {
    const { loading } = this.state
    if (loading) {
      notification.warning({
        top: 92,
        message: '查询中请稍后。',
        duration: 5
      })
      return
    }
    this.setState({inputing: true, procName: name}, () => {
      this.setState({inputing: false})
      this.search(name)
    })
  }
  render () {
    const { loading, content } = this.state
    const { getFieldDecorator } = this.props.form
    const { loading, content, procName, visible, permFuncs, searchable, procList, inputing } = this.state
    let _patten = permFuncs.length ? new RegExp('^(' + permFuncs.join('|') + ')[0-9a-zA-Z_]*$', 'g') : ''
    return (
      <div className="mk-proc-wrap">
        <div className="control-wrap">
          <div className="search-wrap">
            <Search placeholder="请输入存储过程名称" disabled={loading} enterButton="确定" onSearch={this.search}/>
          </div>
          <div className="action-wrap">
        <div className={'searh-list' + (searchable ? ' open' : '')}>
          <Search placeholder="存储过程名称查询" disabled={loading} onSearch={this.searchAll}/>
          <div className="proc-list">
            {procList.map((item, index) => (<div className="proc-item" onClick={() => this.changeProc(item.proc_name)} key={index}>{item.proc_name}</div>))}
            {procList.length === 0 ? <Empty /> : null}
          </div>
        </div>
        <div className="edit-wrap">
          <CodeMirror value={content} onChange={(val) => this.setState({content: val})}/>
        <div className="proc-wrap">
          <div className="control-wrap">
            <div className="search-wrap">
              {searchable ? <MenuUnfoldOutlined onClick={() => this.setState({searchable: !searchable})}/> : <MenuFoldOutlined onClick={() => this.setState({searchable: !searchable})}/>}
              {!inputing ? <Search placeholder="请输入存储过程名称" defaultValue={procName} disabled={loading} enterButton="确定" onSearch={this.search}/> : null}
            </div>
            <div className="action-wrap">
              <Button key="save" className="mk-btn mk-green" disabled={loading} onClick={() => this.save()}>保存</Button>
              <Button key="prev" className="mk-btn mk-primary" disabled={!procName || loading} onClick={this.prev}>上一版本</Button>
              <Button key="next" className="mk-btn mk-primary" disabled={!procName || loading} onClick={this.next}>下一版本</Button>
            </div>
          </div>
          <div className="edit-wrap">
            <CodeMirror value={content} onChange={(val) => this.setState({content: val})}/>
          </div>
        </div>
        <Modal
          title="新建"
          wrapClassName="mk-create-func"
          visible={visible}
          onOk={this.handleConfirm}
          width={540}
          onCancel={() => {this.setState({ visible: false })}}
          destroyOnClose
        >
          <Form.Item label="存储过程名称">
            {getFieldDecorator('name', {
              initialValue: '',
              rules: [
                {
                  required: true,
                  message: '请输入存储过程名称!'
                },
                {
                  pattern: _patten,
                  message: `只允许包含数字、字母和下划线,且以${permFuncs.join(', ')}等字符开始。`
                }
              ]
            })(<Input placeholder="" autoComplete="off" />)}
          </Form.Item>
        </Modal>
      </div>
    )
  }
}
export default ProcControl
export default Form.create()(ProcControl)
src/views/systemproc/proc/index.scss
@@ -1,12 +1,89 @@
.mk-proc-wrap {
  position: relative;
  padding: 65px 20px 0px;
  display: flex;
  
  .searh-list {
    width: 0px;
    margin-right: 15px;
    overflow: hidden;
    transition: width 0.2s;
    .ant-input-search {
      width: 300px;
    }
    .proc-list {
      width: 300px;
      height: calc(100vh - 128px);
      overflow-y: auto;
      overflow-x: hidden;
      margin-top: 10px;
      border: 1px solid #e8e8e8;
      .proc-item {
        padding: 5px;
        margin: 5px;
        word-break: break-all;
        cursor: pointer;
      }
      .ant-empty {
        margin-top: 50px;
      }
    }
    .proc-list::-webkit-scrollbar {
      width: 7px;
      height: 7px;
    }
    .proc-list::-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);
    }
    .proc-list::-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);
    }
  }
  .searh-list.open {
    width: 300px;
  }
  .proc-wrap {
    flex: 1;
  }
  .control-wrap {
    display: flex;
    .search-wrap {
      width: 300px;
      width: 360px;
      display: flex;
      .ant-btn[disabled] {
        background-color: #1890ff!important;
        border-color: #1890ff!important;
        color: #ffffff!important;
        opacity: 0.5;
      }
      .ant-input {
        border-radius: 0;
      }
      >.anticon {
        line-height: 30px;
        width: 35px;
        border: 1px solid #e8e8e8;
        cursor: pointer;
        border-top-left-radius: 4px;
        border-bottom-left-radius: 4px;
      }
    }
    .action-wrap {
      text-align: right;
      flex: 1;
      .ant-btn {
        margin-left: 20px;
      }
      .ant-btn[disabled] {
        background-color: #1890ff!important;
@@ -33,3 +110,15 @@
    }
  }
}
.mk-create-func {
  .ant-modal-body {
    min-height: 180px;
  }
  .ant-form-item {
    display: flex;
    .ant-form-item-control-wrapper {
      flex: 1;
    }
  }
}