From 3683e1475e8d74f690172a468518d88d91a69ccc Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 20 八月 2020 20:15:48 +0800
Subject: [PATCH] 2020-08-20

---
 src/tabviews/treepage/index.jsx                        |    2 
 src/mob/header/index.jsx                               |    4 
 package-lock.json                                      |   21 
 src/components/header/index.jsx                        |    4 
 src/menu/menuform/index.jsx                            |  225 +++++++++
 src/tabviews/zshare/normalTable/index.jsx              |   39 
 src/assets/css/table.scss                              |    6 
 src/tabviews/calendar/index.jsx                        |    2 
 src/mob/components/login/mob-login-1/index.jsx         |   15 
 src/locales/zh-CN/model.js                             |    2 
 src/templates/sharecomponent/tablecomponent/index.jsx  |    2 
 src/api/index.js                                       |    2 
 src/templates/menuconfig/editthdmenu/index.jsx         |   44 +
 src/assets/img/custom.jpg                              |    0 
 src/tabviews/subtable/index.jsx                        |    2 
 src/tabviews/subtabtable/index.jsx                     |    2 
 src/tabviews/commontable/index.jsx                     |    2 
 src/menu/header/index.jsx                              |  121 +++++
 src/templates/treepageconfig/index.scss                |   20 
 src/views/mobdesign/index.jsx                          |    2 
 src/templates/formtabconfig/index.scss                 |   23 
 src/views/menudesign/index.jsx                         |  394 ++++++++++++++++
 src/utils/utils.js                                     |    6 
 src/index.js                                           |  109 ++-
 src/templates/modalconfig/index.scss                   |   23 
 src/locales/zh-CN/mob.js                               |   13 
 src/router/index.js                                    |    4 
 src/menu/header/index.scss                             |   94 +++
 src/templates/menuconfig/menuelement/card.jsx          |    5 
 src/templates/sharecomponent/tablecomponent/index.scss |    4 
 src/templates/subtableconfig/index.scss                |   21 
 src/menu/menuform/index.scss                           |    0 
 src/templates/comtableconfig/index.scss                |   20 
 src/views/menudesign/index.scss                        |  134 +++++
 package.json                                           |    1 
 src/components/sidemenu/index.jsx                      |    4 
 src/utils/option.js                                    |   10 
 src/locales/en-US/mob.js                               |   13 
 38 files changed, 1,214 insertions(+), 181 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 6cda097..cb186a0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3232,6 +3232,11 @@
         }
       }
     },
+    "base64-arraybuffer": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz",
+      "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ=="
+    },
     "base64-js": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
@@ -4337,6 +4342,14 @@
             "uniq": "^1.0.1"
           }
         }
+      }
+    },
+    "css-line-break": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-1.1.1.tgz",
+      "integrity": "sha512-1feNVaM4Fyzdj4mKPIQNL2n70MmuYzAXZ1aytlROFX1JsOo070OsugwGjj7nl6jnDJWHDM8zRZswkmeYVWZJQA==",
+      "requires": {
+        "base64-arraybuffer": "^0.2.0"
       }
     },
     "css-loader": {
@@ -8681,6 +8694,14 @@
         "util.promisify": "1.0.0"
       }
     },
+    "html2canvas": {
+      "version": "1.0.0-rc.7",
+      "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.0.0-rc.7.tgz",
+      "integrity": "sha512-yvPNZGejB2KOyKleZspjK/NruXVQuowu8NnV2HYG7gW7ytzl+umffbtUI62v2dCHQLDdsK6HIDtyJZ0W3neerA==",
+      "requires": {
+        "css-line-break": "1.1.1"
+      }
+    },
     "htmlparser2": {
       "version": "3.10.1",
       "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
diff --git a/package.json b/package.json
index 68fb54f..1106878 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
     "file-loader": "3.0.1",
     "fs-extra": "7.0.1",
     "html-webpack-plugin": "4.0.0-beta.5",
+    "html2canvas": "^1.0.0-rc.7",
     "http-proxy-middleware": "^0.20.0",
     "identity-obj-proxy": "3.0.0",
     "immutability-helper": "^3.0.1",
diff --git a/src/api/index.js b/src/api/index.js
index d3ebe24..ac8f0f2 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -660,7 +660,7 @@
           values += key + param[key]
         }
       })
-      param.sign  = md5(values)
+      param.sign = md5(values)
       param.t = new Date().getTime()
 
       return new Promise(resolve => {
diff --git a/src/assets/css/table.scss b/src/assets/css/table.scss
index 07d592b..4ba1965 100644
--- a/src/assets/css/table.scss
+++ b/src/assets/css/table.scss
@@ -411,6 +411,9 @@
   }
 
   // gray
+  .background.transparent {
+    @include tableBackground(transparent);
+  }
   .background.gray-1 {
     @include tableBackground(#f5f5f5);
   }
@@ -832,6 +835,9 @@
   }
 
   // gray
+  .font.transparent {
+    color: transparent;
+  }
   .font.gray-1 {
     color: #f5f5f5;
   }
diff --git a/src/assets/img/custom.jpg b/src/assets/img/custom.jpg
new file mode 100644
index 0000000..e88565c
--- /dev/null
+++ b/src/assets/img/custom.jpg
Binary files differ
diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index eb80ffe..502960c 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -744,9 +744,9 @@
         {this.props.editLevel === 'HS' ? <Button className="level4-close" type="primary" onClick={this.exitManage}>閫�鍑�</Button> : null}
         {/* 杩涘叆缂栬緫鎸夐挳 */}
         {this.props.editState && !this.props.editLevel ? <Icon onClick={this.enterEdit} className="edit-check" type="edit" /> : null}
-        {/* {this.props.editState && !this.props.editLevel && options.sysType === 'local' && window.GLOB.systemType !== 'production' ?
+        {this.props.editState && !this.props.editLevel && options.sysType === 'local' && window.GLOB.systemType !== 'production' ?
           <a href="#/mobmanage" target="_blank" className="mobile" type="edit"> 搴旂敤绠$悊 <Icon type="arrow-right" /></a> : null
-        } */}
+        }
         {/* 缂栬緫鑿滃崟 */}
         {this.props.editLevel === 'level1' ? <EditMenu menulist={this.state.menulist} reload={this.reload} exitEdit={this.exitEdit}/> : null}
         {/* 澶村儚銆佺敤鎴峰悕 */}
diff --git a/src/components/sidemenu/index.jsx b/src/components/sidemenu/index.jsx
index f84f3fa..2b4da50 100644
--- a/src/components/sidemenu/index.jsx
+++ b/src/components/sidemenu/index.jsx
@@ -109,7 +109,9 @@
 
         if (item.FunMenu) {
           _smenu.children = item.FunMenu.map(child => {
-            let _tmenu = {}
+            let _tmenu = {
+              ParentId: item.ParentID
+            }
 
             // 鎵撳紑鏂伴〉闈㈤摼鎺�
             _tmenu.src = '#/main/' + window.btoa('mm=' + menu.MenuID + '&sm=' + _smenu.MenuID + '&tm=' + child.MenuID + '&ud=' + msg)
diff --git a/src/index.js b/src/index.js
index d9926a8..ad4f31a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -53,35 +53,35 @@
   .then(config => {
     if (!config) return
     
-    window.GLOB = {}
-    window.GLOB.appId = config.appId || ''
-    window.GLOB.lineColor = config.lineColor || ''
-    window.GLOB.filter = config.filter || ''
+    let GLOB = {}
+    GLOB.appId = config.appId || ''
+    GLOB.lineColor = config.lineColor || ''
+    GLOB.filter = config.filter || ''
 
     // 鍙湁涓氬姟绯荤粺鎵嶅彲浠ヨ缃负姝e紡绯荤粺
     if (options.sysType === 'local' && (config.systemType === 'official' || config.systemType === 'production')) {
-      window.GLOB.systemType = 'production'
+      GLOB.systemType = 'production'
     } else {
-      window.GLOB.systemType = ''
+      GLOB.systemType = ''
     }
 
     if (options.sysType === 'cloud') { // cloud涓嶅彲璁剧疆鍗曠偣鏈嶅姟鍣ㄥ湴鍧�,浜戠appkey涓虹郴缁熻缃�
-      window.GLOB.appkey = options.cakey
-      window.GLOB.mainSystemApi = ''
+      GLOB.appkey = options.cakey
+      GLOB.mainSystemApi = ''
     } else if (options.sysType === 'SSO') { // sso涓嶅彲璁剧疆鍗曠偣鏈嶅姟鍣ㄥ湴鍧�
-      window.GLOB.mainSystemApi = ''
+      GLOB.mainSystemApi = ''
       if (config.appkey === options.cakey) {
-        window.GLOB.appkey = ''
+        GLOB.appkey = ''
         console.warn('鍗曠偣绯荤粺appkey涓嶅彲涓庝簯绔浉鍚�')
       } else {
-        window.GLOB.appkey = config.appkey
+        GLOB.appkey = config.appkey
       }
     } else if (options.sysType === 'local') { // 涓氬姟绯荤粺
       if (config.appkey === options.cakey) {
-        window.GLOB.appkey = ''
+        GLOB.appkey = ''
         console.warn('涓氬姟绯荤粺appkey涓嶅彲涓庝簯绔浉鍚�')
       } else {
-        window.GLOB.appkey = config.appkey
+        GLOB.appkey = config.appkey
       }
       if (config.mainSystemApi) {
         let systemApi = config.mainSystemApi
@@ -96,7 +96,7 @@
       
         // // 涓氬姟绯荤粺杩炴帴浜戠鏃讹紝鏍煎紡鍖栧鐞�
         // if (systemApi && systemApi === /^(http|https):\/\/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62}|(:[0-9]{1,4}))+\.?/ig.exec(options.cloudServiceApi)[0]) {
-        //   window.GLOB.dataFormat = true
+        //   GLOB.dataFormat = true
         // }
       
         // if (systemApi) {
@@ -107,10 +107,10 @@
         if (systemApi && systemApi.indexOf('cloud.mk9h.cn') > -1) {
           systemApi = ''
         } else if (systemApi && systemApi.indexOf('sso.mk9h.cn') > -1) {
-          window.GLOB.dataFormat = true
+          GLOB.dataFormat = true
         }
       
-        window.GLOB.mainSystemApi = systemApi
+        GLOB.mainSystemApi = systemApi
       }
     }
 
@@ -120,23 +120,23 @@
       try {
         _systemMsg = JSON.parse(window.decodeURIComponent(window.atob(_systemMsg)))
 
-        window.GLOB.platTitle = _systemMsg.platTitle
-        window.GLOB.platName = _systemMsg.platName
-        window.GLOB.favicon = _systemMsg.favicon
-        window.GLOB.loginlogo = _systemMsg.loginlogo
-        window.GLOB.copyRight = _systemMsg.copyRight
-        window.GLOB.ICP = _systemMsg.ICP
-        window.GLOB.bgImage = _systemMsg.bgImage
-        window.GLOB.mainlogo = _systemMsg.mainlogo
-        window.GLOB.doclogo = _systemMsg.doclogo
-        window.GLOB.webSite = _systemMsg.webSite
-        window.GLOB.style = _systemMsg.style
+        GLOB.platTitle = _systemMsg.platTitle
+        GLOB.platName = _systemMsg.platName
+        GLOB.favicon = _systemMsg.favicon
+        GLOB.loginlogo = _systemMsg.loginlogo
+        GLOB.copyRight = _systemMsg.copyRight
+        GLOB.ICP = _systemMsg.ICP
+        GLOB.bgImage = _systemMsg.bgImage
+        GLOB.mainlogo = _systemMsg.mainlogo
+        GLOB.doclogo = _systemMsg.doclogo
+        GLOB.webSite = _systemMsg.webSite
+        GLOB.style = _systemMsg.style
 
-        if (window.GLOB.favicon) {
+        if (GLOB.favicon) {
           let link = document.querySelector("link[rel*='icon']") || document.createElement('link')
           link.type = 'image/x-icon'
           link.rel = 'shortcut icon'
-          link.href = window.GLOB.favicon
+          link.href = GLOB.favicon
           document.getElementsByTagName('head')[0].appendChild(link)
         }
       } catch {
@@ -144,9 +144,9 @@
       }
     }
 
-    document.title = window.GLOB.platTitle || ''
+    document.title = GLOB.platTitle || ''
 
-    if (window.GLOB.filter === 'true') {
+    if (GLOB.filter === 'true') {
       let html = document.getElementsByTagName('html')[0]
       
       if (html) {
@@ -156,25 +156,54 @@
 
     if (process.env.NODE_ENV === 'production') { // 鐢ㄤ簬鏍¢獙鏄惁瀛樺湪寮�鍙戞潈闄�
       let _service = window.location.href.replace(/\/index.html(.*)|\/#(.*)/ig, '').replace(new RegExp(document.location.origin + '/?', 'ig'), '')
-      window.GLOB.linkurl = window.location.href.split('#')[0]
-      if (!/index.html/ig.test(window.GLOB.linkurl)) {
-        window.GLOB.linkurl = window.GLOB.linkurl + 'index.html'
+      GLOB.linkurl = window.location.href.split('#')[0]
+      if (!/index.html/ig.test(GLOB.linkurl)) {
+        GLOB.linkurl = GLOB.linkurl + 'index.html'
       }
-      window.GLOB.service = _service ? _service + '/' : ''
+      GLOB.service = _service ? _service + '/' : ''
     } else {
-      window.GLOB.linkurl = ''
-      window.GLOB.location = 'http://qingqiumarket.cn/'
-      window.GLOB.service = 'mkwms/'
+      GLOB.linkurl = ''
+      GLOB.location = 'http://qingqiumarket.cn/'
+      GLOB.service = 'mkwms/'
     }
 
     const option = {
       white: 'mk-white'
     }
 
-    if (window.GLOB.style && option[window.GLOB.style]) {
-      document.getElementById('root').className = option[window.GLOB.style]
+    if (GLOB.style && option[GLOB.style]) {
+      document.getElementById('root').className = option[GLOB.style]
     }
 
+    Object.defineProperty(GLOB, 'appId', {
+      writable: false,
+      value: GLOB.appId
+    })
+    Object.defineProperty(GLOB, 'appkey', {
+      writable: false,
+      value: GLOB.appkey
+    })
+    Object.defineProperty(GLOB, 'systemType', {
+      writable: false,
+      value: GLOB.systemType
+    })
+    Object.defineProperty(GLOB, 'mainSystemApi', {
+      writable: false,
+      value: GLOB.mainSystemApi
+    })
+    Object.defineProperty(GLOB, 'linkurl', {
+      writable: false,
+      value: GLOB.linkurl
+    })
+    Object.defineProperty(GLOB, 'dataFormat', {
+      writable: false,
+      value: GLOB.dataFormat
+    })
+    Object.defineProperty(window, 'GLOB', {
+      writable: false,
+      value: GLOB
+    })
+
     render(Route)
   })
 
diff --git a/src/locales/en-US/mob.js b/src/locales/en-US/mob.js
index 7e83f28..a77033e 100644
--- a/src/locales/en-US/mob.js
+++ b/src/locales/en-US/mob.js
@@ -4,12 +4,21 @@
   'mob.submit': '鎻愪氦',
   'mob.cancel': '鍙栨秷',
   'mob.edit': '缂栬緫',
-  'mob.header.logout': '閫�鍑�',
+  'mob.logout': '閫�鍑�',
+  'mob.name': '鍚嶇О',
+  'mob.param': '鍙傛暟',
+  'mob.menu': '鑿滃崟',
+  'mob.menu.first': '涓�绾�',
+  'mob.menu.second': '浜岀骇',
+  'mob.menu.opentype': '鎵撳紑鏂瑰紡',
+  'mob.menu.easycode': '鍔╄鐮�',
+  'mob.component': '缁勪欢',
   'mob.status.open': '鍚敤',
   'mob.status.change': '鍒囨崲',
   'mob.status.forbidden': '绂佺敤',
+  'mob.basemsg': '鍩烘湰淇℃伅',
   'mob.query.delete': '纭畾鍒犻櫎鍚楋紵',
-  'mob.header.logout.hint': '鎮ㄧ‘瀹氳閫�鍑哄悧?',
+  'mob.logout.hint': '鎮ㄧ‘瀹氳閫�鍑哄悧?',
   'mob.required.input': '璇疯緭鍏�',
   'mob.required.select': '璇烽�夋嫨',
 }
\ No newline at end of file
diff --git a/src/locales/zh-CN/mob.js b/src/locales/zh-CN/mob.js
index 7e83f28..a77033e 100644
--- a/src/locales/zh-CN/mob.js
+++ b/src/locales/zh-CN/mob.js
@@ -4,12 +4,21 @@
   'mob.submit': '鎻愪氦',
   'mob.cancel': '鍙栨秷',
   'mob.edit': '缂栬緫',
-  'mob.header.logout': '閫�鍑�',
+  'mob.logout': '閫�鍑�',
+  'mob.name': '鍚嶇О',
+  'mob.param': '鍙傛暟',
+  'mob.menu': '鑿滃崟',
+  'mob.menu.first': '涓�绾�',
+  'mob.menu.second': '浜岀骇',
+  'mob.menu.opentype': '鎵撳紑鏂瑰紡',
+  'mob.menu.easycode': '鍔╄鐮�',
+  'mob.component': '缁勪欢',
   'mob.status.open': '鍚敤',
   'mob.status.change': '鍒囨崲',
   'mob.status.forbidden': '绂佺敤',
+  'mob.basemsg': '鍩烘湰淇℃伅',
   'mob.query.delete': '纭畾鍒犻櫎鍚楋紵',
-  'mob.header.logout.hint': '鎮ㄧ‘瀹氳閫�鍑哄悧?',
+  'mob.logout.hint': '鎮ㄧ‘瀹氳閫�鍑哄悧?',
   'mob.required.input': '璇疯緭鍏�',
   'mob.required.select': '璇烽�夋嫨',
 }
\ No newline at end of file
diff --git a/src/locales/zh-CN/model.js b/src/locales/zh-CN/model.js
index 809a299..0f2b172 100644
--- a/src/locales/zh-CN/model.js
+++ b/src/locales/zh-CN/model.js
@@ -257,7 +257,7 @@
   'form.required.input': '璇疯緭鍏�',
   'form.required.select': '璇烽�夋嫨',
   'form.required.add': '璇锋坊鍔�',
-  'model.tooltip.table.guide': '姝ゅ鍙互娣诲姞椤甸潰閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃锛屽彲閫氳繃宸ュ叿鏍忎腑鐨勬坊鍔犳寜閽紝鍙壒閲忔坊鍔犺〃鏍肩浉鍏冲瓧娈点��',
+  'model.tooltip.table.guide': '娣诲姞椤甸潰閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃锛屽彲閫氳繃甯哥敤琛ㄥ瓧娈垫壒閲忔坊鍔犳悳绱㈡潯浠躲�佹樉绀哄垪銆佹暟鎹簮瀛楁闆嗐��',
   'model.tooltip.search.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃悳绱€�嬩腑锛岄�夋嫨瀵瑰簲鎼滅储妗嗘嫋鑷虫澶勬坊鍔狅紱鎴栫偣鍑绘寜閽�婃坊鍔犳悳绱㈡潯浠躲�嬫壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ��',
   'model.tooltip.action.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃寜閽�嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬寜閽嫋鑷虫澶勬坊鍔狅紝濡傞�夋嫨鎸夐挳绫诲瀷涓鸿〃鍗曘�佹柊鏍囩椤电瓑鍚湁閰嶇疆椤甸潰鐨勬寜閽紝鍙湪宸︿晶宸ュ叿鏍�-鎸夐挳-鍙厤缃寜閽锛岀偣鍑绘寜閽畬鎴愮浉鍏抽厤缃�傛敞锛氬綋璁剧疆鎸夐挳鏄剧ず浣嶇疆涓鸿〃鏍兼椂锛屾樉绀哄垪浼氬鍔犳搷浣滃垪銆�',
   'model.tooltip.column.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃樉绀哄垪銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬樉绀哄垪鎷栬嚦姝ゅ娣诲姞锛涙垨鐐瑰嚮銆婃坊鍔犳樉绀哄垪銆嬫寜閽壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ�傛敞锛氭坊鍔犲悎骞跺垪鏃讹紝闇�璁剧疆鍙�夊垪銆�',
diff --git a/src/menu/header/index.jsx b/src/menu/header/index.jsx
new file mode 100644
index 0000000..76f9955
--- /dev/null
+++ b/src/menu/header/index.jsx
@@ -0,0 +1,121 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { connect } from 'react-redux'
+import { withRouter } from 'react-router-dom'
+import {Dropdown, Menu, Icon, Modal, Tooltip, Button } from 'antd'
+
+import { logout } from '@/store/action'
+import zhCN from '@/locales/zh-CN/mob.js'
+import enUS from '@/locales/en-US/mob.js'
+import avatar from '@/assets/img/avatar.jpg'
+import './index.scss'
+
+const { confirm } = Modal
+
+class MobHeader extends Component {
+  static propTpyes = {
+    saveIng: PropTypes.any,
+    triggerSave: PropTypes.func,
+    closeView: PropTypes.func
+  }
+
+  state = {
+    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    logourl: window.GLOB.mainlogo,
+    avatar: sessionStorage.getItem('CloudAvatar') || avatar,
+    userName: sessionStorage.getItem('CloudUserName')
+  }
+
+  logout = () => {
+    // 閫�鍑虹櫥褰�
+    let _this = this
+    confirm({
+      title: this.state.dict['mob.logout.hint'],
+      content: '',
+      okText: this.state.dict['mob.confirm'],
+      cancelText: this.state.dict['mob.cancel'],
+      onOk() {
+        sessionStorage.clear()
+        _this.props.logout()
+        _this.props.history.replace('/login')
+      },
+      onCancel() {}
+    })
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  // componentDidMount () {
+  //   this.getImage()
+  // }
+
+  // getImage = () => {
+  //   const { logourl } = this.state
+  //   const _this = this
+
+  //   let xhr = new XMLHttpRequest()
+  //   xhr.open('get', logourl, true)
+  //   xhr.responseType = 'blob'
+  //   xhr.onload = function () {
+  //     if (this.status === 200) {
+  //       // document.getElementById(imgId).src =  URL.createObjectURL(this.response)
+  //       _this.setState({
+  //         logourl: URL.createObjectURL(this.response)
+  //       })
+  //     }
+  //   }
+  //   xhr.send(null)
+  // }
+
+  render () {
+
+    return (
+      <header className="mob-header-container">
+        <div className="header-logo"><img src={this.state.logourl} alt=""/></div>
+        <Menu
+          mode="inline"
+          theme="dark"
+          inlineCollapsed={this.state.collapsed}
+        >
+          <Menu.Item key="1">
+            <Tooltip placement="bottom" title="鍏抽棴">
+              <Icon type="close" onClick={this.props.closeView} />
+            </Tooltip>
+          </Menu.Item>
+          <Menu.Item key="2">
+            <Tooltip placement="bottom" title="淇濆瓨">
+              <Button icon="save" loading={this.props.saveIng} onClick={this.props.triggerSave}></Button>
+            </Tooltip>
+          </Menu.Item>
+        </Menu>
+        <Dropdown className="header-setting" overlay={
+          <Menu>
+            <Menu.Item key="2" onClick={this.logout}>{this.state.dict['mob.logout']}</Menu.Item>
+          </Menu>
+        }>
+          <div>
+            <img src={this.state.avatar} alt=""/>
+            <span>
+              <span className="username">{this.state.userName}</span> <Icon type="down" />
+            </span>
+          </div>
+        </Dropdown>
+      </header>
+    )
+  }
+}
+
+const mapStateToProps = () => {
+  return {}
+}
+
+const mapDispatchToProps = (dispatch) => {
+  return {
+    logout: () => dispatch(logout())
+  }
+}
+
+export default withRouter(connect(mapStateToProps, mapDispatchToProps)(MobHeader))
\ No newline at end of file
diff --git a/src/menu/header/index.scss b/src/menu/header/index.scss
new file mode 100644
index 0000000..a71158f
--- /dev/null
+++ b/src/menu/header/index.scss
@@ -0,0 +1,94 @@
+.mob-header-container {
+  width: 100%;
+  height: 48px;
+  padding-right: 320px;
+  color: rgba(255, 255, 255, 0.65);
+  position: fixed;
+  top: 0px;
+  z-index: 10;
+  
+  background: #001529;
+  border-bottom: 1px solid #000;
+
+  .header-logo {
+    float: left;
+    width: 180px;
+    line-height: 48px;
+    text-align: center;
+    padding-left: 5px;
+    box-sizing: border-box;
+    opacity: 1;
+    img {
+      max-width: 100%;
+      max-height: 40px;
+    }
+  }
+  .header-setting {
+    float: right;
+    line-height: 48px;
+    margin-right: 10px;
+    img {
+      width: 29px;
+      height: 29px;
+      border-radius: 30px;
+      margin-right: 7px;
+    }
+    span {
+      color: #ffffff;
+      font-size: 0.95rem;
+      .username {
+        display: inline-block;
+        height: 30px;
+        max-width: 95px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+    }
+  }
+  .mob-manage-title {
+    position: absolute;
+    left: calc(50vw - 45px);
+    color: #ffffff;
+    font-size: 16px;
+    line-height: 48px;
+    letter-spacing: 2px;
+  }
+  >.ant-menu {
+    float: left;
+    width: unset;
+    .ant-menu-item {
+      margin-bottom: 0;
+      float: left;
+      width: unset;
+      cursor: default;
+      .anticon-arrow-left {
+        height: 24px;
+        cursor: pointer;
+      }
+      .ant-btn {
+        color: #fff;
+        width: unset;
+        cursor: pointer;
+        height: 37px;
+        background: transparent;
+        border: 0;
+        .anticon-save {
+          margin-right: 0;
+        }
+      }
+      .ant-btn[ant-click-animating-without-extra-node="true"]::after {
+        display: none!important;
+      }
+      .ant-btn::before {
+        display: none!important;
+      }
+    }
+    .ant-menu-item.ant-menu-item-selected {
+      background-color: transparent;
+    }
+    .ant-menu-item:not(:last-child) {
+      border-right: 1px solid #353535;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/menu/menuform/index.jsx b/src/menu/menuform/index.jsx
new file mode 100644
index 0000000..9f714ff
--- /dev/null
+++ b/src/menu/menuform/index.jsx
@@ -0,0 +1,225 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Select, notification } from 'antd'
+
+import Api from '@/api'
+// import { formRule } from '@/utils/option.js'
+import './index.scss'
+
+class MainSearch extends Component {
+  static propTpyes = {
+    dict: PropTypes.object, // 瀛楀吀椤�
+    config: PropTypes.object,
+    MenuId: PropTypes.string,
+    MenuName: PropTypes.string,
+    MenuNo: PropTypes.string,
+    parentId: PropTypes.string,
+    updateConfig: PropTypes.func
+  }
+
+  state = {
+    fstMenuId: '',
+    menulist: [],
+    smenulist: []
+  }
+
+  UNSAFE_componentWillMount () {
+    const { parentId } = this.props
+    let param = {
+      func: 's_Get_FSMenusForOpen',
+      SndMenuID: parentId,
+      TYPE: 20,
+      TypeCharOne: 'PC'
+    }
+
+    Api.getSystemConfig(param).then(result => {
+      if (result.status) {
+        let menulist = result.data.map(smenu => {
+          let _smenu = {
+            value: smenu.FstID,
+            text: smenu.FstName,
+            options: smenu.SndData.map(menu => {
+              return {
+                value: menu.SndID,
+                text: menu.SndName,
+              }
+            })
+          }
+
+          return _smenu
+        })
+
+        let smenulist = []
+        menulist.forEach(item => {
+          if (item.value === result.FstIDSeleted) {
+            smenulist = item.options
+          }
+        })
+
+        this.setState({
+          fstMenuId: result.FstIDSeleted,
+          menulist,
+          smenulist
+        }, () => {
+          this.props.form.setFieldsValue({
+            fstMenuId: result.FstIDSeleted,
+            parentId: parentId
+          })
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    const { config } = this.props
+    if (!config && nextProps.config) {
+      this.props.form.setFieldsValue({easyCode: nextProps.config.easyCode})
+    }
+  }
+
+  // 涓�浜岀骇鑿滃崟鍒囨崲
+  selectChange = (key, value) => {
+    const { config } = this.props
+    const { menulist } = this.state
+
+    if (key === 'fstMenuId') {
+      let smenulist = []
+      menulist.forEach(item => {
+        if (item.value === value) {
+          smenulist = item.options
+        }
+      })
+
+      this.setState({
+        smenulist
+      }, () => {
+        let _id = smenulist[0] ? smenulist[0].value : ''
+        this.props.form.setFieldsValue({parentId: _id})
+      })
+      this.props.updateConfig({...config, fstMenuId: value})
+    } else if (key === 'parentId') {
+      this.props.updateConfig({...config, parentId: value})
+    }
+  }
+
+  // 鑿滃崟鍚嶇О
+  changeName = (e) => {
+    this.props.updateConfig({...this.props.config, MenuName: e.target.value})
+  }
+
+  // 鑿滃崟鍙傛暟
+  changeNo = (e) => {
+    this.props.updateConfig({...this.props.config, MenuNo: e.target.value})
+  }
+
+  // 鍔╄鐮�
+  changeEasyCode = (e) => {
+    this.props.updateConfig({...this.props.config, easyCode: e.target.value})
+  }
+
+  render() {
+    const { dict, MenuName, MenuNo } = this.props
+    const { menulist, smenulist } = this.state
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="ant-advanced-search-form">
+        <Row>
+          <Col span={24}>
+            <Form.Item label={dict['mob.menu.first'] + dict['mob.menu']}>
+              {getFieldDecorator('fstMenuId', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: dict['mob.required.select'] + dict['mob.menu.first'] + dict['mob.menu'] + '!'
+                  }
+                ]
+              })(
+                <Select onChange={(value) => {this.selectChange('fstMenuId', value)}}>
+                  {menulist.map(option =>
+                    <Select.Option key={option.value} value={option.value}>
+                      {option.text}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item label={dict['mob.menu.second'] + dict['mob.menu']}>
+              {getFieldDecorator('parentId', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: dict['mob.required.select'] + dict['mob.menu.second'] + dict['mob.menu'] + '!'
+                  }
+                ]
+              })(
+                <Select onChange={(value) => {this.selectChange('parentId', value)}}>
+                  {smenulist.map(option =>
+                    <Select.Option key={option.value} value={option.value}>
+                      {option.text}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item label={dict['mob.menu'] + dict['mob.name']}>
+              {getFieldDecorator('MenuName', {
+                initialValue: MenuName,
+                rules: [
+                  {
+                    required: true,
+                    message: dict['mob.required.input'] + dict['mob.menu'] + dict['mob.name'] + '!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" onChange={this.changeName}/>)}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item label={dict['mob.menu'] + dict['mob.param']}>
+              {getFieldDecorator('MenuNo', {
+                initialValue: MenuNo,
+                rules: [
+                  {
+                    required: true,
+                    message: dict['mob.required.input'] + dict['mob.menu'] + dict['mob.param'] + '!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" onChange={this.changeNo}/>)}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item label={dict['mob.menu.easycode']}>
+              {getFieldDecorator('easyCode', {
+                initialValue: ''
+              })(<Input placeholder="" autoComplete="off" onChange={this.changeEasyCode}/>)}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/menu/menuform/index.scss b/src/menu/menuform/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/menu/menuform/index.scss
diff --git a/src/mob/components/login/mob-login-1/index.jsx b/src/mob/components/login/mob-login-1/index.jsx
index 3bc77b6..3904ae5 100644
--- a/src/mob/components/login/mob-login-1/index.jsx
+++ b/src/mob/components/login/mob-login-1/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { InputItem, Icon, Checkbox, List, Button } from 'antd-mobile'
-import { createForm } from 'rc-form'
+// import { createForm } from 'rc-form'
 
 import zhCN from '@/locales/zh-CN/mob.js'
 import enUS from '@/locales/en-US/mob.js'
@@ -135,7 +135,7 @@
 
   render () {
     const { card, editId } = this.props
-    const { getFieldProps } = this.props.form
+    // const { getFieldProps } = this.props.form
     const { rember } = this.state
 
     if (!card.box) return null
@@ -181,11 +181,8 @@
           {card.title.content}
         </div> : null}
         <InputItem
-          placeholder="UserName"
+          placeholder={"UserName"}
           prefixListCls="mk-login-item am-list"
-          {...getFieldProps('userName', {
-            initialValue: 'admin',
-          })}
           disabled={true}
         >
           <Icon type="check-circle-o" />
@@ -193,9 +190,6 @@
         <InputItem
           placeholder="Password"
           prefixListCls="mk-login-item am-list"
-          {...getFieldProps('password', {
-            initialValue: '123456',
-          })}
           type={'password'}
           disabled={true}
         >
@@ -230,4 +224,5 @@
   }
 }
 
-export default createForm()(MobLogin)
\ No newline at end of file
+// export default createForm()(MobLogin)
+export default MobLogin
\ No newline at end of file
diff --git a/src/mob/header/index.jsx b/src/mob/header/index.jsx
index 1b7c9eb..f9547a3 100644
--- a/src/mob/header/index.jsx
+++ b/src/mob/header/index.jsx
@@ -32,7 +32,7 @@
     // 閫�鍑虹櫥褰�
     let _this = this
     confirm({
-      title: this.state.dict['mob.header.logout.hint'],
+      title: this.state.dict['mob.logout.hint'],
       content: '',
       okText: this.state.dict['mob.confirm'],
       cancelText: this.state.dict['mob.cancel'],
@@ -80,7 +80,7 @@
         }
         <Dropdown className="header-setting" overlay={
           <Menu>
-            <Menu.Item key="2" onClick={this.logout}>{this.state.dict['mob.header.logout']}</Menu.Item>
+            <Menu.Item key="2" onClick={this.logout}>{this.state.dict['mob.logout']}</Menu.Item>
           </Menu>
         }>
           <div>
diff --git a/src/router/index.js b/src/router/index.js
index 5dc706b..79f0dd9 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -11,6 +11,7 @@
 const NotFound = asyncComponent(() => import('@/views/404'))
 const MobManage = asyncLoadComponent(() => import('@/views/mobmanage'))
 const MobDesign = asyncLoadComponent(() => import('@/views/mobdesign'))
+const MenuDesign = asyncLoadComponent(() => import('@/views/menudesign'))
 const PrintT = asyncLoadComponent(() => import('@/views/printTemplate'))
 
 const routers = [
@@ -21,12 +22,13 @@
   {path: '/main', name: 'main', component: Main, auth: true},
   {path: '/mobmanage', name: 'mobmanage', component: MobManage, auth: true},
   {path: '/mobdesign/:appId/:appType/:appCode/:appName', name: 'mobdesign', component: MobDesign, auth: true},
+  {path: '/menudesign/:MenuId/:ParentId/:MenuName/:MenuNo', name: 'menudesign', component: MenuDesign, auth: true},
   {path: '/main/:param', name: 'pmain', component: Main, auth: true}
 ]
 
 export default class RouteConfig extends Component {
   controlRoute (item, props) {
-    if (!item.auth) { // 涓嶉渶瑕佹巿鏉冿紝鐩存帴璺宠浆锛堢櫥褰曢〉锛�
+    if (!item.auth) {            // 涓嶉渶瑕佹巿鏉冿紝鐩存帴璺宠浆锛堢櫥褰曢〉锛�
       return (<item.component {...props}/>)
     }
 
diff --git a/src/tabviews/calendar/index.jsx b/src/tabviews/calendar/index.jsx
index f16d051..bf539b6 100644
--- a/src/tabviews/calendar/index.jsx
+++ b/src/tabviews/calendar/index.jsx
@@ -368,7 +368,7 @@
     }
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (options.sysType === 'local' && !window.GLOB.systemType) {
+    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
       param.custom_script &&  console.log(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${param.custom_script}`)
       LText &&  console.log(LText)
     }
diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index 4e62c47..49bf1a7 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -736,7 +736,7 @@
     }
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (options.sysType === 'local' && !window.GLOB.systemType) {
+    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
       param.custom_script &&  console.log(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${param.custom_script}`)
       LText &&  console.log(LText)
     }
diff --git a/src/tabviews/subtable/index.jsx b/src/tabviews/subtable/index.jsx
index ca99320..486f223 100644
--- a/src/tabviews/subtable/index.jsx
+++ b/src/tabviews/subtable/index.jsx
@@ -611,7 +611,7 @@
     }
 
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (options.sysType === 'local' && !window.GLOB.systemType) {
+    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
       param.custom_script &&  console.log(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${param.custom_script}`)
       LText &&  console.log(LText)
     }
diff --git a/src/tabviews/subtabtable/index.jsx b/src/tabviews/subtabtable/index.jsx
index d94c371..a1aa827 100644
--- a/src/tabviews/subtabtable/index.jsx
+++ b/src/tabviews/subtabtable/index.jsx
@@ -512,7 +512,7 @@
     }
     
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (options.sysType === 'local' && !window.GLOB.systemType) {
+    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
       param.custom_script &&  console.log(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${param.custom_script}`)
       LText &&  console.log(LText)
     }
diff --git a/src/tabviews/treepage/index.jsx b/src/tabviews/treepage/index.jsx
index 26e2454..3420fa2 100644
--- a/src/tabviews/treepage/index.jsx
+++ b/src/tabviews/treepage/index.jsx
@@ -539,7 +539,7 @@
     }
     
     // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
-    if (options.sysType === 'local' && !window.GLOB.systemType) {
+    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
       param.custom_script &&  console.log(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${param.custom_script}`)
       LText &&  console.log(LText)
     }
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index 86ac880..cddb597 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -512,8 +512,11 @@
       let contents = []
       let images = []
 
-      item.subColumn.forEach(col => {
+      item.subColumn.forEach((col, index) => {
         if (!col.field || !record.hasOwnProperty(col.field)) return
+        if (index) {
+          col.Align = 'right'
+        }
         
         if (col.type === 'number') {
           let content = ''
@@ -558,7 +561,7 @@
             content = md5(content)
           }
 
-          contents.push(content)
+          contents.push({content, align: col.Align})
         } else if (col.type === 'picture') {
           let photos = []
           try {
@@ -568,7 +571,7 @@
           }
 
           photos.forEach(photo => {
-            images.push({url: photo, scale: col.scale === 'true', maxHeight: col.maxHeight || 128})
+            images.push({url: photo, align: col.Align, scale: col.scale === 'true', maxHeight: col.maxHeight || 128})
           })
         } else if (col.type === 'text') {
           let content = record[col.field]
@@ -601,7 +604,7 @@
             content = md5(content)
           }
 
-          contents.push(content)
+          contents.push({content, align: col.Align})
         } else if (col.type === 'link') {
           let content = col.nameField ? record[col.nameField] : ''
           let _href = record[col.field] || ''
@@ -631,7 +634,7 @@
 
           content = _href ? <a href={_href} target="_blank" rel="noopener noreferrer">{content}</a> : null
 
-          contents.push(content)
+          contents.push({content, align: col.Align})
         } else {
           let content = record[col.field]
 
@@ -643,7 +646,7 @@
             content = md5(content)
           }
 
-          contents.push(content)
+          contents.push({content, align: col.Align})
         }
       })
 
@@ -663,8 +666,8 @@
 
   getCospanContent = (type, contents, images) => {
     if (type === 'vertical') {
-      return contents.map((content, index) => {
-        return (<p key={index}>{content}</p>)
+      return contents.map((cont, index) => {
+        return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
       })
     } else if (type === 'horizontal') {
       return contents.map((content, index) => {
@@ -674,18 +677,18 @@
       return (
         <div className="content-fence">
           <div className="content-fence-left">
-            {contents.map((content, index) => {
+            {contents.map((cont, index) => {
               if (index % 2 === 0) {
-                return (<p key={index}>{content}</p>)
+                return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
               } else {
                 return ''
               }
             })}
           </div>
           <div className="content-fence-right">
-            {contents.map((content, index) => {
+            {contents.map((cont, index) => {
               if (index % 2 === 1) {
-                return (<p key={index}>{content}</p>)
+                return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
               } else {
                 return ''
               }
@@ -696,7 +699,7 @@
     } else if (type === 'topPicBottomText') {
       return (
         <div className="content-fence">
-          <div className="content-fence-top">
+          <div className="content-fence-top" style={images[0] ? {textAlign: images[0].align} : null}>
             {images.map((_img, index) => {
               if (!_img.url) return ''
               if (_img.scale) {
@@ -707,8 +710,8 @@
             })}
           </div>
           <div className="content-fence-bottom">
-            {contents.map((content, index) => {
-              return (<p key={index}>{content}</p>)
+            {contents.map((cont, index) => {
+              return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
             })}
           </div>
         </div>
@@ -716,7 +719,7 @@
     } else if (type === 'leftPicRightText') {
       return (
         <div className="content-fence">
-          <div className="content-fence-left">
+          <div className="content-fence-left" style={images[0] ? {textAlign: images[0].align} : null}>
             {images.map((_img, index) => {
               if (!_img.url) return ''
               if (_img.scale) {
@@ -727,8 +730,8 @@
             })}
           </div>
           <div className="content-fence-right">
-            {contents.map((content, index) => {
-              return (<p key={index}>{content}</p>)
+            {contents.map((cont, index) => {
+              return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
             })}
           </div>
         </div>
diff --git a/src/templates/comtableconfig/index.scss b/src/templates/comtableconfig/index.scss
index 88c2876..a64c17c 100644
--- a/src/templates/comtableconfig/index.scss
+++ b/src/templates/comtableconfig/index.scss
@@ -110,30 +110,22 @@
       min-width: 65px;
     }
   }
-  .tools:hover {
+  .tools {
     overflow-y: auto;
   }
   .tools::-webkit-scrollbar {
-    width: 7px;
+    width: 4px;
   }
   .tools::-webkit-scrollbar-thumb {
     border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
+    background: rgba(0, 0, 0, 0.08);
   }
   .tools::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
-  }
-  .tools:hover::-webkit-scrollbar-thumb {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-    background: rgba(0, 0, 0, 0.13);
-  }
-  .tools:hover::-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);
   }
   .setting {
     position: relative;
diff --git a/src/templates/formtabconfig/index.scss b/src/templates/formtabconfig/index.scss
index 23750f0..9ef7485 100644
--- a/src/templates/formtabconfig/index.scss
+++ b/src/templates/formtabconfig/index.scss
@@ -13,7 +13,7 @@
     background: #ffffff;
     border-right: 1px solid #d9d9d9;
     height: 100%;
-    overflow-y: hidden;
+    overflow-y: auto;
     padding-bottom: 30px;
     .ant-collapse-item {
       position: relative;
@@ -100,30 +100,19 @@
       min-width: 65px;
     }
   }
-  .tools:hover {
-    overflow-y: auto;
-  }
   .tools::-webkit-scrollbar {
-    width: 7px;
+    width: 4px;
   }
   .tools::-webkit-scrollbar-thumb {
     border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
+    background: rgba(0, 0, 0, 0.08);
   }
   .tools::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
-  }
-  .tools:hover::-webkit-scrollbar-thumb {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-    background: rgba(0, 0, 0, 0.13);
-  }
-  .tools:hover::-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);
   }
   .setting {
     position: relative;
diff --git a/src/templates/menuconfig/editthdmenu/index.jsx b/src/templates/menuconfig/editthdmenu/index.jsx
index be00486..1737bd3 100644
--- a/src/templates/menuconfig/editthdmenu/index.jsx
+++ b/src/templates/menuconfig/editthdmenu/index.jsx
@@ -13,6 +13,7 @@
 import mainsubtable from '@/assets/img/mainsubtable.jpg'
 import treepage from '@/assets/img/treepage.jpg'
 import calendar from '@/assets/img/calendar.jpg'
+import customImg from '@/assets/img/custom.jpg'
 
 import Preview from './preview'
 import MenuForm from './menuform'
@@ -38,12 +39,6 @@
 const { confirm } = Modal
 const { TabPane } = Tabs
 const { Search } = Input
-
-const illust = { // 妯℃澘鍥剧墖锛岀敤浜庡凡浣跨敤妯℃澘
-  CommonTable: mainsubtable,
-  TreePage: treepage,
-  CalendarPage: calendar
-}
 
 class EditMenu extends Component {
   static propTpyes = {
@@ -136,7 +131,7 @@
         onCancel() {}
       })
     } else if (menu.type === 'edit') {
-      let _menu = JSON.parse(JSON.stringify(menu.card))
+      let _menu = fromJS(menu.card).toJS()
 
       delete _menu.id
       delete _menu.src
@@ -439,7 +434,7 @@
    * 2銆佷娇鐢ㄥ凡鏈夎彍鍗曟ā鏉挎椂锛岃幏鍙栬彍鍗曢厤缃俊鎭紝鏍囪涓簎ser锛堝鍒惰彍鍗曟寜閽級
    */
   useTemplate = (template, useType) => {
-    let editMenu = JSON.parse(JSON.stringify(this.state.editMenu))
+    let editMenu = fromJS(this.state.editMenu).toJS()
 
     if (!this.state.fstMenuId) {
       notification.warning({
@@ -455,7 +450,7 @@
       editMenu.fstMenuList = this.state.fstMenuList
     }
 
-    if (useType === 'sys' && template.type === 'RolePermission') { // 鐙珛椤甸潰
+    if (useType === 'sys' && (template.type === 'RolePermission' || template.type === 'CustomPage')) { // 鐙珛椤甸潰
       let _menu = {
         ...editMenu,
         MenuID: Utils.getuuid(),
@@ -533,7 +528,7 @@
 
       this.setState({
         loading: false,
-        tabview: template.type,
+        tabview: template.type === 'CustomPage' ? '' : template.type,
         optionLibs: new Map(), // 鏂板缓鏃讹紝鍒濆鍖栦笅鎷夐�夐」搴�
         editMenu: {
           ...editMenu,
@@ -543,12 +538,34 @@
           isSubtable: template.isSubtable
         }
       })
+
+      if (template.type === 'CustomPage') { // 浣跨敤鑷畾涔夌殑宸叉湁鑿滃崟
+        // let _menu = {
+        //   ...editMenu,
+        //   MenuID: Utils.getuuid(),
+        //   MenuName: template.title,
+        //   Template: template.type,
+        //   ParentID: this.props.supMenu.MenuID,
+        // }
+  
+        // this.setState({
+        //   handleMVisible: true,
+        //   sysMenu: _menu
+        // })
+        return
+      }
       document.getElementById('root').style.overflowY = 'hidden'
     })
   }
 
   getUsedTemplate = () => {
     let { sysTemplates } = this.state
+    const illust = { // 妯℃澘鍥剧墖锛岀敤浜庡凡浣跨敤妯℃澘
+      CommonTable: mainsubtable,
+      TreePage: treepage,
+      CalendarPage: calendar,
+      CustomPage: customImg
+    }
 
     Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'menu'}).then(res => {
       let _templates = []
@@ -608,9 +625,10 @@
    */
   memuSubmit = () => {
     const { sysMenu } = this.state
-    let sysTemplates = JSON.parse(JSON.stringify(this.state.sysTemplates))
+    let sysTemplates = fromJS(this.state.sysTemplates).toJS()
 
-    if (sysMenu.isSystem) {
+    // 瑙掕壊鏉冮檺鍒嗛厤妯℃澘锛屽彧鍙互娣诲姞涓�娆�
+    if (sysMenu.isSystem && sysMenu.Template === 'RolePermission') {
       sysTemplates = sysTemplates.map(temp => {
         if (temp.type === sysMenu.type) {
           temp.hidden = true
@@ -709,7 +727,7 @@
             return _smenu
           })
         }, () => {
-          let _menu = JSON.parse(JSON.stringify(this.state.editMenu))
+          let _menu = this.state.editMenu ? fromJS(this.state.editMenu).toJS() : null
   
           if (!_menu || !_menu.loadingFstMenuId) {
             return
diff --git a/src/templates/menuconfig/menuelement/card.jsx b/src/templates/menuconfig/menuelement/card.jsx
index d50f41e..e507a78 100644
--- a/src/templates/menuconfig/menuelement/card.jsx
+++ b/src/templates/menuconfig/menuelement/card.jsx
@@ -31,13 +31,16 @@
   const close = () => {
     closeCard(id)
   }
+
   return (
     <div className="side-card" style={{ opacity }}>
       <div ref={node => drag(drop(node))}>
         {card.PageParam && card.PageParam.Icon && <Icon type={card.PageParam.Icon} />}
         {card.text}
       </div>
-      {!card.forbidden ? <Icon className="edit" type="edit" onClick={edit} /> : null}
+      {/* 鑷畾涔夋ā鏉匡紝鍦ㄦ柊椤甸潰缂栬緫 */}
+      {!card.forbidden && card.type !== 'CustomPage' ? <Icon className="edit" type="edit" onClick={edit} /> : null}
+      {card.type === 'CustomPage' ? <a href={`#/menudesign/${card.MenuID}/${card.ParentId}/${card.MenuName}/${card.MenuNo}`} target="_blank" rel="noopener noreferrer"><Icon className="edit" type="edit" /></a> : null}
       <Icon className="close" type="close" onClick={close} />
     </div>
   )
diff --git a/src/templates/modalconfig/index.scss b/src/templates/modalconfig/index.scss
index 1ad1178..43e5a20 100644
--- a/src/templates/modalconfig/index.scss
+++ b/src/templates/modalconfig/index.scss
@@ -13,7 +13,7 @@
     background: #ffffff;
     border-right: 1px solid #d9d9d9;
     height: 100%;
-    overflow-y: hidden;
+    overflow-y: auto;
     padding-bottom: 30px;
     .ant-collapse-item {
       border: 0;
@@ -88,30 +88,19 @@
       }
     }
   }
-  .tools:hover {
-    overflow-y: auto;
-  }
   .tools::-webkit-scrollbar {
-    width: 7px;
+    width: 4px;
   }
   .tools::-webkit-scrollbar-thumb {
     border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
+    background: rgba(0, 0, 0, 0.08);
   }
   .tools::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
-  }
-  .tools:hover::-webkit-scrollbar-thumb {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-    background: rgba(0, 0, 0, 0.13);
-  }
-  .tools:hover::-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);
   }
   .setting {
     position: relative;
diff --git a/src/templates/sharecomponent/tablecomponent/index.jsx b/src/templates/sharecomponent/tablecomponent/index.jsx
index b91c630..05bcaa8 100644
--- a/src/templates/sharecomponent/tablecomponent/index.jsx
+++ b/src/templates/sharecomponent/tablecomponent/index.jsx
@@ -264,7 +264,7 @@
           value={dict['header.menu.table.placeholder']}
           onChange={this.onTableChange}
           showArrow={false}
-          getPopupContainer={() => document.getElementById(containerId)}
+          getPopupContainer={() => containerId ? document.getElementById(containerId) : document.body}
           filterOption={(input, option) => {
             return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
               option.props.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
diff --git a/src/templates/sharecomponent/tablecomponent/index.scss b/src/templates/sharecomponent/tablecomponent/index.scss
index aa254b7..fa82d90 100644
--- a/src/templates/sharecomponent/tablecomponent/index.scss
+++ b/src/templates/sharecomponent/tablecomponent/index.scss
@@ -4,4 +4,8 @@
       opacity: 0.4!important;
     }
   }
+  .anticon-question-circle {
+    color: #c49f47;
+    margin-right: 3px;
+  }
 }
\ No newline at end of file
diff --git a/src/templates/subtableconfig/index.scss b/src/templates/subtableconfig/index.scss
index 3beec9c..d81d245 100644
--- a/src/templates/subtableconfig/index.scss
+++ b/src/templates/subtableconfig/index.scss
@@ -99,31 +99,24 @@
       min-width: 65px;
     }
   }
-  .tools:hover {
+  .tools {
     overflow-y: auto;
   }
   .tools::-webkit-scrollbar {
-    width: 7px;
+    width: 4px;
   }
   .tools::-webkit-scrollbar-thumb {
     border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
+    background: rgba(0, 0, 0, 0.08);
   }
   .tools::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
     border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0);
+    border: 1px solid rgba(0, 0, 0, 0.07);
     background: rgba(0, 0, 0, 0);
   }
-  .tools:hover::-webkit-scrollbar-thumb {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-    background: rgba(0, 0, 0, 0.13);
-  }
-  .tools:hover::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
-    border: 1px solid rgba(0, 0, 0, 0.07);
-  }
+
   .setting {
     position: relative;
     width: calc(100vw - 235px);
diff --git a/src/templates/treepageconfig/index.scss b/src/templates/treepageconfig/index.scss
index 45cb419..8784403 100644
--- a/src/templates/treepageconfig/index.scss
+++ b/src/templates/treepageconfig/index.scss
@@ -90,30 +90,22 @@
       min-width: 65px;
     }
   }
-  .tools:hover {
+  .tools {
     overflow-y: auto;
   }
   .tools::-webkit-scrollbar {
-    width: 7px;
+    width: 4px;
   }
   .tools::-webkit-scrollbar-thumb {
     border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
+    background: rgba(0, 0, 0, 0.08);
   }
   .tools::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
-    border-radius: 3px;
-    border: 1px solid rgba(0, 0, 0, 0);
-    background: rgba(0, 0, 0, 0);
-  }
-  .tools:hover::-webkit-scrollbar-thumb {
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
-    background: rgba(0, 0, 0, 0.13);
-  }
-  .tools:hover::-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);
   }
   .setting {
     position: relative;
diff --git a/src/utils/option.js b/src/utils/option.js
index d267be0..7804842 100644
--- a/src/utils/option.js
+++ b/src/utils/option.js
@@ -4,6 +4,7 @@
 import mainsubtable from '@/assets/img/mainsubtable.jpg'
 import treepage from '@/assets/img/treepage.jpg'
 import calendar from '@/assets/img/calendar.jpg'
+import customImg from '@/assets/img/custom.jpg'
 import rolemanage from '@/assets/img/rolemanage.jpg'
 
 const _dict =  sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
@@ -74,6 +75,13 @@
     title: '鏃ュ巻',
     type: 'CalendarPage',
     url: calendar,
+    baseconfig: '',
+    isSystem: true
+  },
+  {
+    title: '鑷畾涔�',
+    type: 'CustomPage',
+    url: customImg,
     baseconfig: '',
     isSystem: true
   },
@@ -442,6 +450,7 @@
   'magenta-8': '#9e1068',
   'magenta-9': '#780650',
   'magenta-10': '#520339',
+  'transparent': 'transparent',
   'gray-1': '#f5f5f5',
   'gray-2': '#f0f0f0',
   'gray-3': '#d9d9d9',
@@ -591,6 +600,7 @@
     value: 'Gray',
     label: '涓�ц壊',
     children: [
+      { value: 'transparent', label: 'transparent' },
       { value: 'gray-2', label: 'gray-2' },
       { value: 'gray-4', label: 'gray-4' },
       { value: 'gray-6', label: 'gray-6' },
diff --git a/src/utils/utils.js b/src/utils/utils.js
index ed6c47e..19cc904 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -948,8 +948,7 @@
         
         aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
 
-      // if (window.GLOB.systemType !== 'production' && options.sysType !== 'cloud') {
-      if (window.GLOB.systemType !== 'production') {
+      if ((window.GLOB.systemType !== 'production' && options.sysType !== 'cloud') || window.debugger === true) {
         let fsql = `
         ${_sql}
         ${_sqlInsert}
@@ -1582,8 +1581,7 @@
     _sql += `
         aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
 
-    // if (window.GLOB.systemType !== 'production' && options.sysType !== 'cloud') {
-    if (window.GLOB.systemType !== 'production') {
+    if ((window.GLOB.systemType !== 'production' && options.sysType !== 'cloud') || window.debugger === true) {
       _sql = _sql.replace(/\n\s{8}/ig, '\n')
       console.log(_sql)
     }
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
new file mode 100644
index 0000000..44ec59d
--- /dev/null
+++ b/src/views/menudesign/index.jsx
@@ -0,0 +1,394 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { DndProvider } from 'react-dnd'
+import { is, fromJS } from 'immutable'
+import moment from 'moment'
+import HTML5Backend from 'react-dnd-html5-backend'
+import { Icon, notification, Modal, Collapse } from 'antd'
+import html2canvas from 'html2canvas'
+
+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 asyncComponent from '@/utils/asyncComponent'
+
+import './index.scss'
+
+// const { TabPane } = Tabs
+const { Panel } = Collapse
+const { confirm } = Modal
+
+const Header = asyncComponent(() => import('@/menu/header'))
+const MenuForm = asyncComponent(() => import('@/menu/menuform'))
+// const Controller = asyncComponent(() => import('@/mob/controller'))
+const SourceWrap = asyncComponent(() => import('@/mob/modelsource'))
+// const DataSource = asyncComponent(() => import('@/mob/datasource'))
+const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
+
+class Mobile extends Component {
+  state = {
+    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    MenuId: this.props.match.params.MenuId,
+    activeKey: 'basedata',
+    oriConfig: null,
+    parentId: '',
+    openEdition: '',
+    saveIng: false,
+    config: null,
+    editElem: null
+  }
+
+  UNSAFE_componentWillMount() {
+    this.getMenuParam()
+    // this.testFunc()
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  closeView = () => {
+    const { oriConfig, config } = this.state
+    const _this = this
+
+    if (!is(fromJS(oriConfig), fromJS(config))) {
+      confirm({
+        title: '閰嶇疆宸蹭慨鏀癸紝鏀惧純淇濆瓨鍚楋紵',
+        content: '',
+        okText: _this.state.dict['mob.confirm'],
+        cancelText: _this.state.dict['mob.cancel'],
+        onOk() {
+          window.close()
+        },
+        onCancel() {}
+      })
+    } else {
+      window.close()
+    }
+  }
+
+  triggerSave = () => {
+    const { config, openEdition, parentId } = this.state
+
+    this.setState({
+      saveIng: true
+    })
+
+    let param = {
+      func: 'sPC_TrdMenu_AddUpt',
+      ParentID: parentId,
+      MenuID: config.uuid,
+      MenuNo: config.MenuNo,
+      EasyCode: '',
+      Template: '',
+      MenuName: '',
+      PageParam: '',
+      LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config))),
+      // LText: _vals.func.map(item => `select '${menu.MenuID}' as MenuID,'${item.func}' as ProcName,'${item.label}' as MenuName`),
+      // LTexttb: _tables.map(item => `select '${menu.MenuID}' as MenuID,'${item}' as tbName`),
+      TypeCharOne: 'mob'
+    }
+
+    let _LText = ''
+    // _LText = _LText.join(' union all ')
+    let _LTexttb = ''
+    // _LTexttb = _LTexttb.join(' union all ')
+    
+    param.LText = Utils.formatOptions(_LText)
+    param.LTexttb = Utils.formatOptions(_LTexttb)
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+    if (openEdition) { // 鐗堟湰绠$悊
+      param.open_edition = openEdition
+    }
+
+    Api.getSystemConfig(param).then(response => {
+      if (response.status) {
+        this.setState({
+          oriConfig: fromJS(config).toJS(),
+          openEdition: response.open_edition || '',
+          saveIng: false
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: response.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  testFunc = () => {
+    let datas = [{
+      name: 'a',
+      arr_field: 'MapCode,Country',
+      par_tablename: '',
+      type: '',
+      primaryKey: 'MapCode',
+      foreign_key: '',
+      sql: `select MapCode,Country from @tc1`,
+      script: `declare @tc1 table (MapCode nvarchar(50),Country nvarchar(50)) insert into @tc1 (MapCode,Country) select MapCode,Country from sMap where Province=''`
+    }, {
+      name: 'b',
+      arr_field: 'MapCode,Province,ParMapCode',
+      par_tablename: 'a',
+      type: 'array',
+      primaryKey: 'MapCode',
+      foreign_key: 'ParMapCode',
+      sql: `select MapCode,Province,ParMapCode from @tc2`,
+      script: `declare @tc2 table (MapCode nvarchar(50),Province nvarchar(50),ParMapCode nvarchar(50)) insert into @tc2 (MapCode,Province,ParMapCode) select MapCode,Province,ParMapCode from sMap where Province!='' and City=''`
+    }, {
+      name: 'c',
+      arr_field: 'MapCode,City,ParMapCode',
+      par_tablename: 'b',
+      type: 'array',
+      primaryKey: 'MapCode',
+      foreign_key: 'ParMapCode',
+      sql: `select MapCode,City,ParMapCode from @tc3`,
+      script: `declare @tc3 table (MapCode nvarchar(50),City nvarchar(50),ParMapCode nvarchar(50)) insert into @tc3 (MapCode,City,ParMapCode) select MapCode,City,ParMapCode from sMap where City!='' and Area=''`
+    }, {
+      name: 'd',
+      arr_field: 'MapCode,Area,ParMapCode',
+      par_tablename: 'c',
+      type: 'array',
+      primaryKey: 'MapCode',
+      foreign_key: 'ParMapCode',
+      sql: `select MapCode,Area,ParMapCode from sMap where Area!=''`,
+      script: ``
+    }]
+
+    let LText = datas.map((item, index) => {
+      // item.par_tablename = ''
+      // item.foreign_key = ''
+
+      let _orderBy = 'MapCode desc'
+      let _search = ''
+      let _sql = `select top 1000 ${item.arr_field} from (select ${item.arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from (${item.sql}) tb ${_search}) tmptable order by tmptable.rows `
+      
+      return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(_sql))}' as LText,'${window.btoa(window.encodeURIComponent(item.script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
+    })
+    
+    let LText_field = []
+    datas.forEach(item => {
+      item.arr_field.split(',').forEach(cell => {
+        LText_field.push(`Select '${item.name}' as tablename,'${cell}' as fieldname,'nvarchar(50)' as field_type`)
+      })
+    })
+    
+    let param = {
+      func: 'sPC_Get_structured_data',
+      LText: LText.join(' union all '),
+      LText_field: LText_field.join(' union all ')
+    }
+
+    param.LText = Utils.formatOptions(param.LText)
+    param.LText_field = Utils.formatOptions(param.LText_field)
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+    Api.getLocalConfig(param)
+  }
+
+  getMenuParam = () => {
+    Api.getSystemConfig({
+      func: 'sPC_Get_LongParam',
+      MenuID: this.props.match.params.MenuId
+    }).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
+          }
+        }
+
+        if (!config) {
+          config = {
+            version: 1.0,
+            uuid: this.props.match.params.MenuId,
+            Template: 'CustomPage',
+            easyCode: '',
+            enabled: false,
+            MenuName: this.props.match.params.MenuName,
+            MenuNo: this.props.match.params.MenuNo,
+            tables: [],
+            components: []
+          }
+        }
+        this.setState({
+          oriConfig: config,
+          config: fromJS(config).toJS(),
+          openEdition: result.open_edition || '',
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  deleteCard = (id) => {
+    let _this = this
+    let config = fromJS(this.state.config).toJS()
+
+    confirm({
+      title: '纭畾鍒犻櫎鍏冪礌鍚楋紵',
+      content: '',
+      okText: this.state.dict['mob.confirm'],
+      cancelText: this.state.dict['mob.cancel'],
+      onOk() {
+        config.components = config.components.filter(item => item.uuid !== id)
+
+        _this.setState({
+          config: config
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  editCard = (element) => {
+    this.setState({
+      editElem: element
+    })
+  }
+
+  updateStyle = (proper) => {
+    const { config } = this.state
+
+    config.components = config.components.map(component => {
+      if (component.uuid === proper.componentId) {
+        Object.keys(component).forEach(key => {
+          let _uuid = component[key].uuid
+          if (_uuid && (_uuid === proper.uuid || _uuid === proper.classId)) {
+            if (component[key].substyle) {
+
+            } else {
+              component[key].style = {...component[key].style, ...proper.style}
+              // eslint-disable-next-line
+              for (let index in component[key].style) {
+                if (component[key].style[index] === '') {
+                  delete component[key].style[index]
+                }
+              }
+            }
+          }
+        })
+      }
+      return component
+    })
+    this.setState({config})
+  }
+
+  updateConfig = (config) => {
+    this.setState({
+      config: config
+    })
+  }
+  updatetable = (config) => {
+    // this.setState({
+    //   config: config
+    // })
+  }
+
+  save = () => {
+    html2canvas(document.getElementById('view')).then(canvas => {
+      let imgUri = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream'); // 鑾峰彇鐢熸垚鐨勫浘鐗囩殑url
+      window.location.href = imgUri; // 涓嬭浇鍥剧墖
+    })
+  }
+
+  render () {
+    const { activeKey, saveIng, dict, MenuId, config } = this.state
+
+    return (
+      <div className="pc-menu-view" id="view">
+        <Header view="design" closeView={this.closeView} triggerSave={this.triggerSave} saveIng={saveIng} />
+        <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">
+                  {/* 鑿滃崟淇℃伅 */}
+                  <MenuForm
+                    dict={dict}
+                    config={config}
+                    MenuId={MenuId}
+                    parentId={this.props.match.params.ParentId}
+                    MenuName={this.props.match.params.MenuName}
+                    MenuNo={this.props.match.params.MenuNo}
+                    updateConfig={this.updateConfig}
+                  />
+                  {/* 琛ㄥ悕娣诲姞 */}
+                  {config ? <TableComponent
+                    config={config}
+                    // containerId="main-basedata"
+                    updatetable={this.updatetable}
+                  /> : null}
+                </Panel>
+                {/* 鎼滅储鏉′欢娣诲姞 */}
+                {/* <Panel header={dict['mob.component']} key="component">
+                  <div className="search-element">
+                    {Source.searchItems.map((item, index) => (<SourceElement key={index} content={item}/>))}
+                  </div>
+                  <FieldsComponent
+                    config={config}
+                    type="search"
+                    tableFields={this.state.tableFields}
+                    updatefield={this.updateconfig}
+                  />
+                </Panel> */}
+                
+              </Collapse>
+              {/* <Tabs defaultActiveKey="1" animated={false} size="small">
+                <TabPane tab="閰嶇疆" key="1">
+                  <Controller editElem={editElem} updateStyle={this.updateStyle} />
+                </TabPane>
+                <TabPane tab="鏁版嵁婧�" key="2">
+                  <DataSource config={config} updateConfig={this.updateConfig} />
+                </TabPane>
+              </Tabs> */}
+            </div>
+            <div className="menu-tool">
+              <div className="menu-tool-content">
+                <div className="plus-content">
+                  <Icon type="plus-circle" />娣� 鍔� 缁� 浠�
+                </div>
+                <div className="useable-component">
+                  <SourceWrap appType="Menu" />
+                </div>
+              </div>
+              <div className="menu-tool-other"></div>
+            </div>
+          </div>
+        </DndProvider>
+      </div>
+    )
+  }
+}
+
+const mapStateToProps = () => {
+  return {}
+}
+
+const mapDispatchToProps = () => {
+  return {}
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(Mobile)
\ No newline at end of file
diff --git a/src/views/menudesign/index.scss b/src/views/menudesign/index.scss
new file mode 100644
index 0000000..994438c
--- /dev/null
+++ b/src/views/menudesign/index.scss
@@ -0,0 +1,134 @@
+.pc-menu-view {
+  background: #000;
+  min-height: 100vh;
+  .menu-body {
+    width: 100vw;
+    height: 100vh;
+    overflow-x: hidden;
+    position: relative;
+    background: #ffffff;
+    padding: 50px 300px 0px 40px;
+
+    .menu-tool {
+      position: fixed;
+      left: 0;
+      top: 48px;
+      height: 100%;
+      width: 40px;
+      background: #262626;
+      box-shadow: 2px 0px 2px #000;
+      .menu-tool-content {
+        width: 100%;
+        .plus-content {
+          position: relative;
+          color: #ffffff;
+          width: 100%;
+          display: flex;
+          align-items: center;
+          writing-mode: tb-rl;
+          padding: 16px 0;
+          border-bottom: 1px solid #000;
+          cursor: pointer;
+          z-index: 10;
+          background: #202735;
+          i {
+            margin-bottom: 5px;
+            margin-left: 2px;
+          }
+        }
+
+        .useable-component {
+          position: absolute;
+          width: 305px;
+          top: 0;
+          bottom: 0;
+          left: -340px;
+          background: #fff;
+          opacity: 0;
+          transition: left 0.3s linear 0.1s, opacity 0.3s linear 0.1s;
+          overflow-y: auto;
+        }
+      }
+      .menu-tool-content:hover {
+        .useable-component {
+          opacity: 1;
+          left: 40px;
+        }
+      }
+      .menu-tool-other {
+        position: relative;
+        z-index: 10;
+        height: 1000px;
+        background: #202735;
+      }
+    }
+
+    .menu-setting {
+      position: fixed;
+      left: 0;
+      top: 48px;
+      z-index: 10;
+      height: 100%;
+      width: 300px;
+      background: #ffffff;
+      box-shadow: 0px 2px 5px #bcbcbc;
+
+      > .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;
+          }
+        }
+      }
+
+      >.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;
+          }
+        }
+      }
+    }
+  }
+
+  .flex-container {
+    margin: 0 15px;
+  }
+  .flex-container .inline {
+    width: 80px!important;
+    margin: 9px 9px 9px 0;
+  }
+  .flex-container .small {
+    height: 20px!important;
+    line-height: 20px!important;
+  }
+  .sub-title {
+    color: #888;
+    font-size: 14px;
+    padding: 30px 0 18px 0;
+  }
+  .placeholder {
+    background-color: #ebebef;
+    color: #bbb;
+    text-align: center;
+    height: 30px;
+    line-height: 30px;
+    width: 100%;
+  }
+}
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index daa9099..8b308cd 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -241,7 +241,7 @@
             <div className="mob-tool">
               <div className="mob-tool-content">
                 <div className="plus-content">
-                  <Icon type="plus-circle" />娣� 鍔� 鍐� 瀹�
+                  <Icon type="plus-circle" />娣� 鍔� 缁� 浠�
                 </div>
                 <div className="useable-component">
                   <SourceWrap appType={appType} />

--
Gitblit v1.8.0