From 8904592cf12f091aece5d6fc564fd8478fc8988b Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 13 二月 2020 20:04:56 +0800
Subject: [PATCH] 2020-02-13

---
 src/templates/tableshare/exceleditable/index.jsx                   |  304 +++++++
 src/templates/tableshare/verifycard/customform/index.jsx           |    9 
 src/templates/tableshare/verifycardexcelin/columnform/index.jsx    |  168 ++++
 package-lock.json                                                  |   89 ++
 src/tabviews/formtab/index.jsx                                     |    9 
 src/tabviews/formtab/actionList/index.jsx                          |   77 -
 src/tabviews/tableshare/excelin/index.scss                         |    5 
 src/templates/tableshare/verifycardexcelin/customscript/index.jsx  |  126 +++
 src/templates/formtabconfig/index.jsx                              |    8 
 src/templates/comtableconfig/index.jsx                             |   69 +
 src/tabviews/tableshare/actionList/index.jsx                       |  109 ++
 src/templates/modalconfig/index.jsx                                |    3 
 src/templates/tableshare/dragelement/card.jsx                      |    2 
 src/locales/en-US/main.js                                          |   12 
 src/tabviews/commontable/index.jsx                                 |  234 +++--
 src/templates/ushare/editable/index.jsx                            |   78 +
 src/templates/tableshare/verifycard/customscript/index.jsx         |    7 
 src/templates/tableshare/verifycard/index.jsx                      |    1 
 src/templates/tableshare/verifycardexcelin/columnform/index.scss   |    0 
 src/utils/utils.js                                                 |  137 +++
 src/templates/tableshare/verifycardexcelin/customscript/index.scss |    0 
 src/templates/tableshare/verifycardexcelin/index.scss              |   53 +
 src/templates/ushare/editable/index.scss                           |    4 
 src/templates/comtableconfig/actionform/index.jsx                  |   57 +
 src/templates/formtabconfig/settingform/index.jsx                  |    8 
 src/locales/zh-CN/main.js                                          |   12 
 src/tabviews/formtab/actionList/index.scss                         |   31 
 src/templates/subtableconfig/index.jsx                             |   68 +
 /dev/null                                                          |   16 
 src/templates/tableshare/exceleditable/index.scss                  |   49 +
 src/tabviews/tableshare/excelin/index.jsx                          |  117 ++
 src/tabviews/tableshare/actionList/index.scss                      |    2 
 package.json                                                       |    3 
 src/templates/tableshare/verifycardexcelin/index.jsx               |  510 ++++++++++++
 src/utils/option.js                                                |    6 
 src/templates/ushare/modalform/index.jsx                           |   16 
 36 files changed, 2,110 insertions(+), 289 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 95f859b..c4a90a7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1941,6 +1941,15 @@
         }
       }
     },
+    "adler-32": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz",
+      "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=",
+      "requires": {
+        "exit-on-epipe": "1.0.1",
+        "printj": "1.1.2"
+      }
+    },
     "agentframework": {
       "version": "0.9.22",
       "resolved": "https://registry.npmjs.org/agentframework/-/agentframework-0.9.22.tgz",
@@ -3340,6 +3349,17 @@
       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
       "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
     },
+    "cfb": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.1.3.tgz",
+      "integrity": "sha512-joXBW0nMuwV9no7UTMiyVJnQL6XIU3ThXVjFUDHgl9MpILPOomyfaGqC290VELZ48bbQKZXnQ81UT5HouTxHsw==",
+      "requires": {
+        "adler-32": "1.2.0",
+        "commander": "2.20.0",
+        "crc-32": "1.2.0",
+        "printj": "1.1.2"
+      }
+    },
     "chalk": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -3527,6 +3547,22 @@
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
       "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+    },
+    "codepage": {
+      "version": "1.14.0",
+      "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz",
+      "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=",
+      "requires": {
+        "commander": "2.14.1",
+        "exit-on-epipe": "1.0.1"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.14.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz",
+          "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw=="
+        }
+      }
     },
     "collection-visit": {
       "version": "1.0.0",
@@ -3795,6 +3831,15 @@
         "is-directory": "0.3.1",
         "js-yaml": "3.13.1",
         "parse-json": "4.0.0"
+      }
+    },
+    "crc-32": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz",
+      "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==",
+      "requires": {
+        "exit-on-epipe": "1.0.1",
+        "printj": "1.1.2"
       }
     },
     "create-ecdh": {
@@ -6483,6 +6528,11 @@
       "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
       "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
     },
+    "exit-on-epipe": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
+      "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
+    },
     "expand-brackets": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
@@ -7074,6 +7124,11 @@
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
       "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+    },
+    "frac": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
+      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
     },
     "fragment-cache": {
       "version": "0.2.1",
@@ -12554,6 +12609,11 @@
         }
       }
     },
+    "printj": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
+      "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
+    },
     "private": {
       "version": "0.1.8",
       "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@@ -14970,6 +15030,14 @@
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
     },
+    "ssf": {
+      "version": "0.10.2",
+      "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.2.tgz",
+      "integrity": "sha512-rDhAPm9WyIsY8eZEKyE8Qsotb3j/wBdvMWBUsOhJdfhKGLfQidRjiBUV0y/MkyCLiXQ38FG6LWW/VYUtqlIDZQ==",
+      "requires": {
+        "frac": "1.1.2"
+      }
+    },
     "sshpk": {
       "version": "1.16.1",
       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
@@ -16831,6 +16899,27 @@
         "async-limiter": "1.0.1"
       }
     },
+    "xlsx": {
+      "version": "0.15.5",
+      "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.15.5.tgz",
+      "integrity": "sha512-iWyTqe6UGTkp3XQOeeKPEBcZvmBfzIo3hDIVDfhGIEoTGVIq2JWEk6tIx0F+oKUje3pfZUx4V1W+P6892AB8kQ==",
+      "requires": {
+        "adler-32": "1.2.0",
+        "cfb": "1.1.3",
+        "codepage": "1.14.0",
+        "commander": "2.17.1",
+        "crc-32": "1.2.0",
+        "exit-on-epipe": "1.0.1",
+        "ssf": "0.10.2"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.17.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+          "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
+        }
+      }
+    },
     "xml-name-validator": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
diff --git a/package.json b/package.json
index 4aa7d22..2313fc6 100644
--- a/package.json
+++ b/package.json
@@ -76,7 +76,8 @@
     "webpack": "4.39.1",
     "webpack-dev-server": "3.2.1",
     "webpack-manifest-plugin": "2.0.4",
-    "workbox-webpack-plugin": "4.3.1"
+    "workbox-webpack-plugin": "4.3.1",
+    "xlsx": "^0.15.5"
   },
   "scripts": {
     "dev": "set PORT=3001 && node scripts/start.js",
diff --git a/src/locales/en-US/main.js b/src/locales/en-US/main.js
index ce78f97..f472911 100644
--- a/src/locales/en-US/main.js
+++ b/src/locales/en-US/main.js
@@ -18,6 +18,18 @@
   'main.action.primarykey.repetition': 'There are multiple primary keys!',
   'main.action.primarykey.repetitionbid': 'There are multiple BID!',
   'main.column.operation': '鎿嶄綔',
+  'main.excel.line': '琛�',
+  'main.excel.column': '鍒�',
+  'main.excel.includekey': '鍚湁鍏抽敭瀛�',
+  'main.excel.content.emptyerror': '鍐呭涓嶅彲涓虹┖',
+  'main.excel.content.typeerror': '鍐呭搴斾负鏁板��',
+  'main.excel.content.interror': '鍐呭搴斾负鏁存暟',
+  'main.excel.content.floaterror': '鍐呭搴斾负娴偣鏁�',
+  'main.excel.content.floatIntover': '鏁存暟浣嶈秴鍑鸿寖鍥�',
+  'main.excel.content.floatPointover': '灏忔暟浣嶈秴鍑鸿寖鍥�',
+  'main.excel.content.maxlimit': '鍐呭瓒呴暱',
+  'main.excel.content.limitmin': '灏忎簬鏈�灏忓��',
+  'main.excel.content.limitmax': '澶т簬鏈�澶у��',
   'form.required.input': 'Please input ',
   'form.required.select': 'Please select '
 }
\ No newline at end of file
diff --git a/src/locales/zh-CN/main.js b/src/locales/zh-CN/main.js
index 1d1c15e..2128840 100644
--- a/src/locales/zh-CN/main.js
+++ b/src/locales/zh-CN/main.js
@@ -20,6 +20,18 @@
   'main.action.primarykey.repetitionbid': '瀛樺湪澶氫釜BID锛�',
   'main.column.operation': '鎿嶄綔',
   'main.view.unenabled': '鎶辨瓑锛屼綘璁块棶鐨勯〉闈㈡湭鍚敤锛岃鑱旂郴绠$悊鍛樸��',
+  'main.excel.line': '琛�',
+  'main.excel.column': '鍒�',
+  'main.excel.includekey': '鍚湁鍏抽敭瀛�',
+  'main.excel.content.emptyerror': '鍐呭涓嶅彲涓虹┖',
+  'main.excel.content.typeerror': '鍐呭搴斾负鏁板��',
+  'main.excel.content.interror': '鍐呭搴斾负鏁存暟',
+  'main.excel.content.floaterror': '鍐呭搴斾负娴偣鏁�',
+  'main.excel.content.floatIntover': '鏁存暟浣嶈秴鍑鸿寖鍥�',
+  'main.excel.content.floatPointover': '灏忔暟浣嶈秴鍑鸿寖鍥�',
+  'main.excel.content.maxlimit': '鍐呭瓒呴暱',
+  'main.excel.content.limitmin': '灏忎簬鏈�灏忓��',
+  'main.excel.content.limitmax': '澶т簬鏈�澶у��',
   'form.required.input': '璇疯緭鍏�',
   'form.required.select': '璇烽�夋嫨'
 }
\ No newline at end of file
diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index 57e5426..5b5d3df 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -20,6 +20,7 @@
 import './index.scss'
 
 const SubTabTable = asyncComponent(() => import('@/tabviews/subtabtable'))
+const FormTab = asyncComponent(() => import('@/tabviews/formtab'))
 const { TabPane } = Tabs
 
 class NormalTable extends Component {
@@ -32,6 +33,7 @@
   state = {
     dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     ContainerId: Utils.getuuid(), // 鑿滃崟澶栧眰html Id
+    view: 'commontable',  // 褰撳墠椤甸潰榛樿涓轰富琛�
     loadingview: true,    // 椤甸潰鍔犺浇涓�
     viewlost: false,      // 椤甸潰涓㈠け锛�1銆佹湭鑾峰彇鍒伴厤缃�-椤甸潰涓㈠け锛�2銆侀〉闈㈡湭鍚敤
     lostmsg: '',          // 椤甸潰涓㈠け鏃剁殑鎻愮ず淇℃伅
@@ -524,6 +526,7 @@
    */
   reloadview = () => {
     this.setState({
+      view: 'commontable',
       loadingview: true,
       viewlost: false,
       lostmsg: '',
@@ -731,6 +734,16 @@
       tabs.splice(index + 1, 0, newtab)
       
       this.props.modifyTabview(tabs)
+    } else if (btn.OpenType === 'blank') {
+      this.setState({
+        view: 'formtab',
+        tabBtn: btn,
+        tabParam: {
+          btn: btn,
+          data: data,
+          arr_field: this.state.arr_field
+        }
+      })
     }
   }
 
@@ -760,121 +773,124 @@
   }
 
   render() {
-    const { setting, searchlist, actions, columns, loadingview, viewlost, setsingle, pickup, isLinkMain, config } = this.state
+    const { view, setting, searchlist, actions, columns, loadingview, viewlost, setsingle, pickup, isLinkMain, config } = this.state
 
     return (
-      <div className={'commontable ' + (isLinkMain ? 'pick-control' : '')} id={this.state.ContainerId}>
-        {loadingview && <Spin size="large" />}
-        {searchlist && searchlist.length > 0 ?
-          <MainSearch
-            dict={this.state.dict}
-            searchlist={searchlist}
-            refreshdata={this.refreshbysearch}
-          /> : null
-        }
-        {actions && setting.onload !== 'false' ?
-          <MainAction
-            ref="mainButton"
-            BID=""
-            type="main"
-            setting={setting}
-            actions={actions}
-            dict={this.state.dict}
-            MenuID={this.props.MenuID}
-            logcolumns={this.state.logcolumns}
-            ContainerId={this.state.ContainerId}
-            refreshdata={this.refreshbyaction}
-            triggerPopview={this.triggerPopview}
-            gettableselected={this.gettableselected}
-          /> : null
-        }
-        {columns && setting.onload !== 'false' ?
-          <div className="main-table-box">
-            {isLinkMain ?
-              <div className="pickchange">
-                {setting.tableType === 'checkbox' ? <Switch title="鍗曢�夊垏鎹�" checkedChildren="鍗�" unCheckedChildren="澶�" defaultChecked={setsingle} onChange={this.checkChange} /> : null}
-                {this.state.BIDs.mainTable && (setting.tableType === 'radio' || setsingle) ? <Switch title="鏀惰捣" checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={pickup} onChange={this.pickupChange} /> : null}
-              </div> : null
-            }
-            <MainTable
-              ref="mainTable"
-              pickup={pickup}
-              setting={setting}
-              columns={columns}
-              setsingle={setsingle}
+      <div>
+        {view === 'commontable' ? <div className={'commontable ' + (isLinkMain ? 'pick-control' : '')} id={this.state.ContainerId}>
+          {loadingview && <Spin size="large" />}
+          {searchlist && searchlist.length > 0 ?
+            <MainSearch
               dict={this.state.dict}
-              data={this.state.data}
-              total={this.state.total}
+              searchlist={searchlist}
+              refreshdata={this.refreshbysearch}
+            /> : null
+          }
+          {actions && setting.onload !== 'false' ?
+            <MainAction
+              ref="mainButton"
+              BID=""
+              type="main"
+              setting={setting}
+              actions={actions}
+              dict={this.state.dict}
               MenuID={this.props.MenuID}
-              loading={this.state.loading}
-              refreshdata={this.refreshbytable}
-              buttonTrigger={this.buttonTrigger}
-              handleTableId={this.handleTableId}
-            />
-          </div> : null
-        }
-        {setting && setting.onload !== 'false' &&
-          config.tabgroups.map(group => {
-            if (config[group].length === 0) return null
+              logcolumns={this.state.logcolumns}
+              ContainerId={this.state.ContainerId}
+              refreshdata={this.refreshbyaction}
+              triggerPopview={this.triggerPopview}
+              gettableselected={this.gettableselected}
+            /> : null
+          }
+          {columns && setting.onload !== 'false' ?
+            <div className="main-table-box">
+              {isLinkMain ?
+                <div className="pickchange">
+                  {setting.tableType === 'checkbox' ? <Switch title="鍗曢�夊垏鎹�" checkedChildren="鍗�" unCheckedChildren="澶�" defaultChecked={setsingle} onChange={this.checkChange} /> : null}
+                  {this.state.BIDs.mainTable && (setting.tableType === 'radio' || setsingle) ? <Switch title="鏀惰捣" checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={pickup} onChange={this.pickupChange} /> : null}
+                </div> : null
+              }
+              <MainTable
+                ref="mainTable"
+                pickup={pickup}
+                setting={setting}
+                columns={columns}
+                setsingle={setsingle}
+                dict={this.state.dict}
+                data={this.state.data}
+                total={this.state.total}
+                MenuID={this.props.MenuID}
+                loading={this.state.loading}
+                refreshdata={this.refreshbytable}
+                buttonTrigger={this.buttonTrigger}
+                handleTableId={this.handleTableId}
+              />
+            </div> : null
+          }
+          {setting && setting.onload !== 'false' &&
+            config.tabgroups.map(group => {
+              if (config[group].length === 0) return null
 
-            return (
-              <Tabs defaultActiveKey="0" key={group}>
-                {config[group].map((_tab, index) => {
-                  return (
-                    <TabPane tab={
-                      <span>
-                        {_tab.icon ? <Icon type={_tab.icon} /> : null}
-                        {_tab.label}
-                      </span>
-                    } key={`${index}`}>
-                      {_tab.type === 'SubTable' ?
-                        <SubTable
-                          Tab={_tab}
-                          MenuID={_tab.linkTab}
-                          SupMenuID={this.props.MenuID}
-                          ContainerId={this.state.ContainerId}
-                          BID={this.state.BIDs[_tab.supMenu] || ''}
-                          BData={this.state.BIDs[_tab.supMenu + 'data'] || ''}
-                          handleTableId={this.handleTableId}
-                          handleMainTable={this.handleMainTable}
-                        /> : null}
-                    </TabPane>
-                  )
-                })}
-              </Tabs>
-            )
-          })
-        }
-        <Modal
-          className="popview-modal"
-          title={this.state.popAction.label}
-          width={'80vw'}
-          maskClosable={false}
-          visible={this.state.visible}
-          onCancel={this.popclose}
-          footer={[
-            <Button key="cancel" onClick={this.popclose}>{this.state.dict['main.close']}</Button>
-          ]}
-          destroyOnClose
-        >
-          {<SubTabTable 
-            BID={''}
-            SupMenuID={this.props.MenuID}
-            MenuID={this.state.popAction.linkTab}
-            BData={this.state.BIDs['mainTabledata'] || ''}
-            ContainerId={this.state.ContainerId}
-            ID={this.state.popData ? this.state.popData[setting.primaryKey] : ''}
-            refreshSupView={this.reloadtable}
-          />}
-        </Modal>
-        <BackTop>
-          <div className="ant-back-top">
-            <div className="ant-back-top-content">
-              <div className="ant-back-top-icon"></div>
+              return (
+                <Tabs defaultActiveKey="0" key={group}>
+                  {config[group].map((_tab, index) => {
+                    return (
+                      <TabPane tab={
+                        <span>
+                          {_tab.icon ? <Icon type={_tab.icon} /> : null}
+                          {_tab.label}
+                        </span>
+                      } key={`${index}`}>
+                        {_tab.type === 'SubTable' ?
+                          <SubTable
+                            Tab={_tab}
+                            MenuID={_tab.linkTab}
+                            SupMenuID={this.props.MenuID}
+                            ContainerId={this.state.ContainerId}
+                            BID={this.state.BIDs[_tab.supMenu] || ''}
+                            BData={this.state.BIDs[_tab.supMenu + 'data'] || ''}
+                            handleTableId={this.handleTableId}
+                            handleMainTable={this.handleMainTable}
+                          /> : null}
+                      </TabPane>
+                    )
+                  })}
+                </Tabs>
+              )
+            })
+          }
+          <Modal
+            className="popview-modal"
+            title={this.state.popAction.label}
+            width={'80vw'}
+            maskClosable={false}
+            visible={this.state.visible}
+            onCancel={this.popclose}
+            footer={[
+              <Button key="cancel" onClick={this.popclose}>{this.state.dict['main.close']}</Button>
+            ]}
+            destroyOnClose
+          >
+            {<SubTabTable 
+              BID={''}
+              SupMenuID={this.props.MenuID}
+              MenuID={this.state.popAction.linkTab}
+              BData={this.state.BIDs['mainTabledata'] || ''}
+              ContainerId={this.state.ContainerId}
+              ID={this.state.popData ? this.state.popData[setting.primaryKey] : ''}
+              refreshSupView={this.reloadtable}
+            />}
+          </Modal>
+          <BackTop>
+            <div className="ant-back-top">
+              <div className="ant-back-top-content">
+                <div className="ant-back-top-icon"></div>
+              </div>
             </div>
-          </div>
-        </BackTop>
-        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
+          </BackTop>
+          {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
+        </div> : null}
+        {view === 'formtab' ? <FormTab MenuID={this.state.tabBtn.uuid} param={this.state.tabParam}/> : null}
       </div>
     )
   }
diff --git a/src/tabviews/formtab/actionList/index.jsx b/src/tabviews/formtab/actionList/index.jsx
index fcf6651..f6a51ac 100644
--- a/src/tabviews/formtab/actionList/index.jsx
+++ b/src/tabviews/formtab/actionList/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import moment from 'moment'
-import { Button, Modal, notification, Spin, message } from 'antd'
+import { Button, Modal, notification, message } from 'antd'
 import Utils from '@/utils/utils.js'
 import Api from '@/api'
 import './index.scss'
@@ -10,59 +10,28 @@
 
 class MainAction extends Component {
   static propTpyes = {
-    BData: PropTypes.any,          // 涓昏〃鏁版嵁
-    type: PropTypes.string,        // 鍒ゆ柇褰撳墠涓轰富琛紙main锛夈�佸瓙琛紙sub锛夈�佸瓙琛ㄦ爣绛撅紙subtab锛�
     MenuID: PropTypes.string,      // 鑿滃崟ID
     actions: PropTypes.array,      // 鎸夐挳缁�
-    logcolumns: PropTypes.array,   // 鏃ュ織涓樉绀哄垪
+    logcolumns: PropTypes.array,   // 鏄剧ず鍒�
     dict: PropTypes.object,        // 瀛楀吀椤�
+    data: PropTypes.any,           // 鏁版嵁
     setting: PropTypes.any,        // 椤甸潰閫氱敤璁剧疆
-    triggerPopview: PropTypes.func // 寮圭獥鏍囩椤佃Е鍙�
+    refreshdata: PropTypes.func,   // 鎵ц瀹屾垚鍚庢暟鎹埛鏂�
   }
 
   state = {
-    visible: false,
     formdata: null,
     tabledata: null,
-    confirmLoading: false,
-    loadingUuid: '',
-    btnloading: false
+    loadingUuid: ''
   }
   
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (item, record) => {
-    const { setting } = this.props
+  actionTrigger = (item) => {
+    const { data } = this.props
 
     let _this = this
-    let data = this.props.gettableselected() || []
-
-    if (item.Ot !== 'notRequired' && data.length === 0) {
-      // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
-      notification.warning({
-        top: 92,
-        message: this.props.dict['main.action.confirm.selectline'],
-        duration: 10
-      })
-      return
-    } else if (item.Ot === 'requiredSgl' && data.length !== 1) {
-      // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
-      notification.warning({
-        top: 92,
-        message: this.props.dict['main.action.confirm.selectSingleLine'],
-        duration: 10
-      })
-      return
-    } else if (item.Ot !== 'notRequired' && !setting.primaryKey) {
-      // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾槸鍚﹁缃富閿�
-      notification.warning({
-        top: 92,
-        message: '鏈缃富閿紒',
-        duration: 10
-      })
-      return
-    }
 
     if (item.OpenType === 'prompt') {
       confirm({
@@ -78,17 +47,6 @@
       this.setState({loadingUuid: item.uuid})
       this.execSubmit(item, data, () => {
         this.setState({loadingUuid: ''})
-      })
-    } else if (item.OpenType === 'pop') {
-      this.setState({
-        tabledata: data,
-        btnloading: true
-      })
-    } else {
-      notification.warning({
-        top: 92,
-        message: '瀹屽杽涓�傘�傘��',
-        duration: 10
       })
     }
   }
@@ -474,12 +432,6 @@
     } else if (res && res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
 
     }
-    
-    if (btn.OpenType === 'pop' && btn.setting && btn.setting.finish !== 'unclose') {
-      this.setState({
-        visible: false
-      })
-    }
 
     this.props.refreshdata(btn, 'success')
   }
@@ -528,10 +480,10 @@
 
   
   render() {
-    const { loadingUuid, btnloading } = this.state
+    const { loadingUuid } = this.state
 
     return (
-      <div className="button-list toolbar-button">
+      <div className="button-list formtab-button">
         {this.props.actions.map((item, index) => {
           if (loadingUuid === item.uuid) {
             return (
@@ -554,17 +506,6 @@
             )
           }
         })}
-        <Button
-          className={'mk-btn'}
-          // icon={item.icon}
-          onClick={() => {this.actionTrigger()}}
-        >纭畾</Button>
-        <Button
-          className={'mk-btn'}
-          // icon={item.icon}
-          onClick={() => {this.actionTrigger()}}
-        >杩斿洖</Button>
-        {btnloading && <Spin size="large" />}
       </div>
     )
   }
diff --git a/src/tabviews/formtab/actionList/index.scss b/src/tabviews/formtab/actionList/index.scss
index 1d576f0..7e84e37 100644
--- a/src/tabviews/formtab/actionList/index.scss
+++ b/src/tabviews/formtab/actionList/index.scss
@@ -1,5 +1,5 @@
-.button-list.toolbar-button {
-  padding: 10px 20px 5px;
+.button-list.formtab-button {
+  padding: 20px 20px 10px;
   background: #ffffff;
   button {
     min-width: 65px;
@@ -13,30 +13,3 @@
     top: calc(50vh - 70px);
   }
 }
-// 璁剧疆妯℃�佹鏍峰紡锛岃瀹氭渶澶ф渶灏忛珮搴︼紝閲嶇疆婊氬姩鏉�
-.action-modal {
-  .ant-modal {
-    max-width: 95vw;
-  }
-  .ant-modal-body {
-    max-height: calc(100vh - 235px);
-    min-height: 150px;
-    overflow-y: auto;
-    padding-bottom: 35px;
-  }
-  .ant-modal-body::-webkit-scrollbar {
-    width: 10px;
-    height: 10px;
-  }
-  .ant-modal-body::-webkit-scrollbar-thumb {
-    border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-    background: rgba(0, 0, 0, 0.13);
-  }
-  .ant-modal-body::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-    border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0.07);
-    background: rgba(0, 0, 0, 0);
-  }
-}
\ No newline at end of file
diff --git a/src/tabviews/formtab/index.jsx b/src/tabviews/formtab/index.jsx
index f375050..15a81fc 100644
--- a/src/tabviews/formtab/index.jsx
+++ b/src/tabviews/formtab/index.jsx
@@ -21,8 +21,8 @@
 
 class NormalTable extends Component {
   static propTpyes = {
-    MenuNo: PropTypes.string,    // 鑿滃崟鍙傛暟
-    MenuName: PropTypes.string,  // 鑿滃崟鍙傛暟
+    // MenuNo: PropTypes.string,    // 鑿滃崟鍙傛暟
+    // MenuName: PropTypes.string,  // 鑿滃崟鍙傛暟
     MenuID: PropTypes.string,    // 鑿滃崟Id
     param: PropTypes.any         // 涓昏〃浼犻�掑弬鏁�
   }
@@ -89,7 +89,7 @@
       }
 
       let _arrField = []     // 瀛楁闆�
-
+      console.log(this.props.param)
       if (this.props.param && this.props.param.arr_field) {
         _arrField = this.props.param.arr_field
       } else {
@@ -136,7 +136,7 @@
       let _isCustomData = false
 
       if (this.props.param && this.props.param.data) {
-        _data = this.props.param.data
+        _data = this.props.param.data[0] || null
       }
 
       if ((config.setting.interType === 'inner' && config.setting.innerFunc) || (config.setting.interType === 'outer' && config.setting.interface)) {
@@ -407,6 +407,7 @@
             setting={setting}
             actions={actions}
             dict={this.state.dict}
+            data={this.state.data}
             MenuID={this.props.MenuID}
             logcolumns={[]}
             refreshdata={this.refreshbyaction}
diff --git a/src/tabviews/tableshare/actionList/index.jsx b/src/tabviews/tableshare/actionList/index.jsx
index 9bfa175..5f897b6 100644
--- a/src/tabviews/tableshare/actionList/index.jsx
+++ b/src/tabviews/tableshare/actionList/index.jsx
@@ -3,6 +3,7 @@
 import moment from 'moment'
 import { Button, Affix, Modal, notification, Spin, message } from 'antd'
 import MutilForm from '@/tabviews/tableshare/mutilform'
+import ExcelIn from '../excelin'
 import Utils from '@/utils/utils.js'
 import Api from '@/api'
 import './index.scss'
@@ -11,17 +12,19 @@
 
 class MainAction extends Component {
   static propTpyes = {
-    BID: PropTypes.string,         // 涓昏〃ID
-    BData: PropTypes.any,          // 涓昏〃鏁版嵁
-    Tab: PropTypes.any,            // 濡傛灉褰撳墠鍏冪礌涓烘爣绛炬椂锛宼ab涓烘爣绛句俊鎭�
-    type: PropTypes.string,        // 鍒ゆ柇褰撳墠涓轰富琛紙main锛夈�佸瓙琛紙sub锛夈�佸瓙琛ㄦ爣绛撅紙subtab锛�
-    MenuID: PropTypes.string,      // 鑿滃崟ID
-    actions: PropTypes.array,      // 鎸夐挳缁�
-    logcolumns: PropTypes.array,   // 鏃ュ織涓樉绀哄垪
-    dict: PropTypes.object,        // 瀛楀吀椤�
-    setting: PropTypes.any,        // 椤甸潰閫氱敤璁剧疆
-    ContainerId: PropTypes.any,    // tab椤甸潰ID锛岀敤浜庡脊绐楁帶鍒�
-    triggerPopview: PropTypes.func // 寮圭獥鏍囩椤佃Е鍙�
+    BID: PropTypes.string,            // 涓昏〃ID
+    BData: PropTypes.any,             // 涓昏〃鏁版嵁
+    Tab: PropTypes.any,               // 濡傛灉褰撳墠鍏冪礌涓烘爣绛炬椂锛宼ab涓烘爣绛句俊鎭�
+    type: PropTypes.string,           // 鍒ゆ柇褰撳墠涓轰富琛紙main锛夈�佸瓙琛紙sub锛夈�佸瓙琛ㄦ爣绛撅紙subtab锛�
+    MenuID: PropTypes.string,         // 鑿滃崟ID
+    actions: PropTypes.array,         // 鎸夐挳缁�
+    logcolumns: PropTypes.array,      // 鏃ュ織涓樉绀哄垪
+    dict: PropTypes.object,           // 瀛楀吀椤�
+    setting: PropTypes.any,           // 椤甸潰閫氱敤璁剧疆
+    ContainerId: PropTypes.any,       // tab椤甸潰ID锛岀敤浜庡脊绐楁帶鍒�
+    refreshdata: PropTypes.func,      // 鎵ц瀹屾垚鍚庢暟鎹埛鏂�
+    triggerPopview: PropTypes.func,   // 寮圭獥鏍囩椤佃Е鍙�
+    gettableselected: PropTypes.func  // 鑾峰彇琛ㄦ牸涓暟鎹�
   }
 
   state = {
@@ -113,6 +116,16 @@
     } else if (item.OpenType === 'excelOut') {
       this.setState({loadingUuid: item.uuid})
       this.refreshdata(item, 'excelOut')
+    } else if (item.OpenType === 'excelIn') {
+      if (item.verify && item.verify.sheet && item.verify.columns && item.verify.columns.length > 0) {
+        this.refs.excelIn.exceltrigger(item)
+      } else {
+        notification.warning({
+          top: 92,
+          message: 'excel瀵煎叆楠岃瘉淇℃伅鏈缃紒',
+          duration: 10
+        })
+      }
     } else if (item.OpenType === 'popview' && this.props.type !== 'subtab') {
       this.props.triggerPopview(item, data)
     } else if (item.OpenType === 'popview' && this.props.type === 'subtab') {
@@ -525,7 +538,7 @@
    * 5銆侀�氱煡涓诲垪琛ㄥ埛鏂�
    */
   execSuccess = (btn, res) => {
-    if (btn.OpenType === 'excelOut') { // 瀵煎嚭excel
+    if (btn.OpenType === 'excelOut' || btn.OpenType === 'excelIn') { // 瀵煎嚭excel
       this.setState({
         loadingUuid: ''
       })
@@ -584,7 +597,7 @@
       message.error(res.message || res.ErrMesg)
     }
     
-    if (btn.OpenType === 'excelOut') {
+    if (btn.OpenType === 'excelOut' || btn.OpenType === 'excelIn') {
       this.setState({
         loadingUuid: ''
       })
@@ -778,6 +791,74 @@
     })
   }
 
+  getexceldata = (data, btn, errors) => {
+    if (errors && errors.length > 0) {
+      notification.warning({
+        top: 92,
+        message: errors.join(',') + '琛ㄥご璁剧疆閿欒锛�',
+        duration: 10
+      })
+      return
+    }
+    if (!data || data.length === 0) {
+      notification.warning({
+        top: 92,
+        message: '鏈幏鍙栧埌excel鏁版嵁锛�',
+        duration: 10
+      })
+      return
+    }
+
+    let result = Utils.getExcelInSql(btn, data, this.props.dict)
+    if (result.errors) {
+      notification.warning({
+        top: 92,
+        message: result.errors,
+        duration: 10
+      })
+      return
+    }
+    if (!btn.innerFunc) {
+      let param = { // 绯荤粺瀛樺偍杩囩▼
+        func: 'sPC_TableData_InUpDe',
+        BID: this.props.BID
+      }
+
+      param.LText = Utils.formatOptions(result.sql)
+      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+      param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+      this.setState({loadingUuid: btn.uuid})
+
+      Api.genericInterface(param).then((res) => {
+        if (res.status) {
+          this.execSuccess(btn, res)
+        } else {
+          this.execError(res, btn)
+        }
+      })
+    } else {
+      let param = { // 鑷畾涔夊瓨鍌ㄨ繃绋�
+        func: btn.innerFunc,
+        BID: this.props.BID
+      }
+
+      param.LText = Utils.formatOptions(result.sql)
+      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+      param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+      this.setState({loadingUuid: btn.uuid})
+
+      Api.genericInterface(param).then((res) => {
+        if (res.status) {
+          this.execSuccess(btn, res)
+        } else {
+          this.execError(res, btn)
+        }
+      })
+    }
+  }
+
   /**
    * @description 妯℃�佹锛堣〃鍗曪級锛岀‘璁�
    */
@@ -948,6 +1029,7 @@
             })}
             {this.getModels()}
             {btnloading && <Spin size="large" />}
+            <ExcelIn MenuID={this.props.MenuID} returndata={this.getexceldata} ref="excelIn" />
           </div>
         </Affix>
       )
@@ -978,6 +1060,7 @@
           })}
           {this.getModels()}
           {btnloading && <Spin size="large" />}
+          <ExcelIn MenuID={this.props.MenuID} returndata={this.getexceldata} ref="excelIn" />
         </div>
       )
     }
diff --git a/src/tabviews/tableshare/actionList/index.scss b/src/tabviews/tableshare/actionList/index.scss
index 1d576f0..9dd1f19 100644
--- a/src/tabviews/tableshare/actionList/index.scss
+++ b/src/tabviews/tableshare/actionList/index.scss
@@ -1,10 +1,12 @@
 .button-list.toolbar-button {
+  position: relative;
   padding: 10px 20px 5px;
   background: #ffffff;
   button {
     min-width: 65px;
     margin-right: 15px;
     margin-bottom: 10px;
+    overflow: hidden;
   }
   .ant-spin {
     position: fixed;
diff --git a/src/tabviews/tableshare/excelin/index.jsx b/src/tabviews/tableshare/excelin/index.jsx
new file mode 100644
index 0000000..d0906a8
--- /dev/null
+++ b/src/tabviews/tableshare/excelin/index.jsx
@@ -0,0 +1,117 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { notification } from 'antd'
+import * as XLSX from 'xlsx'
+import Utils from '@/utils/utils.js'
+import './index.scss'
+
+class ExcelIn extends Component {
+  static propTpyes = {
+    MenuID: PropTypes.string,     // 鑿滃崟ID
+    returndata: PropTypes.func    // 鑿滃崟ID
+  }
+
+  state = {
+    excelbtn: null,
+    excelId: Utils.getuuid()
+  }
+
+  exceltrigger = (item) => {
+    const { excelId } = this.state
+    this.setState({
+      excelbtn: item
+    })
+
+    let _excelInput = document.getElementById(excelId + this.props.MenuID)
+    
+    if (_excelInput) {
+      _excelInput.click()
+    }
+  }
+  onImportExcel = file => {
+    const { excelbtn } = this.state
+
+    let columns = excelbtn.verify.columns.map(option => option.Column)
+    let range = excelbtn.verify.range || 0
+
+    // excel鏁版嵁澶勭悊
+    const { files } = file.target
+    const fileReader = new FileReader()
+
+    fileReader.onload = event => {
+      try {
+        const { result } = event.target
+        // 浠ヤ簩杩涘埗娴佹柟寮忚鍙栧緱鍒版暣浠絜xcel琛ㄦ牸瀵硅薄
+        const workbook = XLSX.read(result, { type: 'binary' })
+
+        let errors = []
+        if (range === 1) {
+          workbook.SheetNames.forEach(sheetname => {
+            if (workbook.Sheets.hasOwnProperty(sheetname)) {
+              let header = XLSX.utils.sheet_to_json(workbook.Sheets[sheetname], {header: columns})[0]
+              
+              if (!header) {
+                errors.push(sheetname)
+              } else {
+                let iserror = false
+                excelbtn.verify.columns.forEach(op => {
+                  if (header[op.Column] !== op.Text) {
+                    iserror = true
+                  }
+                })
+
+                if (iserror) {
+                  errors.push(sheetname)
+                }
+              }
+            }
+          })
+        }
+
+        let data = []
+
+        workbook.SheetNames.forEach(sheetname => {
+          if (workbook.Sheets.hasOwnProperty(sheetname)) {
+            data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheetname], {header: columns, range: (range)}))
+          }
+        })
+
+        // 鏈�缁堣幏鍙栧埌骞朵笖鏍煎紡鍖栧悗鐨� json 鏁版嵁
+        this.props.returndata(data, excelbtn, errors)
+        this.setState({
+          excelId: ''
+        }, () => {
+          this.setState({
+            excelId: Utils.getuuid()
+          })
+        })
+      } catch (e) {
+        this.setState({
+          excelId: ''
+        }, () => {
+          this.setState({
+            excelId: Utils.getuuid()
+          })
+        })
+        notification.warning({
+          top: 92,
+          message: '鏂囦欢瑙f瀽閿欒锛岃妫�鏌ユ枃浠舵牸寮忥紒',
+          duration: 10
+        })
+      }
+    }
+
+    // 浠ヤ簩杩涘埗鏂瑰紡鎵撳紑鏂囦欢
+    fileReader.readAsBinaryString(files[0])
+  }
+
+  render() {
+    return (
+      <span>
+        {this.state.excelId ? <input className="excel-in-input" id={this.state.excelId + this.props.MenuID} type='file' accept='.xlsx, .xls' onChange={this.onImportExcel} /> : null}
+      </span>
+    )
+  }
+}
+
+export default ExcelIn
\ No newline at end of file
diff --git a/src/tabviews/tableshare/excelin/index.scss b/src/tabviews/tableshare/excelin/index.scss
new file mode 100644
index 0000000..f1bf76a
--- /dev/null
+++ b/src/tabviews/tableshare/excelin/index.scss
@@ -0,0 +1,5 @@
+.excel-in-input {
+  position: absolute;
+  opacity: 0;
+  z-index: -1;
+}
\ No newline at end of file
diff --git a/src/templates/comtableconfig/actionform/index.jsx b/src/templates/comtableconfig/actionform/index.jsx
index a20436a..d65053e 100644
--- a/src/templates/comtableconfig/actionform/index.jsx
+++ b/src/templates/comtableconfig/actionform/index.jsx
@@ -100,12 +100,14 @@
       _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate']
     } else if (_opentype === 'popview') {                                // 妯℃�佹鏍囩椤�
       _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabType', 'linkTab', 'popClose']
-    } else if (_opentype === 'excelIn' || _opentype === 'excelOut') {    // 瀵煎叆瀵煎嚭
+    } else if (_opentype === 'excelOut') {    // 瀵煎叆瀵煎嚭
       if (_intertype === 'outer') {
         _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'icon', 'class', 'execSuccess', 'execError', 'method']
       } else {
         _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError']
       }
+    } else if (_opentype === 'excelIn') {    // 瀵煎叆瀵煎嚭
+      _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError']
     } else {
       if (_intertype === 'outer') {
         _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'method']
@@ -147,6 +149,9 @@
           if (!initTab) {
             item.initVal = ''
           }
+        } else if (item.key === 'intertype' && _opentype === 'excelIn') {
+          item.initVal = 'inner'
+          item.readonly = true
         }
         item.hidden = !_options.includes(item.key)
         return item
@@ -184,12 +189,14 @@
         _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabTemplate']
       } else if (value === 'popview') {
         _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabType', 'linkTab', 'popClose']
-      } else if (value === 'excelIn' || value === 'excelOut') {
+      } else if (value === 'excelOut') {
         if (this.state.interType === 'outer') {
           _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'icon', 'class', 'execSuccess', 'execError', 'method']
         } else {
           _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError']
         }
+      } else if (value === 'excelIn') {
+        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError']
       } else {
         if (this.state.interType === 'inner') {
           _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType']
@@ -205,8 +212,12 @@
 
         if (item.hidden) return item
 
-        if (item.key === 'intertype') {
+        if (item.key === 'intertype' && value === 'excelIn') {
+          _fieldval.intertype = 'inner'
+          item.readonly = true
+        } else if (item.key === 'intertype' && value !== 'excelIn') {
           _fieldval.intertype = this.state.interType
+          item.readonly = false
         } else if (item.key === 'Ot') {
           if (value === 'innerpage' || this.state.position === 'grid') {
             item.options = this.state.reqOptionSgl
@@ -282,13 +293,28 @@
   }
 
   onChange = (e, key) => {
+    const { openType } = this.state
     let value = e.target.value
     if (key === 'intertype') {
       let _options = null
-      if (value === 'inner') {
-        _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType']
+      if (openType === 'excelOut') {
+        if (value === 'outer') {
+          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'icon', 'class', 'execSuccess', 'execError', 'method']
+        } else {
+          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError']
+        }
+      } else if (openType === 'excelIn') {
+        if (value === 'outer') {
+          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'icon', 'class', 'execSuccess', 'execError', 'method']
+        } else {
+          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError']
+        }
       } else {
-        _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'method']
+        if (value === 'inner') {
+          _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType']
+        } else {
+          _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc', 'method']
+        }
       }
 
       this.setState({
@@ -379,7 +405,7 @@
             </Form.Item>
           </Col>
         )
-      } else if (item.type === 'number') { // 鏂囨湰鎼滅储
+      } else if (item.type === 'number') {
         fields.push(
           <Col span={12} key={index}>
             <Form.Item label={item.tooltip ?
@@ -389,8 +415,14 @@
               </Tooltip> : item.label
             }>
               {getFieldDecorator(item.key, {
-                initialValue: item.initVal
-              })(<InputNumber min={1} max={10000} precision={0} />)}
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: item.readonly ? false : !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  }
+                ]
+              })(<InputNumber min={0} max={10000} precision={0} />)}
             </Form.Item>
           </Col>
         )
@@ -441,7 +473,7 @@
                   }
                 ]
               })(
-                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}}>
+                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}} disabled={item.readonly}>
                   {
                     item.options.map(option => {
                       return (
@@ -477,7 +509,10 @@
           values.uuid = this.props.card.uuid
           values.verify = this.props.card.verify || null
 
-          if (values.OpenType === 'excelIn' || values.OpenType === 'excelOut') {
+          if (values.OpenType === 'excelIn') {
+            values.position = 'toolbar'
+            values.Ot = 'notRequired'
+          } else if (values.OpenType === 'excelOut') {
             values.position = 'toolbar'
             values.Ot = 'notRequired'
           } else if (values.OpenType === 'popview' && !values.linkTab) { // 娌℃湁鍏宠仈鏍囩锛堟柊寤烘椂锛夛紝鍒涘缓鏂版爣绛綢d
diff --git a/src/templates/comtableconfig/index.jsx b/src/templates/comtableconfig/index.jsx
index ad2b0f7..d50cd94 100644
--- a/src/templates/comtableconfig/index.jsx
+++ b/src/templates/comtableconfig/index.jsx
@@ -23,6 +23,7 @@
 import GridBtnForm from '@/templates/tableshare/gridbtnform'
 import EditCard from '@/templates/tableshare/editcard'
 import VerifyCard from '@/templates/tableshare/verifycard'
+import VerifyCardExcelIn from '@/templates/tableshare/verifycardexcelin'
 import MenuForm from '@/templates/tableshare/menuform'
 import TabDragElement from '@/templates/tableshare/tabdragelement'
 import SourceElement from '@/templates/tableshare/dragelement/source'
@@ -185,7 +186,8 @@
   componentDidMount () {
     let param = {
       func: 'sPC_Get_SelectedList',
-      LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
+      // LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
+      LText: 'select TbName,Remark from (select TbName,Remark from sDataDictb where appkey= @appkey@ and Deleted=0 union select a.TbName,Remark from (select TbName,Remark from sDataDictb where appkey= \'\' and Deleted=0 ) a left join (select TbName from sDataDictb where appkey= @appkey@ and Deleted=0 ) b on a.TbName=b.TbName where b.TbName is null ) t',
       obj_name: 'data',
       arr_field: 'TbName,Remark'
     }
@@ -1282,6 +1284,53 @@
     const { card } = this.state
     let config = JSON.parse(JSON.stringify(this.state.config))
     let _verify = this.verifyRef.state.verify
+
+    if (card.OpenType !== 'excelIn') {
+      if (_verify.default === 'false' && _verify.scripts.length === 0) {
+        notification.warning({
+          top: 92,
+          message: '涓嶆墽琛岄粯璁ql鏃讹紝蹇呴』璁剧疆鑷畾涔夎剼鏈紒',
+          duration: 10
+        })
+        return
+      }
+    } else if (card.OpenType === 'excelIn') {
+      let cols = _verify.columns.map(col => col.Column)
+      cols = Array.from(new Set(cols))
+
+      if (!_verify.sheet) {
+        notification.warning({
+          top: 92,
+          message: '璇疯缃鍏ヨ〃鍚�!',
+          duration: 10
+        })
+        return
+      } else if (_verify.columns.length === 0) {
+        notification.warning({
+          top: 92,
+          message: '璇疯缃瓻xcel鍒楀瓧娈�!',
+          duration: 10
+        })
+        return
+      } else if (_verify.columns.length > cols.length) {
+        notification.warning({
+          top: 92,
+          message: 'Excel鍒楀瓧娈靛悕锛屼笉鍙噸澶�!',
+          duration: 10
+        })
+        return
+      } else if (_verify.range === 1) {
+        let tEmptys = _verify.columns.filter(op => !op.Text)
+        if (tEmptys.length > 0) {
+          notification.warning({
+            top: 92,
+            message: '蹇界暐棣栬鏃讹紝浼氫娇鐢═ext鍊兼牎楠孍xcel棣栬鍐呭锛孴ext鍊间笌Excel琛ㄩ琛屽唴瀹圭浉鍚岋紝涓斿潎涓嶅彲涓虹┖锛�',
+            duration: 10
+          })
+          return
+        }
+      }  
+    }
 
     config.action = config.action.map(item => {
       if (item.uuid === card.uuid) {
@@ -2495,7 +2544,7 @@
         <Modal
           title={modaltype === 'actionEdit' ? this.state.dict['header.modal.action.edit'] : this.state.dict['header.modal.action.copy']}
           visible={modaltype === 'actionEdit' || modaltype === 'actionCopy'}
-          width={700}
+          width={800}
           onCancel={this.editModalCancel}
           footer={[
             modaltype === 'actionEdit' ? <Button key="delete" className="mk-btn mk-purple" onClick={this.creatFunc} loading={this.state.funcLoading}>{this.state.dict['header.menu.func.create']}</Button> : null,
@@ -2612,7 +2661,21 @@
           onCancel={() => { this.setState({ profileVisible: false }) }}
           destroyOnClose
         >
-          <VerifyCard card={this.state.card} columns={this.state.config.columns} wrappedComponentRef={(inst) => this.verifyRef = inst} dict={this.state.dict} />
+          {this.state.card && this.state.card.OpenType !== 'excelIn' ?
+            <VerifyCard
+              card={this.state.card}
+              dict={this.state.dict}
+              columns={this.state.config.columns}
+              wrappedComponentRef={(inst) => this.verifyRef = inst}
+            /> : null
+          }
+          {this.state.card && this.state.card.OpenType === 'excelIn' ?
+            <VerifyCardExcelIn
+              card={this.state.card}
+              dict={this.state.dict}
+              wrappedComponentRef={(inst) => this.verifyRef = inst}
+            /> : null
+          }
         </Modal>
         {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */}
         <Modal
diff --git a/src/templates/formtabconfig/editable/index.jsx b/src/templates/formtabconfig/editable/index.jsx
deleted file mode 100644
index 4f10603..0000000
--- a/src/templates/formtabconfig/editable/index.jsx
+++ /dev/null
@@ -1,258 +0,0 @@
-import React, {Component} from 'react'
-import { Table, Input, Button, Popconfirm, Form, Icon } from 'antd'
-import Utils from '@/utils/utils.js'
-import './index.scss'
-
-const EditableContext = React.createContext()
-
-const EditableRow = ({ form, index, ...props }) => (
-  <EditableContext.Provider value={form}>
-    <tr {...props} />
-  </EditableContext.Provider>
-)
-
-const EditableFormRow = Form.create()(EditableRow)
-
-class EditableCell extends Component {
-  state = {
-    editing: false
-  }
-
-  toggleEdit = () => {
-    const editing = !this.state.editing
-    this.setState({ editing }, () => {
-      if (editing) {
-        this.input.focus()
-      }
-    })
-  }
-
-  save = e => {
-    const { record, handleSave } = this.props
-    this.form.validateFields((error, values) => {
-      handleSave({ ...record, ...values })
-      if (error && error[e.currentTarget.id]) {
-        return
-      }
-      this.toggleEdit()
-      // handleSave({ ...record, ...values })
-    })
-  }
-
-  renderCell = form => {
-    this.form = form
-    const { children, dataIndex, record } = this.props
-    const { editing } = this.state
-    return editing ? (
-      <Form.Item style={{ margin: 0 }}>
-        {form.getFieldDecorator(dataIndex, {
-          rules: [
-            {
-              required: true,
-              message: 'NOT NULL.',
-            },
-          ],
-          initialValue: record[dataIndex]
-        })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)}
-      </Form.Item>
-    ) : (
-      <div
-        className="editable-cell-value-wrap"
-        onClick={this.toggleEdit}
-      >
-        {children}
-      </div>
-    )
-  }
-
-  render() {
-    const {
-      editable,
-      dataIndex,
-      title,
-      record,
-      index,
-      handleSave,
-      children,
-      ...restProps
-    } = this.props
-    return (
-      <td {...restProps}>
-        {editable ? (
-          <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer>
-        ) : (
-          children
-        )}
-      </td>
-    )
-  }
-}
-
-class EditTable extends Component {
-  constructor(props) {
-    super(props)
-    let columns = [
-      {
-        title: 'Value',
-        dataIndex: 'Value',
-        width: props.type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: 'Text',
-        dataIndex: 'Text',
-        width: props.type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
-          ) : null,
-      }
-    ]
-
-    if (props.type === 'link') {
-      columns.unshift({
-        title: 'ParentID',
-        dataIndex: 'ParentID',
-        width: '27%',
-        editable: true
-      })
-    }
-
-    this.state = {
-      columns: columns,
-      dataSource: props.data,
-      count: props.data.length,
-      type: props.type
-    }
-  }
-
-  handleDelete = key => {
-    const dataSource = [...this.state.dataSource]
-    this.setState({ dataSource: dataSource.filter(item => item.key !== key) })
-  }
-
-  handleAdd = () => {
-    const { type, count, dataSource } = this.state
-    const newData = {
-      key: Utils.getuuid(),
-      Value: `${count}`,
-      Text: `${count}`
-    }
-    if (type === 'link') {
-      newData.ParentID = `${count}`
-    }
-    this.setState({
-      dataSource: [...dataSource, newData],
-      count: count + 1
-    })
-  }
-
-  handleSave = row => {
-    const newData = [...this.state.dataSource]
-    const index = newData.findIndex(item => row.key === item.key)
-    const item = newData[index]
-    newData.splice(index, 1, {
-      ...item,
-      ...row
-    })
-    this.setState({ dataSource: newData })
-  }
-
-  resetColumn = (type) => {
-    let columns = [
-      {
-        title: 'Value',
-        dataIndex: 'Value',
-        width: type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: 'Text',
-        dataIndex: 'Text',
-        width: type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
-          ) : null,
-      }
-    ]
-
-    if (type === 'link') {
-      columns.unshift({
-        title: 'ParentID',
-        dataIndex: 'ParentID',
-        width: '27%',
-        editable: true
-      })
-    }
-
-    this.setState({
-      columns: columns,
-      type: type
-    })
-  }
-
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (this.props.type !== nextProps.type) {
-      this.resetColumn(nextProps.type)
-    }
-  }
-
-  render() {
-    const { dataSource } = this.state
-    const components = {
-      body: {
-        row: EditableFormRow,
-        cell: EditableCell
-      }
-    }
-    const columns = this.state.columns.map(col => {
-      if (!col.editable) {
-        return col
-      }
-      return {
-        ...col,
-        onCell: record => ({
-          record,
-          editable: col.editable,
-          dataIndex: col.dataIndex,
-          title: col.title,
-          handleSave: this.handleSave,
-        })
-      }
-    })
-    return (
-      <div className="common-modal-edit-table">
-        <Button onClick={this.handleAdd} type="primary" className="add-row">
-          娣诲姞
-        </Button>
-        <Table
-          components={components}
-          rowClassName={() => 'editable-row'}
-          bordered
-          dataSource={dataSource}
-          columns={columns}
-          pagination={false}
-        />
-      </div>
-    )
-  }
-}
-
-export default EditTable
\ No newline at end of file
diff --git a/src/templates/formtabconfig/editable/index.scss b/src/templates/formtabconfig/editable/index.scss
deleted file mode 100644
index f8f0942..0000000
--- a/src/templates/formtabconfig/editable/index.scss
+++ /dev/null
@@ -1,36 +0,0 @@
-.common-modal-edit-table {
-  .add-row {
-    position: absolute;
-    z-index: 1;
-    right: 12px;
-    top: -40px;
-  }
-  .ant-table-thead > tr > th {
-    padding: 10px 16px;
-  }
-  .ant-table-tbody > tr > td {
-    padding: 0px 16px;
-  }
-  .editable-cell-value-wrap {
-    cursor: pointer;
-    height: 40px;
-    width: 100px;
-    display: table-cell;
-    vertical-align: middle;
-    word-wrap: break-word;
-    word-break: break-word;
-    .ant-input {
-      height: 30px;
-      padding: 0 11px;
-    }
-  }
-  .ant-form-item-control-wrapper {
-    width: 100%;
-  }
-  .ant-table-placeholder {
-    padding: 5px 16px;
-    .ant-empty-normal {
-      margin: 0;
-    }
-  }
-}
diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx
index af05280..830ea64 100644
--- a/src/templates/formtabconfig/index.jsx
+++ b/src/templates/formtabconfig/index.jsx
@@ -13,9 +13,10 @@
 import Utils from '@/utils/utils.js'
 import { getModalForm, getActionForm } from '@/templates/tableshare/formconfig'
 
+import ModalForm from '@/templates/ushare/modalform'
 import ActionForm from './actionform'
 import SettingForm from './settingform'
-import ModalForm from './modalform'
+// import ModalForm from './modalform'
 import DragElement from './dragelement'
 import GroupForm from './groupform'
 import TabForm from '@/templates/tableshare/tabform'
@@ -122,7 +123,8 @@
   componentDidMount () {
     let param = {
       func: 'sPC_Get_SelectedList',
-      LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
+      // LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
+      LText: 'select TbName,Remark from (select TbName,Remark from sDataDictb where appkey= @appkey@ and Deleted=0 union select a.TbName,Remark from (select TbName,Remark from sDataDictb where appkey= \'\' and Deleted=0 ) a left join (select TbName from sDataDictb where appkey= @appkey@ and Deleted=0 ) b on a.TbName=b.TbName where b.TbName is null ) t',
       obj_name: 'data',
       arr_field: 'TbName,Remark'
     }
@@ -1210,7 +1212,7 @@
         func: 'sPC_Button_AddUpt',
         Type: 60,      // 娣诲姞鎸夐挳琛ㄥ崟椤典笅鐨勬寜閽�
         ParentID: menu.MenuID,
-        MenuNo: res.menuNo,
+        MenuNo: menu.MenuNo,
         Template: menu.PageParam.Template || '',
         PageParam: '',
         LongParam: '',
diff --git a/src/templates/formtabconfig/modalform/index.jsx b/src/templates/formtabconfig/modalform/index.jsx
deleted file mode 100644
index f21bf57..0000000
--- a/src/templates/formtabconfig/modalform/index.jsx
+++ /dev/null
@@ -1,416 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Select, Icon, Radio, notification, InputNumber } from 'antd'
-import { formRule } from '@/utils/option.js'
-import { dateOptions } from '@/utils/option.js'
-import EditTable from '../editable'
-import './index.scss'
-
-const { TextArea } = Input
-
-class MainSearch extends Component {
-  static propTpyes = {
-    dict: PropTypes.object, // 瀛楀吀椤�
-    formlist: PropTypes.any,
-    card: PropTypes.object
-  }
-
-  state = {
-    openType: null,
-    resourceType: null,
-    formlist: null
-  }
-
-  UNSAFE_componentWillMount () {
-    let formlist = JSON.parse(JSON.stringify(this.props.formlist))
-
-    let type = formlist.filter(cell => cell.key === 'type')[0].initVal
-    let resourceType = formlist.filter(cell => cell.key === 'resourceType')[0].initVal
-    let _options = ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden'] // 榛樿鏄剧ず椤�
-
-    if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '0') { // 閫夋嫨绫诲瀷銆佽嚜瀹氫箟璧勬簮
-      _options = [..._options, 'resourceType', 'options']
-    } else if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '1') { // 閫夋嫨绫诲瀷銆佹暟鎹簮
-      _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database']
-    } else if (type === 'number') {
-      _options = [..._options, 'decimal', 'min', 'max']
-    } else if (type === 'fileupload') {
-      _options = ['label', 'field', 'type', 'readonly', 'required']
-    }
-
-    if (type === 'select') {
-      _options = [..._options, 'setAll']
-      if (resourceType === '1') {
-        _options.push('linkSubField')
-      }
-    } else if (type === 'link') {          // 鍏宠仈绫诲瀷銆佸鍔犲叧鑱斿瓧娈�
-      _options = [..._options, 'setAll', 'linkField']
-    } else if (type === 'funcvar') {       // 璁剧疆涓哄嚱鏁板彉閲忔椂锛屼笉闇�瑕佸叾浠栦俊鎭�
-      _options = ['label', 'field', 'type']
-    }
-    
-    this.setState({
-      openType: type,
-      resourceType: resourceType,
-      formlist: formlist.map(form => {
-        if (dateOptions.hasOwnProperty(type) && form.key === 'initval') {
-          form.options = dateOptions[type]
-          form.type = 'select'
-        } else if (type === 'number' && form.key === 'initval') {
-          form.type = 'number'
-        }
-        form.hidden = !_options.includes(form.key)
-        return form
-      })
-    })
-  }
-
-  componentDidMount () {
-    const { card } = this.props
-
-    if (card.focus) {
-      try {
-        let _form = document.getElementById('label')
-        _form.select()
-      } catch {
-        console.warn('琛ㄥ崟focus澶辫触锛�')
-      }
-    }
-  }
-
-  openTypeChange = (key, value) => {
-    if (key === 'type') {
-      let _options = ['label', 'field', 'initval', 'type', 'readonly', 'required', 'hidden']
-
-      if ((value === 'multiselect' || value === 'select' || value === 'link') && this.state.resourceType === '0') { // 閫夋嫨绫诲瀷銆佽嚜瀹氫箟璧勬簮
-        _options = [..._options, 'resourceType', 'options']
-      } else if ((value === 'multiselect' || value === 'select' || value === 'link') && this.state.resourceType === '1') { // 閫夋嫨绫诲瀷銆佹暟鎹簮
-        _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database']
-      } else if (value === 'number') {
-        _options = [..._options, 'decimal', 'min', 'max']
-      } else if (value === 'fileupload') {
-        _options = ['label', 'field', 'type', 'readonly', 'required']
-      }
-
-      if (value === 'select') {
-        _options = [..._options, 'setAll']
-        if (this.state.resourceType === '1') {
-          _options.push('linkSubField')
-        }
-      } else if (value === 'link') {
-        _options = [..._options, 'setAll', 'linkField']
-      } else if (value === 'funcvar') {
-        _options = ['label', 'field', 'type']
-      }
-      
-      this.setState({
-        openType: value,
-        formlist: this.state.formlist.map(form => {
-          form.hidden = !_options.includes(form.key)
-          if (form.key === 'initval') {
-            if (dateOptions.hasOwnProperty(value)) {
-              form.options = dateOptions[value]
-              form.type = 'select'
-              form.initVal = ''
-            } else if (value === 'number') {
-              form.type = 'number'
-              form.initVal = 0
-            } else {
-              form.type = 'text'
-              form.initVal = ''
-            }
-            form.hidden = true
-          }
-          return form
-        })
-      }, () => {
-        this.setState({
-          formlist: this.state.formlist.map(form => {
-            if (form.key === 'initval' && value !== 'fileupload' && value !== 'funcvar') {
-              form.hidden = false
-            }
-            return form
-          })
-        })
-      })
-    }
-  }
-
-  onChange = (e, key) => {
-    const { openType } = this.state
-    let value = e.target.value
-    if (key === 'resourceType') {
-      let _options = ['label', 'field', 'initval', 'type', 'resourceType', 'readonly', 'required']
-      if (value === '0') {
-        _options = [..._options, 'options']
-      } else if (value === '1') {
-        _options = [..._options, 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database']
-      }
-
-      if (openType === 'select') {
-        _options = [..._options, 'setAll']
-        if (value === '1') {
-          _options.push('linkSubField')
-        }
-      } else if (openType === 'link') {
-        _options = [..._options, 'setAll', 'linkField']
-      }
-      
-      this.setState({
-        resourceType: value,
-        formlist: this.state.formlist.map(form => {
-          form.hidden = !_options.includes(form.key)
-          return form
-        })
-      })
-    }
-  }
-
-  getFields() {
-    const { getFieldDecorator } = this.props.form
-    const fields = []
-
-    this.state.formlist.forEach((item, index) => {
-      if (item.hidden) return
-
-      if (item.type === 'text') { // 鏂囨湰鎼滅储
-        let rules = []
-        if (item.key === 'field') {
-          rules = [{
-            pattern: formRule.field.pattern,
-            message: formRule.field.message
-          }, {
-            max: formRule.field.max,
-            message: formRule.field.maxMessage
-          }]
-        } else {
-          rules = [
-            {
-              max: formRule.input.max,
-              message: formRule.input.message
-            }
-          ]
-        }
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || '',
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  },
-                  ...rules
-                ]
-              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'number') {
-        if (item.key === 'decimal') {
-          fields.push(
-            <Col span={12} key={index}>
-              <Form.Item label={item.label}>
-                {getFieldDecorator(item.key, {
-                  initialValue: item.initVal || 0,
-                  rules: [
-                    {
-                      required: !!item.required,
-                      message: this.props.dict['form.required.input'] + item.label + '!'
-                    }
-                  ]
-                })(<InputNumber min={0} max={18} precision={0} />)}
-              </Form.Item>
-            </Col>
-          )
-        } else {
-          fields.push(
-            <Col span={12} key={index}>
-              <Form.Item label={item.label}>
-                {getFieldDecorator(item.key, {
-                  initialValue: item.initVal,
-                  rules: [
-                    {
-                      required: !!item.required,
-                      message: this.props.dict['form.required.input'] + item.label + '!'
-                    }
-                  ]
-                })(<InputNumber />)}
-              </Form.Item>
-            </Col>
-          )
-        }
-      } else if (item.type === 'select') { // 涓嬫媺鎼滅储
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || '',
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <Select
-                  showSearch
-                  filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                  onChange={(value) => {this.openTypeChange(item.key, value)}}
-                  getPopupContainer={() => document.getElementById('modal-fields-form-box')}
-                >
-                  {item.options.map(option =>
-                    <Select.Option id={option.value} title={option.text} key={option.value} value={option.value}>
-                      {item.key === 'icon' && <Icon type={option.text} />} {option.text}
-                    </Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'multiselect') { // 澶氶��
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal
-              })(
-                <Select
-                  showSearch
-                  mode="multiple"
-                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                >
-                  {item.options.map(option =>
-                    <Select.Option id={option.uuid} key={option.uuid} value={option.field}>{option.label}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'radio') {
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal,
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}}>
-                  {
-                    item.options.map(option => {
-                      return (
-                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
-                      )
-                    })
-                  }
-                </Radio.Group>,
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'textarea') {
-        fields.push(
-          <Col span={20} offset={4} key={index}>
-            <Form.Item className="text-area">
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal,
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  }
-                ]
-              })(<TextArea rows={4} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'options') {
-        fields.push(
-          <Col span={20} offset={4} key={index}>
-            <EditTable data={item.initVal} type={this.state.openType} ref="editTable"/>
-          </Col>
-        )
-      }
-    })
-
-    return fields
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          let isvalid = true
-          values.uuid = this.props.card.uuid
-          // 涓嬫媺鑿滃崟鎴栧叧鑱旇彍鍗�
-          if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '0') {
-            values.options = this.refs.editTable.state.dataSource
-            values.dataSource = ''
-            let emptys = []
-            if (values.type === 'multiselect' || values.type === 'select') {
-              emptys = values.options.filter(op => !(op.Value && op.Text))
-            } else {
-              emptys = values.options.filter(op => !(op.Value && op.Text && op.ParentID))
-            }
-            if (emptys.length > 0) {
-              isvalid = false
-              notification.warning({
-                top: 92,
-                message: this.props.dict['header.form.selectItem.error'],
-                duration: 10
-              })
-            }
-          } else if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '1') {
-            values.options = []
-          } else if (values.type === 'funcvar') { // 鍑芥暟鍙橀噺涓哄彧璇诲厓绱�
-            values.readonly = 'true'
-          } else if (values.type === 'number' && (values.min || values.min === 0) && (values.max || values.max === 0)) { // 鏁板�煎瀷楠岃瘉鏈�灏忔渶澶у��
-            if (values.min > values.max) {
-              isvalid = false
-              notification.warning({
-                top: 92,
-                message: '鏈�灏忓�间笉鍙ぇ浜庢渶澶у�硷紒',
-                duration: 10
-              })
-            }
-          }
-
-          if (isvalid) {
-            resolve(values)
-          }
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  render() {
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-    return (
-      <Form {...formItemLayout} className="ant-advanced-search-form modal-fields-form" id="modal-fields-form-box">
-        <Row gutter={24}>{this.getFields()}</Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/templates/formtabconfig/modalform/index.scss b/src/templates/formtabconfig/modalform/index.scss
deleted file mode 100644
index 0cdacad..0000000
--- a/src/templates/formtabconfig/modalform/index.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-.ant-advanced-search-form.modal-fields-form {
-  min-height: 180px;
-  .ant-col-offset-4 {
-    padding-left: 6px!important;
-    padding-bottom: 20px;
-  }
-  .ant-form-item.text-area {
-    margin-bottom: 0px;
-    .ant-form-item-control-wrapper {
-      width: 100%;
-    }
-  }
-  .ant-input-number {
-    width: 100%;
-  }
-}
\ No newline at end of file
diff --git a/src/templates/formtabconfig/settingform/index.jsx b/src/templates/formtabconfig/settingform/index.jsx
index 035ce8d..c724b8b 100644
--- a/src/templates/formtabconfig/settingform/index.jsx
+++ b/src/templates/formtabconfig/settingform/index.jsx
@@ -4,7 +4,7 @@
 import { formRule } from '@/utils/option.js'
 import './index.scss'
 
-// const { TextArea } = Input
+const { TextArea } = Input
 
 class SettingForm extends Component {
   static propTpyes = {
@@ -132,7 +132,7 @@
   }
 
   render() {
-    const { dict, usefulFields } = this.props
+    const { dict, usefulFields, menu } = this.props
     const { getFieldDecorator } = this.props.form
     const { interType, columns, selectTabs, setting } = this.state
 
@@ -256,7 +256,7 @@
               })(<Input placeholder="" autoComplete="off" />)}
             </Form.Item>
           </Col> : null}
-          {/* {interType !== 'outer' ? <Col span={24}>
+          {interType !== 'outer' ? <Col span={24}>
             <Form.Item help={'鏁版嵁ID锛�' + menu.MenuID} label={
               <Tooltip placement="topLeft" title="浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愶紝鑷畾涔夊嚱鏁版椂锛屽彲蹇界暐銆�">
                 <Icon type="question-circle" />
@@ -267,7 +267,7 @@
                 initialValue: setting.dataresource
               })(<TextArea rows={4} />)}
             </Form.Item>
-          </Col> : null} */}
+          </Col> : null}
           {interType === 'outer' ? <Col span={12}>
             <Form.Item label={dict['header.form.outerFunc']}>
               {getFieldDecorator('outerFunc', {
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index 297e7a3..4b7b064 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -131,7 +131,8 @@
   componentDidMount () {
     let param = {
       func: 'sPC_Get_SelectedList',
-      LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
+      // LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
+      LText: 'select TbName,Remark from (select TbName,Remark from sDataDictb where appkey= @appkey@ and Deleted=0 union select a.TbName,Remark from (select TbName,Remark from sDataDictb where appkey= \'\' and Deleted=0 ) a left join (select TbName from sDataDictb where appkey= @appkey@ and Deleted=0 ) b on a.TbName=b.TbName where b.TbName is null ) t',
       obj_name: 'data',
       arr_field: 'TbName,Remark'
     }
diff --git a/src/templates/subtableconfig/index.jsx b/src/templates/subtableconfig/index.jsx
index fa7a7d0..38d0960 100644
--- a/src/templates/subtableconfig/index.jsx
+++ b/src/templates/subtableconfig/index.jsx
@@ -22,6 +22,7 @@
 import GridBtnForm from '@/templates/tableshare/gridbtnform'
 import EditCard from '@/templates/tableshare/editcard'
 import VerifyCard from '@/templates/tableshare/verifycard'
+import VerifyCardExcelIn from '@/templates/tableshare/verifycardexcelin'
 import MenuForm from '@/templates/tableshare/menuform'
 import SourceElement from '@/templates/tableshare/dragelement/source'
 import Source from './source'
@@ -154,7 +155,8 @@
   componentDidMount () {
     let param = {
       func: 'sPC_Get_SelectedList',
-      LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
+      // LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
+      LText: 'select TbName,Remark from (select TbName,Remark from sDataDictb where appkey= @appkey@ and Deleted=0 union select a.TbName,Remark from (select TbName,Remark from sDataDictb where appkey= \'\' and Deleted=0 ) a left join (select TbName from sDataDictb where appkey= @appkey@ and Deleted=0 ) b on a.TbName=b.TbName where b.TbName is null ) t',
       obj_name: 'data',
       arr_field: 'TbName,Remark'
     }
@@ -1123,6 +1125,53 @@
     let config = JSON.parse(JSON.stringify(this.state.config))
     let _verify = this.verifyRef.state.verify
 
+    if (card.OpenType !== 'excelIn') {
+      if (_verify.default === 'false' && _verify.scripts.length === 0) {
+        notification.warning({
+          top: 92,
+          message: '涓嶆墽琛岄粯璁ql鏃讹紝蹇呴』璁剧疆鑷畾涔夎剼鏈紒',
+          duration: 10
+        })
+        return
+      }
+    } else if (card.OpenType === 'excelIn') {
+      let cols = _verify.columns.map(col => col.Column)
+      cols = Array.from(new Set(cols))
+
+      if (!_verify.sheet) {
+        notification.warning({
+          top: 92,
+          message: '璇疯缃鍏ヨ〃鍚�!',
+          duration: 10
+        })
+        return
+      } else if (_verify.columns.length === 0) {
+        notification.warning({
+          top: 92,
+          message: '璇疯缃瓻xcel鍒楀瓧娈�!',
+          duration: 10
+        })
+        return
+      } else if (_verify.columns.length > cols.length) {
+        notification.warning({
+          top: 92,
+          message: 'Excel鍒楀瓧娈靛悕锛屼笉鍙噸澶�!',
+          duration: 10
+        })
+        return
+      } else if (_verify.range === 1) {
+        let tEmptys = _verify.columns.filter(op => !op.Text)
+        if (tEmptys.length > 0) {
+          notification.warning({
+            top: 92,
+            message: '蹇界暐棣栬鏃讹紝浼氫娇鐢═ext鍊兼牎楠孍xcel棣栬鍐呭锛孴ext鍊间笌Excel琛ㄩ琛屽唴瀹圭浉鍚岋紝涓斿潎涓嶅彲涓虹┖锛�',
+            duration: 10
+          })
+          return
+        }
+      }  
+    }
+    
     config.action = config.action.map(item => {
       if (item.uuid === card.uuid) {
         item.verify = _verify
@@ -2167,7 +2216,22 @@
           onCancel={() => { this.setState({ profileVisible: false }) }}
           destroyOnClose
         >
-          <VerifyCard floor="subtable" card={this.state.card} columns={this.state.config.columns} wrappedComponentRef={(inst) => this.verifyRef = inst} dict={this.state.dict} />
+          {this.state.card && this.state.card.OpenType !== 'excelIn' ?
+            <VerifyCard
+              floor="subtable"
+              card={this.state.card}
+              dict={this.state.dict}
+              columns={this.state.config.columns}
+              wrappedComponentRef={(inst) => this.verifyRef = inst}
+            /> : null
+          }
+          {this.state.card && this.state.card.OpenType === 'excelIn' ?
+            <VerifyCardExcelIn
+              card={this.state.card}
+              dict={this.state.dict}
+              wrappedComponentRef={(inst) => this.verifyRef = inst}
+            /> : null
+          }
         </Modal>
         {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */}
         <Modal
diff --git a/src/templates/tableshare/dragelement/card.jsx b/src/templates/tableshare/dragelement/card.jsx
index a74f323..cb6963f 100644
--- a/src/templates/tableshare/dragelement/card.jsx
+++ b/src/templates/tableshare/dragelement/card.jsx
@@ -148,7 +148,7 @@
       <Icon className="edit" title="缂栬緫" type="edit" onClick={edit} />
       <Icon className="edit close" title="鍒犻櫎" type="close" onClick={del} />
       {type === 'action' ? <Icon className="edit copy" title="澶嶅埗" type="copy" onClick={copy} /> : null}
-      {type === 'action' && ['pop', 'prompt', 'exec'].includes(card.OpenType) && card.intertype === 'inner' && !card.innerFunc ?
+      {type === 'action' && ['pop', 'prompt', 'exec', 'excelIn'].includes(card.OpenType) && card.intertype === 'inner' && !card.innerFunc ?
         <Icon className="edit profile" title="鏍¢獙瑙勫垯" type="profile" onClick={profile} /> : null
       }
     </div>
diff --git a/src/templates/tableshare/exceleditable/index.jsx b/src/templates/tableshare/exceleditable/index.jsx
new file mode 100644
index 0000000..332fe1b
--- /dev/null
+++ b/src/templates/tableshare/exceleditable/index.jsx
@@ -0,0 +1,304 @@
+import React, {Component} from 'react'
+import { Table, Input, Button, Popconfirm, Form, Icon, InputNumber, Select } from 'antd'
+import Utils from '@/utils/utils.js'
+import './index.scss'
+
+const EditableContext = React.createContext()
+
+const EditableRow = ({ form, index, ...props }) => (
+  <EditableContext.Provider value={form}>
+    <tr {...props} />
+  </EditableContext.Provider>
+)
+
+const EditableFormRow = Form.create()(EditableRow)
+
+class EditableCell extends Component {
+  state = {
+    editing: false
+  }
+
+  toggleEdit = () => {
+    const editing = !this.state.editing
+
+    this.setState({ editing }, () => {
+      if (editing && this.input && this.input.select) {
+        this.input.select()
+      } else if (editing && this.input && this.input.focus) {
+        this.input.focus()
+      }
+    })
+  }
+
+  save = e => {
+    const { record, handleSave } = this.props
+    this.form.validateFields((error, values) => {
+      handleSave({ ...record, ...values })
+      if (error && error[e.currentTarget.id]) {
+        return
+      }
+      this.toggleEdit()
+    })
+  }
+
+  typeChange = (key, val) => {
+    const { record, handleSave } = this.props
+
+    handleSave({ ...record, ...{[key]: val} })
+
+    this.toggleEdit()
+  }
+
+  renderCell = form => {
+    this.form = form
+    const { children, dataIndex, record } = this.props
+    const { editing } = this.state
+
+    return editing ? (
+      <div>
+        {dataIndex === 'Column' || dataIndex === 'Text' ? <Form.Item style={{ margin: 0 }}>
+          {form.getFieldDecorator(dataIndex, {
+            initialValue: record[dataIndex],
+            rules: [
+              {
+                required: dataIndex === 'Column',
+                message: 'NOT NULL.',
+              },
+            ]
+          })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)}
+        </Form.Item> : null}
+        {dataIndex === 'min' || dataIndex === 'max' ? <Form.Item style={{ margin: 0 }}>
+          {form.getFieldDecorator(dataIndex, {
+            initialValue: record[dataIndex]
+          })(<InputNumber ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)}
+        </Form.Item> : null}
+        {dataIndex === 'required' ? <Form.Item style={{ margin: 0 }}>
+          {form.getFieldDecorator(dataIndex, {
+            initialValue: record[dataIndex] || 'false'
+          })(
+            <Select
+              onChange={(value) => {this.typeChange(dataIndex, value)}}
+              onBlur={(value) => {this.typeChange(dataIndex, value)}}
+              defaultOpen={true}
+            >
+              <Select.Option value='false'>鍚�</Select.Option>
+              <Select.Option value='true'>鏄�</Select.Option>
+            </Select>
+          )}
+        </Form.Item> : null}
+        {dataIndex === 'type' ? <Form.Item style={{ margin: 0 }}>
+          {form.getFieldDecorator(dataIndex, {
+            initialValue: record[dataIndex] || 'text'
+          })(
+            <Select
+              onChange={(value) => {this.typeChange(dataIndex, value)}}
+              onBlur={(value) => {this.typeChange(dataIndex, value)}}
+              defaultOpen={true}
+            >
+              <Select.Option value='text'>鏂囨湰</Select.Option>
+              <Select.Option value='number'>鏁板��</Select.Option>
+            </Select>
+          )}
+        </Form.Item> : null}
+      </div>
+    ) : (
+      <div
+        className="editable-cell-value-wrap"
+        onClick={this.toggleEdit}
+      >
+        {children}
+      </div>
+    )
+  }
+
+  render() {
+    const {
+      editable,
+      dataIndex,
+      title,
+      record,
+      index,
+      handleSave,
+      children,
+      ...restProps
+    } = this.props
+    return (
+      <td {...restProps}>
+        {editable ? (
+          <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer>
+        ) : (
+          children
+        )}
+      </td>
+    )
+  }
+}
+
+class EditTable extends Component {
+  constructor(props) {
+    super(props)
+
+    let columns = [
+      {
+        title: 'Column',
+        dataIndex: 'Column',
+        width: '15%',
+        editable: true
+      },
+      {
+        title: 'Text',
+        dataIndex: 'Text',
+        width: '18%',
+        editable: true
+      },
+      {
+        title: '鏄惁蹇呭~',
+        dataIndex: 'required',
+        width: '12%',
+        editable: true,
+        render: (text, record) => record.required === 'true' ? '鏄�' : '鍚�'
+      },
+      {
+        title: '绫诲瀷',
+        dataIndex: 'type',
+        width: '12%',
+        editable: true,
+        render: (text, record) => record.type === 'number' ? '鏁板��' : '鏂囨湰'
+      },
+      {
+        title: '鏈�灏忓��',
+        dataIndex: 'min',
+        width: '13%',
+        editable: true
+      },
+      {
+        title: '鏈�澶у��',
+        dataIndex: 'max',
+        width: '13%',
+        editable: true
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          this.state.dataSource.length >= 1 ? (
+            <div>
+              <span className="operation-btn" title={props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+              <span className="operation-btn" title={props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+              <Popconfirm
+                title={props.dict['header.form.query.delete']}
+                okText={props.dict['header.confirm']}
+                cancelText={props.dict['header.cancel']}
+                onConfirm={() => this.handleDelete(record.key)
+              }>
+                <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
+              </Popconfirm>
+            </div>
+          ) : null,
+      }
+    ]
+
+    this.state = {
+      columns: columns,
+      dataSource: props.data
+    }
+  }
+
+  handleUpDown = (record, direction) => {
+    const { dataSource } = this.state
+    let index = 0
+
+    let _data = dataSource.filter((item, i) => {
+      if (item.key === record.key) {
+        index = i
+      }
+
+      return item.key !== record.key
+    })
+    if ((index === 0 && direction === 'up') || (index === dataSource.length - 1 && direction === 'down')) {
+      return
+    }
+
+    if (direction === 'up') {
+      _data.splice(index - 1, 0, record)
+    } else {
+      _data.splice(index + 1, 0, record)
+    }
+
+    this.setState({
+      dataSource: _data
+    })
+  }
+
+  handleDelete = key => {
+    const dataSource = [...this.state.dataSource]
+    this.setState({ dataSource: dataSource.filter(item => item.key !== key) })
+  }
+
+  handleAdd = () => {
+    const { dataSource } = this.state
+    const newData = {
+      key: Utils.getuuid(),
+      Column: '',
+      Text: ''
+    }
+
+    this.setState({
+      dataSource: [...dataSource, newData]
+    })
+  }
+
+  handleSave = row => {
+    const newData = [...this.state.dataSource]
+    const index = newData.findIndex(item => row.key === item.key)
+    const item = newData[index]
+    newData.splice(index, 1, {
+      ...item,
+      ...row
+    })
+    this.setState({ dataSource: newData })
+  }
+
+  render() {
+    const { dataSource } = this.state
+    const components = {
+      body: {
+        row: EditableFormRow,
+        cell: EditableCell
+      }
+    }
+    const columns = this.state.columns.map(col => {
+      if (!col.editable) {
+        return col
+      }
+      return {
+        ...col,
+        onCell: record => ({
+          record,
+          editable: col.editable,
+          dataIndex: col.dataIndex,
+          title: col.title,
+          handleSave: this.handleSave,
+        })
+      }
+    })
+    return (
+      <div className="common-excel-edit-table">
+        <Button onClick={this.handleAdd} type="primary" className="add-row">
+          娣诲姞
+        </Button>
+        <Table
+          components={components}
+          rowClassName={() => 'editable-row'}
+          bordered
+          dataSource={dataSource}
+          columns={columns}
+          pagination={false}
+        />
+      </div>
+    )
+  }
+}
+
+export default EditTable
\ No newline at end of file
diff --git a/src/templates/tableshare/exceleditable/index.scss b/src/templates/tableshare/exceleditable/index.scss
new file mode 100644
index 0000000..9961a89
--- /dev/null
+++ b/src/templates/tableshare/exceleditable/index.scss
@@ -0,0 +1,49 @@
+.common-excel-edit-table {
+  margin-top: 30px;
+  margin-left: -23px;
+  margin-bottom: 15px;
+  .add-row {
+    position: absolute;
+    z-index: 1;
+    right: 12px;
+    top: -10px;
+  }
+  .ant-table-thead > tr > th {
+    padding: 10px 0px;
+    text-align: center;
+  }
+  .ant-table-tbody > tr > td {
+    padding: 0px 5px;
+    .ant-input-number-input {
+      padding: 0 3px;
+    }
+    .ant-input {
+      padding: 0 3px;
+    }
+  }
+  .editable-cell-value-wrap {
+    cursor: pointer;
+    height: 40px;
+    width: 200px;
+    display: table-cell;
+    vertical-align: middle;
+    word-wrap: break-word;
+    word-break: break-word;
+    .ant-input {
+      height: 30px;
+    }
+  }
+  .ant-form-item-control-wrapper {
+    width: 100%;
+  }
+  .ant-table-placeholder {
+    padding: 5px 16px;
+    .ant-empty-normal {
+      margin: 0;
+    }
+  }
+  .operation-btn {
+    margin-right: 10px;
+    cursor: pointer;
+  }
+}
diff --git a/src/templates/tableshare/verifycard/customform/index.jsx b/src/templates/tableshare/verifycard/customform/index.jsx
index 2ed3c12..5ddb237 100644
--- a/src/templates/tableshare/verifycard/customform/index.jsx
+++ b/src/templates/tableshare/verifycard/customform/index.jsx
@@ -59,8 +59,15 @@
             duration: 10
           })
           return
+        } else if (/--/ig.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
+            duration: 10
+          })
+          return
         }
-
+        
         this.props.customChange(values)
         this.setState({
           editItem: null
diff --git a/src/templates/tableshare/verifycard/customscript/index.jsx b/src/templates/tableshare/verifycard/customscript/index.jsx
index 4079de4..549ba8c 100644
--- a/src/templates/tableshare/verifycard/customscript/index.jsx
+++ b/src/templates/tableshare/verifycard/customscript/index.jsx
@@ -55,6 +55,13 @@
             duration: 10
           })
           return
+        } else if (/--/ig.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
+            duration: 10
+          })
+          return
         }
 
         this.props.scriptsChange(values)
diff --git a/src/templates/tableshare/verifycard/index.jsx b/src/templates/tableshare/verifycard/index.jsx
index c28c8bb..fff84eb 100644
--- a/src/templates/tableshare/verifycard/index.jsx
+++ b/src/templates/tableshare/verifycard/index.jsx
@@ -363,6 +363,7 @@
 
     this.setState({
       verify: {
+        ..._verify,
         default: _verify.default || 'true',
         invalid: _verify.invalid || 'false',
         uniques: _verify.uniques || [],
diff --git a/src/templates/tableshare/verifycardexcelin/columnform/index.jsx b/src/templates/tableshare/verifycardexcelin/columnform/index.jsx
new file mode 100644
index 0000000..2b420a7
--- /dev/null
+++ b/src/templates/tableshare/verifycardexcelin/columnform/index.jsx
@@ -0,0 +1,168 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Select, Button, Input, InputNumber } from 'antd'
+import './index.scss'
+
+
+class UniqueForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,         // 瀛楀吀椤�
+    range: PropTypes.any,           // 瀛楀吀椤�
+    columnChange: PropTypes.func    // 淇敼鍑芥暟
+  }
+
+  state = {
+    editItem: null, // 缂栬緫鍏冪礌
+    type: 'Nvarchar(50)'
+  }
+
+  edit = (record) => {
+    this.setState({
+      editItem: record,
+      type: record.type || 'Nvarchar(50)'
+    }, () => {
+      if (!/^Nvarchar/.test(record.type)) {
+        this.props.form.setFieldsValue({
+          min: record.min,
+          max: record.max
+        })
+      }
+    })
+
+    this.props.form.setFieldsValue({
+      Column: record.Column,
+      Text: record.Text,
+      required: record.required,
+      type: record.type
+    })
+  }
+
+  typeChange = (val) => {
+    this.setState({
+      type: val
+    })
+  }
+
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+
+        this.props.columnChange(values)
+        this.setState({
+          editItem: null
+        })
+        this.props.form.setFieldsValue({
+          Column: '',
+          Text: '',
+          required: 'false',
+          type: 'Nvarchar(50)'
+        })
+      }
+    })
+  }
+
+  render() {
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    let haslimit = !/^Nvarchar/.test(this.state.type)
+
+    return (
+      <Form {...formItemLayout} className="verify-form">
+        <Row gutter={24}>
+          <Col span={7}>
+            <Form.Item label={'Column'}>
+              {getFieldDecorator('Column', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + 'Column!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'Text'}>
+              {getFieldDecorator('Text', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: this.props.range === 1,
+                    message: this.props.dict['form.required.input'] + 'Text!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'鏄惁蹇呭~'}>
+              {getFieldDecorator('required', {
+                initialValue: 'false'
+              })(
+                <Select>
+                  <Select.Option value="false"> 鍚� </Select.Option>
+                  <Select.Option value="true"> 鏄� </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={3} className="add">
+            <Button onClick={this.handleConfirm} type="primary" className="add-row">
+              纭畾
+            </Button>
+          </Col>
+          <Col span={7}>
+            <Form.Item label={'绫诲瀷'}>
+              {getFieldDecorator('type', {
+                initialValue: 'Nvarchar(50)'
+              })(
+                <Select onChange={this.typeChange}>
+                  <Select.Option value="Nvarchar(10)"> Nvarchar(10) </Select.Option>
+                  <Select.Option value="Nvarchar(20)"> Nvarchar(20) </Select.Option>
+                  <Select.Option value="Nvarchar(50)"> Nvarchar(50) </Select.Option>
+                  <Select.Option value="Nvarchar(100)"> Nvarchar(100) </Select.Option>
+                  <Select.Option value="Nvarchar(512)"> Nvarchar(512) </Select.Option>
+                  <Select.Option value="Int"> Int </Select.Option>
+                  <Select.Option value="Decimal(18,0)"> Decimal(18,0) </Select.Option>
+                  <Select.Option value="Decimal(18,2)"> Decimal(18,2) </Select.Option>
+                  <Select.Option value="Decimal(18,4)"> Decimal(18,4) </Select.Option>
+                  <Select.Option value="Decimal(18,6)"> Decimal(18,6) </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          {haslimit ? <Col span={7}>
+            <Form.Item label={'鏈�灏忓��'}>
+              {getFieldDecorator('min', {
+                initialValue: ''
+              })(<InputNumber />)}
+            </Form.Item>
+          </Col> : null}
+          {haslimit ? <Col span={7}>
+            <Form.Item label={'鏈�澶у��'}>
+              {getFieldDecorator('max', {
+                initialValue: ''
+              })(<InputNumber />)}
+            </Form.Item>
+          </Col> : null}
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(UniqueForm)
\ No newline at end of file
diff --git a/src/templates/tableshare/verifycardexcelin/columnform/index.scss b/src/templates/tableshare/verifycardexcelin/columnform/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/templates/tableshare/verifycardexcelin/columnform/index.scss
diff --git a/src/templates/tableshare/verifycardexcelin/customscript/index.jsx b/src/templates/tableshare/verifycardexcelin/customscript/index.jsx
new file mode 100644
index 0000000..599b1b7
--- /dev/null
+++ b/src/templates/tableshare/verifycardexcelin/customscript/index.jsx
@@ -0,0 +1,126 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Button, notification } from 'antd'
+import './index.scss'
+
+const { TextArea } = Input
+
+class CustomForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,         // 瀛楀吀椤�
+    usefulfields: PropTypes.string, // 鍙敤瀛楁
+    scriptsChange: PropTypes.func   // 琛ㄥ崟
+  }
+
+  state = {
+    editItem: null
+  }
+
+  edit = (record) => {
+    this.setState({
+      editItem: record
+    })
+
+    this.props.form.setFieldsValue({
+      sql: record.sql
+    })
+  }
+
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+
+        let _quot = values.sql.match(/'{1}/g)
+        let _lparen = values.sql.match(/\({1}/g)
+        let _rparen = values.sql.match(/\){1}/g)
+
+        _quot = _quot ? _quot.length : 0
+        _lparen = _lparen ? _lparen.length : 0
+        _rparen = _rparen ? _rparen.length : 0
+
+        if (_quot % 2 !== 0) {
+          notification.warning({
+            top: 92,
+            message: 'sql涓璡'蹇呴』鎴愬鍑虹幇',
+            duration: 10
+          })
+          return
+        } else if (_lparen !== _rparen) {
+          notification.warning({
+            top: 92,
+            message: 'sql涓�()蹇呴』鎴愬鍑虹幇',
+            duration: 10
+          })
+          return
+        } else if (/--/ig.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
+            duration: 10
+          })
+          return
+        }
+
+        this.props.scriptsChange(values)
+        this.setState({
+          editItem: null
+        })
+        this.props.form.setFieldsValue({
+          sql: ''
+        })
+      }
+    })
+  }
+
+  render() {
+    const { usefulfields } = this.props
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    let _fields = usefulfields.map(item => item.Column).join(', ')
+
+    return (
+      <Form {...formItemLayout} className="verify-form" id="verifycard2">
+        <Row gutter={24}>
+          {_fields ? <Col span={21} className="sqlfield">
+            <Form.Item label={'鍙敤瀛楁'}>
+              {_fields}
+            </Form.Item>
+          </Col> : null}
+          <Col span={21} className="sql">
+            <Form.Item label={'sql'}>
+              {getFieldDecorator('sql', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + 'sql!'
+                  }
+                ]
+              })(<TextArea rows={15} />)}
+            </Form.Item>
+          </Col>
+          <Col span={3} className="add">
+            <Button onClick={this.handleConfirm} type="primary" className="add-row">
+              纭畾
+            </Button>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(CustomForm)
\ No newline at end of file
diff --git a/src/templates/tableshare/verifycardexcelin/customscript/index.scss b/src/templates/tableshare/verifycardexcelin/customscript/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/templates/tableshare/verifycardexcelin/customscript/index.scss
diff --git a/src/templates/tableshare/verifycardexcelin/index.jsx b/src/templates/tableshare/verifycardexcelin/index.jsx
new file mode 100644
index 0000000..cd13e2f
--- /dev/null
+++ b/src/templates/tableshare/verifycardexcelin/index.jsx
@@ -0,0 +1,510 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Tabs, Row, Col, Input, Button, Table, Popconfirm, Icon, notification, Modal, message, InputNumber } from 'antd'
+import { formRule } from '@/utils/option.js'
+
+import Utils from '@/utils/utils.js'
+
+import ColumnForm from './columnform'
+import CustomScript from './customscript'
+import './index.scss'
+
+const { TabPane } = Tabs
+
+class VerifyCard extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,    // 瀛楀吀椤�
+    card: PropTypes.object,
+  }
+
+  state = {
+    verify: {},
+    excelColumns: [
+      {
+        title: 'Column',
+        dataIndex: 'Column',
+        width: '16%',
+        editable: true
+      },
+      {
+        title: 'Text',
+        dataIndex: 'Text',
+        width: '19%',
+        editable: true
+      },
+      {
+        title: '鏄惁蹇呭~',
+        dataIndex: 'required',
+        width: '12%',
+        editable: true,
+        render: (text, record) => record.required === 'true' ? '鏄�' : '鍚�'
+      },
+      {
+        title: '绫诲瀷',
+        dataIndex: 'type',
+        width: '12%',
+        editable: true
+      },
+      {
+        title: '鏈�灏忓��',
+        dataIndex: 'min',
+        width: '12%',
+        editable: true
+      },
+      {
+        title: '鏈�澶у��',
+        dataIndex: 'max',
+        width: '12%',
+        editable: true
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (
+            <div>
+              <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+              <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'columns', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+              <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'columns', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+              <Popconfirm
+                title={this.props.dict['header.form.query.delete']}
+                okText={this.props.dict['header.confirm']}
+                cancelText={this.props.dict['header.cancel']}
+                onConfirm={() => this.handleDelete(record, 'columns')
+              }>
+                <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
+              </Popconfirm>
+            </div>
+          )
+      }
+    ],
+    scriptsColumns: [
+      {
+        title: 'SQL',
+        dataIndex: 'sql',
+        width: '70%'
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        width: '10%',
+        render: (text, record) => record.status === 'false' ?
+          (
+            <div>
+              {this.props.dict['header.form.status.forbidden']}
+              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
+            </div>
+          ) :
+          (
+            <div>
+              {this.props.dict['header.form.status.open']}
+              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
+            </div>
+          )
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        width: '20%',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (<div>
+            <span className="operation-btn" title={this.props.dict['header.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'scripts', 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'scripts', 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
+            <Popconfirm
+              title={this.props.dict['header.form.query.delete']}
+              okText={this.props.dict['header.confirm']}
+              cancelText={this.props.dict['header.cancel']}
+              onConfirm={() => this.handleDelete(record, 'scripts')
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ]
+  }
+
+  UNSAFE_componentWillMount() {
+    let _verify = this.props.card.verify || {}
+
+    this.setState({
+      verify: {
+        ..._verify,
+        sheet: _verify.sheet || '',
+        range: _verify.range || 0,
+        columns: _verify.columns || [],
+        scripts: _verify.scripts || []
+      }
+    })
+  }
+
+  columnChange = (values) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+
+    if (values.uuid) {
+      verify.columns = verify.columns.map(item => {
+        if (item.uuid === values.uuid) {
+          return values
+        } else {
+          return item
+        }
+      })
+    } else {
+      values.uuid = Utils.getuuid()
+      verify.columns.push(values)
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  scriptsChange = (values) => {
+    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({
+      verify: verify
+    })
+  }
+
+  handleDelete = (record, type) => {
+    const { verify } = this.state
+
+    if (type === 'columns') {
+      verify.columns = verify.columns.filter(item => item.uuid !== record.uuid)
+    } else if (type === 'scripts') {
+      verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid)
+    }
+    this.setState({ verify: verify })
+  }
+
+  handleEdit = (record, type) => {
+    if (type === 'columns') {
+      this.columnForm.edit(record)
+    } else if (type === 'scripts') {
+      this.scriptsForm.edit(record)
+    }
+
+    let node = document.getElementById('verify-excel-box-tab').parentNode
+
+    if (node && node.scrollTop) {
+      node.scrollTop = 0
+    }
+  }
+
+  handleStatus = (record, type) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+    record.status = record.status === 'false' ? 'true' : 'false'
+
+    if (type === 'scripts') {
+      verify.scripts = verify.scripts.map(item => {
+        if (item.uuid === record.uuid) {
+          return record
+        } else {
+          return item
+        }
+      })
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  handleUpDown = (record, type, direction) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
+    let index = 0
+
+    if (type === 'columns') {
+      verify.columns = verify.columns.filter((item, i) => {
+        if (item.uuid === record.uuid) {
+          index = i
+        }
+
+        return item.uuid !== record.uuid
+      })
+      if ((index === 0 && direction === 'up') || (index === verify.columns.length && direction === 'down')) {
+        return
+      }
+
+      if (direction === 'up') {
+        verify.columns.splice(index - 1, 0, record)
+      } else {
+        verify.columns.splice(index + 1, 0, record)
+      }
+    } else if (type === 'scripts') {
+      verify.scripts = verify.scripts.filter((item, i) => {
+        if (item.uuid === record.uuid) {
+          index = i
+        }
+
+        return item.uuid !== record.uuid
+      })
+      if ((index === 0 && direction === 'up') || (index === verify.scripts.length && direction === 'down')) {
+        return
+      }
+
+      if (direction === 'up') {
+        verify.scripts.splice(index - 1, 0, record)
+      } else {
+        verify.scripts.splice(index + 1, 0, record)
+      }
+    }
+
+    this.setState({
+      verify: verify
+    })
+  }
+
+  sheetChange = (e) => {
+    const { verify } = this.state
+
+    this.setState({}, () => {
+      this.props.form.validateFields(['sheet'], (errors, values) => {
+        if (!errors) {
+          this.setState({
+            verify: {
+              ...verify,
+              ...values
+            }
+          })
+        } else {
+          this.setState({
+            verify: {
+              ...verify,
+              sheet: ''
+            }
+          })
+        }
+      })
+    })
+  }
+  
+  rangeChange = (value) => {
+    const { verify } = this.state
+
+    this.setState({
+      verify: {
+        ...verify,
+        range: value || 0
+      }
+    })
+  }
+
+  showError = (errorType) => {
+    if (errorType === 'S') {
+      notification.success({
+        top: 92,
+        message: '鎵ц鎴愬姛锛�',
+        duration: 2
+      })
+    } else if (errorType === 'F') {
+      notification.error({
+        className: 'notification-custom-error',
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: 15
+      })
+    } else if (errorType === 'N') {
+      notification.error({
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: 15
+      })
+    } 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}
+    })
+  }
+
+  render() {
+    const { getFieldDecorator } = this.props.form
+    const { verify, excelColumns, scriptsColumns } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <div id="verify-excel-box-tab">
+        <Tabs defaultActiveKey="1" className="verify-card-box" onChange={this.tabchange}>
+          <TabPane tab="鍩虹楠岃瘉" key="1">
+            <Form {...formItemLayout}>
+              <Row gutter={24}>
+                <Col span={8}>
+                  <Form.Item label={this.props.dict['header.form.tablename']}>
+                    {getFieldDecorator('sheet', {
+                      initialValue: verify.sheet || '',
+                      rules: [
+                        {
+                          required: true,
+                          message: this.props.dict['form.required.input'] + this.props.dict['header.form.tablename'] + '!'
+                        },
+                        {
+                          pattern: formRule.table.pattern,
+                          message: formRule.table.message
+                        }, {
+                          max: formRule.table.max,
+                          message: formRule.table.maxMessage
+                        }
+                      ]
+                    })(<Input placeholder="" autoComplete="off" onChange={this.sheetChange} />)}
+                  </Form.Item>
+                </Col>
+                <Col span={8}>
+                  <Form.Item label={'蹇界暐琛�'}>
+                    <InputNumber min={0} max={100} precision={0} defaultValue={0} onChange={this.rangeChange} />
+                  </Form.Item>
+                </Col>
+              </Row>
+            </Form>
+          </TabPane>
+          <TabPane tab="Excel鍒楄缃�" key="2x">
+            <ColumnForm
+              dict={this.props.dict}
+              range={verify.range}
+              columnChange={this.columnChange}
+              wrappedComponentRef={(inst) => this.columnForm = inst}
+            />
+            <Table
+              bordered
+              rowKey="uuid"
+              className="custom-table"
+              dataSource={verify.columns}
+              columns={excelColumns}
+              pagination={false}
+            />
+          </TabPane>
+          <TabPane tab="鑷畾涔夎剼鏈�" key="6">
+            <CustomScript
+              usefulfields={verify.columns}
+              dict={this.props.dict}
+              scriptsChange={this.scriptsChange}
+              wrappedComponentRef={(inst) => this.scriptsForm = inst}
+            />
+            <Table
+              bordered
+              rowKey="uuid"
+              className="custom-table"
+              dataSource={verify.scripts}
+              columns={scriptsColumns}
+              pagination={false}
+            />
+          </TabPane>
+          <TabPane tab="淇℃伅鎻愮ず" key="7">
+            <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={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"> -1 </span>
+                    涓嶆彁绀�
+                  </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={15} 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={15} 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>
+            </Form>
+          </TabPane>
+        </Tabs>
+      </div>
+    )
+  }
+}
+
+export default Form.create()(VerifyCard)
\ No newline at end of file
diff --git a/src/templates/tableshare/verifycardexcelin/index.scss b/src/templates/tableshare/verifycardexcelin/index.scss
new file mode 100644
index 0000000..63ab4c0
--- /dev/null
+++ b/src/templates/tableshare/verifycardexcelin/index.scss
@@ -0,0 +1,53 @@
+.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;
+  }
+  .ant-input-number {
+    width: 100%;
+  }
+  .verify-form {
+    .sql {
+      .ant-col-sm-8 {
+        width: 10.5%;
+      }
+      .ant-col-sm-16 {
+        width: 89.5%;
+        padding-top: 4px;
+      }
+    }
+    .sqlfield {
+      .ant-form-item {
+        margin-bottom: 5px;
+      }
+      .ant-col-sm-8 {
+        width: 10.5%;
+      }
+      .ant-col-sm-16 {
+        width: 89.5%;
+      }
+    }
+    .add {
+      padding-top: 4px;
+    }
+  }
+  .custom-table .ant-empty {
+    margin: 20px 8px!important;
+  }
+  .errorval {
+    display: inline-block;
+    width: 30px;
+  }
+  .operation-btn {
+    display: inline-block;
+    font-size: 16px;
+    padding: 0 5px;
+    cursor: pointer;
+  }
+}
\ No newline at end of file
diff --git a/src/templates/ushare/editable/index.jsx b/src/templates/ushare/editable/index.jsx
index 085aab2..7e41ec8 100644
--- a/src/templates/ushare/editable/index.jsx
+++ b/src/templates/ushare/editable/index.jsx
@@ -22,7 +22,9 @@
   toggleEdit = () => {
     const editing = !this.state.editing
     this.setState({ editing }, () => {
-      if (editing) {
+      if (editing && this.input && this.input.select) {
+        this.input.select()
+      } else if (editing && this.input && this.input.focus) {
         this.input.focus()
       }
     })
@@ -99,7 +101,7 @@
 
     if (props.type === 'link') {
       _width = '27%'
-    } else {
+    } else if (props.type === 'select') {
       _width = Math.floor(80 / (props.linkSubFields.length + 2)) + '%'
       fields = props.linkSubFields.map(field => {
         return {
@@ -131,9 +133,18 @@
         dataIndex: 'operation',
         render: (text, record) =>
           this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
+            <div>
+              <span className="operation-btn" title={props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+              <span className="operation-btn" title={props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+              <Popconfirm
+                title={props.dict['header.form.query.delete']}
+                okText={props.dict['header.confirm']}
+                cancelText={props.dict['header.cancel']}
+                onConfirm={() => this.handleDelete(record.key)
+              }>
+                <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
+              </Popconfirm>
+            </div>
           ) : null,
       }
     ]
@@ -154,6 +165,32 @@
       type: props.type,
       linkSubFields: props.linkSubFields
     }
+  }
+
+  handleUpDown = (record, direction) => {
+    const { dataSource } = this.state
+    let index = 0
+
+    let _data = dataSource.filter((item, i) => {
+      if (item.key === record.key) {
+        index = i
+      }
+
+      return item.key !== record.key
+    })
+    if ((index === 0 && direction === 'up') || (index === dataSource.length - 1 && direction === 'down')) {
+      return
+    }
+
+    if (direction === 'up') {
+      _data.splice(index - 1, 0, record)
+    } else {
+      _data.splice(index + 1, 0, record)
+    }
+
+    this.setState({
+      dataSource: _data
+    })
   }
 
   handleDelete = key => {
@@ -192,18 +229,22 @@
     let dataSource = JSON.parse(JSON.stringify(this.state.dataSource))
     let _width = '40%'
     let fields = []
-
+    console.log(linkSubFields)
     if (type === 'select' && linkSubFields.length > this.state.linkSubFields) {
       let addcol = linkSubFields[linkSubFields.length - 1]
       dataSource = dataSource.map(data => {
         data[addcol.field] = data.Text
         return data
       })
+      console.log(addcol)
     }
+    // console.log(linkSubFields)
+    // console.log(type)
+    // console.log(dataSource)
 
     if (type === 'link') {
       _width = '27%'
-    } else {
+    } else if (type === 'select') {
       _width = Math.floor(80 / (linkSubFields.length + 2)) + '%'
       fields = linkSubFields.map(field => {
         return {
@@ -214,6 +255,8 @@
         }
       })
     }
+
+    console.log(fields)
 
     let columns = [
       {
@@ -235,9 +278,18 @@
         dataIndex: 'operation',
         render: (text, record) =>
           this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
+            <div>
+              <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+              <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+              <Popconfirm
+                title={this.props.dict['header.form.query.delete']}
+                okText={this.props.dict['header.confirm']}
+                cancelText={this.props.dict['header.cancel']}
+                onConfirm={() => this.handleDelete(record.key)
+              }>
+                <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
+              </Popconfirm>
+            </div>
           ) : null,
       }
     ]
@@ -259,10 +311,8 @@
   }
 
   UNSAFE_componentWillReceiveProps (nextProps) {
-    if (this.props.type !== nextProps.type) {
-      this.resetColumn(nextProps.type)
-    } else if (!is(fromJS(this.props.linkSubFields), fromJS(nextProps.linkSubFields))) {
-      this.resetColumn(this.props.type, nextProps.linkSubFields)
+    if (!is(fromJS(this.props.linkSubFields), fromJS(nextProps.linkSubFields)) || this.props.type !== nextProps.type) {
+      this.resetColumn(nextProps.type, nextProps.linkSubFields)
     }
   }
 
diff --git a/src/templates/ushare/editable/index.scss b/src/templates/ushare/editable/index.scss
index f8f0942..79e7caf 100644
--- a/src/templates/ushare/editable/index.scss
+++ b/src/templates/ushare/editable/index.scss
@@ -33,4 +33,8 @@
       margin: 0;
     }
   }
+  .operation-btn {
+    margin-right: 10px;
+    cursor: pointer;
+  }
 }
diff --git a/src/templates/ushare/modalform/index.jsx b/src/templates/ushare/modalform/index.jsx
index 7eb8e38..3b27a2d 100644
--- a/src/templates/ushare/modalform/index.jsx
+++ b/src/templates/ushare/modalform/index.jsx
@@ -182,12 +182,18 @@
   multiselectChange = (key, value, options) => {
     if (key === 'linkSubField') {
       let arr = []
-      let linkSubFields = options.filter(option => {
+      let linkSubField = {}
+      options.forEach(option => {
         if (!['Value', 'Text'].includes(option.field) && value.includes(option.field) && !arr.includes(option.field)) {
           arr.push(option.field)
-          return true
-        } else {
-          return false
+          linkSubField[option.field] = option
+        }
+      })
+
+      let linkSubFields = []
+      value.forEach(item => {
+        if (linkSubField[item]) {
+          linkSubFields.push(linkSubField[item])
         }
       })
 
@@ -415,7 +421,7 @@
       } else if (item.type === 'options') {
         fields.push(
           <Col span={20} offset={4} key={index}>
-            <EditTable data={item.initVal} type={this.state.openType} linkSubFields={this.state.linkSubFields} ref="editTable"/>
+            <EditTable data={item.initVal} dict={this.props.dict} type={this.state.openType} linkSubFields={this.state.linkSubFields} ref="editTable"/>
           </Col>
         )
       }
diff --git a/src/utils/option.js b/src/utils/option.js
index 4d68064..5091a41 100644
--- a/src/utils/option.js
+++ b/src/utils/option.js
@@ -24,6 +24,12 @@
     innerPattern: '[0-9a-zA-Z_]*',
     innerMessage: '鍐呴儴鍑芥暟鍚嶇О鍙厑璁稿寘鍚暟瀛椼�佸瓧姣嶅拰涓嬪垝绾匡紝涓斾互鎸囧畾瀛楃寮�濮嬨��'
   },
+  table: { // 鍑芥暟鍚�
+    max: 100,
+    pattern: /^[0-9a-zA-Z_]*$/,
+    message: '琛ㄥ悕鍙厑璁稿寘鍚暟瀛椼�佸瓧姣嶅拰涓嬪垝绾裤��',
+    maxMessage: '琛ㄥ悕涓嶈秴杩�100涓瓧绗︺��'
+  },
   textarea: {
     max: 1024,
     message: '闀挎枃鏈渶澶�1024涓瓧绗︺��'
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 5bc7055..3bf9737 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -441,6 +441,131 @@
   }
 
   /**
+   * @description 鑾峰彇excel瀵煎叆鍙傛暟
+   * @return {String} btn   鎸夐挳
+   * @return {String} data  excel鏁版嵁
+   */
+  static getExcelInSql (item, data, dict) {
+    let btn = item.verify
+    let keys = ['delete', 'drop', 'insert', 'truncate', 'update']
+
+    let errors = []
+    let _topline = btn.range || 0
+    let _Ltext = data.map((item, lindex) => {
+      let vals = btn.columns.map((col, cindex) => {
+        let val = item[col.Column] !== undefined ? item[col.Column] : ''
+        let _position = (_topline + lindex + 1) + dict['main.excel.line'] + ' ' + (cindex + 1) + dict['main.excel.column']  + ' '
+
+        if (/^Nvarchar/ig.test(col.type)) {
+          if (typeof(val) === 'number') {
+            val = val.toString()
+          }
+
+          val = val.replace(/(^\s*$)|\t*|\v*/ig, '')
+
+          let limitlen = col.type.match(/\d+/)[0]
+
+          if (!val && col.required === 'true') { // 蹇呭~鏍¢獙
+            let _error =  _position + dict['main.excel.content.emptyerror']
+            errors.push(_error)
+          } else if (val.length > limitlen) {    // 闀垮害鏍¢獙
+            let _error =  _position + dict['main.excel.content.maxlimit']
+            errors.push(_error)
+          } else {                               // 鍏抽敭瀛楁牎楠�
+            keys.forEach(key => {
+              let _patten = new RegExp('(^' + key + '\\s+)|(\\s+' + key + '\\s+)', 'ig')
+              if (_patten.test(val)) {
+                let _error = _position + dict['main.excel.includekey'] + key
+                errors.push(_error)
+              }
+            })
+          }
+        } else if (/^int/ig.test(col.type)) {
+          if (typeof(val) !== 'number' || parseInt(val) < parseFloat(val)) { // 妫�楠屾槸鍚︿负鏁存暟
+            let _error = _position + dict['main.excel.content.interror']
+            errors.push(_error)
+          } else if ((col.min || col.min === 0) && val < col.min) {          // 鏈�灏忓�兼楠�
+            let _error = _position + dict['main.excel.content.limitmin']
+            errors.push(_error)
+          } else if ((col.max || col.max === 0) && val > col.max) {          // 鏈�澶у�兼楠�
+            let _error = _position + dict['main.excel.content.limitmax']
+            errors.push(_error)
+          }
+        } else if (/^Decimal/ig.test(col.type)) {
+          let _val = val + ''
+          _val = _val.split('.')
+          let limitlen = col.type.match(/\d+/ig)[1]
+
+          if (typeof(val) !== 'number') {                           // 妫�楠屾槸鍚︿负娴偣鏁�
+            let _error = _position + dict['main.excel.content.floaterror']
+            errors.push(_error)
+          } else if (_val[0].length > 18) {                         // 妫�楠屾暣鏁颁綅
+            let _error = _position + dict['main.excel.content.floatIntover']
+            errors.push(_error)
+          } else if (_val[1] && _val[1].length > limitlen) {        // 鏈�灏忓�兼楠�
+            let _error = _position + dict['main.excel.content.floatPointover']
+            errors.push(_error)
+          } else if ((col.min || col.min === 0) && val < col.min) { // 鏈�灏忓�兼楠�
+            let _error = _position + dict['main.excel.content.limitmin']
+            errors.push(_error)
+          } else if ((col.max || col.max === 0) && val > col.max) { // 鏈�澶у�兼楠�
+            let _error = _position + dict['main.excel.content.limitmax']
+            errors.push(_error)
+          }
+        }
+        
+        return `'${val}' as ${col.Column}`
+      })
+
+      if (!item.innerFunc) {
+        vals.push(`@upid+'${this.getuuid()}' as jskey`)
+      }
+
+      return `Select ${vals.join(',')}`
+    })
+
+    _Ltext = _Ltext.join(' Union all ')
+
+    let _sql = ''
+
+    if (!item.innerFunc) {
+      let declarefields = []
+      let fields = []
+      let timestamp = new Date().getTime()
+
+      btn.columns.forEach(col => {
+        declarefields.push(`${col.Column} ${col.type}`)
+        fields.push(col.Column)
+      })
+
+      fields = fields.join(',')
+
+      _sql = `declare @${btn.sheet} table (${declarefields.join(',')},jskey nvarchar(50) )
+      Declare @UserName nvarchar(50),@FullName nvarchar(50) ,@upid nvarchar(50)
+      select @UserName=UserName,@FullName=FullName from SUsers where UID=@UserID@
+      
+      set @upid='${timestamp}'
+     
+      Insert into  @${btn.sheet} (${fields},jskey)
+      ${_Ltext}
+
+      Insert into ${btn.sheet} (${fields},createuserid,createuser,createstaff,bid,upid) 
+      Select ${fields},@userid@,@username,@fullname,@BID@,@upid From @${btn.sheet}
+
+      Delete @${btn.sheet}`
+
+    } else {
+      _sql = _Ltext
+    }
+
+    console.log(_sql)
+    return {
+      sql: _sql,
+      errors: errors.join('; ')
+    }
+  }
+
+  /**
    * @description 浣跨敤绯荤粺鍑芥暟鏃讹紙sPC_TableData_InUpDe 锛夛紝鐢熸垚sql璇彞
    * @return {String} type   鎵ц绫诲瀷
    * @return {String} table  琛ㄥ悕
@@ -552,10 +677,10 @@
         `
     }
 
-    // 娣诲姞鏃朵富閿负绌�
-    if (btn.sqlType === 'insert') {
-      primaryId = ''
-    }
+    // 娣诲姞鏃朵富閿负绌� 鏀逛负鍓嶅彴鐢熸垚
+    // if (btn.sqlType === 'insert') {
+    //   primaryId = ''
+    // }
 
     // 鍘婚櫎绂佺敤鐨勯獙璇�
     if (verify.contrasts) {
@@ -759,6 +884,10 @@
         }
       })
 
+      if (!keys.includes(primaryKey)) {
+        keys.push(primaryKey)
+        values.push('\'' + primaryId + '\'')
+      }
       if (!keys.includes('createuserid')) {
         keys.push('createuserid')
         values.push('@userid@')

--
Gitblit v1.8.0