From 5df578ff69f6b02e821d59a8883bc75d78695a62 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期二, 10 十一月 2020 11:07:31 +0800
Subject: [PATCH] 2020-11-10

---
 src/templates/zshare/editTable/index.jsx                                 |  257 +++++++++
 package-lock.json                                                        |   95 +++
 src/menu/components/card/cardcellcomponent/dragaction/index.scss         |    3 
 src/templates/subtableconfig/source.jsx                                  |    2 
 src/menu/datasource/verifycard/index.scss                                |    6 
 src/menu/menuform/index.jsx                                              |    4 
 src/menu/actioncomponent/formconfig.jsx                                  |    4 
 src/menu/padcontroller/index.jsx                                         |   12 
 src/locales/zh-CN/model.js                                               |    4 
 src/templates/sharecomponent/fieldscomponent/index.jsx                   |   16 
 src/views/billprint/index.scss                                           |  160 +++++
 src/locales/en-US/model.js                                               |    4 
 src/tabviews/zshare/actionList/newpagebutton/index.jsx                   |   16 
 src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx    |    7 
 src/views/billprint/index.jsx                                            |  345 ++++++++++++
 src/components/sidemenu/config.jsx                                       |    8 
 src/templates/sharecomponent/settingcomponent/settingform/index.jsx      |    7 
 src/templates/zshare/editTable/index.scss                                |   47 +
 src/views/menudesign/index.jsx                                           |  221 +++++--
 src/menu/datasource/verifycard/columnform/index.jsx                      |   34 -
 src/menu/datasource/verifycard/index.jsx                                 |  119 ++--
 src/tabviews/custom/components/card/table-card/index.scss                |    4 
 src/tabviews/custom/components/card/table-card/index.jsx                 |   47 +
 src/tabviews/custom/components/card/cardcellList/index.jsx               |    2 
 src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx       |    6 
 src/templates/zshare/formconfig.jsx                                      |   20 
 src/templates/comtableconfig/source.jsx                                  |    2 
 src/templates/sharecomponent/actioncomponent/actionform/index.jsx        |    9 
 src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss   |    6 
 src/templates/zshare/verifycard/index.jsx                                |    5 
 src/router/index.js                                                      |    2 
 src/templates/sharecomponent/settingcomponent/settingform/index.scss     |    6 
 src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx  |    7 
 src/menu/modelsource/option.jsx                                          |    4 
 src/templates/sharecomponent/actioncomponent/index.jsx                   |   57 +
 src/menu/modalconfig/index.jsx                                           |    4 
 src/views/menudesign/index.scss                                          |    5 
 package.json                                                             |    2 
 src/tabviews/custom/components/card/cardcellList/index.scss              |    3 
 src/menu/menushell/index.jsx                                             |    2 
 src/menu/modelsource/index.jsx                                           |   23 
 src/templates/sharecomponent/treesettingcomponent/settingform/index.scss |    6 
 42 files changed, 1,356 insertions(+), 237 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 586361c..d3e14d4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4128,6 +4128,58 @@
         }
       }
     },
+    "braft-convert": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/braft-convert/-/braft-convert-2.3.0.tgz",
+      "integrity": "sha512-5km+dLHk8iYDv2iEYDrDQ2ld/ZoUx66QLql0qdm5PqZEcNXc8dBHGLORfzeu3iMw1jLeAiHxtdY5+ypuIhczVg==",
+      "requires": {
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3"
+      }
+    },
+    "braft-editor": {
+      "version": "2.3.9",
+      "resolved": "https://registry.npmjs.org/braft-editor/-/braft-editor-2.3.9.tgz",
+      "integrity": "sha512-mqdPk/zI2dhFK8tW/A4Qj/AkkARLh5L/niNw+iif5wFqb6zh15rMlrShgz1nWO/QXyAKr8XtDgxiBbR0zWwtRg==",
+      "requires": {
+        "@babel/runtime": "^7.0.0",
+        "braft-convert": "^2.3.0",
+        "braft-finder": "^0.0.19",
+        "braft-utils": "^3.0.8",
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3",
+        "draft-js-multidecorators": "^1.0.0",
+        "draftjs-utils": "^0.9.4",
+        "immutable": "~3.7.4"
+      },
+      "dependencies": {
+        "immutable": {
+          "version": "3.7.6",
+          "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
+          "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
+        }
+      }
+    },
+    "braft-extensions": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/braft-extensions/-/braft-extensions-0.1.0.tgz",
+      "integrity": "sha512-i7/GjJY2FCJUKqdHiFeohasWQvY1BMK1BU4KGDZo+K+d3i55sIsiBmmRRDrOazDLWBVqYi1rBu2uqFQvxJu1jw==",
+      "requires": {
+        "@babel/runtime": "^7.0.0",
+        "braft-convert": "^2.1.10",
+        "braft-utils": "^3.0.12"
+      }
+    },
+    "braft-finder": {
+      "version": "0.0.19",
+      "resolved": "https://registry.npmjs.org/braft-finder/-/braft-finder-0.0.19.tgz",
+      "integrity": "sha512-0kzI6/KbomJJhYX1hpjn4edCKhblyUyWdUrsgBmOrwy0vrj+pPkm69+Uf8Uj6KGAULM6LF0ooC++p7fqUGgFHw=="
+    },
+    "braft-utils": {
+      "version": "3.0.12",
+      "resolved": "https://registry.npmjs.org/braft-utils/-/braft-utils-3.0.12.tgz",
+      "integrity": "sha512-O2cKysURNC4HSEMKgNmQ2RluwcrxvYrztlEmyPN5SzktiNX3vaLFQoo0Ez3PlIhvjaGrIBSIT2Oyh2N6mn6TFg=="
+    },
     "brorand": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
@@ -5972,6 +6024,36 @@
       "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.2.0.tgz",
       "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU="
     },
+    "draft-convert": {
+      "version": "2.1.10",
+      "resolved": "https://registry.npmjs.org/draft-convert/-/draft-convert-2.1.10.tgz",
+      "integrity": "sha512-PRdcjBqFUfEb2jlPM+bOyyCNlTzGaHdyhvKsw5nur6Dj1YclmuAiTwJ8yTsEa95YI9kwzbO5ccZ/+tYj/LlS0A==",
+      "requires": {
+        "@babel/runtime": "^7.5.5",
+        "immutable": "~3.7.4",
+        "invariant": "^2.2.1"
+      },
+      "dependencies": {
+        "@babel/runtime": {
+          "version": "7.12.5",
+          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
+          "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
+          "requires": {
+            "regenerator-runtime": "^0.13.4"
+          }
+        },
+        "immutable": {
+          "version": "3.7.6",
+          "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
+          "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
+        },
+        "regenerator-runtime": {
+          "version": "0.13.7",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+          "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+        }
+      }
+    },
     "draft-js": {
       "version": "0.10.5",
       "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz",
@@ -5989,6 +6071,19 @@
         }
       }
     },
+    "draft-js-multidecorators": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/draft-js-multidecorators/-/draft-js-multidecorators-1.0.0.tgz",
+      "integrity": "sha1-bEvo17eN0rlm7lHubMF5ubU15hI=",
+      "requires": {
+        "immutable": "*"
+      }
+    },
+    "draftjs-utils": {
+      "version": "0.9.4",
+      "resolved": "https://registry.npmjs.org/draftjs-utils/-/draftjs-utils-0.9.4.tgz",
+      "integrity": "sha512-KYjABSbGpJrwrwmxVj5UhfV37MF/p0QRxKIyL+/+QOaJ8J9z1FBKxkblThbpR0nJi9lxPQWGg+gh+v0dAsSCCg=="
+    },
     "dragact": {
       "version": "0.2.12",
       "resolved": "https://registry.npmjs.org/dragact/-/dragact-0.2.12.tgz",
diff --git a/package.json b/package.json
index a7a7776..f119939 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,8 @@
     "babel-plugin-import": "^1.11.0",
     "babel-plugin-named-asset-import": "^0.3.3",
     "babel-preset-react-app": "9.0.0",
+    "braft-editor": "^2.3.9",
+    "braft-extensions": "^0.1.0",
     "browserslist": "^4.13.0",
     "camelcase": "^5.2.0",
     "caniuse-lite": "^1.0.30001102",
diff --git a/src/components/sidemenu/config.jsx b/src/components/sidemenu/config.jsx
index 324df40..553511e 100644
--- a/src/components/sidemenu/config.jsx
+++ b/src/components/sidemenu/config.jsx
@@ -55,6 +55,14 @@
       text: '鏍囩鎵撳嵃妯℃澘'
     }, {
       src: '',
+      PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
+      type: 'ManageTable',
+      MenuID: '16044812935562g807p3p12huk8kokmb',
+      MenuNo: 'sPrintTemplate_webM',
+      MenuName: '鍗曟嵁鎵撳嵃妯℃澘',
+      text: '鍗曟嵁鎵撳嵃妯℃澘'
+    }, {
+      src: '',
       systems: ['SSO', 'cloud'],
       PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
       type: 'ManageTable',
diff --git a/src/locales/en-US/model.js b/src/locales/en-US/model.js
index c929fca..cc1d782 100644
--- a/src/locales/en-US/model.js
+++ b/src/locales/en-US/model.js
@@ -22,6 +22,7 @@
   'model.true': 'True',
   'model.false': 'False',
   'model.add': 'Add ',
+  'model.batchAdd': 'BatchAdd',
   'model.update': 'Update ',
   'model.thaw': 'Thaw ',
   'model.menu': 'Menu ',
@@ -34,6 +35,7 @@
   'model.window': 'Window',
   'model.empty': 'Empty',
   'model.pay': 'Pay',
+  'model.operation': 'Action',
   'model.switch.open': 'Open',
   'model.switch.close': 'Close',
   'model.menu.level1': 'Level 1 menu',
@@ -74,13 +76,11 @@
   'header.menu.datasource': 'The data source',
   'header.menu.maintable': 'The main table',
   'header.menu.query': 'The query',
-  'header.menu.printTemplate': 'Printed template',
   'model.form.tabType': 'The tag type',
   'header.form.search.placeholder': 'Please add search criteria',
   'header.form.modal.placeholder': 'Please add the form',
   'header.form.action.placeholder': 'Please add buttons',
   'header.form.column.placeholder': 'Please add columns',
-  'model.form.column.action': 'Action',
   'model.form.width': 'Width',
   'header.form.title': 'Title',
   'model.form.field': 'Field',
diff --git a/src/locales/zh-CN/model.js b/src/locales/zh-CN/model.js
index 95bdf87..1c8f910 100644
--- a/src/locales/zh-CN/model.js
+++ b/src/locales/zh-CN/model.js
@@ -22,6 +22,7 @@
   'model.true': '鏄�',
   'model.false': '鍚�',
   'model.add': '娣诲姞',
+  'model.batchAdd': '鎵归噺娣诲姞',
   'model.update': '淇敼',
   'model.thaw': '瑙e喕',
   'model.menu': '鑿滃崟',
@@ -34,6 +35,7 @@
   'model.window': '绐楀彛',
   'model.empty': '绌�',
   'model.pay': '鏀粯',
+  'model.operation': '鎿嶄綔',
   'model.switch.open': '寮�',
   'model.switch.close': '鍏�',
   'model.menu.level1': '涓�绾ц彍鍗�',
@@ -74,13 +76,11 @@
   'header.menu.datasource': '鏁版嵁鏉ユ簮',
   'header.menu.maintable': '涓昏〃',
   'header.menu.query': '鏌ヨ',
-  'header.menu.printTemplate': '鎵撳嵃妯℃澘',
   'model.form.tabType': '鏍囩绫诲瀷',
   'header.form.search.placeholder': '璇锋坊鍔犳悳绱㈡潯浠�',
   'header.form.modal.placeholder': '璇锋坊鍔犺〃鍗�',
   'header.form.action.placeholder': '璇锋坊鍔犳寜閽�',
   'header.form.column.placeholder': '璇锋坊鍔犳樉绀哄垪',
-  'model.form.column.action': '鎿嶄綔',
   'model.form.width': '瀹藉害',
   'header.form.title': '鏍囬',
   'model.form.field': '瀛楁',
diff --git a/src/menu/actioncomponent/formconfig.jsx b/src/menu/actioncomponent/formconfig.jsx
index 01043a7..de09940 100644
--- a/src/menu/actioncomponent/formconfig.jsx
+++ b/src/menu/actioncomponent/formconfig.jsx
@@ -150,8 +150,8 @@
       initVal: card.pageTemplate || '',
       required: true,
       options: [{
-        value: 'print',
-        text: Formdict['header.menu.printTemplate']
+        value: 'billprint',
+        text: '鍗曟嵁鎵撳嵃'
       }, {
         value: 'pay',
         text: Formdict['model.pay']
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.scss b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
index 9f90b10..7f5a539 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.scss
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -88,6 +88,9 @@
   }
   .ant-mk-splitline {
     border-top: 1px solid;
+    border-bottom: 0;
+    border-left: 0;
+    border-right: 0;
   }
   .ant-mk-picture {
     background-size: cover;
diff --git a/src/menu/datasource/verifycard/columnform/index.jsx b/src/menu/datasource/verifycard/columnform/index.jsx
index c8ef7bb..7e2a407 100644
--- a/src/menu/datasource/verifycard/columnform/index.jsx
+++ b/src/menu/datasource/verifycard/columnform/index.jsx
@@ -10,34 +10,13 @@
     columnChange: PropTypes.func  // 淇敼鍑芥暟
   }
 
-  state = {
-    editItem: null // 缂栬緫鍏冪礌
-  }
-
-  edit = (record) => {
-    this.setState({
-      editItem: record
-    })
-
-    this.props.form.setFieldsValue({
-      label: record.label,
-      field: record.field,
-      datatype: record.datatype
-    })
-  }
-
+  state = {}
 
   handleConfirm = () => {
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
-        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
-
-        this.setState({
-          editItem: null
-        }, () => {
-          this.props.columnChange(values)
-        })
+        this.props.columnChange(values)
         this.props.form.setFieldsValue({
           label: '',
           field: ''
@@ -47,6 +26,7 @@
   }
 
   render() {
+    const { dict } = this.props
     const { getFieldDecorator } = this.props.form
     const formItemLayout = {
       labelCol: {
@@ -69,7 +49,7 @@
                 rules: [
                   {
                     required: true,
-                    message: this.props.dict['form.required.input'] + '鍚嶇О!'
+                    message: dict['form.required.input'] + '鍚嶇О!'
                   }
                 ]
               })(<Input placeholder="" autoComplete="off" />)}
@@ -82,7 +62,7 @@
                 rules: [
                   {
                     required: true,
-                    message: this.props.dict['form.required.input'] + '瀛楁!'
+                    message: dict['form.required.input'] + '瀛楁!'
                   }
                 ]
               })(<Input placeholder="" autoComplete="off" />)}
@@ -95,7 +75,7 @@
                 rules: [
                   {
                     required: true,
-                    message: this.props.dict['form.required.select'] + '鏁版嵁绫诲瀷!'
+                    message: dict['form.required.select'] + '鏁版嵁绫诲瀷!'
                   }
                 ]
               })(
@@ -133,7 +113,7 @@
           </Col>
           <Col span={3} className="add">
             <Button onClick={this.handleConfirm} type="primary" className="mk-green">
-              淇濆瓨
+              {dict['model.add']}
             </Button>
           </Col>
         </Row>
diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx
index 8332eac..b26eef2 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -18,6 +18,7 @@
 const { Paragraph } = Typography
 
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
+const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
 
 class VerifyCard extends Component {
   static propTpyes = {
@@ -41,34 +42,51 @@
       {
         title: '鍚嶇О',
         dataIndex: 'label',
-        width: '25%'
+        inputType: 'input',
+        editable: true,
+        width: '28%'
       },
       {
         title: '瀛楁',
         dataIndex: 'field',
-        width: '25%'
+        inputType: 'input',
+        editable: true,
+        width: '28%'
       },
       {
         title: '鏁版嵁绫诲瀷',
         dataIndex: 'datatype',
+        inputType: 'select',
+        options: [
+          { value: 'Nvarchar(50)', text: 'Nvarchar(50)' },
+          { value: 'Nvarchar(100)', text: 'Nvarchar(100)' },
+          { value: 'Nvarchar(512)', text: 'Nvarchar(512)' },
+          { value: 'Nvarchar(1024)', text: 'Nvarchar(1024)' },
+          { value: 'Nvarchar(2048)', text: 'Nvarchar(2048)' },
+          { value: 'Nvarchar(max)', text: 'Nvarchar(max)' },
+          { value: 'Int', text: 'Int' },
+          { value: 'Decimal(18,0)', text: 'Decimal(18,0)' },
+          { value: 'Decimal(18,1)', text: 'Decimal(18,1)' },
+          { value: 'Decimal(18,2)', text: 'Decimal(18,2)' },
+          { value: 'Decimal(18,3)', text: 'Decimal(18,3)' },
+          { value: 'Decimal(18,4)', text: 'Decimal(18,4)' },
+          { value: 'Decimal(18,5)', text: 'Decimal(18,5)' },
+          { value: 'Decimal(18,6)', text: 'Decimal(18,6)' },
+          { value: 'Decimal(18,7)', text: 'Decimal(18,7)' },
+          { value: 'Decimal(18,8)', text: 'Decimal(18,8)' },
+          { value: 'Decimal(18,9)', text: 'Decimal(18,9)' },
+          { value: 'Decimal(18,10)', text: 'Decimal(18,10)' },
+          { value: 'Decimal(18,11)', text: 'Decimal(18,11)' },
+          { value: 'Decimal(18,12)', text: 'Decimal(18,12)' },
+          { value: 'Decimal(18,13)', text: 'Decimal(18,13)' },
+          { value: 'Decimal(18,14)', text: 'Decimal(18,14)' },
+          { value: 'Decimal(18,15)', text: 'Decimal(18,15)' },
+          { value: 'Decimal(18,16)', text: 'Decimal(18,16)' },
+          { value: 'Decimal(18,17)', text: 'Decimal(18,17)' },
+          { value: 'Decimal(18,18)', text: 'Decimal(18,18)' },
+        ],
+        editable: true,
         width: '25%',
-      },
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        width: '25%',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          (<div>
-            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'columns')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
-            <Popconfirm
-              overlayClassName="popover-confirm"
-              title={this.props.dict['model.query.delete']}
-              onConfirm={() => this.deleteColumn(record)
-            }>
-              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
-            </Popconfirm>
-          </div>)
       }
     ],
     scriptsColumns: [
@@ -105,7 +123,7 @@
         dataIndex: 'operation',
         render: (text, record) =>
           (<div>
-            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><Icon type="edit" /></span>
             <span className="operation-btn" onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
             <span className="operation-btn" onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
             <span className="operation-btn" title={this.props.dict['model.status.change']} onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
@@ -135,13 +153,13 @@
       if (!conf.parentId && box.Template === 'CustomPage') {
         box.components.forEach(item => {
           if (item.uuid !== conf.uuid && item.setting && item.setting.varMark) {
-            Marks.push(item.setting.varMark)
+            Marks.push(item.setting.varMark.toLowerCase())
           }
         })
       } else if (conf.parentId === box.parentId && conf.tabId === box.uuid) {
         box.components.forEach(item => {
           if (item.uuid !== conf.uuid && item.setting && item.setting.varMark) {
-            Marks.push(item.setting.varMark)
+            Marks.push(item.setting.varMark.toLowerCase())
           }
         })
       } else {
@@ -239,39 +257,20 @@
   }
 
   columnChange = (values) => {
-    let columns = fromJS(this.state.columns).toJS()
+    const { columns } = this.state
 
-    if (values.uuid) {
-      columns = columns.map(item => {
-        if (item.uuid === values.uuid) {
-          return values
-        } else {
-          return item
-        }
-      })
-    } else {
-      values.uuid = Utils.getuuid()
-      columns.push(values)
-    }
+    values.uuid = Utils.getuuid()
 
-    this.setState({ columns })
-  }
-
-  deleteColumn = (record) => {
-    this.setState({ columns: this.state.columns.filter(item => item.uuid !== record.uuid) })
+    this.setState({ columns: [...columns, values] })
   }
 
   deleteScript = (record) => {
     this.setState({ scripts: this.state.scripts.filter(item => item.uuid !== record.uuid) })
   }
 
-  handleEdit = (record, type) => {
-    if (type === 'scripts') {
-      this.scriptsForm.edit(record)
-    } else if (type === 'columns') {
-      this.contrastForm.edit(record)
-    }
-
+  handleEdit = (record) => {
+    this.scriptsForm.edit(record)
+    
     let node = document.getElementById('model-verify-card-box-tab').parentNode
 
     if (node && node.scrollTop) {
@@ -379,7 +378,7 @@
           search = [...search, ...mainSearch]
         }
 
-        if (res.varMark && varMarks.includes(res.varMark)) {
+        if (res.varMark && varMarks.includes(res.varMark.toLowerCase())) {
           notification.warning({
             top: 92,
             message: '鍙橀噺鏍囪瘑涓嶅彲閲嶅锛�',
@@ -455,7 +454,7 @@
             search = [...search, ...mainSearch]
           }
 
-          if (res.varMark && varMarks.includes(res.varMark)) {
+          if (res.varMark && varMarks.includes(res.varMark.toLowerCase())) {
             notification.warning({
               top: 92,
               message: '鍙橀噺鏍囪瘑涓嶅彲閲嶅锛�',
@@ -588,27 +587,21 @@
             />
           </TabPane>
           <TabPane tab="瀛楁闆�" key="columns">
-            <ColForm
-              dict={this.props.dict}
-              columnChange={this.columnChange}
-              wrappedComponentRef={(inst) => this.contrastForm = inst}
-            />
+            <ColForm dict={this.props.dict} columnChange={this.columnChange}/>
             <FieldsComponent
               config={{...config, columns}}
               type="fields"
               tableFields={menu.tableFields}
               updatefield={this.updatefields}
             />
-            <Table
-              bordered
-              rowKey="uuid"
-              className="custom-table"
-              dataSource={columns}
-              columns={colColumns}
-              pagination={false}
-            />
+            <EditTable data={columns} columns={colColumns} onChange={(columns) => this.setState({columns})}/>
           </TabPane>
-          <TabPane tab="鑷畾涔夎剼鏈�" key="scripts">
+          <TabPane tab={
+            <span>
+              鑷畾涔夎剼鏈�
+              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
+            </span>
+          } key="scripts">
             <CustomScriptsForm
               setting={setting}
               searches={searches}
diff --git a/src/menu/datasource/verifycard/index.scss b/src/menu/datasource/verifycard/index.scss
index 31e4d0a..f2718d6 100644
--- a/src/menu/datasource/verifycard/index.scss
+++ b/src/menu/datasource/verifycard/index.scss
@@ -9,6 +9,12 @@
     .ant-tabs-nav-scroll {
       text-align: center;
     }
+    .count-tip {
+      position: absolute;
+      top: 0px;
+      color: #1890ff;
+      font-size: 12px;
+    }
     .ant-tabs-content {
       min-height: 40vh;
     }
diff --git a/src/menu/menuform/index.jsx b/src/menu/menuform/index.jsx
index a08e50b..a0fe3e8 100644
--- a/src/menu/menuform/index.jsx
+++ b/src/menu/menuform/index.jsx
@@ -128,7 +128,7 @@
   }
 
   render() {
-    const { dict, MenuName, MenuNo } = this.props
+    const { dict, MenuName, MenuNo, config } = this.props
     const { menulist, smenulist } = this.state
     const { getFieldDecorator } = this.props.form
     const formItemLayout = {
@@ -216,7 +216,7 @@
           <Col span={24}>
             <Form.Item label={dict['mob.menu.easycode']}>
               {getFieldDecorator('easyCode', {
-                initialValue: ''
+                initialValue: config.easyCode
               })(<Input placeholder="" autoComplete="off" onChange={this.changeEasyCode}/>)}
             </Form.Item>
           </Col>
diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx
index 35a5a66..382b732 100644
--- a/src/menu/menushell/index.jsx
+++ b/src/menu/menushell/index.jsx
@@ -131,7 +131,7 @@
   })
 
   return (
-    <div ref={drop} className="menu-shell-inner" style={menu.style}>
+    <div ref={drop} className="menu-shell-inner" id="menu-shell-inner" style={menu.style}>
       <div className="ant-row">
         {cards.map(card => (
           <Card
diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx
index 5a0b8c9..cb8a9eb 100644
--- a/src/menu/modalconfig/index.jsx
+++ b/src/menu/modalconfig/index.jsx
@@ -747,7 +747,7 @@
                     return (<SourceElement key={index} content={item}/>)
                   })}
                 </div>
-                <Button type="primary" block onClick={() => this.queryField()}>{this.state.dict['header.menu.form.add']}</Button>
+                <Button type="primary" block onClick={() => this.queryField()}>{this.state.dict['model.batchAdd']}</Button>
                 <Button type="primary" block onClick={() => this.handleGroup()}>{this.state.dict['header.menu.group.add']}</Button>
               </Panel>
             </Collapse>
@@ -828,7 +828,7 @@
         <Modal
           title={this.state.dict['model.edit']}
           visible={this.state.visible}
-          width={700}
+          width={850}
           onCancel={this.editModalCancel}
           onOk={this.handleSubmit}
           confirmLoading={this.state.sqlVerifing}
diff --git a/src/menu/modelsource/index.jsx b/src/menu/modelsource/index.jsx
index 7eb339f..91f4c24 100644
--- a/src/menu/modelsource/index.jsx
+++ b/src/menu/modelsource/index.jsx
@@ -5,12 +5,29 @@
 import SourceWrap from './dragsource'
 import './index.scss'
 
-class CardChart extends Component {
+class ModelSource extends Component {
+  state = {
+    menuOptions: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { MenuType } = this.props
+    let options = fromJS(menuOptions).toJS()
+
+    options = options.filter(item => !item.forbid || !item.forbid.includes(MenuType))
+
+    this.setState({
+      menuOptions: options
+    })
+  }
+
   shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+    return !is(fromJS(this.state), fromJS(nextState))
   }
 
   render() {
+    const { menuOptions } = this.state
+
     return (
       <div className="mob-card-source-box">
         {menuOptions.map((item, index) => (<SourceWrap key={index} content={item} />))}
@@ -19,4 +36,4 @@
   }
 }
 
-export default CardChart
\ No newline at end of file
+export default ModelSource
\ No newline at end of file
diff --git a/src/menu/modelsource/option.jsx b/src/menu/modelsource/option.jsx
index 477ba9f..c74af33 100644
--- a/src/menu/modelsource/option.jsx
+++ b/src/menu/modelsource/option.jsx
@@ -17,8 +17,8 @@
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
-  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '鏍囩椤�', width: 24 },
-  { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '鎼滅储鏉′欢', width: 24 },
+  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '鏍囩椤�', width: 24, forbid: ['billPrint'] },
+  { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '鎼滅储鏉′欢', width: 24, forbid: ['billPrint'] },
   { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '鏁版嵁鍗�', config: `[{"uuid":"160135809128212dm7i29fim9ksto9od","setting":{"width":6},"style":{"paddingTop":"15px","marginTop":"4px","paddingRight":"15px","marginRight":"8px","marginLeft":"8px","backgroundColor":"rgba(255, 255, 255, 1)","borderColor":"#e8e8e8","paddingLeft":"15px","marginBottom":"4px","borderWidth":"1px","paddingBottom":"10px"},"backStyle":{},"elements":[{"datatype":"static","width":12,"marks":null,"height":1,"value":"鍏冲崟","style":{},"prefix":"","postfix":"","format":"","eleType":"text","uuid":"160231860159931untbea62sgokunc5s"},{"datatype":"dynamic","width":12,"marks":null,"style":{"color":"rgba(250, 219, 20, 1)","textAlign":"right"},"btnstyle":{},"eleType":"icon","icon":"question-circle","field":"nvarchar2","uuid":"1602318768361nv8ql4t47sgcsn88b0u"},{"datatype":"static","width":24,"marks":null,"height":1,"innerHeight":36,"value":"100","style":{"fontSize":"24px","fontWeight":"500","color":"rgba(0, 0, 0, 1)"},"prefix":"","btnstyle":{},"postfix":"","format":"","eleType":"text","uuid":"1602318817884v70gtgb65ubnm8mbcvv"},{"color":"#1890ff","width":24,"marks":null,"maxValue":100,"style":{"color":"rgba(250, 140, 22, 1)","paddingTop":"20px","paddingBottom":"10px"},"btnstyle":{},"eleType":"slider","field":"int1","uuid":"16023188871233rkktuvpp1h077igrsu"},{"eleType":"splitline","width":24,"color":"#e8e8e8","uuid":"1602320017038n31bk9o831ggug0tu0b","marks":null,"style":{"marginTop":"10px","marginBottom":"10px"},"btnstyle":{}},{"datatype":"static","width":12,"marks":null,"height":1,"value":"100","style":{"marginTop":"6px"},"prefix":"鍏冲崟","btnstyle":{},"postfix":"","format":"","eleType":"text","uuid":"1602320061243drd7lf3agvn04kgr175"}],"backElements":[]}]` },
   { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '灞炴�у崱', config: `[{"uuid":"1603681387259qaqf1127f72esmtchge","setting":{"width":6,"type":"simple"},"style":{"paddingTop":"15px","marginTop":"8px","paddingRight":"15px","marginRight":"8px","marginLeft":"8px","borderColor":"#e8e8e8","paddingLeft":"15px","marginBottom":"8px","borderWidth":"1px","paddingBottom":"15px"},"backStyle":{},"elements":[{"datatype":"static","width":12,"marks":null,"height":1,"value":"瓒呮椂宸ュ崟","style":{"color":"rgba(67, 67, 67, 0.51)"},"prefix":"","postfix":"","format":"","eleType":"text","uuid":"1603681402945qnkgm7q8cng65evn5ev"},{"eleType":"icon","datatype":"static","width":12,"icon":"question-circle","tooltip":"瓒呮椂宸ュ崟","uuid":"1603681473384i2crkbtofg4pu76k06a","marks":null,"style":{"textAlign":"right","color":"rgba(250, 219, 20, 1)"}},{"datatype":"static","width":24,"marks":null,"height":1,"innerHeight":36,"value":"100","style":{"fontSize":"24px","color":"rgba(0, 0, 0, 1)"},"prefix":"","postfix":"","format":"","eleType":"number","uuid":"1603681539870d704ufqf98kc6t7537t"},{"color":"rgba(250, 219, 20, 1)","datatype":"static","width":24,"marks":null,"maxValue":100,"value":50,"style":{"paddingTop":"10px","paddingBottom":"10px"},"eleType":"slider","uuid":"1603683067556mvupau0odvrtv45u7o8"},{"eleType":"splitline","width":24,"color":"#e8e8e8","uuid":"1603683117981t9k55k8an430fuppmci","marks":null,"style":{"paddingTop":"5px","paddingBottom":"5px"}},{"datatype":"static","width":12,"marks":null,"height":1,"value":"100","style":{"color":"rgba(0, 0, 0, 0.65)","marginTop":"10px"},"prefix":"瓒呮椂宸ュ崟  ","postfix":"","format":"","eleType":"text","uuid":"1603683136553uvsmkfohkft9idbfkhu"}],"backElements":[]}]` },
   { type: 'menu', url: TableCard, component: 'table', subtype: 'tablecard', title: '琛ㄦ牸', width: 12 },
diff --git a/src/menu/padcontroller/index.jsx b/src/menu/padcontroller/index.jsx
index 7a50d27..589dd25 100644
--- a/src/menu/padcontroller/index.jsx
+++ b/src/menu/padcontroller/index.jsx
@@ -45,18 +45,18 @@
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
-        sm: { span: 6 }
+        sm: { span: 4 }
       },
       wrapperCol: {
         xs: { span: 24 },
-        sm: { span: 18 }
+        sm: { span: 20 }
       }
     }
 
     return (
       <div className="menu-padding-controller">
         <Form {...formItemLayout}>
-          <Col span={12}>
+          <Col span={24}>
             <Form.Item
               colon={false}
               label={<Icon title="涓婅竟璺�" type="arrow-up"/>}
@@ -64,7 +64,7 @@
               <StyleInput defaultValue={config.style.paddingTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingTop')}/>
             </Form.Item>
           </Col>
-          <Col span={12}>
+          <Col span={24}>
             <Form.Item
               colon={false}
               label={<Icon title="涓嬭竟璺�" type="arrow-down"/>}
@@ -72,7 +72,7 @@
               <StyleInput defaultValue={config.style.paddingBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingBottom')}/>
             </Form.Item>
           </Col>
-          <Col span={12}>
+          <Col span={24}>
             <Form.Item
               colon={false}
               label={<Icon title="宸﹁竟璺�" type="arrow-left"/>}
@@ -80,7 +80,7 @@
               <StyleInput defaultValue={config.style.paddingLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingLeft')}/>
             </Form.Item>
           </Col>
-          <Col span={12}>
+          <Col span={24}>
             <Form.Item
               colon={false}
               label={<Icon title="鍙宠竟璺�" type="arrow-right"/>}
diff --git a/src/router/index.js b/src/router/index.js
index 84ee2f0..7b67105 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -13,6 +13,7 @@
 const MobManage = asyncLoadComponent(() => import('@/views/mobmanage'))
 const MobDesign = asyncLoadComponent(() => import('@/views/mobdesign'))
 const MenuDesign = asyncLoadComponent(() => import('@/views/menudesign'))
+const BillPrint = asyncLoadComponent(() => import('@/views/billprint'))
 const PrintT = asyncLoadComponent(() => import('@/views/printTemplate'))
 
 const routers = [
@@ -24,6 +25,7 @@
   {path: '/mobmanage', name: 'mobmanage', component: MobManage, auth: true},
   {path: '/mobdesign/:appId/:appType/:appCode/:appName', name: 'mobdesign', component: MobDesign, auth: true},
   {path: '/menudesign/:param', name: 'menudesign', component: MenuDesign, auth: true},
+  {path: '/billprint/:param', name: 'billprint', component: BillPrint, auth: true},
   {path: '/paramsmain/:param', name: 'pmain', component: Main, auth: true}
 ]
 
diff --git a/src/tabviews/custom/components/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx
index a77d793..ab52d69 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.jsx
+++ b/src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -47,7 +47,7 @@
   }
 
   shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState))
+    return !is(fromJS(this.state), fromJS(nextState)) || !is(fromJS(this.props), fromJS(nextProps))
   }
 
   /**
diff --git a/src/tabviews/custom/components/card/cardcellList/index.scss b/src/tabviews/custom/components/card/cardcellList/index.scss
index e994d95..c55fce9 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.scss
+++ b/src/tabviews/custom/components/card/cardcellList/index.scss
@@ -93,6 +93,9 @@
   }
   .ant-mk-splitline {
     border-top: 1px solid;
+    border-bottom: 0;
+    border-left: 0;
+    border-right: 0;
   }
   .ant-slider {
     margin: 0px;
diff --git a/src/tabviews/custom/components/card/table-card/index.jsx b/src/tabviews/custom/components/card/table-card/index.jsx
index 4f76e24..abbc960 100644
--- a/src/tabviews/custom/components/card/table-card/index.jsx
+++ b/src/tabviews/custom/components/card/table-card/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Col, Empty } from 'antd'
+import { Spin, notification, Col, Empty, Pagination } from 'antd'
 
 import asyncComponent from '@/utils/asyncComponent'
 import Api from '@/api'
@@ -24,6 +24,9 @@
   state = {
     config: null,              // 鍥捐〃閰嶇疆淇℃伅
     loading: false,            // 鏁版嵁鍔犺浇鐘舵��
+    preIndex: 0,               // 寮�濮嬬储寮�
+    pageIndex: 1,              // 椤电爜
+    total: 0,                  // 鎬绘暟
     sync: false,               // 鏄惁缁熶竴璇锋眰鏁版嵁
     data: null,                // 鏁版嵁
     title: '',                 // 鏍囬
@@ -46,6 +49,12 @@
     let showHeader = false
     if (_config.wrap.title || _config.search.length > 0) {
       showHeader = true
+    }
+
+    if (_config.setting.laypage) {
+      _config.wrap.contentHeight = _config.wrap.height - (showHeader ? 85 : 40)
+    } else {
+      _config.wrap.contentHeight = _config.wrap.height - (showHeader ? 45 : 0)
     }
 
     _config.columns.forEach(item => {
@@ -121,12 +130,16 @@
 
     if (syncId && syncId !== config.uuid) return
 
-    this.loadData()
+    this.setState({
+      pageIndex: 1
+    }, () => {
+      this.loadData()
+    })
   }
 
   async loadData () {
     const { mainSearch, BID, menuType, dataManager } = this.props
-    const { config, arr_field } = this.state
+    const { config, arr_field, pageIndex } = this.state
 
     let searches = []
     if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
@@ -143,12 +156,19 @@
     })
 
     let _orderBy = config.setting.order || ''
-    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID, menuType, dataManager)
+    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, pageIndex, config.setting.pageSize, BID, menuType, dataManager)
 
     let result = await Api.genericInterface(param)
     if (result.status) {
+      let _preIndex = 0
+      if (config.setting.laypage) {
+        _preIndex = config.setting.pageSize * (pageIndex - 1)
+      }
+
       this.setState({
         data: result.data,
+        total: result.total,
+        preIndex: _preIndex,
         loading: false
       })
     } else {
@@ -175,6 +195,14 @@
         }
       }
     }
+  }
+
+  changePageIndex = (page) => {
+    this.setState({
+      pageIndex: page
+    }, () => {
+      this.loadData()
+    })
   }
 
   getLines = (data, seq) => {
@@ -219,7 +247,7 @@
   }
 
   render() {
-    const { config, loading, data, title, showHeader } = this.state
+    const { config, loading, data, title, showHeader, pageIndex, preIndex, total } = this.state
 
     return (
       <div className="custom-table-card-box" style={{...config.style, height: config.wrap.height}}>
@@ -233,10 +261,13 @@
           <span className="table-title">{title}</span>
           {/* <searchLine /> */}
         </div> : null}
-        {data && data.length > 0 ? <div className="card-row-list" style={{height: config.wrap.height - (showHeader ? 45 : 0)}}>
-          {data.map((item, index) => this.getLines(item, index + 1))}
+        {data && data.length > 0 ? <div className="card-row-list" style={{height: config.wrap.contentHeight}}>
+          {data.map((item, index) => this.getLines(item, preIndex + index + 1))}
         </div> : null}
-        {data && data.length === 0 ? <Empty description={false}/> : null}
+        {data && data.length === 0 ? <div className="card-row-list" style={{height: config.wrap.contentHeight}}>
+          <Empty description={false}/>
+        </div> : null}
+        {config.setting.laypage ? <Pagination size="small" current={pageIndex} total={total} onChange={this.changePageIndex} /> : null}
       </div>
     )
   }
diff --git a/src/tabviews/custom/components/card/table-card/index.scss b/src/tabviews/custom/components/card/table-card/index.scss
index 3f5ac95..26c5a25 100644
--- a/src/tabviews/custom/components/card/table-card/index.scss
+++ b/src/tabviews/custom/components/card/table-card/index.scss
@@ -22,6 +22,10 @@
       font-style: inherit;
     }
   }
+  >.ant-pagination {
+    margin-top: 10px;
+    float: right;
+  }
 
   .card-row-list::after {
     content: ' ';
diff --git a/src/tabviews/zshare/actionList/newpagebutton/index.jsx b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
index 7115ff9..0d53b5d 100644
--- a/src/tabviews/zshare/actionList/newpagebutton/index.jsx
+++ b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -80,11 +80,23 @@
     }
 
     let Id = ''
-    if (btn.Ot === 'requiredSgl') {
+    let name = ''
+    let MenuNo = ''
+    let Remark = ''
+    if (btn.Ot === 'requiredSgl' && data[0]) {
       Id = data[0][setting.primaryKey] || ''
+      name = data[0].PrintTempName || ''
+      MenuNo = data[0].PrintTempNO || ''
+      Remark = data[0].Remark || ''
     }
 
-    if (btn.pageTemplate === 'print') {
+    if (btn.pageTemplate === 'billprint') {
+      let src = '#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp })))
+      window.open(src)
+    } else if (btn.pageTemplate === 'billprintTemp') {
+      let src = '#/menudesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'billPrint', MenuId: Id, MenuNo: MenuNo, MenuName: name || '鎵撳嵃', Remark: Remark })))
+      window.open(src)
+    } else if (btn.pageTemplate === 'print') {
       let cloudmsg = '&cuid=' + (sessionStorage.getItem('CloudUserID') || '') + '&clid=' + (sessionStorage.getItem('CloudLoginUID') || '') + '&cun=' + (sessionStorage.getItem('CloudUserName') || '')
       let msg = '&uid=' + sessionStorage.getItem('UserID') + '&lid=' + sessionStorage.getItem('LoginUID') + '&un=' + sessionStorage.getItem('User_Name')
       let src = '#/print/' + window.btoa('ID=' + Id + msg + cloudmsg)
diff --git a/src/templates/comtableconfig/source.jsx b/src/templates/comtableconfig/source.jsx
index 96fefce..0c0ee33 100644
--- a/src/templates/comtableconfig/source.jsx
+++ b/src/templates/comtableconfig/source.jsx
@@ -165,7 +165,7 @@
       Align: 'center',
       IsSort: 'false',
       uuid: Utils.getuuid(),
-      label: CommonDict['model.form.column.action'],
+      label: CommonDict['model.operation'],
       type: 'action',
       style: 'button',
       show: 'horizontal',
diff --git a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
index 41f60cc..fb9af54 100644
--- a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -160,6 +160,8 @@
     if (_opentype === 'innerpage') {         // 鏂伴〉闈紝鍙�夋ā鏉�(鑷畾涔夋椂锛屽彲濉叆澶栭儴閾炬帴)
       if (_pageTemplate === 'custom') {
         _options.push('url', 'joint')
+      } else if (_pageTemplate === 'billprint') {
+        _options.push('printTemp')
       }
     } else if (_opentype === 'blank' || _opentype === 'tab') { // 鏂版爣绛炬垨褰撳墠椤甸潰鏇挎崲
       if (_tabTemplate === 'ThdMenu') {
@@ -355,13 +357,8 @@
         this.props.form.setFieldsValue(_fieldval)
       })
     } else if (key === 'pageTemplate') {
-      let _options = null
+      let _options = this.getOptions('innerpage', this.state.interType, this.state.funcType, value, card.tabTemplate)
       let _fieldval = {}
-      if (value === 'custom') {
-        _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'url', 'joint', 'icon', 'class', 'position']
-      } else {
-        _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position']
-      }
 
       this.setState({
         openType: value,
diff --git a/src/templates/sharecomponent/actioncomponent/index.jsx b/src/templates/sharecomponent/actioncomponent/index.jsx
index 1c9d9bc..9d03aa8 100644
--- a/src/templates/sharecomponent/actioncomponent/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/index.jsx
@@ -43,6 +43,7 @@
     actionlist: null,    // 鎸夐挳缁�
     copying: false,      // 鎸夐挳澶嶅埗涓�
     visible: false,      // 妯℃�佹鎺у埗
+    printTemps: [],      // 鍗曟嵁鎵撳嵃妯℃澘
     profVisible: false   // 楠岃瘉淇℃伅妯℃�佹
   }
 
@@ -67,6 +68,54 @@
     } else if (!is(fromJS(nextProps.config.action), fromJS(this.props.config.action)) && !is(fromJS(nextProps.config.action), fromJS(actionlist))) {
       this.setState({actionlist: fromJS(nextProps.config.action).toJS()})
     }
+  }
+
+  componentDidMount () {
+    this.getBillPrintTemp()
+  }
+
+  getBillPrintTemp = () => {
+    let _sql = `select PrintTempNO,Images,PrintTempNO+PrintTempName as PN from sPrintTemplate 
+    where appkey= @appkey@ and Deleted=0  and typechartwo='web_print'
+    union select ID,Images,a.PrintTempNO+PrintTempName as PN 
+    from (select * from sPrintTemplate where appkey= '' and Deleted=0  and typechartwo='web_print') a 
+    left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@  and Deleted=0 ) b 
+    on a.PrintTempNO=b.PrintTempNO 
+    left join (select Srcid from sPrintTemplate_Log where appkey='' and apicode= @appkey@ and Deleted=0 ) c 
+    on a.ID=c.Srcid where b.PrintTempNO is null and c.Srcid is null`
+
+    let param = {
+      func: 'sPC_Get_SelectedList',
+      LText: Utils.formatOptions(_sql),
+      obj_name: 'data',
+      arr_field: 'PN,PrintTempNO,Images'
+    }
+
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 浜戠鏁版嵁楠岃瘉
+
+    Api.getSystemConfig(param).then(res => {
+      if (res.status) {
+        let temps = res.data.map(temp => {
+          return {
+            value: temp.PrintTempNO,
+            text: temp.PN
+          }
+        })
+
+        this.setState({
+          printTemps: temps
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+      }
+    })
   }
 
   /**
@@ -154,14 +203,14 @@
         this.setState({
           visible: true,
           card: card,
-          formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist)
+          formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist, this.state.printTemps)
         })
       })
     } else {
       this.setState({
         visible: true,
         card: card,
-        formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist)
+        formlist: getActionForm(card, functip, this.props.config, this.props.usefulFields, this.props.type, menulist, this.state.printTemps)
       })
     }
   }
@@ -400,7 +449,7 @@
             Align: 'center',
             IsSort: 'false',
             uuid: Utils.getuuid(),
-            label: this.state.dict['model.form.column.action'],
+            label: this.state.dict['model.operation'],
             type: 'action',
             style: 'button',
             show: 'horizontal',
@@ -621,7 +670,7 @@
             Align: 'center',
             IsSort: 'false',
             uuid: Utils.getuuid(),
-            label: this.state.dict['model.form.column.action'],
+            label: this.state.dict['model.operation'],
             type: 'action',
             style: 'button',
             show: 'horizontal',
diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
index ecbed5d..006c55d 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -47,10 +47,10 @@
 
   componentDidMount() {
     let _sql = `select PrintTempNO,Images,PrintTempNO+PrintTempName as PN from sPrintTemplate 
-    where appkey= @appkey@ and Deleted=0 
+    where appkey= @appkey@ and Deleted=0  and typechartwo=''
     union select ID,Images,a.PrintTempNO+PrintTempName as PN 
-    from (select * from sPrintTemplate where appkey= '' and Deleted=0 ) a 
-    left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@ and Deleted=0 ) b 
+    from (select * from sPrintTemplate where appkey= '' and Deleted=0  and typechartwo='') a 
+    left join (select PrintTempNO from sPrintTemplate where appkey= @appkey@  and Deleted=0 ) b 
     on a.PrintTempNO=b.PrintTempNO 
     left join (select Srcid from sPrintTemplate_Log where appkey='' and apicode= @appkey@ and Deleted=0 ) c 
     on a.ID=c.Srcid where b.PrintTempNO is null and c.Srcid is null`
diff --git a/src/templates/sharecomponent/fieldscomponent/index.jsx b/src/templates/sharecomponent/fieldscomponent/index.jsx
index b138d3c..2aefd5c 100644
--- a/src/templates/sharecomponent/fieldscomponent/index.jsx
+++ b/src/templates/sharecomponent/fieldscomponent/index.jsx
@@ -145,11 +145,6 @@
             resourceType: '0',
             setAll: 'false',
             options: [],
-            dataSource: '',
-            linkField: '',
-            valueField: '',
-            valueText: '',
-            orderBy: '',
             orderType: 'asc',
             match: _match,
             display: 'dropdown'
@@ -276,18 +271,9 @@
     const { type } = this.props
     const { dict, fields } = this.state
 
-    let label = ''
-    if (type === 'search') {
-      label = dict['header.menu.search.add']
-    } else if (type === 'columns') {
-      label = dict['model.menu.column.add']
-    } else if (type === 'fields') {
-      label = dict['model.menu.field.add']
-    }
-
     return (
       <div className="quickly-add">
-        <Button type="primary" block onClick={this.queryField}>{label}</Button>
+        <Button type="primary" block onClick={this.queryField}>{dict['model.batchAdd']}</Button>
         {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */}
         <Modal
           wrapClassName="model-table-fieldmanage-modal"
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx b/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx
index 03249cb..2cc9b20 100644
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx
+++ b/src/templates/sharecomponent/settingcalcomponent/verifycard/index.jsx
@@ -366,7 +366,12 @@
               pagination={false}
             />
           </TabPane>
-          <TabPane tab="鑷畾涔夎剼鏈�" key="scripts">
+          <TabPane tab={
+            <span>
+              鑷畾涔夎剼鏈�
+              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
+            </span>
+          } key="scripts">
             <CustomScript
               dict={this.props.dict}
               setting={setting}
diff --git a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss b/src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss
index 3847eb4..1722c65 100644
--- a/src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss
+++ b/src/templates/sharecomponent/settingcalcomponent/verifycard/index.scss
@@ -6,6 +6,12 @@
     z-index: 1;
   }
   .verify-card-box {
+    .count-tip {
+      position: absolute;
+      top: 0px;
+      color: #1890ff;
+      font-size: 12px;
+    }
     .ant-tabs-nav-scroll {
       text-align: center;
     }
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
index 73fff8f..629c8db 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
@@ -395,7 +395,12 @@
               wrappedComponentRef={(inst) => this.settingForm = inst}
             />
           </TabPane>
-          <TabPane tab="鑷畾涔夎剼鏈�" key="scripts">
+          <TabPane tab={
+            <span>
+              鑷畾涔夎剼鏈�
+              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
+            </span>
+          } key="scripts">
             <CustomScript
               dict={dict}
               setting={setting}
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/index.scss b/src/templates/sharecomponent/settingcomponent/settingform/index.scss
index 65b7791..0be7ab4 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/index.scss
+++ b/src/templates/sharecomponent/settingcomponent/settingform/index.scss
@@ -6,6 +6,12 @@
     top: 150px;
     left: calc(50% - 16px);
   }
+  .count-tip {
+    position: absolute;
+    top: 0px;
+    color: #1890ff;
+    font-size: 12px;
+  }
   .model-table-setting-form {
     .textarea {
       .ant-form-item-label {
diff --git a/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx b/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
index 0de743e..badfe77 100644
--- a/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
+++ b/src/templates/sharecomponent/treesettingcomponent/settingform/index.jsx
@@ -248,7 +248,12 @@
               wrappedComponentRef={(inst) => this.settingForm = inst}
             />
           </TabPane>
-          <TabPane tab="鑷畾涔夎剼鏈�" key="scripts">
+          <TabPane tab={
+            <span>
+              鑷畾涔夎剼鏈�
+              {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
+            </span>
+          } key="scripts">
             <CustomScript
               dict={this.props.dict}
               setting={setting}
diff --git a/src/templates/sharecomponent/treesettingcomponent/settingform/index.scss b/src/templates/sharecomponent/treesettingcomponent/settingform/index.scss
index a129595..e8742ec 100644
--- a/src/templates/sharecomponent/treesettingcomponent/settingform/index.scss
+++ b/src/templates/sharecomponent/treesettingcomponent/settingform/index.scss
@@ -16,6 +16,12 @@
       margin-right: 3px;
     }
   }
+  .count-tip {
+    position: absolute;
+    top: 0px;
+    color: #1890ff;
+    font-size: 12px;
+  }
   .operation-btn {
     display: inline-block;
     font-size: 16px;
diff --git a/src/templates/subtableconfig/source.jsx b/src/templates/subtableconfig/source.jsx
index 85e2405..e71cdb6 100644
--- a/src/templates/subtableconfig/source.jsx
+++ b/src/templates/subtableconfig/source.jsx
@@ -164,7 +164,7 @@
       Align: 'center',
       IsSort: 'false',
       uuid: Utils.getuuid(),
-      label: CommonDict['model.form.column.action'],
+      label: CommonDict['model.operation'],
       type: 'action',
       style: 'button',
       show: 'horizontal',
diff --git a/src/templates/zshare/editTable/index.jsx b/src/templates/zshare/editTable/index.jsx
new file mode 100644
index 0000000..d67614e
--- /dev/null
+++ b/src/templates/zshare/editTable/index.jsx
@@ -0,0 +1,257 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Table, Input, InputNumber, Popconfirm, Form, Icon, Select } from 'antd'
+
+import ColorSketch from '@/mob/colorsketch'
+// import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import './index.scss'
+
+const EditableContext = React.createContext()
+
+class EditableCell extends Component {
+  getInput = (form) => {
+    const { inputType, options } = this.props
+
+    if (inputType === 'number') {
+      return <InputNumber min={12} max={50} precision={0} onPressEnter={() => this.getValue(form)} />
+    } else if (inputType === 'color') {
+      return <ColorSketch />
+    } else if (inputType === 'select') {
+      return <Select>
+        {options.map((item, i) => (<Select.Option key={i} value={item.field || item.value}> {item.label || item.text} </Select.Option>))}
+      </Select>
+    } else {
+      return <Input onPressEnter={() => this.getValue(form)} />
+    }
+  }
+
+  getValue = (form) => {
+    const { record } = this.props
+    form.validateFields((error, row) => {
+      if (error) {
+        return
+      }
+      this.props.onSave({...record, ...row})
+    })
+  }
+
+  renderCell = (form) => {
+    const { getFieldDecorator } = form
+    const { editing, dataIndex, title, record, children, className, required } = this.props
+
+    return (
+      <td className={className}>
+        {editing ? (
+          <Form.Item style={{ margin: 0 }}>
+            {getFieldDecorator(dataIndex, {
+              rules: [
+                {
+                  required: required,
+                  message: `Please Input ${title}!`,
+                }
+              ],
+              initialValue: record[dataIndex],
+            })(this.getInput(form))}
+          </Form.Item>
+        ) : (
+          children
+        )}
+      </td>
+    )
+  }
+
+  render() {
+    return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
+  }
+}
+
+class EditTable extends Component {
+  static propTpyes = {
+    onChange: PropTypes.func        // 鏁版嵁鍙樺寲
+  }
+
+  state = {
+    data: [],
+    editingKey: '',
+    columns: []
+  }
+
+  UNSAFE_componentWillMount () {
+    const { data } = this.props
+    let columns = fromJS(this.props.columns).toJS()
+    let dict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
+
+    columns.push({
+      title: dict['model.operation'],
+      dataIndex: 'operation',
+      width: '140px',
+      render: (text, record) => {
+        const { editingKey } = this.state
+        const editable = this.isEditing(record)
+        return editable ? (
+          <span>
+            <EditableContext.Consumer>
+              {form => (
+                <span onClick={() => this.save(form, record.uuid)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
+                  {dict['model.save']}
+                </span>
+              )}
+            </EditableContext.Consumer>
+            <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>{dict['model.cancel']}</span>
+          </span>
+        ) : (
+          <div className={'operation-btn' + (editingKey !== '' ? ' disabled' : '')}>
+            <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><Icon type="edit" /></span>
+            <span className="primary" onClick={() => {editingKey === '' && this.handleUpDown(record.uuid, 'up')}}><Icon type="arrow-up" /></span>
+            <span className="danger" onClick={() => {editingKey === '' && this.handleUpDown(record.uuid, 'down')}}><Icon type="arrow-down" /></span>
+            {editingKey === '' ? <Popconfirm
+              overlayClassName="popover-confirm"
+              title={dict['model.query.delete']}
+              onConfirm={() => this.handleDelete(record.uuid)
+            }>
+              <span className="danger"><Icon type="delete" /></span>
+            </Popconfirm> : null}
+            {editingKey !== '' ? <span className="danger"><Icon type="delete" /></span> : null}
+          </div>
+        )
+      }
+    })
+
+    this.setState({
+      data: data || [],
+      columns,
+      dict
+    })
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    if (!is(fromJS(this.state.data), fromJS(nextProps.data))) {
+      this.setState({data: nextProps.data, editingKey: ''})
+    }
+  }
+
+  isEditing = record => record.uuid === this.state.editingKey
+
+  cancel = () => {
+    this.setState({ editingKey: '' })
+  }
+
+  onSave = (record) => {
+    const newData = [...this.state.data]
+    const index = newData.findIndex(item => record.uuid === item.uuid)
+
+    if (index === -1) return
+
+    newData.splice(index, 1, record)
+    this.setState({ data: newData, editingKey: '' }, () => {
+      this.props.onChange(newData)
+    })
+  }
+
+  handleDelete = (uuid) => {
+    const { data } = this.state
+    let _data = data.filter(item => uuid !== item.uuid)
+
+    this.setState({
+      data: _data
+    }, () => {
+      this.props.onChange(_data)
+    })
+  }
+
+  handleUpDown = (uuid, direction) => {
+    let _data = fromJS(this.state.data).toJS()
+    const index = _data.findIndex(item => uuid === item.uuid)
+
+    if ((index === 0 && direction === 'up') || (index === _data.length - 1 && direction === 'down')) {
+      return
+    }
+
+    if (direction === 'up') {
+      _data.splice(index - 1, 0, ..._data.splice(index, 1))
+    } else {
+      _data.splice(index + 1, 0, ..._data.splice(index, 1))
+    }
+
+    this.setState({
+      data: _data
+    }, () => {
+      this.props.onChange(_data)
+    })
+  }
+
+  save(form, uuid) {
+    form.validateFields((error, row) => {
+      if (error) {
+        return;
+      }
+      const newData = [...this.state.data]
+      const index = newData.findIndex(item => uuid === item.uuid)
+      if (index > -1) {
+        const item = newData[index]
+        newData.splice(index, 1, {
+          ...item,
+          ...row,
+        })
+        this.setState({ data: newData, editingKey: '' }, () => {
+          this.props.onChange(newData)
+        })
+      } else {
+        newData.push(row);
+        this.setState({ data: newData, editingKey: '' }, () => {
+          this.props.onChange(newData)
+        })
+      }
+    })
+  }
+
+  edit(uuid) {
+    this.setState({ editingKey: uuid })
+  }
+
+  render() {
+    const components = {
+      body: {
+        cell: EditableCell,
+      }
+    }
+    
+    const columns = this.state.columns.map(col => {
+      if (!col.editable) return col
+      return {
+        ...col,
+        onCell: record => ({
+          record,
+          inputType: col.inputType,
+          dataIndex: col.dataIndex,
+          options: col.options || [],
+          required: col.required !== false ? true : false,
+          title: col.title,
+          editing: this.isEditing(record),
+          onSave: this.onSave,
+        }),
+      }
+    })
+
+    return (
+      <EditableContext.Provider value={this.props.form}>
+        <div className="modal-edit-table">
+          <Table
+            bordered
+            rowKey="uuid"
+            components={components}
+            dataSource={this.state.data}
+            columns={columns}
+            rowClassName="editable-row"
+            pagination={false}
+          />
+        </div>
+      </EditableContext.Provider>
+    )
+  }
+}
+
+export default Form.create()(EditTable)
\ No newline at end of file
diff --git a/src/templates/zshare/editTable/index.scss b/src/templates/zshare/editTable/index.scss
new file mode 100644
index 0000000..0db6245
--- /dev/null
+++ b/src/templates/zshare/editTable/index.scss
@@ -0,0 +1,47 @@
+.modal-edit-table {
+  .editable-row {
+    .ant-form-explain {
+      position: absolute;
+      font-size: 12px;
+      margin-top: -4px;
+    }
+    .color-sketch-block {
+      width: 200px;
+      position: relative;
+      top: 8px;
+    }
+    .ant-select {
+      width: 100%;
+    }
+    > td {
+      padding: 16px 10px;
+    }
+  }
+  .operation-btn {
+    span {
+      margin-right: 10px;
+      cursor: pointer;
+    }
+    .primary {
+      color: #1890ff;
+    }
+    .danger {
+      color: #ff4d4f;
+    }
+  }
+  .operation-btn.disabled {
+    cursor: default;
+    span {
+      cursor: default;
+    }
+    .primary {
+      color: rgba(0, 0, 0, .25);
+    }
+    .danger {
+      color: rgba(0, 0, 0, .25);
+    }
+  }
+  .ant-empty {
+    margin: 0;
+  }
+}
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index 6c39520..824e11a 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -592,7 +592,7 @@
  * @param {*} permFuncField  瀛樺偍杩囩▼鍙敤鐨勫紑濮嬪瓧娈�
  * @param {*} type           鎸夐挳绫诲瀷锛岀敤浜庡尯鍒嗗彲閫夌殑鎵撳紑鏂瑰紡
  */
-export function getActionForm (card, functip, config, permFuncField, type, menulist = []) {
+export function getActionForm (card, functip, config, permFuncField, type, menulist = [], printTemps = []) {
   let opentypes = [
     {
       value: 'pop',
@@ -764,8 +764,14 @@
       initVal: card.pageTemplate || '',
       required: true,
       options: [{
-        value: 'print',
-        text: Formdict['header.menu.printTemplate']
+      //   value: 'print',
+      //   text: '鏍囩鎵撳嵃妯℃澘'
+      // }, {
+      //   value: 'billprintTemp',
+      //   text: '鍗曟嵁鎵撳嵃妯℃澘'
+      // }, {
+        value: 'billprint',
+        text: '鍗曟嵁鎵撳嵃'
       }, {
         value: 'pay',
         text: Formdict['model.pay']
@@ -775,6 +781,14 @@
       }]
     },
     {
+      type: 'select',
+      key: 'printTemp',
+      label: '鎵撳嵃妯℃澘',
+      initVal: card.printTemp || '',
+      required: true,
+      options: printTemps
+    },
+    {
       type: 'text',
       key: 'url',
       label: Formdict['model.form.newpage.url'],
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index 427775d..a1c1109 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -643,8 +643,9 @@
       if (card.sqlType === 'insert' || card.sqlType === 'insertOrUpdate') {
         let keys = []
         let values = []
+
         _fields.forEach(item => {
-          if (!item.field) return
+          if (!item.field || item.writein === 'false') return
 
           keys.push(item.field.toLowerCase())
 
@@ -686,7 +687,7 @@
         let _arr = []
 
         _fields.forEach(item => {
-          if (!item.field) return
+          if (!item.field || item.writein === 'false') return
 
           _arr.push(item.field.toLowerCase())
           _form.push(item.field + '=@' + item.field)
diff --git a/src/views/billprint/index.jsx b/src/views/billprint/index.jsx
new file mode 100644
index 0000000..b52d34e
--- /dev/null
+++ b/src/views/billprint/index.jsx
@@ -0,0 +1,345 @@
+import React, { Component } from 'react'
+import { DndProvider } from 'react-dnd'
+import { is, fromJS } from 'immutable'
+import HTML5Backend from 'react-dnd-html5-backend'
+import { ConfigProvider, notification, Collapse, Card, Switch, Button } from 'antd'
+
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/mob.js'
+import enUS from '@/locales/en-US/mob.js'
+import antdEnUS from 'antd/es/locale/en_US'
+import antdZhCN from 'antd/es/locale/zh_CN'
+import asyncComponent from '@/utils/asyncComponent'
+
+import './index.scss'
+
+const { Panel } = Collapse
+const _locale = localStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS
+
+const Header = asyncComponent(() => import('@/menu/header'))
+const MenuForm = asyncComponent(() => import('@/menu/menuform'))
+const SourceWrap = asyncComponent(() => import('@/menu/modelsource'))
+const MenuShell = asyncComponent(() => import('@/menu/menushell'))
+const BgController = asyncComponent(() => import('@/menu/bgcontroller'))
+const PaddingController = asyncComponent(() => import('@/menu/padcontroller'))
+const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
+const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller'))
+const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
+
+class BillPrint extends Component {
+  state = {
+    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    BID: '',
+    tempId: '',
+    config: null,
+  }
+
+  UNSAFE_componentWillMount() {
+    try {
+      let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
+
+      this.setState({
+        BID: param.id,
+        tempId: param.tempId,
+      }, () => {
+        this.getMenuParam()
+      })
+    } catch {
+      notification.warning({
+        top: 92,
+        message: '鑿滃崟淇℃伅瑙f瀽閿欒锛�',
+        duration: 5
+      })
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+
+  getMenuParam = () => {
+    const { tempId } = this.state
+
+    let param = {
+      func: 's_PrintTemplateMGetData',
+      Type: 'Y',
+      PrintTempNO: tempId
+    }
+
+    if (window.GLOB.mainSystemApi) { // 浠庡崟鐐圭櫥褰曟湇鍔″櫒鍙栨墦鍗伴厤缃俊鎭�
+      param.rduri = window.GLOB.mainSystemApi
+    }
+
+    Api.getLocalConfig(param).then(result => {
+      if (result.status) {
+        // let config = null
+
+        // try {
+        //   config = JSON.parse(window.decodeURIComponent(window.atob(result.ConfigParam)))
+        // } catch (e) {
+        //   console.warn('Parse Failure')
+        //   config = null
+        // }
+      } else {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+      }
+    })
+
+    // Api.getSystemConfig(param).then(result => {
+    //   if (result.status) {
+    //     let config = null
+
+    //     try {
+    //       config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
+    //     } catch (e) {
+    //       console.warn('Parse Failure')
+    //       config = null
+    //     }
+
+    //     if (!config) {
+    //       config = {
+    //         version: 1.0,
+    //         uuid: MenuId,
+    //         MenuID: MenuId,
+    //         parentId: ParentId,
+    //         Template: 'CustomPage',
+    //         MenuType: MenuType,
+    //         easyCode: '',
+    //         enabled: false,
+    //         MenuName: MenuName,
+    //         MenuNo: MenuNo,
+    //         tables: [],
+    //         components: [],
+    //         style: {
+    //           backgroundColor: '#ffffff', backgroundImage: '',
+    //           paddingTop: '16px', paddingBottom: '80px', paddingLeft: '16px', paddingRight: '16px'
+    //         }
+    //       }
+    //     } else {
+    //       config.uuid = MenuId
+    //       config.MenuID = MenuId
+    //       config.MenuType = config.MenuType || MenuType
+    //     }
+
+    //     if (MenuType === 'billPrint') {
+    //       config.FstID = 'BillPrintTemp'
+    //       config.SndID = 'BillPrintTemp'
+    //       config.ParentID = 'BillPrintTemp'
+    //     }
+
+    //     this.setState({
+    //       oriConfig: config,
+    //       config: fromJS(config).toJS(),
+    //       openEdition: result.open_edition || '',
+    //     })
+
+    //     this.getRoleFields()
+    //   } else {
+    //     notification.warning({
+    //       top: 92,
+    //       message: result.message,
+    //       duration: 5
+    //     })
+    //   }
+    // })
+  }
+
+  getRoleFields = () => {
+    Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
+      if (res.status) {
+        let _permFuncField = []
+        let _sysRoles = []
+
+        if (res.Roles && res.Roles.length > 0) {
+          _sysRoles = res.Roles.map(role => {
+            return {
+              uuid: Utils.getuuid(),
+              value: role.RoleID,
+              text: role.RoleName
+            }
+          })
+        }
+
+        if (res.sModular && res.sModular.length > 0) {
+          res.sModular.forEach(field => {
+            if (field.ModularNo) {
+              _permFuncField.push(field.ModularNo)
+            }
+          })
+          _permFuncField = _permFuncField.sort()
+        }
+
+        let config = {...this.state.config, sysRoles: _sysRoles, permFuncField: _permFuncField}
+
+        this.setState({config})
+      }
+    })
+  }
+
+  initMenuList = (msg) => {
+    let config = {...this.state.config, ...msg}
+
+    this.setState({config})
+  }
+
+  onEnabledChange = () => {
+    const { config } = this.state
+
+    if (!config.enabled && this.verifyConfig(true)) {
+      return
+    }
+
+    this.setState({
+      config: {...config, enabled: !config.enabled}
+    })
+  }
+
+  verifyConfig = (show) => {
+    const { config } = this.state
+    let error = ''
+
+    if (!config.MenuID) {
+      notification.warning({
+        top: 92,
+        message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒',
+        duration: 5
+      })
+      return
+    } else if (config.MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
+      notification.warning({
+        top: 92,
+        message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒',
+        duration: 5
+      })
+      return
+    }
+
+    config.components.forEach(item => {
+      if (error) return
+      if (item.subtype === 'propcard' && item.wrap.datatype === 'static') return
+
+      if (item.setting) {
+        if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
+          error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒`
+        } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) {
+          error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆鏁版嵁婧愶紒`
+        } else if (item.setting.interType && !item.setting.primaryKey) {
+          error = `缁勪欢銆�${item.name}銆嬫湭璁剧疆涓婚敭锛乣
+        }
+      }
+      if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') {
+        if (!item.plot.Xaxis) {
+          error = `缁勪欢銆�${item.name}銆嬪浘琛ㄥ瓧娈靛皻鏈缃紒`
+        }
+      }
+    })
+
+    if (show && error) {
+      notification.warning({
+        top: 92,
+        message: error,
+        duration: 5
+      })
+    }
+
+    return error
+  }
+
+  // 鏇存柊閰嶇疆淇℃伅
+  updateConfig = (config) => {
+    this.setState({
+      config: config
+    })
+  }
+
+  /**
+   * @description 鏇存柊甯哥敤琛ㄤ俊鎭紝蹇嵎娣诲姞鍚庢洿鏂伴厤缃俊鎭�
+   */
+  updatetable = (config, fields) => {
+    const { tableFields } = this.state
+
+    config.tableFields = fields ? fields : tableFields
+
+    this.setState({
+      tableFields: fields ? fields : tableFields,
+      config
+    })
+  }
+
+  render () {
+    const { activeKey, MenuType, dict, MenuId, config, ParentId, MenuName, MenuNo, menuloading } = this.state
+
+    return (
+      <ConfigProvider locale={_locale}>
+        <div className="pc-menu-view" id="view">
+          <Header view="design" closeView={this.closeView} />
+          <DndProvider backend={HTML5Backend}>
+            <div className="menu-body">
+              <div className="menu-setting">
+                <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
+                  {/* 鍩烘湰淇℃伅 */}
+                  <Panel header={dict['mob.basemsg']} key="basedata">
+                    {/* 鑿滃崟淇℃伅 */}
+                    {config && MenuType === 'custom' ? <MenuForm
+                      dict={dict}
+                      config={config}
+                      MenuId={MenuId}
+                      parentId={ParentId}
+                      MenuName={MenuName}
+                      MenuNo={MenuNo}
+                      initMenuList={this.initMenuList}
+                      updateConfig={this.updateConfig}
+                    /> : null}
+                    {/* 琛ㄥ悕娣诲姞 */}
+                    {config ? <TableComponent config={config} updatetable={this.updatetable}/> : null}
+                  </Panel>
+                  {/* 缁勪欢娣诲姞 */}
+                  <Panel header={dict['mob.component']} key="component">
+                    <SourceWrap MenuType={MenuType} />
+                  </Panel>
+                  <Panel header={'鑳屾櫙'} key="background">
+                    {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
+                  </Panel>
+                  <Panel header={'鍐呰竟璺�'} key="padding">
+                    {config ? <PaddingController config={config} updateConfig={this.updateConfig} /> : null}
+                  </Panel>
+                </Collapse>
+              </div>
+              <div className={'menu-view ' + (menuloading ? 'saving' : '')}>
+                <Card title={
+                  <div> {config && config.MenuName} </div>
+                } bordered={false} extra={
+                  <div>
+                    {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null}
+                    <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button>
+                  </div>
+                } style={{ width: '100%' }}>
+                  {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
+                </Card>
+              </div>
+            </div>
+          </DndProvider>
+          <StyleController />
+          <ModalController />
+        </div>
+      </ConfigProvider>
+    )
+  }
+}
+
+export default BillPrint
\ No newline at end of file
diff --git a/src/views/billprint/index.scss b/src/views/billprint/index.scss
new file mode 100644
index 0000000..fa70742
--- /dev/null
+++ b/src/views/billprint/index.scss
@@ -0,0 +1,160 @@
+.pc-menu-view {
+  background: #000;
+  min-height: 100vh;
+  .menu-body {
+    width: 100vw;
+    height: 100vh;
+    overflow-x: hidden;
+    position: relative;
+    background: #ffffff;
+    padding: 50px 0px 0px 0px;
+
+    
+    .menu-setting {
+      position: fixed;
+      left: 0;
+      top: 48px;
+      z-index: 10;
+      height: calc(100vh - 48px);
+      width: 300px;
+      background: #ffffff;
+      box-shadow: 0px 2px 5px #bcbcbc;
+      overflow-y: auto;
+
+      > .ant-collapse {
+        .ant-collapse-item.ant-collapse-item-active {
+          border-bottom: 1px solid #d9d9d9;
+        }
+        .ant-collapse-header {
+          padding: 11px 16px 10px 40px;
+          border-bottom: 1px solid #d9d9d9;
+          background: #1890ff;
+          color: #ffffff;
+        }
+        .ant-collapse-content-box {
+          .ant-form-item {
+            margin-bottom: 10px;
+          }
+          .model-table-tablemanage-view {
+            >.ant-list {
+              margin-top: 20px;
+              .ant-list-item {
+                display: -webkit-box;
+                padding-right: 20px;
+                position: relative;
+                padding-left: 5px;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                -webkit-line-clamp: 2;
+                -webkit-box-orient: vertical;
+                min-height: 55px;
+                width: 100%;
+                .anticon {
+                  position: absolute;
+                  top: 0px;
+                  right: 0px;
+                  padding: 3px 3px 10px 10px;
+                  cursor: pointer;
+                }
+              }
+            }
+            >.tables {
+              width: 66.66666667%!important;
+            }
+            >.ant-form-item-label {
+              width: 33.33333333%;
+            }
+          }
+        }
+      }
+
+      >.ant-tabs {
+        >.ant-tabs-bar {
+          border-bottom: 1px solid #181F29;
+          margin-bottom: 0px;
+          min-height: 48px;
+          .ant-tabs-tab {
+            padding: 14px 16px;
+            color: rgba(255, 255, 255, 0.85);
+          }
+          .ant-tabs-tab-active.ant-tabs-tab {
+            color: #1890ff;
+          }
+        }
+      }
+    }
+    .menu-setting::-webkit-scrollbar {
+      width: 4px;
+    }
+    .menu-setting::-webkit-scrollbar-thumb {
+      border-radius: 5px;
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
+      background: rgba(0, 0, 0, 0.08);
+    }
+    .menu-setting::-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);
+    }
+
+    .menu-view {
+      position: relative;
+      width: calc(100vw - 300px);
+      margin-left: 300px;
+      height: calc(100vh - 50px);
+      overflow-y: auto;
+
+      > .ant-card {
+        >.ant-card-head {
+          margin-bottom: 0px;
+          .ant-card-head-title {
+            color: #1890ff;
+            padding: 5px 0;
+          }
+          .ant-card-extra {
+            padding: 5px 0;
+            button {
+              margin-left: 20px;
+            }
+            .ant-switch.big {
+              min-width: 60px;
+              height: 28px;
+              line-height: 28px;
+              margin-top: -2px;
+              .ant-switch-inner {
+                font-size: 14px;
+              }
+            }
+            .ant-switch.big:after {
+              width: 24px;
+              height: 24px;
+            }
+          }
+        }
+        >.ant-card-body {
+          padding: 0px;
+        }
+      }
+    }
+    .menu-view.saving {
+      .anticon-tool {
+        display: none;
+      }
+    }
+    .menu-view::-webkit-scrollbar {
+      width: 7px;
+    }
+    .menu-view::-webkit-scrollbar-thumb {
+      border-radius: 5px;
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
+      background: rgba(0, 0, 0, 0.08);
+    }
+    .menu-view::-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);
+    }
+  }
+}
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
index 894a4a9..0312098 100644
--- a/src/views/menudesign/index.jsx
+++ b/src/views/menudesign/index.jsx
@@ -4,7 +4,8 @@
 import { is, fromJS } from 'immutable'
 import moment from 'moment'
 import HTML5Backend from 'react-dnd-html5-backend'
-import { ConfigProvider, notification, Modal, Collapse, Card, Icon, Switch, Button } from 'antd'
+import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button } from 'antd'
+import html2canvas from 'html2canvas'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -48,7 +49,6 @@
     oriConfig: null,
     openEdition: '',
     config: null,
-    editElem: null,
   }
 
   UNSAFE_componentWillMount() {
@@ -86,10 +86,6 @@
     }
   }
 
-  reloadTab = () => {
-    
-  }
-
   closeView = () => {
     const { oriConfig, config } = this.state
 
@@ -108,16 +104,16 @@
   }
 
   submitConfig = () => {
-    const { config, MenuType, openEdition } = this.state
+    const { config, openEdition } = this.state
 
-    if (!config.MenuID) {
+    if (config.MenuType === 'billPrint' && (!config.MenuName || !config.MenuNo)) {
       notification.warning({
         top: 92,
-        message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒',
+        message: '璇峰畬鍠勫熀鏈俊鎭紒',
         duration: 5
       })
       return
-    } else if (MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
+    } else if (config.MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
       notification.warning({
         top: 92,
         message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒',
@@ -137,17 +133,19 @@
     delete _config.tableFields
 
     let funcs = []
-    _config.components.forEach(component => {
-      if (component.setting && component.setting.innerFunc) {
-        funcs.push(`select '${_config.uuid}' as MenuID,'${component.setting.innerFunc}' as ProcName,'${component.setting.name}' as MenuName`)
-      }
-      if (component.action) {
-        component.action.forEach(item => {
-          if (!item.innerFunc) return
-          funcs.push(`select '${_config.uuid}' as MenuID,'${item.innerFunc}' as ProcName,'${item.label}' as MenuName`)
-        })
-      }
-    })
+    if (config.MenuType !== 'billPrint') {
+      _config.components.forEach(component => {
+        if (component.setting && component.setting.innerFunc) {
+          funcs.push(`select '${_config.uuid}' as MenuID,'${component.setting.innerFunc}' as ProcName,'${component.setting.name}' as MenuName`)
+        }
+        if (component.action) {
+          component.action.forEach(item => {
+            if (!item.innerFunc) return
+            funcs.push(`select '${_config.uuid}' as MenuID,'${item.innerFunc}' as ProcName,'${item.label}' as MenuName`)
+          })
+        }
+      })
+    }
 
     let param = {
       func: 'sPC_TrdMenu_AddUpt',
@@ -155,10 +153,10 @@
       SndID: _config.parentId,
       ParentID: _config.parentId,
       MenuID: _config.uuid,
-      MenuNo: _config.MenuNo,
-      EasyCode: _config.easyCode,
+      MenuNo: _config.MenuNo || '',
+      EasyCode: _config.easyCode || '',
       Template: 'CustomPage',
-      MenuName: _config.MenuName,
+      MenuName: _config.MenuName || '',
       PageParam: JSON.stringify({Template: 'CustomPage', OpenType: 'newtab'}),
       LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_config))),
       LText: funcs.join(' union all '),
@@ -175,51 +173,123 @@
 
     this.setState({
       menuloading: true
+    }, () => {
+      new Promise(resolve => {
+        if (config.MenuType === 'billPrint') {
+          html2canvas(document.getElementById('menu-shell-inner')).then(canvas => {
+            let img = canvas.toDataURL('image/png') // 鑾峰彇鐢熸垚鐨勫浘鐗�
+            Api.fileuploadbase64(img, 'cloud').then(result => {
+              if (result.status) {
+                Api.getSystemConfig({
+                  func: 's_PrintTemplateMSub',
+                  ID: _config.uuid,
+                  Images: Utils.getcloudurl(result.Images),
+                  Remark: '',
+                  temp_type: 'billprint',
+                }).then(response => {
+                  if (response.status) {
+                    resolve(true)
+                  } else {
+                    notification.warning({
+                      top: 92,
+                      message: response.message,
+                      duration: 5
+                    })
+                    this.setState({
+                      menuloading: false
+                    })
+                    resolve(false)
+                  }
+                })
+              } else {
+                notification.warning({
+                  top: 92,
+                  message: result.ErrMesg,
+                  duration: 5
+                })
+                this.setState({
+                  menuloading: false
+                })
+                resolve(false)
+              }
+            })
+          })
+        } else {
+          resolve(true)
+        }
+      }).then(res => {
+        if (!res) return
+
+        Api.getSystemConfig(param).then(response => {
+          if (response.status) {
+            this.setState({
+              oriConfig: fromJS(config).toJS(),
+              openEdition: response.open_edition || '',
+              menuloading: false
+            })
+            notification.success({
+              top: 92,
+              message: '淇濆瓨鎴愬姛',
+              duration: 2
+            })
+          } else {
+            this.setState({
+              openEdition: response.open_edition || '',
+              menuloading: false
+            })
+            notification.warning({
+              top: 92,
+              message: response.message,
+              duration: 5
+            })
+          }
+        })
+      })
     })
 
-    Api.getSystemConfig(param).then(response => {
-      if (response.status) {
-        this.setState({
-          oriConfig: fromJS(config).toJS(),
-          openEdition: response.open_edition || '',
-          menuloading: false
-        })
-        notification.success({
-          top: 92,
-          message: '淇濆瓨鎴愬姛',
-          duration: 2
-        })
-      } else {
-        this.setState({
-          openEdition: response.open_edition || '',
-          menuloading: false
-        })
-        notification.warning({
-          top: 92,
-          message: response.message,
-          duration: 5
-        })
-      }
-    })
+    // Api.getSystemConfig(param).then(response => {
+    //   if (response.status) {
+    //     this.setState({
+    //       oriConfig: fromJS(config).toJS(),
+    //       openEdition: response.open_edition || '',
+    //       menuloading: false
+    //     })
+    //     notification.success({
+    //       top: 92,
+    //       message: '淇濆瓨鎴愬姛',
+    //       duration: 2
+    //     })
+    //   } else {
+    //     this.setState({
+    //       openEdition: response.open_edition || '',
+    //       menuloading: false
+    //     })
+    //     notification.warning({
+    //       top: 92,
+    //       message: response.message,
+    //       duration: 5
+    //     })
+    //   }
+    // })
   }
 
   getMenuParam = () => {
-    const { MenuId, ParentId, MenuName, MenuNo } = this.state
-    
-    Api.getSystemConfig({
+    const { MenuId, ParentId, MenuName, MenuNo, MenuType } = this.state
+
+    let param = {
       func: 'sPC_Get_LongParam',
       MenuID: MenuId
-    }).then(result => {
+    }
+
+    Api.getSystemConfig(param).then(result => {
       if (result.status) {
         let config = null
 
-        if (result.LongParam) {
-          try {
-            config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
-          } catch (e) {
-            console.warn('Parse Failure')
-            config = null
-          }
+        try {
+          config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
+        } catch (e) {
+          console.warn('Parse Failure')
+          config = null
         }
 
         if (!config) {
@@ -229,6 +299,7 @@
             MenuID: MenuId,
             parentId: ParentId,
             Template: 'CustomPage',
+            MenuType: MenuType,
             easyCode: '',
             enabled: false,
             MenuName: MenuName,
@@ -243,6 +314,13 @@
         } else {
           config.uuid = MenuId
           config.MenuID = MenuId
+          config.MenuType = config.MenuType || MenuType
+        }
+
+        if (MenuType === 'billPrint') {
+          config.FstID = 'BillPrintTemp'
+          config.SndID = 'BillPrintTemp'
+          config.ParentID = 'BillPrintTemp'
         }
 
         this.setState({
@@ -302,12 +380,6 @@
     this.props.modifyCustomMenu(config)
   }
 
-  editCard = (element) => {
-    this.setState({
-      editElem: element
-    })
-  }
-
   onEnabledChange = () => {
     const { config } = this.state
 
@@ -321,7 +393,7 @@
   }
 
   verifyConfig = (show) => {
-    const { config, MenuType } = this.state
+    const { config } = this.state
     let error = ''
 
     if (!config.MenuID) {
@@ -331,7 +403,7 @@
         duration: 5
       })
       return
-    } else if (MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
+    } else if (config.MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
       notification.warning({
         top: 92,
         message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒',
@@ -397,7 +469,7 @@
   }
 
   render () {
-    const { activeKey, MenuType, dict, MenuId, config, ParentId, MenuName, MenuNo } = this.state
+    const { activeKey, MenuType, dict, MenuId, config, ParentId, MenuName, MenuNo, menuloading } = this.state
 
     return (
       <ConfigProvider locale={_locale}>
@@ -410,7 +482,7 @@
                   {/* 鍩烘湰淇℃伅 */}
                   <Panel header={dict['mob.basemsg']} key="basedata">
                     {/* 鑿滃崟淇℃伅 */}
-                    {MenuType === 'custom' ? <MenuForm
+                    {config && MenuType === 'custom' ? <MenuForm
                       dict={dict}
                       config={config}
                       MenuId={MenuId}
@@ -425,7 +497,7 @@
                   </Panel>
                   {/* 缁勪欢娣诲姞 */}
                   <Panel header={dict['mob.component']} key="component">
-                    <SourceWrap />
+                    <SourceWrap MenuType={MenuType} />
                   </Panel>
                   <Panel header={'鑳屾櫙'} key="background">
                     {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
@@ -435,16 +507,13 @@
                   </Panel>
                 </Collapse>
               </div>
-              <div className="menu-view">
+              <div className={'menu-view ' + (menuloading ? 'saving' : '')}>
                 <Card title={
-                  <div>
-                    {config && config.MenuName} 
-                    <Icon type="redo" style={{marginLeft: '10px'}} title="鍒锋柊鏍囩鍒楄〃" onClick={() => this.reloadTab()} />
-                  </div>
+                  <div> {config && config.MenuName} </div>
                 } bordered={false} extra={
                   <div>
                     {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null}
-                    <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{dict['mob.save']}</Button>
+                    <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button>
                   </div>
                 } style={{ width: '100%' }}>
                   {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
diff --git a/src/views/menudesign/index.scss b/src/views/menudesign/index.scss
index 0ed352f..fa70742 100644
--- a/src/views/menudesign/index.scss
+++ b/src/views/menudesign/index.scss
@@ -137,6 +137,11 @@
         }
       }
     }
+    .menu-view.saving {
+      .anticon-tool {
+        display: none;
+      }
+    }
     .menu-view::-webkit-scrollbar {
       width: 7px;
     }

--
Gitblit v1.8.0