From 4677982c003e357cff8f2544be44706bf31ea6de Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 05 五月 2022 19:12:19 +0800
Subject: [PATCH] 2022-05-05

---
 package-lock.json                                                    |    5 
 src/api/w4k.js                                                       |  113 ++++
 src/menu/components/share/actioncomponent/dragaction/card.jsx        |    2 
 src/tabviews/zshare/normalTable/index.jsx                            |   13 
 public/options.json                                                  |   14 
 src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx       |    8 
 src/views/rolemanage/index.jsx                                       |   18 
 src/tabviews/zshare/actionList/index.jsx                             |   17 
 src/api/index.js                                                     |   24 
 src/tabviews/custom/components/share/normalTable/index.jsx           |    7 
 src/templates/sharecomponent/actioncomponent/dragaction/card.jsx     |    2 
 src/tabviews/custom/components/card/cardcellList/index.jsx           |   16 
 src/templates/zshare/formconfig.jsx                                  |   28 
 src/menu/components/share/actioncomponent/formconfig.jsx             |   22 
 src/templates/sharecomponent/actioncomponent/actionform/index.jsx    |    2 
 src/tabviews/zshare/actionList/funcMegvii/index.jsx                  |  547 +++++++++++++++++++++
 src/menu/components/share/actioncomponent/index.jsx                  |   80 +-
 src/templates/sharecomponent/actioncomponent/verifymegvii/index.jsx  |  249 +++++++++
 src/setupProxy.js                                                    |   97 +-
 src/templates/sharecomponent/actioncomponent/verifymegvii/index.scss |   38 +
 src/tabviews/zshare/actionList/funcMegvii/mock.js                    |   27 +
 src/menu/components/share/actioncomponent/actionform/index.jsx       |    4 
 src/templates/sharecomponent/actioncomponent/index.jsx               |   80 +-
 package.json                                                         |    1 
 src/tabviews/zshare/fileupload/index.jsx                             |  111 ++-
 src/tabviews/zshare/actionList/funcMegvii/index.scss                 |   26 +
 26 files changed, 1,345 insertions(+), 206 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index e8545cb..95bceca 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5888,6 +5888,11 @@
         "randomfill": "^1.0.3"
       }
     },
+    "crypto-js": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
+      "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
+    },
     "css": {
       "version": "2.2.4",
       "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz",
diff --git a/package.json b/package.json
index 5965a90..19c51c9 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
     "camelcase": "^5.2.0",
     "case-sensitive-paths-webpack-plugin": "2.2.0",
     "codemirror": "^5.52.2",
+    "crypto-js": "^4.1.1",
     "css-loader": "2.1.1",
     "dotenv": "6.2.0",
     "dotenv-expand": "4.2.0",
diff --git a/public/options.json b/public/options.json
index fa76f1c..f5f2215 100644
--- a/public/options.json
+++ b/public/options.json
@@ -1,18 +1,18 @@
 {
-  "appId": "201912040924165801464FF1788654BC5AC73",
-  "appkey": "20191106103859640976D6E924E464D029CF0",
+  "appId": "202108312122504607B107A83F55B40C98CCF",
+  "appkey": "20210831212235413F287EC3BF489424496C8",
   "mainSystemApi": "http://sso.mk9h.cn/cloud/webapi/dostars",
   "systemType": "",
   "externalDatabase": "false",
   "lineColor": "",
   "filter": "false",
-  "defaultApp": "mk",
+  "defaultApp": "mkindustry",
   "defaultLang": "zh-CN",
   "WXAppID": "",
   "debugger": false,
-  "licenseKey": "",
-  "probation": "",
+  "licenseKey": "7EFE13KIKLILIJB64C12",
+  "probation": "2021-12-31",
   "keepPassword": "true",
-  "host": "http://qingqiumarket.cn",
-  "service": "MKWMS/"
+  "host": "http://demo.mk9h.cn",
+  "service": "erp_new/"
 }
\ No newline at end of file
diff --git a/src/api/index.js b/src/api/index.js
index a542dfc..bdaed71 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -66,16 +66,22 @@
     return Promise.resolve(response.data)
   }
 }, (error) => {
-  if (error && error.response) {
-    notification.error({
-      className: 'notification-custom-error',
-      bottom: 0,
-      message: '鐘舵�佺爜-' + error.response.status + '锛岃鑱旂郴绠$悊鍛�',
-      placement: 'bottomRight',
-      duration: 15
-    })
+  let response = error.response
+
+  if (response) {
+    if (!response.data || !response.data.errors) { // 杩囨护鏃疯鎶ラ敊淇℃伅
+      notification.error({
+        className: 'notification-custom-error',
+        bottom: 0,
+        message: '鐘舵�佺爜-' + response.status + '锛岃鑱旂郴绠$悊鍛�',
+        placement: 'bottomRight',
+        duration: 15
+      })
+    }
+    return Promise.reject(response)
+  } else {
+    return Promise.reject()
   }
-  return Promise.reject(error.response)
 })
 
 class Api {
diff --git a/src/api/w4k.js b/src/api/w4k.js
new file mode 100644
index 0000000..5c47975
--- /dev/null
+++ b/src/api/w4k.js
@@ -0,0 +1,113 @@
+import axios from 'axios'
+import jsSHA from 'jssha'
+
+class W4kApi {
+  /**
+   * @description 閴存潈鎸戞垬
+   * @param {Object} param 鏌ヨ鍙婃彁浜ゅ弬鏁�
+   */
+  login (ip, username = 'admin', password) {
+    return new Promise((resolve, reject) => {
+      let challurl = ip + '/api/auth/login/challenge?username=' + username
+      challurl = '/trans/redirect?rd=' + challurl + '&method=get'
+
+      let loginurl = ip + '/api/auth/login'
+      loginurl = '/trans/redirect?rd=' + loginurl + '&method=post'
+
+      axios({ 
+        url: challurl,
+        method: 'post' // get
+      }).then(res => {
+        if (res.errors) {
+          reject(res)
+        } else {
+          const shaObj = new jsSHA('SHA-256', 'TEXT', { encoding: 'UTF8' })
+          shaObj.update(password + res.salt + res.challenge)
+          const hash = shaObj.getHash('HEX')
+  
+          axios({
+            url: loginurl,
+            method: 'post',
+            data: {
+              session_id: res.session_id,
+              username: username,
+              password: hash
+            }
+          }).then(result => {
+            resolve(result)
+          }, (err) => {
+            reject(err)
+          })
+        }
+      }, (err) => {
+        reject(err)
+      })
+    })
+  }
+
+  queryUsers (ip) {
+    let url = ip + '/api/persons/query'
+    url = '/trans/redirect?rd=' + url + '&method=post'
+
+    return axios({
+      url: url,
+      method: 'POST',
+      withCredentials: true,
+      headers: { 'Content-Type': 'application/json' },
+      data: {
+        limit: 100,
+        offset: 0,
+        sort: 'desc',
+        query_id: '',
+        query_string: ''
+      }
+    })
+  }
+
+  addUsers (ip, data) {
+    return new Promise((resolve, reject) => {
+      let delurl = ip + '/api/persons/item/' + data.id
+      delurl = '/trans/redirect?rd=' + delurl + '&method=DELETE'
+
+      let addurl = ip + '/api/persons/item'
+      addurl = '/trans/redirect?rd=' + addurl + '&method=post'
+
+      if (data.deleted) {
+        delete data.deleted
+        axios({ 
+          url: delurl,
+          method: 'post' // DELETE
+        }).then(res => {
+          if (res.errors) {
+            reject(res)
+          } else {
+            axios({
+              url: addurl,
+              method: 'post',
+              data: data
+            }).then(result => {
+              resolve(result)
+            }, (err) => {
+              reject(err)
+            })
+          }
+        }, (err) => {
+          reject(err)
+        })
+      } else {
+        delete data.deleted
+        axios({
+          url: addurl,
+          method: 'post',
+          data: data
+        }).then(result => {
+          resolve(result)
+        }, (err) => {
+          reject(err)
+        })
+      }
+    })
+  }
+}
+
+export default new W4kApi()
\ No newline at end of file
diff --git a/src/menu/components/share/actioncomponent/actionform/index.jsx b/src/menu/components/share/actioncomponent/actionform/index.jsx
index ce4fea6..06d891e 100644
--- a/src/menu/components/share/actioncomponent/actionform/index.jsx
+++ b/src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -344,8 +344,8 @@
         reTooltip.linkmenu = '浣跨敤鎵爜鐧诲綍鍔熻兘鎴栬彍鍗曡烦杞姛鑳芥椂锛岄渶閫夋嫨璺宠浆鐨勮彍鍗曘��'
       } else if (_funcType === 'goBack') {
         shows.push('reload')
-      // } else if (_funcType === 'megvii') {
-      //   shows.push('subFunc')
+      } else if (_funcType === 'megvii') {
+        shows.push('subFunc')
       }
     }
     
diff --git a/src/menu/components/share/actioncomponent/dragaction/card.jsx b/src/menu/components/share/actioncomponent/dragaction/card.jsx
index 2e38f86..9ff2c22 100644
--- a/src/menu/components/share/actioncomponent/dragaction/card.jsx
+++ b/src/menu/components/share/actioncomponent/dragaction/card.jsx
@@ -37,6 +37,8 @@
     hasProfile = true
   } else if (card.funcType === 'print') {
     hasProfile = true
+  } else if (card.funcType === 'megvii') {
+    hasProfile = true
   }
 
   let btnElement = null
diff --git a/src/menu/components/share/actioncomponent/formconfig.jsx b/src/menu/components/share/actioncomponent/formconfig.jsx
index 171b5ef..2ce0980 100644
--- a/src/menu/components/share/actioncomponent/formconfig.jsx
+++ b/src/menu/components/share/actioncomponent/formconfig.jsx
@@ -88,6 +88,7 @@
     { value: 'changeuser', text: '鍒囨崲鐢ㄦ埛' },
     { value: 'print', text: '鏍囩鎵撳嵃' },
     { value: 'closetab', text: '鏍囩鍏抽棴' },
+    { value: 'megvii', text: '鏃疯闈㈡澘鏈�' },
   ]
   
   if (isApp) {
@@ -112,7 +113,6 @@
       { value: 'mkUnsubscribe', text: '娉ㄩ攢璐︽埛' },
       { value: 'reAuth', text: '鍒囨崲绯荤粺锛堟竻绌虹紦瀛�-灏忕▼搴忥級' },
       { value: 'goBack', text: '杩斿洖' },
-      // { value: 'megvii', text: '鏃疯闈㈡澘鏈�' },
     ]
     pageTemps = [
       { value: 'linkpage', text: '鍏宠仈鑿滃崟' },
@@ -179,16 +179,16 @@
       required: true,
       options: funTypes
     },
-    // {
-    //   type: 'select',
-    //   key: 'subFunc',
-    //   label: '鎺ュ彛鍚嶇О',
-    //   initVal: card.subFunc || '',
-    //   required: true,
-    //   options: [
-    //     { value: 'login', text: '鐧诲綍' }
-    //   ]
-    // },
+    {
+      type: 'radio',
+      key: 'subFunc',
+      label: '鎺ュ彛鍚嶇О',
+      initVal: card.subFunc || 'addUser',
+      required: true,
+      options: [
+        { value: 'addUser', text: '娣诲姞鐢ㄦ埛' },
+      ]
+    },
     {
       type: 'radio',
       key: 'formType',
diff --git a/src/menu/components/share/actioncomponent/index.jsx b/src/menu/components/share/actioncomponent/index.jsx
index 6f5275c..de91452 100644
--- a/src/menu/components/share/actioncomponent/index.jsx
+++ b/src/menu/components/share/actioncomponent/index.jsx
@@ -21,6 +21,7 @@
 const VerifyPrint = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyprint'))
 const VerifyExcelIn = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelin'))
 const VerifyExcelOut = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelout'))
+const VerifyMegvii = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifymegvii'))
 
 class ActionComponent extends Component {
   static propTpyes = {
@@ -446,6 +447,51 @@
     })
   }
 
+  getVerify = (card) => {
+    const { config } = this.props
+    const { dict } = this.state
+
+    if (!card) return null
+
+    if (['pop', 'prompt', 'exec'].includes(card.OpenType)) {
+      return <VerifyCard
+        card={card}
+        dict={dict}
+        config={config}
+        columns={config.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    } else if (card.OpenType === 'excelIn') {
+      return <VerifyExcelIn
+        card={card}
+        dict={dict}
+        columns={config.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    } else if (card.OpenType === 'excelOut') {
+      return <VerifyExcelOut
+        card={card}
+        dict={dict}
+        config={config}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    } else if (card.OpenType === 'funcbutton' && card.funcType === 'print') {
+      return <VerifyPrint
+        card={card}
+        dict={dict}
+        columns={config.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    } else if (card.OpenType === 'funcbutton' && card.funcType === 'megvii') {
+      return <VerifyMegvii
+        card={card}
+        dict={dict}
+        columns={config.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    }
+  }
+
   render() {
     const { config, type } = this.props
     const { actionlist, visible, appType, card, dict, profVisible } = this.state
@@ -507,39 +553,7 @@
           }}
           destroyOnClose
         >
-          {card && !card.execMode && card.OpenType !== 'excelIn' && card.OpenType !== 'excelOut' ?
-            <VerifyCard
-              card={card}
-              dict={dict}
-              config={config}
-              columns={config.columns}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-          {card && card.execMode ?
-            <VerifyPrint
-              card={card}
-              dict={dict}
-              columns={config.columns}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-          {card && card.OpenType === 'excelIn' ?
-            <VerifyExcelIn
-              card={card}
-              dict={dict}
-              columns={config.columns}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-          {card && card.OpenType === 'excelOut' ?
-            <VerifyExcelOut
-              card={card}
-              dict={dict}
-              config={config}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
+          {this.getVerify(card)}
         </Modal>
       </div>
     )
diff --git a/src/setupProxy.js b/src/setupProxy.js
index c5707d5..78c88f7 100644
--- a/src/setupProxy.js
+++ b/src/setupProxy.js
@@ -1,52 +1,55 @@
-// const proxy = require('http-proxy-middleware')
-// const host = 'http://qingqiumarket.cn'
-// const service = 'mkwms/'
+const proxy = require('http-proxy-middleware')
+const host = 'http://qingqiumarket.cn'
+const service = 'mkwms/'
 
-module.exports = function() {}
-// module.exports = function(app) {
-//   app.use(proxy('/webapi', { 
-//     target: `${host}/${service}webapi`,
-//     secure: false,
-//     changeOrigin: true,
-//     pathRewrite: {
-//     '^/webapi': '/'
-//     }
-//     // cookieDomainRewrite: "http://localhost:3000"
-//   }))
+// module.exports = function(app) {}
+module.exports = function(app) {
+  // app.use(proxy('/webapi', { 
+  //   target: `${host}/${service}webapi`,
+  //   secure: false,
+  //   changeOrigin: true,
+  //   pathRewrite: {
+  //   '^/webapi': '/'
+  //   }
+  //   // cookieDomainRewrite: "http://localhost:3000"
+  // }))
   
-//   app.use(proxy('/zh-CN', { // 鐧诲綍鎺ュ彛
-//     target: `${host}/${service}zh-CN`,
-//     secure: false,
-//     changeOrigin: true,
-//     pathRewrite: {
-//     '^/zh-CN': '/'
-//     }
-//   }))
+  // app.use(proxy('/zh-CN', { // 鐧诲綍鎺ュ彛
+  //   target: `${host}/${service}zh-CN`,
+  //   secure: false,
+  //   changeOrigin: true,
+  //   pathRewrite: {
+  //   '^/zh-CN': '/'
+  //   }
+  // }))
 
-//   app.use(proxy('/Upload', {
-//     target: `${host}/${service}zh-CN/Home/Upload`,
-//     secure: false,
-//     changeOrigin: true,
-//     pathRewrite: {
-//     '^/Upload': '/'
-//     }
-//   }))
+  // app.use(proxy('/Upload', {
+  //   target: `${host}/${service}zh-CN/Home/Upload`,
+  //   secure: false,
+  //   changeOrigin: true,
+  //   pathRewrite: {
+  //   '^/Upload': '/'
+  //   }
+  // }))
 
-//   app.use(proxy('/wxpay', {
-//     target: `${host}/${service}wxpay`,
-//     secure: false,
-//     changeOrigin: true,
-//     pathRewrite: {
-//     '^/wxpay': '/'
-//     }
-//   }))
+  // app.use(proxy('/wxpay', {
+  //   target: `${host}/${service}wxpay`,
+  //   secure: false,
+  //   changeOrigin: true,
+  //   pathRewrite: {
+  //   '^/wxpay': '/'
+  //   }
+  // }))
 
-//   app.use(proxy('/trans', {
-//     target: `${host}/${service}trans`,
-//     secure: false,
-//     changeOrigin: true,
-//     pathRewrite: {
-//     '^/trans': '/'
-//     }
-//   }))
-// }
\ No newline at end of file
+  app.use(proxy('/trans', {
+    target: `${host}/${service}`,
+    secure: false,
+    changeOrigin: true
+  }))
+
+  app.use(proxy('/api', { // 鏃疯闈㈡澘鏈烘帴鍙f祴璇�
+    target: `http://192.168.1.66:80`,
+    secure: false,
+    changeOrigin: true
+  }))
+}
\ No newline at end of file
diff --git a/src/tabviews/custom/components/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx
index 50fb15b..04bd074 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.jsx
+++ b/src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -21,6 +21,7 @@
 const NewPageButton = asyncComponent(() => import('@/tabviews/zshare/actionList/newpagebutton'))
 const ChangeUserButton = asyncComponent(() => import('@/tabviews/zshare/actionList/changeuserbutton'))
 const PrintButton = asyncComponent(() => import('@/tabviews/zshare/actionList/printbutton'))
+const FuncMegvii = asyncComponent(() => import('@/tabviews/zshare/actionList/funcMegvii'))
 const BarCode = asyncElementComponent(() => import('@/components/barcode'))
 const QrCode = asyncElementComponent(() => import('@/components/qrcode'))
 const MkProgress = asyncElementComponent(() => import('@/components/mkProgress'))
@@ -873,6 +874,21 @@
               />
             </Col>
           )
+        } else if (card.funcType === 'megvii') {
+          return (
+            <Col key={card.uuid} className="mk-cell-btn" style={card.wrapStyle} span={card.width}>
+              <FuncMegvii
+                BID={data.$$BID}
+                disabled={_disabled}
+                lineId={data.$$key || ''}
+                btn={card}
+                show={card.show}
+                style={card.style}
+                setting={cards.setting}
+                selectedData={_data}
+              />
+            </Col>
+          )
         }
       }
     }
diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx
index 0c6f9ad..a646dcb 100644
--- a/src/tabviews/custom/components/share/normalTable/index.jsx
+++ b/src/tabviews/custom/components/share/normalTable/index.jsx
@@ -224,7 +224,12 @@
       let photos = ''
       if (record[col.field]) {
         photos = `${record[col.field]}`
-        photos = photos.split(',')
+      }
+
+      if (/^data:image/.test(photos)) {
+        photos = [photos]
+      } else {
+        photos = photos.split(',').filter(Boolean)
       }
 
       let cols = 24 / (col.picSort || 1)
diff --git a/src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx b/src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx
index b2c76db..cd65eaa 100644
--- a/src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx
+++ b/src/tabviews/zshare/actionList/excelInbutton/excelin/index.jsx
@@ -61,8 +61,12 @@
             btn.verify.columns.forEach(op => {
               let _name = typeof(header[op.Column]) === 'string' ? header[op.Column].replace(/(^\s*|\s*$)/g, '') : header[op.Column]
               let _text = op.Text ? op.Text.replace(/(^\s*|\s*$)/g, '') : op.Text
-              
-              if (_name !== _text && !iserror) {
+
+              if (!_name && !iserror) {
+                iserror = true
+                errors = 'headerError'
+                errDetail = `Excel涓笉瀛樺湪锛�${_text}锛夊垪锛乣
+              } else if (_name !== _text && !iserror) {
                 iserror = true
                 errors = 'headerError'
                 errDetail = `Excel涓紙${_name}锛変笌鎸夐挳鍒椾俊鎭紙${_text}锛変笉涓�鑷达紒`
diff --git a/src/tabviews/zshare/actionList/funcMegvii/index.jsx b/src/tabviews/zshare/actionList/funcMegvii/index.jsx
new file mode 100644
index 0000000..42a12e9
--- /dev/null
+++ b/src/tabviews/zshare/actionList/funcMegvii/index.jsx
@@ -0,0 +1,547 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { withRouter } from 'react-router'
+import { is, fromJS } from 'immutable'
+import { Button, Modal, notification, message } from 'antd'
+import CryptoJS from 'crypto-js'
+import moment from 'moment'
+
+import NApi from '@/api'
+import Utils from '@/utils/utils.js'
+import Api from '@/api/w4k.js'
+import MKEmitter from '@/utils/events.js'
+import MkIcon from '@/components/mk-icon'
+
+// import { mockdata } from './mock'
+
+import './index.scss'
+
+class FuncButton extends Component {
+  static propTpyes = {
+    btn: PropTypes.object,            // 鎸夐挳
+    disabled: PropTypes.any,          // 琛屾寜閽鐢�
+  }
+
+  state = {
+    loading: false,
+    disabled: false,
+    loadingNumber: '',
+    hidden: false,
+    IpList: [],
+    lines: [],
+    selectIp: {},
+    visible: false
+  }
+
+  UNSAFE_componentWillMount () {
+    const { btn, selectedData } = this.props
+    let disabled = false
+
+    if (btn.controlField && selectedData && selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒�
+      selectedData.forEach(item => {
+        let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
+        if (btn.controlVals.includes(s)) {
+          disabled = true
+        }
+      })
+      this.setState({hidden: disabled && btn.control === 'hidden'})
+    }
+
+    if (this.props.disabled || disabled) {
+      this.setState({disabled: true})
+    }
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('triggerBtnId', this.actionTrigger)
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    const { btn, selectedData } = this.props
+
+    let disabled = false
+    if (btn.controlField && !is(fromJS(nextProps.selectedData || []), fromJS(selectedData || []))) {
+      if (nextProps.selectedData && nextProps.selectedData.length > 0) { // 琛ㄦ牸涓寜閽殣钘忔帶鍒�
+        nextProps.selectedData.forEach(item => {
+          let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
+          if (btn.controlVals.includes(s)) {
+            disabled = true
+          }
+        })
+      }
+      this.setState({hidden: disabled && btn.control === 'hidden'})
+    }
+
+    if (nextProps.disabled || disabled) {
+      this.setState({disabled: true})
+    } else {
+      this.setState({disabled: false})
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('triggerBtnId', this.actionTrigger)
+  }
+
+  /**
+   * @description 瑙﹀彂鎸夐挳鎿嶄綔
+   */
+  actionTrigger = (triggerId, record, type) => {
+    const { Tab, BID, btn, selectedData, setting } = this.props
+    const { loading, disabled } = this.state
+
+    if (loading || disabled) return
+    if (triggerId) {
+      if (btn.uuid !== triggerId) return
+      if (this.props.lineId && record && record[0] && this.props.lineId !== record[0].$$key) {
+        return
+      }
+    }
+
+    if (((Tab && Tab.supMenu) || setting.supModule) && !BID) {
+      notification.warning({
+        top: 92,
+        message: '闇�瑕佷笂绾т富閿�硷紒',
+        duration: 5
+      })
+      return
+    } else if (type === 'linkbtn' && selectedData && selectedData.length === 1) {
+      if (record[0].$Index !== selectedData[0].$Index) {
+        return
+      }
+    }
+
+    let data = record || selectedData || []
+    // let data = fromJS(mockdata.data).toJS()
+    
+    if (data.length === 0) {
+      // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨琛岋紒',
+        duration: 5
+      })
+      return
+    }
+
+    this.setState({
+      loading: true,
+      lines: data
+    })
+
+    this.getIpList()
+  }
+
+  getIpList = () => {
+    let _scriptSql = `select ID,data_code,data_name,Remark,face_ip,face_uname,face_pwd from bd_data where typecharone='face_device'  and deleted=0`
+
+    _scriptSql = Utils.formatOptions(_scriptSql)
+
+    let _sParam = {
+      func: 'sPC_Get_SelectedList',
+      LText: _scriptSql,
+      obj_name: 'data',
+      arr_field: 'ID,data_code,data_name,Remark,face_ip,face_uname,face_pwd'
+    }
+    
+    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
+    
+    NApi.getSystemCacheConfig(_sParam).then(res => {
+      if (res.status) {
+        let IpList = res.data || []
+
+        if (IpList.length === 0) {
+          notification.warning({
+            top: 92,
+            message: '鏈幏鍙栧埌璁惧淇℃伅锛�',
+            duration: 5
+          })
+          this.setState({
+            loading: false
+          })
+        } else {
+          this.setState({
+            IpList: IpList.map(item => {
+              if (item.face_ip) {
+                if (!/^http:/.test(item.face_ip)) {
+                  item.face_ip = 'http://' + item.face_ip
+                }
+                if (!/:\d{2,4}$/.test(item.face_ip)) {
+                  item.face_ip = item.face_ip + ':80'
+                }
+              }
+              return item
+            }),
+            selectIp: {},
+            visible: true
+          })
+        }
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  loginDevice = () => {
+    const { lines, selectIp } = this.state
+
+    // let ip = 'http://localhost:3001'
+    let ip = selectIp.face_ip
+
+    Api.login(ip, selectIp.face_uname, selectIp.face_pwd).then(result => {
+      if (result.errors) {
+        this.execPreError(result)
+        return
+      }
+
+      document.cookie = 'sessionID=' + result.session_id
+
+      Api.queryUsers(ip).then(res => {
+        if (res.errors) {
+          this.execPreError(res)
+          return
+        }
+
+        let persons = {}
+        res.data.forEach(item => {
+          persons[item.id] = true
+        })
+
+        let data = lines.map(cell => {
+          let item = {}
+          Object.keys(cell).forEach(key => {
+            item[key.toLowerCase()] = cell[key]
+          })
+
+          return {
+            deleted: persons[item.id] || false,
+            recognition_type: item.recognition_type || 'staff',
+            is_admin: item.is_admin === 'true',
+            person_name: item.person_name || '',
+            id: item.id || '',
+            card_number: item.card_number || '',
+            person_code: item.person_code || '',
+            group_list: item.group_list ? item.group_list.split(',') : [],
+            password: item.password || '',
+            id_number: item.id_number || '',
+            face_list: [{
+              idx: item.face_idx || 0,
+              data: item.face_data ? item.face_data.replace(/^data:image\/(jpeg|png|jpg|gif);base64,/, '') : '',
+            }]
+          }
+        })
+
+        this.addUser(ip, data, result.session_id)
+      })
+    }, err => {
+      this.execPreError(err)
+    })
+  }
+
+  addUser = (ip, datas, sessionId) => {
+    let data = datas.shift()
+
+    this.setState({
+      loadingNumber: datas.length || ''
+    })
+
+    let error = ''
+    if (!data.person_name) {
+      error = '浜哄憳鍚嶇О涓嶅彲涓虹┖'
+    } else if (!data.id) {
+      error = '浜哄憳id涓嶅彲涓虹┖'
+    } else if (data.group_list.length === 0) {
+      error = '浜哄憳鍒嗙粍涓嶅彲涓虹┖'
+    } else if (!data.face_list[0].data) {
+      error = '浜哄憳鍥剧墖涓嶅彲涓虹┖'
+    } else if (data.password) {
+      if (/^\d{6}$/.test(data.password)) {
+        let key = CryptoJS.enc.Utf8.parse(sessionId)
+        let srcs = CryptoJS.enc.Utf8.parse(data.password)
+        let encrypted = CryptoJS.AES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7})
+
+        data.password = CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
+      } else {
+        error = '瀵嗙爜浣跨敤6浣嶆暟瀛�'
+      }
+    }
+
+    if (error) {
+      this.execError({ErrCode: 'E', ErrMesg: error})
+      return
+    }
+
+    if (data.id_number) {
+      let key = CryptoJS.enc.Utf8.parse(sessionId)
+      let srcs = CryptoJS.enc.Utf8.parse(data.id_number)
+      let encrypted = CryptoJS.AES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7})
+
+      data.id_number = CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
+    }
+
+    Api.addUsers(ip, data).then(res => {
+      if (res.errors) {
+        this.execPreError(res, data)
+        return
+      }
+      if (datas.length > 0) {
+        this.addUser(ip, datas, sessionId)
+      } else {
+        this.execSuccess({ErrCode: 'S', ErrMesg: '鎵ц鎴愬姛銆�'})
+      }
+    }, (err) => {
+      this.execPreError(err, data)
+    })
+  }
+
+  /**
+   * @description 鎿嶄綔鎴愬姛鍚庡鐞�
+   * 1銆乪xcel瀵煎嚭锛屾垚鍔熷悗鍙栨秷瀵煎嚭鎸夐挳鍔犺浇涓姸鎬�
+   * 2銆佺姸鎬佺爜涓� S 鏃讹紝鏄剧ず鎴愬姛淇℃伅鍚庣郴缁熼粯璁や俊鎭�
+   * 3銆佺姸鎬佺爜涓� -1 鏃讹紝涓嶆樉绀轰换浣曚俊鎭�
+   * 4銆佹ā鎬佹鎵ц鎴愬姛鍚庢槸鍚﹀叧闂�
+   * 5銆侀�氱煡涓诲垪琛ㄥ埛鏂�
+   */
+  execSuccess = (res) => {
+    const { btn } = this.props
+
+    if (res && (res.ErrCode === 'S' || !res.ErrCode)) { // 鎵ц鎴愬姛
+      notification.success({
+        top: 92,
+        message: res.ErrMesg || '鎵ц鎴愬姛',
+        duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
+      })
+    } else if (res && res.ErrCode === 'Y') { // 鎵ц鎴愬姛
+      Modal.success({
+        title: res.ErrMesg || '鎵ц鎴愬姛'
+      })
+    } else if (res && res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
+
+    }
+
+    this.setState({
+      loading: false,
+      loadingNumber: ''
+    })
+
+    if (btn.execSuccess !== 'never') {
+      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn)
+    }
+  }
+
+  execPreError = (err, data) => {
+    if (err.data && err.data.errors && err.data.errors[0]) {
+      let error = err.data.errors[0]
+      let message = error.detail
+      if (error.source.pointer === '/api/persons/item' && error.error_code) {
+        let list = [
+          {val: 1, msg: '鍥剧墖鏍煎紡閿欒'},
+          {val: 2, msg: '鍥剧墖澶у皬瓒呭嚭闄愬埗'},
+          {val: 3, msg: '鍥剧墖鍒嗚鲸鐜囪秴鍑洪檺鍒�'},
+          {val: 16, msg: '浜鸿劯鏃犵壒寰佸��'},
+          {val: 17, msg: '鍏ュ簱鏃犲浘鐗�'},
+          {val: 18, msg: '鏈娴嬪埌浜鸿劯'},
+          {val: 19, msg: '妫�娴嬪埌澶氫釜浜鸿劯'},
+          {val: 20, msg: '浜鸿劯澶皬'},
+          {val: 21, msg: '鍥剧墖澶寒'},
+          {val: 22, msg: '鍥剧墖澶殫'},
+          {val: 23, msg: '浜鸿劯澶ā绯�'},
+          {val: 24, msg: '浜鸿劯鏂瑰悜閿欒'},
+          {val: 32, msg: '鏁版嵁搴撴弧'},
+          {val: 33, msg: '浜鸿劯鍥剧墖閲嶅'},
+          {val: 34, msg: '浜哄憳缂栧彿閲嶅'},
+          {val: 35, msg: '鍗″彿閲嶅'},
+          {val: 48, msg: '浜哄憳鍚嶇О閲嶅'},
+          {val: -1, msg: '鏈煡閿欒'},
+          {val: -2141716476, msg: '绯荤粺鍙傛暟閿欒锛屾湁鍙兘鏄汉鍛樼粍涓嶅瓨鍦ㄣ��'},
+        ]
+
+        list.forEach(item => {
+          if (item.val === error.error_code) {
+            message = (data ? data.person_name + ' - ' : '') + item.msg
+          }
+        })
+      }
+
+      this.execError({
+        ErrCode: 'E',
+        message: message
+      })
+    } else {
+      this.execError({
+        ErrCode: 'E',
+        message: '璇锋鏌ヨ澶囩姸鎬侊紒'
+      })
+    }
+  }
+
+  /**
+   * @description 鎿嶄綔澶辫触鍚庡鐞�
+   */
+  execError = (res) => {
+    const { btn } = this.props
+
+    if (res.ErrCode === 'E') {
+      Modal.error({
+        title: res.message || res.ErrMesg,
+      })
+    } else if (res.ErrCode === 'N') {
+      notification.error({
+        top: 92,
+        message: res.message || res.ErrMesg,
+        duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
+      })
+    } else if (res.ErrCode === 'F') {
+      notification.error({
+        className: 'notification-custom-error',
+        top: 92,
+        message: res.message || res.ErrMesg,
+        duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
+      })
+    } else if (res.ErrCode === 'NM') {
+      message.error(res.message || res.ErrMesg)
+    }
+    
+    this.setState({
+      loading: false,
+      loadingNumber: ''
+    })
+
+    if (btn.execError !== 'never') {
+      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn)
+    }
+  }
+
+  handleOk = () => {
+    const { selectIp } = this.state
+
+    if (!selectIp.ID) {
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨闈㈡澘鏈猴紒',
+        duration: 5
+      })
+      return
+    } else if (!selectIp.face_ip) {
+      notification.warning({
+        top: 92,
+        message: '闈㈡澘鏈篒P缂哄け锛�',
+        duration: 5
+      })
+      return
+    } else if (!selectIp.face_uname) {
+      notification.warning({
+        top: 92,
+        message: '闈㈡澘鏈虹敤鎴峰悕缂哄け锛�',
+        duration: 5
+      })
+      return
+    } else if (!selectIp.face_pwd) {
+      notification.warning({
+        top: 92,
+        message: '闈㈡澘鏈哄瘑鐮佺己澶憋紒',
+        duration: 5
+      })
+      return
+    }
+
+    this.setState({
+      visible: false
+    })
+
+    this.loginDevice()
+  }
+
+  getModels = () => {
+    const { IpList, visible, selectIp } = this.state
+
+    return (
+      <Modal
+        title="璇烽�夋嫨闈㈡澘鏈�"
+        maskClosable={false}
+        getContainer={document.body}
+        wrapClassName='ip-list-modal'
+        visible={visible}
+        width={700}
+        onOk={this.handleOk}
+        onCancel={() => this.setState({visible: false, loading: false})}
+        destroyOnClose
+      >
+        {IpList.map(item => {
+          return <div className={'ip-item' + (selectIp.ID === item.ID ? ' active' : '')} key={item.ID} onClick={() => {this.setState({selectIp: item})}}>
+            <div className="ip">IP锛歿item.face_ip}</div>
+            <div className="user">鐢ㄦ埛锛歿item.face_uname}</div>
+            <div className="remark">澶囨敞锛歿item.Remark}</div>
+          </div>
+        })}
+      </Modal>
+    )
+  }
+
+  render() {
+    const { btn, show } = this.props
+    const { loading, disabled, hidden, loadingNumber } = this.state
+
+    if (hidden) return null
+
+    if (show === 'actionList') {
+      return (
+        <>
+          <Button
+            icon={btn.icon}
+            loading={loading}
+            disabled={disabled}
+            title={disabled ? (btn.reason || '') : ''}
+            className={'mk-btn mk-' + btn.class}
+            onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
+          >{(loadingNumber ? `(${loadingNumber})` : '') + btn.label}</Button>
+          {this.getModels()}
+        </>
+      )
+    } else { // icon銆乼ext銆� all 鍗$墖
+      let label = ''
+      let icon = ''
+
+      if (show === 'button') {
+        label = btn.label
+        icon = btn.icon || ''
+      } else if (show === 'link') {
+        label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
+        icon = ''
+      } else if (show === 'icon') {
+        icon = btn.icon || ''
+      } else {
+        label = btn.label
+      }
+
+      return (
+        <>
+          <Button
+            type="link"
+            title={disabled ? (btn.reason || '') : (show === 'icon' ? btn.label : '')}
+            loading={loading}
+            disabled={disabled}
+            style={btn.style}
+            icon={icon}
+            onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
+          >{label}</Button>
+          {this.getModels()}
+        </>
+      )
+    }
+  }
+}
+
+export default withRouter(FuncButton)
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/funcMegvii/index.scss b/src/tabviews/zshare/actionList/funcMegvii/index.scss
new file mode 100644
index 0000000..eed792c
--- /dev/null
+++ b/src/tabviews/zshare/actionList/funcMegvii/index.scss
@@ -0,0 +1,26 @@
+.ip-list-modal {
+  .ip-item {
+    display: inline-block;
+    border: 1px solid #d9d9d9;
+    padding: 10px;
+    height: 100px;
+    width: calc(33% - 20px);
+    margin: 10px;
+    cursor: pointer;
+    .ip {
+      color: #000000;
+    }
+    .remark {
+      word-break: break-all;
+      text-overflow: ellipsis;
+      display: -webkit-box;
+      -webkit-box-orient: vertical;
+      -webkit-line-clamp: 2;
+      overflow: hidden;
+    }
+  }
+  .ip-item.active {
+    border-color: var(--antd-wave-shadow-color);
+    box-shadow: 0 0 2px var(--antd-wave-shadow-color);
+  }
+}
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/funcMegvii/mock.js b/src/tabviews/zshare/actionList/funcMegvii/mock.js
new file mode 100644
index 0000000..669ad8e
--- /dev/null
+++ b/src/tabviews/zshare/actionList/funcMegvii/mock.js
@@ -0,0 +1,27 @@
+export const mockdata = {
+  data: [
+    {
+      "recognition_type": "staff",
+      "id": "2226169",
+      "type": "persons",
+      "is_admin": "true",
+      "person_name": "king",
+      "card_number": "mk001",
+      "person_code": "2018",
+      "id_number": "130982193002054729",
+      "group_list": "1",
+      "face_data":""
+    },
+    {
+      "recognition_type": "staff",
+      "id": "3272487",
+      "is_admin": 'false',
+      "person_name": "jinfei",
+      "card_number": "mk002",
+      "person_code": "02",
+      "id_number": "",
+      "group_list": "1",
+      "face_data": ""
+    }
+  ]
+}
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/index.jsx b/src/tabviews/zshare/actionList/index.jsx
index be12727..3b4c230 100644
--- a/src/tabviews/zshare/actionList/index.jsx
+++ b/src/tabviews/zshare/actionList/index.jsx
@@ -14,6 +14,7 @@
 const NewPageButton = asyncComponent(() => import('./newpagebutton'))
 const ChangeUserButton = asyncComponent(() => import('./changeuserbutton'))
 const PrintButton = asyncComponent(() => import('./printbutton'))
+const FuncMegvii = asyncComponent(() => import('./funcMegvii'))
 
 class ActionList extends Component {
   static propTpyes = {
@@ -37,7 +38,6 @@
 
   getButtonList = (actions) => {
     const { BID, BData, MenuID, Tab, columns, setting, ContainerId, selectedData, lock } = this.props
-
     return actions.map(item => {
       if (['exec', 'prompt', 'pop'].includes(item.OpenType)) {
         return (
@@ -113,7 +113,7 @@
         return (
           <NewPageButton
             key={item.uuid}
-            show="actionList"
+            show={item.show || 'actionList'}
             disabled={lock || false}
             btn={item}
             BData={BData}
@@ -151,6 +151,19 @@
               selectedData={selectedData}
             />
           )
+        } else if (item.funcType === 'megvii') {
+          return (
+            <FuncMegvii
+              key={item.uuid}
+              show={item.show || 'actionList'}
+              disabled={lock || false}
+              BID={BID}
+              Tab={Tab}
+              btn={item}
+              setting={setting}
+              selectedData={selectedData}
+            />
+          )
         }
       }
       return null
diff --git a/src/tabviews/zshare/fileupload/index.jsx b/src/tabviews/zshare/fileupload/index.jsx
index 1e71103..5148154 100644
--- a/src/tabviews/zshare/fileupload/index.jsx
+++ b/src/tabviews/zshare/fileupload/index.jsx
@@ -39,28 +39,42 @@
 
     let filelist = []
     if (config.initval) {
-      try {
-        filelist = config.initval.split(',').map((url, index) => {
-          return {
-            uid: `${index}`,
-            name: url.slice(url.lastIndexOf('/') + 1),
-            status: 'done',
-            url: url,
-            origin: true
-          }
-        })
-      } catch (e) {
-        filelist = []
+      if (/^data:image/.test(config.initval)) {
+        filelist = [{
+          uid: '0',
+          name: 'data:image/jpeg;base64',
+          status: 'done',
+          url: config.initval,
+          origin: true
+        }]
+      } else {
+        try {
+          filelist = config.initval.split(',').map((url, index) => {
+            return {
+              uid: `${index}`,
+              name: url.slice(url.lastIndexOf('/') + 1),
+              status: 'done',
+              url: url,
+              origin: true
+            }
+          })
+        } catch (e) {
+          filelist = []
+        }
       }
     }
 
     let accept = ''
     let accepts = null
     let compress = false
-    if (config.compress === 'true') {
+    let maxFile = config.maxfile && config.maxfile > 0 ? config.maxfile : null
+    if (config.compress === 'true' || config.compress === 'base64') {
       compress = true
       accepts = ['.jpg', '.png', '.gif', '.jpeg']
       accept = accepts.join(',')
+      if (config.compress === 'base64') {
+        maxFile = 1
+      }
     } else if (config.suffix) {
       accepts = config.suffix.split(',').map(item => {
         if (!/^\./ig.test(item)) {
@@ -83,7 +97,7 @@
       filelist,
       compress,
       limit: config.limit || 2,
-      maxFile: config.maxfile && config.maxfile > 0 ? config.maxfile : null,
+      maxFile: maxFile,
       fileType: config.fileType || 'text'
     })
   }
@@ -281,34 +295,49 @@
 
           let param = {Base64Img: cvs.toDataURL('image/jpeg', compressRate)}
 
-          if (rduri) {
-            param.rduri = rduri
-          }
-
-          Api.fileuploadbase64(param).then(result => {
-            if (result.status && result.Images) {
-              let url = service + result.Images
-
-              if (rduri) {
-                url = rduri.replace(/webapi(.*)$/, '') + result.Images
-              }
-
-              this.onUpdate(url)
-
-              this.setState({
-                percent: 100
-              }, () => {
-                setTimeout(() => {
-                  this.setState({
-                    showprogress: false,
-                    percent: 0
-                  })
-                }, 200)
-              })
-            } else {
-              this.onFail(result.message)
+          if (this.props.config.compress === 'base64') {
+            this.onUpdate(param.Base64Img)
+  
+            this.setState({
+              percent: 100
+            }, () => {
+              setTimeout(() => {
+                this.setState({
+                  showprogress: false,
+                  percent: 0
+                })
+              }, 200)
+            })
+          } else {
+            if (rduri) {
+              param.rduri = rduri
             }
-          })
+  
+            Api.fileuploadbase64(param).then(result => {
+              if (result.status && result.Images) {
+                let url = service + result.Images
+  
+                if (rduri) {
+                  url = rduri.replace(/webapi(.*)$/, '') + result.Images
+                }
+  
+                this.onUpdate(url)
+  
+                this.setState({
+                  percent: 100
+                }, () => {
+                  setTimeout(() => {
+                    this.setState({
+                      showprogress: false,
+                      percent: 0
+                    })
+                  }, 200)
+                })
+              } else {
+                this.onFail(result.message)
+              }
+            })
+          }
         }
 
         img.onerror = () => {
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index 2481f06..9c42ac2 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -654,9 +654,11 @@
       let photos = ''
       if (item.field && record.hasOwnProperty(item.field)) {
         photos = record[item.field] + ''
-        photos = photos.split(',').filter(Boolean)
+      }
+      if (/^data:image/.test(photos)) {
+        photos = [photos]
       } else {
-        photos = ''
+        photos = photos.split(',').filter(Boolean)
       }
 
       let maxHeight = item.maxHeight || 128
@@ -857,7 +859,12 @@
           let photos = []
           try {
             photos = record[col.field] + ''
-            photos = photos.split(',').filter(Boolean)
+
+            if (/^data:image/.test(photos)) {
+              photos = [photos]
+            } else {
+              photos = photos.split(',').filter(Boolean)
+            }
           } catch (e) {
             photos = []
           }
diff --git a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
index d0ef468..0065cc4 100644
--- a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -266,6 +266,8 @@
         }
       } else if (_funcType === 'closetab') {
         shows.push('refreshTab')
+      } else if (_funcType === 'megvii') {
+        shows.push('subFunc')
       }
     }
 
diff --git a/src/templates/sharecomponent/actioncomponent/dragaction/card.jsx b/src/templates/sharecomponent/actioncomponent/dragaction/card.jsx
index d1d61c5..21a74ec 100644
--- a/src/templates/sharecomponent/actioncomponent/dragaction/card.jsx
+++ b/src/templates/sharecomponent/actioncomponent/dragaction/card.jsx
@@ -42,6 +42,8 @@
     }
   } else if (card.funcType === 'print') {
     hasProfile = true
+  } else if (card.funcType === 'megvii') {
+    hasProfile = true
   }
 
   return (
diff --git a/src/templates/sharecomponent/actioncomponent/index.jsx b/src/templates/sharecomponent/actioncomponent/index.jsx
index 8a0a704..da66039 100644
--- a/src/templates/sharecomponent/actioncomponent/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/index.jsx
@@ -24,6 +24,7 @@
 const VerifyCard = asyncSpinComponent(() => import('@/templates/zshare/verifycard'))
 const VerifyPrint = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyprint'))
 const VerifyExcelIn = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelin'))
+const VerifyMegvii = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifymegvii'))
 const VerifyExcelOut = asyncSpinComponent(() => import('@/templates/sharecomponent/actioncomponent/verifyexcelout'))
 
 class ActionComponent extends Component {
@@ -858,6 +859,51 @@
     MKEmitter.removeListener('pasteButton', this.pasteButton)
   }
 
+  getVerify = (card) => {
+    const { config } = this.props
+    const { dict } = this.state
+
+    if (!card) return null
+
+    if (['pop', 'prompt', 'exec'].includes(card.OpenType)) {
+      return <VerifyCard
+        card={card}
+        dict={dict}
+        config={config}
+        columns={config.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    } else if (card.OpenType === 'excelIn') {
+      return <VerifyExcelIn
+        card={card}
+        dict={dict}
+        columns={config.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    } else if (card.OpenType === 'excelOut') {
+      return <VerifyExcelOut
+        card={card}
+        dict={dict}
+        config={config}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    } else if (card.OpenType === 'funcbutton' && card.funcType === 'print') {
+      return <VerifyPrint
+        card={card}
+        dict={dict}
+        columns={config.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    } else if (card.OpenType === 'funcbutton' && card.funcType === 'megvii') {
+      return <VerifyMegvii
+        card={card}
+        dict={dict}
+        columns={config.columns}
+        wrappedComponentRef={(inst) => this.verifyRef = inst}
+      />
+    }
+  }
+
   render() {
     const { config } = this.props
     const { actionlist, visible, card, dict, copying, profVisible } = this.state
@@ -921,39 +967,7 @@
           }}
           destroyOnClose
         >
-          {card && !card.execMode && card.OpenType !== 'excelIn' && card.OpenType !== 'excelOut' ?
-            <VerifyCard
-              card={card}
-              dict={dict}
-              config={config}
-              columns={config.columns}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-          {card && card.execMode ?
-            <VerifyPrint
-              card={card}
-              dict={dict}
-              columns={config.columns}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-          {card && card.OpenType === 'excelIn' ?
-            <VerifyExcelIn
-              card={card}
-              dict={dict}
-              columns={config.columns}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
-          {card && card.OpenType === 'excelOut' ?
-            <VerifyExcelOut
-              card={card}
-              dict={dict}
-              config={config}
-              wrappedComponentRef={(inst) => this.verifyRef = inst}
-            /> : null
-          }
+          {this.getVerify(card)}
         </Modal>
       </div>
     )
diff --git a/src/templates/sharecomponent/actioncomponent/verifymegvii/index.jsx b/src/templates/sharecomponent/actioncomponent/verifymegvii/index.jsx
new file mode 100644
index 0000000..66780c3
--- /dev/null
+++ b/src/templates/sharecomponent/actioncomponent/verifymegvii/index.jsx
@@ -0,0 +1,249 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
+import { Form, Tabs, Table, Row, Col, Button, notification, Modal, message, InputNumber } from 'antd'
+
+import './index.scss'
+
+const { TabPane } = Tabs
+
+class MegviiCard extends Component {
+  static propTpyes = {
+    columns: PropTypes.array,  // 鏄剧ず鍒�
+    dict: PropTypes.object,    // 瀛楀吀椤�
+    card: PropTypes.object,
+  }
+
+  state = {
+    verify: {},
+    activeKey: 'excelcolumn',
+    excelColumns: [
+      {
+        title: '鍚嶇О',
+        dataIndex: 'field',
+        width: '20%'
+      },
+      {
+        title: '鏁版嵁绫诲瀷',
+        dataIndex: 'datatype',
+        width: '20%'
+      },
+      {
+        title: '鍙橀噺绫诲瀷',
+        dataIndex: 'type',
+        width: '20%'
+      },
+      {
+        title: '鏄惁蹇呴』',
+        dataIndex: 'required',
+        width: '15%'
+      },
+      {
+        title: '澶囨敞',
+        dataIndex: 'remark',
+        width: '25%',
+      }
+    ],
+    excelData: [
+      {field: 'id', datatype: 'string', type: 'nvarchar(50)', required: '蹇呴』', remark: '浜哄憳id'},
+      {field: 'person_name', datatype: 'string', type: 'nvarchar(50)', required: '蹇呴』', remark: '浜哄憳鍚嶇О'},
+      {field: 'group_list', datatype: 'string', type: 'nvarchar(50)', required: '蹇呴』', remark: '缁戝畾浜哄憳缁勭殑鍒楄〃锛屽涓娇鐢ㄩ�楀彿鍒嗛殧锛岀ず渚嬶細\'1,2\''},
+      {field: 'face_data', datatype: 'string', type: 'text', required: '蹇呴』', remark: 'Base64缂栫爜鐨勭収鐗囨暟鎹紙浜鸿劯淇℃伅锛�'},
+      {field: 'face_idx', datatype: 'integer', type: 'int', required: '闈炲繀椤�', remark: '鐓х墖绱㈠紩锛岄粯璁や负0'},
+      {field: 'is_admin', datatype: 'string', type: 'nvarchar(50)', required: '闈炲繀椤�', remark: '鏄惁鍚敤绠$悊鍛樻潈闄愶紝榛樿涓篭'false\''},
+      {field: 'recognition_type', datatype: 'string', type: 'nvarchar(50)', required: '闈炲繀椤�', remark: '浜哄憳绫诲瀷锛宻taff 鈥� 鏅�氫汉鍛橈紙榛樿锛夛紝visitor 鈥� 璁垮锛宐lacklist 鈥� 榛戝悕鍗�'},
+      {field: 'password', datatype: 'string', type: 'nvarchar(50)', required: '闈炲繀椤�', remark: '瀵嗙爜浣跨敤6浣嶆暟瀛楋紙AES鍔犲瘑锛�'},
+      {field: 'id_number', datatype: 'string', type: 'nvarchar(50)', required: '闈炲繀椤�', remark: '韬唤璇佸彿鐮侊紙AES鍔犲瘑锛�'},
+      {field: 'person_code', datatype: 'string', type: 'nvarchar(50)', required: '闈炲繀椤�', remark: '浜哄憳缂栧彿'},
+      {field: 'card_number', datatype: 'string', type: 'nvarchar(50)', required: '闈炲繀椤�', remark: '鍗″彿锛屾渶澶�20浣嶆暟瀛�'},
+    ]
+  }
+
+  UNSAFE_componentWillMount() {
+    const { card } = this.props
+    let _verify = fromJS(card.verify || {}).toJS()
+
+    this.setState({
+      verify: _verify
+    })
+  }
+
+  componentDidMount () {
+    
+  }
+
+  handleConfirm = () => {
+    const { verify } = this.state
+
+    return Promise.resolve(verify)
+  }
+
+  showError = (errorType) => {
+    if (errorType === 'S') {
+      notification.success({
+        top: 92,
+        message: '鎵ц鎴愬姛锛�',
+        duration: 2
+      })
+    } else if (errorType === 'Y') {
+      Modal.success({
+        title: '鎵ц鎴愬姛锛�'
+      })
+    } else if (errorType === 'F') {
+      notification.error({
+        className: 'notification-custom-error',
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: 10
+      })
+    } else if (errorType === 'N') {
+      notification.error({
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: 10
+      })
+    } else if (errorType === 'E') {
+      Modal.error({
+        title: '鎵ц澶辫触锛�'
+      })
+    } else if (errorType === 'NM') {
+      message.error('鎵ц澶辫触锛�')
+    }
+  }
+
+  timeChange = (val, type) => {
+    const { verify } = this.state
+
+    this.setState({
+      verify: {...verify, [type]: val}
+    })
+  }
+
+  tabchange = (val) => {
+    this.setState({activeKey: val})
+  }
+
+  render() {
+    const { verify, excelColumns, excelData, activeKey } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <div>
+        <Tabs activeKey={activeKey} className="megvii-verify-card-box" onChange={this.tabchange}>
+          <TabPane tab={
+            <span>
+              鍒楄缃�
+            </span>
+          } key="excelcolumn">
+            <Table
+              bordered
+              rowKey="field"
+              className="custom-table"
+              dataSource={excelData}
+              columns={excelColumns}
+              pagination={false}
+            />
+          </TabPane>
+          <TabPane tab="淇℃伅鎻愮ず" key="tip">
+            <Form {...formItemLayout}>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                    <span className="errorval"> S </span>
+                    <Button onClick={() => {this.showError('S')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+                <Col span={8}>
+                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                    <InputNumber defaultValue={verify.stime || 2} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'stime')}} />
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                    <span className="errorval"> Y </span>
+                    <Button onClick={() => {this.showError('Y')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                    <span className="errorval"> N </span>
+                    <Button onClick={() => {this.showError('N')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+                <Col span={8}>
+                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                    <InputNumber defaultValue={verify.ntime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ntime')}} />
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                    <span className="errorval"> F </span>
+                    <Button onClick={() => {this.showError('F')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+                <Col span={8}>
+                  <Form.Item label={'鍋滅暀鏃堕棿'}>
+                    <InputNumber defaultValue={verify.ftime || 10} min={1} max={10000} precision={0} onChange={(val) => {this.timeChange(val, 'ftime')}} />
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                    <span className="errorval"> E </span>
+                    <Button onClick={() => {this.showError('E')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                    <span className="errorval"> NM </span>
+                    <Button onClick={() => {this.showError('NM')}} type="primary" size="small">
+                      鏌ョ湅
+                    </Button>
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={24}>
+                <Col offset={6} span={6}>
+                  <Form.Item label={'鎻愮ず缂栫爜'}>
+                    <span className="errorval"> -1 </span>
+                    涓嶆彁绀�
+                  </Form.Item>
+                </Col>
+              </Row>
+            </Form>
+          </TabPane>
+        </Tabs>
+      </div>
+    )
+  }
+}
+
+export default Form.create()(MegviiCard)
\ No newline at end of file
diff --git a/src/templates/sharecomponent/actioncomponent/verifymegvii/index.scss b/src/templates/sharecomponent/actioncomponent/verifymegvii/index.scss
new file mode 100644
index 0000000..c26f463
--- /dev/null
+++ b/src/templates/sharecomponent/actioncomponent/verifymegvii/index.scss
@@ -0,0 +1,38 @@
+.megvii-verify-card-box {
+  .ant-tabs-nav-scroll {
+    text-align: center;
+  }
+  .ant-tabs-content {
+    min-height: 40vh;
+  }
+  table tr td {
+    word-wrap: break-word;
+    word-break: break-word;
+  }
+
+  .excel-custom-table {
+    position: relative;
+    top: -25px;
+  }
+  .errorval {
+    display: inline-block;
+    width: 30px;
+  }
+  .operation-btn {
+    display: inline-block;
+    font-size: 16px;
+    padding: 0 5px;
+    cursor: pointer;
+  }
+  .ant-tabs-tabpane {
+    position: relative;
+    .excel-col-add {
+      position: relative;
+      float: right;
+      right: -9px;
+      margin-right: 10px;
+      top: 10px;
+      z-index: 1;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index 5761a1e..a5f39fd 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -953,7 +953,20 @@
       }, {
         value: 'closetab',
         text: '鏍囩鍏抽棴'
+      }, {
+        value: 'megvii',
+        text: '鏃疯闈㈡澘鏈�'
       }]
+    },
+    { // 鏃疯闈㈡澘鏈烘帴鍙� 寰呮墿灞�
+      type: 'radio',
+      key: 'subFunc',
+      label: '鎺ュ彛鍚嶇О',
+      initVal: card.subFunc || 'addUser',
+      required: true,
+      options: [
+        { value: 'addUser', text: '娣诲姞鐢ㄦ埛' },
+      ]
     },
     {
       type: 'select',
@@ -3205,15 +3218,18 @@
     {
       type: 'radio',
       key: 'compress',
-      label: '鍘嬬缉',
+      label: '鏂囦欢澶勭悊',
       initVal: card.compress || 'false',
-      tooltip: '鏂囦欢鍘嬬缉蹇呴』涓哄浘鐗囷紝鍥剧墖鏍煎紡涓簀pg銆乸ng銆乬if 鎴� jpeg',
+      tooltip: '鏂囦欢鍘嬬缉鎴朾ase64蹇呴』涓哄浘鐗囷紝鍥剧墖鏍煎紡涓簀pg銆乸ng銆乬if 鎴� jpeg銆傛敞锛歜ase64鍙彲涓婁紶涓�寮犲浘鐗囥��',
       options: [{
-        value: 'true',
-        text: Formdict['model.true']
-      }, {
         value: 'false',
-        text: Formdict['model.false']
+        text: '鏃�'
+      }, {
+        value: 'true',
+        text: '鍘嬬缉'
+      }, {
+        value: 'base64',
+        text: 'base64'
       }]
     },
     {
diff --git a/src/views/rolemanage/index.jsx b/src/views/rolemanage/index.jsx
index e4df34d..608da40 100644
--- a/src/views/rolemanage/index.jsx
+++ b/src/views/rolemanage/index.jsx
@@ -689,17 +689,17 @@
   }
 
   saveTree = () => {
-    const { trees } = this.state
+    // const { trees } = this.state
     const _this = this
 
-    if (!trees || trees.length === 0) {
-      notification.warning({
-        top: 92,
-        message: '鏈幏鍙栧埌鏉冮檺淇℃伅锛�',
-        duration: 5
-      })
-      return
-    }
+    // if (!trees || trees.length === 0) {
+    //   notification.warning({
+    //     top: 92,
+    //     message: '鏈幏鍙栧埌鏉冮檺淇℃伅锛�',
+    //     duration: 5
+    //   })
+    //   return
+    // }
 
     confirm({
       content: '纭畾鎵ц鍚楋紵',

--
Gitblit v1.8.0