From a9a5211f48607fa7ac5bae91233f3a5e6df43587 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 20 一月 2022 14:09:04 +0800
Subject: [PATCH] 2022-01-20

---
 src/index.js                               |    2 
 src/views/imdesign/menuform/index.scss     |   25 
 src/views/appmanage/index.scss             |    4 
 src/pc/bgcontroller/index.jsx              |   25 
 src/views/pcdesign/index.jsx               |   26 
 src/mob/modulesource/dragsource/index.jsx  |    2 
 src/menu/replaceField/index.jsx            |    2 
 src/router/index.js                        |    2 
 src/menu/pastecontroller/index.jsx         |    2 
 public/options.json                        |   14 
 src/views/rolemanage/index.jsx             |   70 +
 src/assets/img/back.jpg                    |    0 
 src/views/mobdesign/index.scss             |   46 +
 src/views/pcdesign/index.scss              |   11 
 src/views/appmanage/index.jsx              |   69 +-
 src/views/imdesign/index.scss              |  341 ++++++++++++
 src/views/imdesign/index.jsx               |  597 ++++++++++++++++++++++
 src/views/appmanage/submutilform/index.jsx |   67 +-
 src/views/mobdesign/index.jsx              |  148 ++++
 src/menu/sysinterface/index.jsx            |    2 
 src/views/imdesign/menuform/index.jsx      |   77 ++
 src/views/imdesign/options.jsx             |   29 +
 22 files changed, 1,439 insertions(+), 122 deletions(-)

diff --git a/public/options.json b/public/options.json
index 0f5b891..f317ad5 100644
--- a/public/options.json
+++ b/public/options.json
@@ -1,17 +1,17 @@
 {
-  "appId": "202108312122504607B107A83F55B40C98CCF",
-  "appkey": "20210831212235413F287EC3BF489424496C8",
+  "appId": "201912040924165801464FF1788654BC5AC73",
+  "appkey": "20191106103859640976D6E924E464D029CF0",
   "mainSystemApi": "http://sso.mk9h.cn/cloud/webapi/dostars",
   "systemType": "",
   "externalDatabase": "false",
   "lineColor": "",
   "filter": "false",
-  "defaultApp": "mkindustry",
+  "defaultApp": "mk",
   "defaultLang": "zh-CN",
   "WXAppID": "",
   "debugger": false,
-  "licenseKey": "7EFE13KIKKILIJ7C8CFC",
-  "probation": "2021-12-31",
-  "host": "http://demo.mk9h.cn",
-  "service": "erp_new/"
+  "licenseKey": "",
+  "probation": "",
+  "host": "http://qingqiumarket.cn",
+  "service": "MKWMS/"
 }
\ No newline at end of file
diff --git a/src/assets/img/back.jpg b/src/assets/img/back.jpg
new file mode 100644
index 0000000..d06b32b
--- /dev/null
+++ b/src/assets/img/back.jpg
Binary files differ
diff --git a/src/index.js b/src/index.js
index cee8479..02692e1 100644
--- a/src/index.js
+++ b/src/index.js
@@ -34,7 +34,7 @@
   })())
 }
 
-const render  = Component => {
+const render = Component => {
   ReactDOM.render(
     <Provider store={store}>
       <Component/>
diff --git a/src/menu/pastecontroller/index.jsx b/src/menu/pastecontroller/index.jsx
index f0cb87c..858866b 100644
--- a/src/menu/pastecontroller/index.jsx
+++ b/src/menu/pastecontroller/index.jsx
@@ -109,7 +109,7 @@
     const { visible } = this.state
 
     return (
-      <div style={{display: 'inline-block'}}>
+      <div className="mk-view-paste" style={{display: 'inline-block'}}>
         <Button style={{borderColor: '#40a9ff', color: '#40a9ff'}} onClick={() => {this.setState({visible: true})}}><SnippetsOutlined />绮樿创</Button>
         <Modal
           title="绮樿创"
diff --git a/src/menu/replaceField/index.jsx b/src/menu/replaceField/index.jsx
index d965cba..74e0380 100644
--- a/src/menu/replaceField/index.jsx
+++ b/src/menu/replaceField/index.jsx
@@ -358,7 +358,7 @@
     const { visible, loadingTable, tables, confirming } = this.state
 
     return (
-      <div style={{display: 'inline-block'}}>
+      <div className="mk-replace-field" style={{display: 'inline-block'}}>
         <Button className="mk-border-yellow" icon="swap" loading={loadingTable} onClick={this.trigger}>瀛楁鏇挎崲</Button>
         <Modal
           title="瀛楁鏇挎崲"
diff --git a/src/menu/sysinterface/index.jsx b/src/menu/sysinterface/index.jsx
index 589f57b..bec6e8a 100644
--- a/src/menu/sysinterface/index.jsx
+++ b/src/menu/sysinterface/index.jsx
@@ -177,7 +177,7 @@
     const { visible, setvisible, columns, interfaces, card } = this.state
 
     return (
-      <div style={{display: 'inline-block'}}>
+      <div className="mk-sys-interface" style={{display: 'inline-block'}}>
         <Button className="mk-border-green" onClick={this.trigger}><ApiOutlined /> 鎺ュ彛绠$悊</Button>
         <Modal
           title="鎺ュ彛绠$悊"
diff --git a/src/mob/modulesource/dragsource/index.jsx b/src/mob/modulesource/dragsource/index.jsx
index 7b5a6ea..5e00912 100644
--- a/src/mob/modulesource/dragsource/index.jsx
+++ b/src/mob/modulesource/dragsource/index.jsx
@@ -6,7 +6,7 @@
 const MobSourceElement = ({item, triggerDel}) => {
   const [, drag] = useDrag({ item })
   return (
-    <div className="menu-source-item">
+    <div className={'menu-source-item ' + item.component + '-' + item.subtype}>
       <div className="property"><span>{item.title}</span>{item.config ? <CloseCircleOutlined onClick={() => triggerDel(item)}/> : null}</div>
       <img ref={drag} src={item.url} alt=""/>
     </div>
diff --git a/src/pc/bgcontroller/index.jsx b/src/pc/bgcontroller/index.jsx
index 63c0545..9b149f7 100644
--- a/src/pc/bgcontroller/index.jsx
+++ b/src/pc/bgcontroller/index.jsx
@@ -23,7 +23,7 @@
     backgroundImage: '',
     backgroundSize: '',
     backgroundRepeat: '',
-    backgroundPositon: '',
+    backgroundPosition: '',
     opacity: '',
   }
 
@@ -42,7 +42,7 @@
       backgroundImage: bgImg,
       backgroundSize: config.style.backgroundSize || '100%',
       backgroundRepeat: config.style.backgroundRepeat || 'repeat',
-      backgroundPositon: config.style.backgroundPositon || 'center'
+      backgroundPosition: config.style.backgroundPosition || 'center'
     })
   }
 
@@ -114,18 +114,18 @@
 
   backgroundPositonChange = (val) => {
     this.setState({
-      backgroundPositon: val
+      backgroundPosition: val
     })
 
     let config = fromJS(this.props.config).toJS()
-    config.style.backgroundPositon = val
+    config.style.backgroundPosition = val
 
     this.props.updateConfig(config)
   }
 
   render () {
     const { config } = this.props
-    const { backgroundColor, backgroundImage, backgroundSize, backgroundRepeat, backgroundPositon } = this.state
+    const { backgroundColor, backgroundImage, backgroundSize, backgroundRepeat, backgroundPosition } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -143,6 +143,7 @@
           <Form.Item
             colon={false}
             label="瀹藉害"
+            className="normal-view"
           >
             <StyleInput defaultValue={config.style.width || '100%'} options={['px', '%', 'vw']} onChange={(val) => this.changePadding(val, 'width')}/>
           </Form.Item>
@@ -170,58 +171,66 @@
             </Select>
           </Form.Item>
           <Form.Item colon={false} label="浣嶇疆">
-            <Select defaultValue={backgroundPositon} onChange={this.backgroundPositonChange}>
+            <Select defaultValue={backgroundPosition} onChange={this.backgroundPositonChange}>
               <Option value="center">center</Option>
               <Option value="top">top</Option>
               <Option value="bottom">bottom</Option>
             </Select>
           </Form.Item>
-          <p style={{borderBottom: '1px solid #eaeaea', color: '#40a9ff'}}>鍐呰竟璺�</p>
+          <p className="normal-view" style={{borderBottom: '1px solid #eaeaea', color: '#40a9ff'}}>鍐呰竟璺�</p>
           <Form.Item
             colon={false}
+            className="normal-view"
             label={<ArrowUpOutlined title="涓婅竟璺�"/>}
           >
             <StyleInput defaultValue={config.style.paddingTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingTop')}/>
           </Form.Item>
           <Form.Item
             colon={false}
+            className="normal-view"
             label={<ArrowDownOutlined title="涓嬭竟璺�"/>}
           >
             <StyleInput defaultValue={config.style.paddingBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingBottom')}/>
           </Form.Item>
           <Form.Item
             colon={false}
+            className="normal-view"
             label={<ArrowLeftOutlined title="宸﹁竟璺�"/>}
           >
             <StyleInput defaultValue={config.style.paddingLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingLeft')}/>
           </Form.Item>
           <Form.Item
             colon={false}
+            className="normal-view"
             label={<ArrowRightOutlined title="鍙宠竟璺�"/>}
           >
             <StyleInput defaultValue={config.style.paddingRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingRight')}/>
           </Form.Item>
-          <p style={{borderBottom: '1px solid #eaeaea', color: '#40a9ff'}}>澶栬竟璺�</p>
+          <p className="normal-view" style={{borderBottom: '1px solid #eaeaea', color: '#40a9ff'}}>澶栬竟璺�</p>
           <Form.Item
             colon={false}
+            className="normal-view"
             label={<ArrowUpOutlined title="涓婅竟璺�"/>}
           >
             <StyleInput defaultValue={config.style.marginTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginTop')}/>
           </Form.Item>
           <Form.Item
             colon={false}
+            className="normal-view"
             label={<ArrowDownOutlined title="涓嬭竟璺�"/>}
           >
             <StyleInput defaultValue={config.style.marginBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginBottom')}/>
           </Form.Item>
           <Form.Item
             colon={false}
+            className="normal-view"
             label={<ArrowLeftOutlined title="宸﹁竟璺�"/>}
           >
             <StyleInput defaultValue={config.style.marginLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginLeft')}/>
           </Form.Item>
           <Form.Item
             colon={false}
+            className="normal-view"
             label={<ArrowRightOutlined title="鍙宠竟璺�"/>}
           >
             <StyleInput defaultValue={config.style.marginRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginRight')}/>
diff --git a/src/router/index.js b/src/router/index.js
index 78c75a3..204b72b 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -16,6 +16,7 @@
 const AppCheck = asyncLoadComponent(() => import('@/views/appcheck'))
 const PCDesign = asyncLoadComponent(() => import('@/views/pcdesign'))
 const MobDesign = asyncLoadComponent(() => import('@/views/mobdesign'))
+const ImDesign = asyncLoadComponent(() => import('@/views/imdesign'))
 const MenuDesign = asyncLoadComponent(() => import('@/views/menudesign'))
 const BillPrint = asyncLoadComponent(() => import('@/views/billprint'))
 const PrintT = asyncLoadComponent(() => import('@/views/printTemplate'))
@@ -33,6 +34,7 @@
   {path: '/appcheck', name: 'appcheck', component: AppCheck, auth: true},
   {path: '/pcdesign/:param', name: 'pcdesign', component: PCDesign, auth: true},
   {path: '/mobdesign/:param', name: 'mobdesign', component: MobDesign, auth: true},
+  {path: '/imdesign/:param', name: 'imdesign', component: ImDesign, 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/views/appmanage/index.jsx b/src/views/appmanage/index.jsx
index 66bc9b7..a9081be 100644
--- a/src/views/appmanage/index.jsx
+++ b/src/views/appmanage/index.jsx
@@ -467,8 +467,8 @@
               } catch (e) {
                 _param = {}
               }
-              cell.copyright = _param.copyright || ''
-              cell.logo = _param.logo || ''
+              // cell.copyright = _param.copyright || ''
+              // cell.logo = _param.logo || ''
               cell.apptype = _param.apptype || ''
               cell.delay = _param.delay || 0
               cell.statusBarColor = _param.statusBarColor || 'black'
@@ -477,10 +477,17 @@
               if (cell.adapter && (cell.adapter === 'true' || cell.adapter === 'false')) {
                 cell.adapter = ''
               }
+
+              cell.userbind = _param.userbind || ''
+              cell.instantMessage = _param.instantMessage || ''
             }
 
-            if (!cell.adapter && (cell.user_binding || cell.apptype)) {
-              cell.adapter = 'app,weixin'
+            if (cell.user_binding !== 'true') {
+              cell.user_binding = 'false'
+            }
+
+            if (!cell.adapter && cell.apptype) {
+              cell.adapter = 'app'
             }
 
             return cell
@@ -616,9 +623,16 @@
 
     let sublist = fromJS(selectApp.sublist).toJS()
     sublist = sublist.filter(item => item.ID !== record.ID)
+    sublist = sublist.map(item => {
+      if (item.typename !== 'pc') {
+        item.userbind = md5(selectApp.kei_no + item.typename + item.lang).replace(/^.{8}/, 'userbind')
+        item.instantMessage = md5(selectApp.kei_no + item.typename + item.lang).replace(/^.{14}/, 'instantmessage')
+      }
+      return item
+    })
 
-    // param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','${item.login_types || 'true'}','${item.link_type || 'true'}','${item.role_type || 'true'}','${item.lang || 'zh-CN'}'`)
-    param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || ''}','${item.sms_id || ''}','${window.btoa(window.encodeURIComponent(JSON.stringify({copyright: item.copyright || '', logo: item.logo || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', adapter: item.adapter || ''})))}'`)
+    // 瀛愬簲鐢↖D銆乼ypename銆佸簲鐢↖D銆丆loudUserID銆乤ppkey銆乴ogin_types(鏄惁闇�瑕佺櫥褰曪紝宸插純鐢�)銆乴ink_type(鏄惁浣跨敤鐭繛鎺ワ紝宸插純鐢�)銆乺ole_type(鏄惁浣跨敤瑙掕壊绠$悊)銆乴ang銆乧ss(鐨偆)銆乼itle(鏍囬)銆乫avicon(鍥炬爣)銆乽ser_binding(鐢ㄦ埛缁戝畾)銆乻ms_id(鐭俊妯℃澘ID)銆佽嚜瀹氫箟
+    param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', adapter: item.adapter || ''})))}'`)
     param.LText = param.LText.join(' union all ')
     param.LText = Utils.formatOptions(param.LText)
     
@@ -841,8 +855,15 @@
       param.secretkey = Utils.encrypt('', param.timestamp)
 
       if (visible === 'edit') {
-        // param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','${item.login_types || 'true'}','${item.link_type || 'true'}','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}'`)
-        param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || ''}','${item.sms_id || ''}','${window.btoa(window.encodeURIComponent(JSON.stringify({copyright: item.copyright || '', logo: item.logo || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', adapter: item.adapter || ''})))}'`)
+        selectApp.sublist = selectApp.sublist.map(item => {
+          if (item.typename !== 'pc') {
+            item.userbind = md5(selectApp.kei_no + item.typename + item.lang).replace(/^.{8}/, 'userbind')
+            item.instantMessage = md5(selectApp.kei_no + item.typename + item.lang).replace(/^.{14}/, 'instantmessage')
+          }
+          return item
+        })
+
+        param.LText = selectApp.sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', adapter: item.adapter || ''})))}'`)
         param.LText = param.LText.join(' union all ')
         param.LText = Utils.formatOptions(param.LText)
       }
@@ -927,8 +948,15 @@
         })
       }
 
-      // param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','${item.login_types || 'true'}','${item.link_type || 'true'}','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}'`)
-      param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || ''}','${item.sms_id || ''}','${window.btoa(window.encodeURIComponent(JSON.stringify({copyright: item.copyright || '', logo: item.logo || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', adapter: item.adapter || ''})))}'`)
+      sublist = sublist.map(item => {
+        if (item.typename !== 'pc') {
+          item.userbind = md5(selectApp.kei_no + item.typename + item.lang).replace(/^.{8}/, 'userbind')
+          item.instantMessage = md5(selectApp.kei_no + item.typename + item.lang).replace(/^.{14}/, 'instantmessage')
+        }
+        return item
+      })
+
+      param.LText = sublist.map(item => `select '${item.ID}','${item.typename}','${selectApp.ID}','${sessionStorage.getItem('CloudUserID') || ''}','${window.GLOB.appkey || ''}','false','false','${item.role_type || 'true'}','${item.lang || 'zh-CN'}','${item.css || ''}','${item.title || ''}','${item.favicon || ''}','${item.user_binding || 'false'}','','${window.btoa(window.encodeURIComponent(JSON.stringify({userbind: item.userbind || '', instantMessage: item.instantMessage || '', apptype: item.apptype || '', delay: item.delay || 0, statusBarColor: item.statusBarColor || 'black', sysBgColor: item.sysBgColor || '#ffffff', adapter: item.adapter || ''})))}'`)
       param.LText = param.LText.join(' union all ')
       param.LText = Utils.formatOptions(param.LText)
 
@@ -1046,13 +1074,8 @@
                 let css = skinStyle[item.css] ? skinStyle[item.css].name : ''
                 let color = skinStyle[item.css] ? skinStyle[item.css].color : '#e8e8e8'
                 let binding = ''
-                if (item.user_binding) {
-                  if (item.user_binding.indexOf('uname_pwd') > -1) {
-                    binding = '鐢ㄦ埛鍚�'
-                  }
-                  if (item.user_binding.indexOf('sms_vcode') > -1) {
-                    binding = binding ? binding + '锛屾墜鏈哄彿' : '鎵嬫満鍙�'
-                  }
+                if (item.user_binding === 'true') {
+                  binding = '闇�瑕�'
                 }
                 return (
                   <div className="sub-app" key={index} style={{borderColor: color}}>
@@ -1108,18 +1131,6 @@
                         <div className="app-item">
                           <div className="label">缃戠珯澶村儚:</div>
                           <div className="content">{item.favicon ? <img style={{width: '18px', height: '18px'}} src={item.favicon} alt="" /> : '鏃�'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">鐗堟潈:</div>
-                          <div className="content">{item.copyright || '鏃�'}</div>
-                        </div>
-                      </Col>
-                      <Col span={12}>
-                        <div className="app-item">
-                          <div className="label">LOGO:</div>
-                          <div className="content">{item.logo ? <img style={{height: '18px'}} src={item.logo} alt="" /> : '鏃�'}</div>
                         </div>
                       </Col>
                     </Row>
diff --git a/src/views/appmanage/index.scss b/src/views/appmanage/index.scss
index 2594659..65395e4 100644
--- a/src/views/appmanage/index.scss
+++ b/src/views/appmanage/index.scss
@@ -66,7 +66,7 @@
       .sub-app {
         margin: 10px 10px 25px;
         border: 1px solid #e8e8e8;
-        height: 210px;
+        height: 185px;
         border-radius: 4px;
         padding-top: 10px;
 
@@ -95,7 +95,7 @@
         .action {
           text-align: right;
           padding: 5px 20px;
-          margin-top: 5px;
+          margin-top: 10px;
           border-top: 1px solid #e8e8e8;
 
           .ant-typography-copy {
diff --git a/src/views/appmanage/submutilform/index.jsx b/src/views/appmanage/submutilform/index.jsx
index 0579e45..bc52f1f 100644
--- a/src/views/appmanage/submutilform/index.jsx
+++ b/src/views/appmanage/submutilform/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Select, Radio, Input, Tooltip, notification, InputNumber, Checkbox } from 'antd'
+import { Form, Row, Col, Select, Radio, Input, Tooltip, InputNumber, Checkbox } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -16,26 +16,19 @@
     inputSubmit: PropTypes.func  // input鍥炶溅鎻愪氦
   }
 
-  state = {msgs: [], typename: 'mob', user_binding: [], adapters: []}
+  state = {typename: 'mob', adapters: []}
 
   UNSAFE_componentWillMount() {
     const { card } = this.props
-    let msgs = sessionStorage.getItem('msgTemplate')
-    let user_binding = []
     let adapters = []
     let typename = 'mob'
 
     if (card) {
       typename = card.typename || 'mob'
-      user_binding = card.user_binding ? card.user_binding.split(',') : []
       adapters = card.adapter ? card.adapter.split(',') : []
-
-      if (!adapters.includes('weixin') && !adapters.includes('wxmini')) {
-        user_binding = []
-      }
     }
 
-    this.setState({msgs: JSON.parse(msgs), typename, user_binding, adapters})
+    this.setState({typename, adapters})
   }
 
   /**
@@ -45,31 +38,31 @@
     return new Promise(resolve => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
-          values.user_binding = values.user_binding ? values.user_binding.join(',') : ''
+          // values.user_binding = values.user_binding ? values.user_binding.join(',') : ''
           values.adapter = values.adapter ? values.adapter.join(',') : ''
-          if (values.user_binding.indexOf('sms_vcode') > -1 && !values.sms_id) {
-            notification.warning({
-              top: 92,
-              message: '鎵嬫満鍙风粦瀹氭椂锛岄渶瑕佺煭淇℃ā鏉匡紒',
-              duration: 5
-            })
-            return
-          }
+          // if (values.user_binding.indexOf('sms_vcode') > -1 && !values.sms_id) {
+          //   notification.warning({
+          //     top: 92,
+          //     message: '鎵嬫満鍙风粦瀹氭椂锛岄渶瑕佺煭淇℃ā鏉匡紒',
+          //     duration: 5
+          //   })
+          //   return
+          // }
           resolve(values)
         }
       })
     })
   }
 
-  onChange = (vals) => {
-    this.setState({user_binding: vals})
-  }
+  // onChange = (vals) => {
+  //   this.setState({user_binding: vals})
+  // }
 
   onAdapterChange = (vals) => {
     this.setState({adapters: vals})
-    if (!vals.includes('weixin') && !vals.includes('wxmini')) {
-      this.setState({user_binding: []})
-    }
+    // if (!vals.includes('weixin') && !vals.includes('wxmini')) {
+    //   this.setState({user_binding: []})
+    // }
   }
 
   /**
@@ -83,7 +76,7 @@
   render() {
     const { card, type } = this.props
     const { getFieldDecorator } = this.props.form
-    const { msgs, typename, user_binding, adapters } = this.state
+    const { typename, adapters } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -175,16 +168,20 @@
           {typename !== 'pc' && (adapters.includes('weixin') || adapters.includes('wxmini')) ? <Col span={12}>
             <Form.Item label="鐢ㄦ埛缁戝畾">
               {getFieldDecorator('user_binding', {
-                initialValue: user_binding
+                initialValue: card ? card.user_binding : 'false'
               })(
-                <Checkbox.Group onChange={this.onChange}>
-                  <Checkbox value="uname_pwd">璐﹀彿</Checkbox>
-                  <Checkbox value="sms_vcode">鎵嬫満鐭俊</Checkbox>
-                </Checkbox.Group>
+                <Radio.Group>
+                  <Radio value="true">闇�瑕�</Radio>
+                  <Radio value="false">涓嶉渶瑕�</Radio>
+                </Radio.Group>
+                // <Checkbox.Group onChange={this.onChange}>
+                //   <Checkbox value="uname_pwd">璐﹀彿</Checkbox>
+                //   <Checkbox value="sms_vcode">鎵嬫満鐭俊</Checkbox>
+                // </Checkbox.Group>
               )}
             </Form.Item>
           </Col> : null}
-          {typename !== 'pc' && user_binding.includes('sms_vcode') ? <Col span={12}>
+          {/* {typename !== 'pc' && user_binding.includes('sms_vcode') ? <Col span={12}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="鐭俊妯℃澘鍙湪 浜戠郴缁�->搴旂敤鏈嶅姟->寮�鍙戣�呬腑蹇�->鐭俊妯℃澘 澶勬坊鍔犮��">
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -205,7 +202,7 @@
                 </Select>
               )}
             </Form.Item>
-          </Col> : null}
+          </Col> : null} */}
           <Col span={12}>
             <Form.Item label="鏍囬">
               {getFieldDecorator('title', {
@@ -222,7 +219,7 @@
               )}
             </Form.Item>
           </Col>
-          {typename !== 'pc' && user_binding.length > 0 ? <Col span={12}>
+          {/* {typename !== 'pc' && user_binding.length > 0 ? <Col span={12}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="浣跨敤寰俊鎺堟潈鐧诲綍鏃讹紝缁戝畾鐢ㄦ埛椤甸潰鐨勭増鏉冨0鏄庯紝娉細鍙坊鍔爃tml鏍囩銆�">
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -247,7 +244,7 @@
                 <SourceComponent type="picture" placement="right"/>
               )}
             </Form.Item>
-          </Col> : null}
+          </Col> : null} */}
           {typename !== 'pc' && adapters.includes('app') ? <Col span={12}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="鍦ㄤ娇鐢ㄦ槑绉戜簯APP鏃讹紝椤甸潰鐨勫垏鎹㈡ā寮�">
diff --git a/src/views/imdesign/index.jsx b/src/views/imdesign/index.jsx
new file mode 100644
index 0000000..8282715
--- /dev/null
+++ b/src/views/imdesign/index.jsx
@@ -0,0 +1,597 @@
+import React, { Component } from 'react'
+import { DndProvider } from 'react-dnd'
+import { withRouter } from 'react-router'
+import { is, fromJS } from 'immutable'
+import moment from 'moment'
+import HTML5Backend from 'react-dnd-html5-backend'
+import { ConfigProvider, notification, Modal, Collapse, Button, Spin } from 'antd'
+import { DoubleLeftOutlined, DoubleRightOutlined, LeftOutlined, UserOutlined, EllipsisOutlined } from '@ant-design/icons'
+
+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 MKEmitter from '@/utils/events.js'
+import asyncComponent from '@/utils/asyncComponent'
+import getWrapForm from './options'
+
+import './index.scss'
+
+const { Panel } = Collapse
+const { confirm } = Modal
+
+const Header = asyncComponent(() => import('@/mob/header'))
+const MenuForm = asyncComponent(() => import('./menuform'))
+const CreateView = asyncComponent(() => import('@/pc/createview'))
+const Transfer = asyncComponent(() => import('@/pc/transfer'))
+const BgController = asyncComponent(() => import('@/pc/bgcontroller'))
+const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
+const NormalForm = asyncComponent(() => import('@/components/normalform'))
+
+sessionStorage.setItem('isEditState', 'true')
+sessionStorage.setItem('appType', 'mob')       // 搴旂敤绫诲瀷
+document.body.className = ''
+window.GLOB.CacheIndependent = new Map()
+
+class ImDesign extends Component {
+  state = {
+    localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
+    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    loading: true,
+    MenuId: '',
+    MenuName: '',
+    MenuNo: '',
+    menuloading: false,
+    oriConfig: null,
+    config: null,
+    direction: 'vertical',
+    settingshow: true,
+    controlshow: true,
+    adapters: [],
+  }
+
+  UNSAFE_componentWillMount() {
+    try {
+      let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
+
+      if (param.type === 'app') {
+        sessionStorage.setItem('appId', param.ID || '')
+        sessionStorage.setItem('lang', param.lang || 'zh-CN')
+        sessionStorage.setItem('kei_no', param.kei_no || '')
+        sessionStorage.setItem('role_type', param.role_type || 'true')
+        sessionStorage.setItem('login_types', param.login_types || 'false')
+        sessionStorage.setItem('typename', param.typename || 'mob')
+        sessionStorage.setItem('adapter', param.adapter || '')
+        sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
+        sessionStorage.setItem('userbind', param.userbind || '')
+        sessionStorage.setItem('instantMessage', param.instantMessage || '')
+
+        this.setState({
+          localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
+          dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
+        })
+        this.getAppMessage(param.MenuID)
+      } else if (param.type === 'view') {
+        window.GLOB.winWidth = 420
+        window.GLOB.winHeight = 738
+        window.GLOB.shellWidth = 376
+        window.GLOB.shellHeight = 680
+
+        if (sessionStorage.getItem('typename') === 'pad') {
+          window.GLOB.winWidth = 736
+          window.GLOB.winHeight = 945
+          window.GLOB.shellWidth = 640
+          window.GLOB.shellHeight = 853
+        }
+
+        let adapters = sessionStorage.getItem('adapter')
+        if (adapters) {
+          adapters = adapters.split(',')
+        } else {
+          adapters = []
+        }
+
+        this.setState({
+          adapters,
+          MenuId: param.MenuID,
+        }, () => {
+          this.getMenuParam()
+        })
+      }
+    } catch (e) {
+      notification.warning({
+        top: 92,
+        message: '鑿滃崟淇℃伅瑙f瀽閿欒锛�',
+        duration: 5
+      })
+    }
+  }
+
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    if (this.props.match.params.param !== nextProps.match.params.param) {
+      window.location.reload()
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentDidMount () {
+    setTimeout(() => {
+      this.getAppPictures()
+    }, 1000)
+
+    document.onkeydown = (event) => {
+      let e = event || window.event
+      let keyCode = e.keyCode || e.which || e.charCode
+      let preKey = ''
+
+      if (e.ctrlKey) {
+        preKey = 'ctrl'
+      }
+      if (e.shiftKey) {
+        preKey = 'shift'
+      } else if (e.altKey) {
+        preKey = 'alt'
+      }
+      
+      if (!preKey || !keyCode) return
+      
+      let _shortcut = `${preKey}+${keyCode}`
+
+      if (_shortcut === 'ctrl+83') {
+        let node = document.getElementById('save-config')
+        if (node) {
+          node.click()
+        }
+        return false
+      }
+    }
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  changeEditMenu = () => {
+    const { oriConfig, config } = this.state
+
+    if (!oriConfig || !is(fromJS(oriConfig), fromJS(config))) {
+      notification.warning({
+        top: 92,
+        message: '閰嶇疆淇℃伅鏈繚瀛橈紒',
+        duration: 5
+      })
+      return
+    }
+
+    let param = {
+      MenuID: config.wrap.linkmenu,
+      copyMenuId: '',
+      type: 'view'
+    }
+
+    param = window.btoa(window.encodeURIComponent(JSON.stringify(param)))
+
+    this.props.history.push('/mobdesign/' + param)
+  }
+
+  getAppMessage = (MenuID) => {
+    Api.getSystemConfig({
+      func: 's_get_keyids',
+      bid: sessionStorage.getItem('appId')
+    }).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        return
+      }
+
+      let appViewList = []
+      if (res.data && res.data.length > 0) {
+        appViewList = res.data
+      }
+
+      sessionStorage.setItem('appViewList', JSON.stringify(appViewList))
+      this.props.history.replace('/imdesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({MenuID: MenuID, type: 'view'}))))
+    })
+  }
+
+  getAppPictures = () => {
+    if (sessionStorage.getItem('app_videos') || sessionStorage.getItem('app_pictures')) return
+
+    Api.getSystemConfig({
+      func: 's_url_db_adduptdel',
+      PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
+      PageSize: 0,   // 0 浠h〃鍏ㄩ儴
+      typecharone: 'image',
+      type: 'search'
+    }).then(res => {
+      if (res.status) {
+        sessionStorage.setItem('app_pictures', JSON.stringify(res.data || []))
+      }
+
+      Api.getSystemConfig({
+        func: 's_url_db_adduptdel',
+        PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
+        PageSize: 0,   // 0 浠h〃鍏ㄩ儴
+        typecharone: 'video',
+        type: 'search'
+      }).then(res => {
+        if (res.status) {
+          sessionStorage.setItem('app_videos', JSON.stringify(res.data || []))
+        }
+      })
+      Api.getSystemConfig({
+        func: 's_url_db_adduptdel',
+        PageIndex: 0,  // 0 浠h〃鍏ㄩ儴
+        PageSize: 0,   // 0 浠h〃鍏ㄩ儴
+        typecharone: 'color',
+        type: 'search'
+      }).then(res => {
+        if (res.status) {
+          sessionStorage.setItem('app_colors', JSON.stringify(res.data || []))
+        }
+      })
+    })
+  }
+
+  closeView = () => {
+    const { oriConfig, config } = this.state
+
+    if (!config) {
+      window.close()
+    } else if (!oriConfig || !is(fromJS(oriConfig), fromJS(config))) {
+      confirm({
+        title: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾鍏抽棴鍚楋紵',
+        content: '',
+        onOk() {
+          window.close()
+        },
+        onCancel() {}
+      })
+    } else {
+      window.close()
+    }
+  }
+
+  backView = () => {
+    const { oriConfig, config } = this.state
+
+    if (!config) {
+      window.history.back()
+    } else if (!oriConfig || !is(fromJS(oriConfig), fromJS(config))) {
+      confirm({
+        title: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾鍚庨��鍚楋紵',
+        content: '',
+        onOk() {
+          window.history.back()
+        },
+        onCancel() {}
+      })
+    } else {
+      window.history.back()
+    }
+  }
+
+  getMenuParam = () => {
+    const { MenuId } = this.state
+
+    let param = {
+      func: 'sPC_Get_LongParam',
+      TypeCharOne: sessionStorage.getItem('kei_no'),
+      typename: sessionStorage.getItem('typename'),
+      MenuID: MenuId
+    }
+
+    Api.getSystemConfig(param).then(result => {
+      if (!result.status) {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+        this.setState({loading: false})
+        return
+      } else {
+        let config = null
+        let isCreate = false
+
+        try {
+          config = result.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) : null
+        } catch (e) {
+          console.warn('Parse Failure')
+          config = null
+        }
+
+        if (!config) {
+          isCreate = true
+          config = {
+            version: 1.0,
+            uuid: MenuId,
+            MenuID: MenuId,
+            Template: 'imPage',
+            enabled: false,
+            MenuName: '鍗虫椂閫氫俊',
+            MenuNo: 'im',
+            tables: [],
+            components: [],
+            viewType: 'im',
+            wrap: {},
+            style: {
+              backgroundColor: '#ededed', backgroundImage: ''
+            }
+          }
+        }
+        
+        config.uuid = MenuId
+        config.MenuID = MenuId
+        config.open_edition = result.open_edition || ''
+
+        this.setState({
+          oriConfig: isCreate ? null : config,
+          config: fromJS(config).toJS(),
+          loading: false
+        })
+      }
+    })
+    this.getAppMenus()
+  }
+
+  getAppMenus = () => {
+    let _param = {
+      func: 's_get_app_menus',
+      TypeCharOne: sessionStorage.getItem('kei_no'),
+      typename: sessionStorage.getItem('typename'),
+      LText: `select '${window.GLOB.appkey}'`,
+      timestamp: moment().format('YYYY-MM-DD HH:mm:ss')
+    }
+
+    _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
+
+    Api.getSystemConfig(_param).then(res => {
+      if (!res.status) {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+        return
+      }
+
+      let appIndeList = sessionStorage.getItem('appViewList')
+      appIndeList = JSON.parse(appIndeList)
+      appIndeList = appIndeList.map(item => (item.keys_type !== 'index' ? item.keys_id : '')).join(',')
+
+      if (sessionStorage.getItem('userbind')) {
+        appIndeList = appIndeList + ',' + sessionStorage.getItem('userbind')
+      }
+      if (sessionStorage.getItem('instantMessage')) {
+        appIndeList = appIndeList + ',' + sessionStorage.getItem('instantMessage')
+      }
+
+      let menus = res.menus.filter(item => appIndeList.indexOf(item.MenuID) === -1)
+      menus = menus.map(item => {
+        item.value = item.MenuID
+        item.label = item.MenuName
+        return item
+      })
+      sessionStorage.setItem('appMenus', JSON.stringify(menus))
+    })
+  }
+
+  submitConfig = () => {
+    const { adapters } = this.state
+    let config = fromJS(this.state.config).toJS()
+
+    if (!config.MenuName || !config.MenuNo) {
+      notification.warning({
+        top: 92,
+        message: '璇峰畬鍠勮彍鍗曞熀鏈俊鎭紒',
+        duration: 5
+      })
+      this.setState({
+        settingshow: true
+      })
+      return
+    }
+
+    this.setState({
+      menuloading: true
+    })
+
+    setTimeout(() => {
+      let roleParam = {type: 'im', key: config.uuid, title: config.MenuName, children: []}
+
+      if (adapters.includes('wxmini')) {
+        config = this.getMiniStyle(config)
+      }
+
+      let param = {
+        func: 'sPC_TrdMenu_AddUpt',
+        FstID: 'mk_app',
+        SndID: 'mk_app',
+        ParentID: 'mk_app',
+        MenuID: config.uuid,
+        MenuNo: config.MenuNo || '',
+        EasyCode: '',
+        Template: 'imPage',
+        TypeCharOne: sessionStorage.getItem('kei_no'),
+        Typename: sessionStorage.getItem('typename'),
+        MenuName: config.MenuName || '',
+        PageParam: JSON.stringify({Template: 'imPage'}),
+        open_edition: config.open_edition,
+        menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roleParam))),
+        LText: '',
+        LTexttb: ''
+      }
+
+      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+      param.secretkey = Utils.encrypt('', param.timestamp)
+
+      let _config = fromJS(config).toJS()
+
+      param.LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
+
+      Api.getSystemConfig(param).then(res => {
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 5
+          })
+          this.setState({
+            menuloading: false
+          })
+          return
+        }
+
+        config.open_edition = res.open_edition || ''
+        
+        this.setState({
+          config,
+          oriConfig: fromJS(config).toJS(),
+          menuloading: false
+        })
+
+        notification.success({
+          top: 92,
+          message: '淇濆瓨鎴愬姛',
+          duration: 2
+        })
+      })
+    }, 300)
+  }
+
+  getWrapForms = () => {
+    const { config } = this.state
+
+    return getWrapForm(config.wrap)
+  }
+
+  updateWrap = (res) => {
+    let _config = {...this.state.config, wrap: res}
+
+    this.setState({
+      config: _config
+    })
+  }
+
+  // 鏇存柊閰嶇疆淇℃伅
+  updateConfig = (config) => {
+    this.setState({
+      config: config
+    })
+  }
+
+  render () {
+    const { localedict, loading, settingshow, controlshow, dict, MenuId, config, menuloading, adapters } = this.state
+
+    return (
+      <ConfigProvider locale={localedict}>
+        <div className="mk-mob-view" id="mk-mob-design-view">
+          <Header/>
+          {loading ? <Spin className="view-spin" size="large" /> : null}
+          <DndProvider backend={HTML5Backend}>
+            <div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}>
+              <div className="draw">
+                {settingshow ? <DoubleLeftOutlined onClick={() => {this.setState({settingshow: false})}} /> : null}
+                {!settingshow ? <DoubleRightOutlined onClick={() => {this.setState({settingshow: true})}} /> : null}
+              </div>
+              <div className="pc-setting-tools">
+                <Collapse accordion defaultActiveKey="basedata" bordered={false}>
+                  {/* 鍩烘湰淇℃伅 */}
+                  <Panel header={dict['mob.basemsg']} forceRender key="basedata">
+                    {/* 鑿滃崟淇℃伅 */}
+                    {config ? <MenuForm
+                      dict={dict}
+                      config={config}
+                      MenuId={MenuId}
+                      adapters={adapters}
+                      updateConfig={this.updateConfig}
+                    /> : null}
+                  </Panel>
+                  <Panel header={'椤甸潰鏍峰紡'} key="background">
+                    {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
+                  </Panel>
+                </Collapse>
+              </div>
+            </div>
+            <div className={'menu-control ' + (!controlshow ? 'hidden' : '')}>
+              <div className="draw">
+                {controlshow ? <DoubleRightOutlined onClick={() => {this.setState({controlshow: false})}}/> : null}
+                {!controlshow ? <DoubleLeftOutlined onClick={() => {this.setState({controlshow: true})}}/> : null}
+              </div>
+              <div className="wrap">
+                <Button type="primary" onClick={this.submitConfig} id="save-config" loading={menuloading}>{dict['mob.save']}</Button>
+                <NormalForm title="鍗虫椂閫氫俊璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
+                  <Button type="default" style={{borderColor: 'rgb(64, 169, 255)', color: 'rgb(64, 169, 255)'}}>璁剧疆</Button>
+                </NormalForm>
+                <Button type="default" className="mk-border-purple" onClick={this.backView}>鍚庨��</Button>
+                <CreateView resetmenu={this.getAppMenus} />
+                <Transfer MenuID={MenuId} />
+                <Button type="default" onClick={this.closeView}>鍏抽棴</Button>
+              </div>
+            </div>
+            <div className={'menu-body menu-view'}>
+              <div className="mob-shell" style={{width: window.GLOB.shellWidth, height: window.GLOB.shellHeight}}>
+                <div className="instant-message" style={config ? config.style : null}>
+                  <div className="header">
+                    <LeftOutlined/>
+                    <span className="title">friend</span>
+                    {config && config.wrap.linkmenu ? <EllipsisOutlined onClick={this.changeEditMenu}/> : null}
+                  </div>
+                  <div className="mk-content-wrap">
+                    <div className="line-wrap">
+                      <div className="time-line">12:34</div>
+                      <div className="line-msg">
+                        <div className="portrait">
+                          <div className="img"><UserOutlined /></div>
+                        </div>
+                        <div className="msg">
+                          <div className="title">friend</div>
+                          <div className="words">鎮ㄥソ</div>
+                        </div>
+                      </div>
+                    </div>
+                    <div className="line-wrap">
+                      <div className="time-line">12:45</div>
+                      <div className="line-msg right">
+                        <div className="msg">
+                          <div className="words">
+                            鎮ㄥソ
+                          </div>
+                        </div>
+                        <div className="portrait">
+                          <div className="img"><UserOutlined /></div>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                  <div className="send-wrap">
+                    <div className="adm-input"></div>
+                    <div className="send"><Button>鍙戦��</Button></div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </DndProvider>
+          <StyleController />
+        </div>
+      </ConfigProvider>
+    )
+  }
+}
+
+export default withRouter(ImDesign)
\ No newline at end of file
diff --git a/src/views/imdesign/index.scss b/src/views/imdesign/index.scss
new file mode 100644
index 0000000..9a392f8
--- /dev/null
+++ b/src/views/imdesign/index.scss
@@ -0,0 +1,341 @@
+.mk-mob-view {
+  min-height: 100vh;
+
+  .change-view {
+    display: none;
+  }
+  >.view-spin {
+    position: absolute;
+    z-index: 3;
+    left: calc(50% - 16px);
+    top: calc(50vh - 70px);
+  }
+  .modal-form-board {
+    padding-top: 0;
+  }
+  .menu-setting {
+    position: fixed;
+    left: 0;
+    top: 48px;
+    z-index: 10;
+    transition: left 0.3s;
+
+    .draw {
+      position: absolute;
+      z-index: 1;
+      background: #ffffff;
+      right: -20px;
+      top: 0px;
+      box-shadow: 0 0 1px #959595;
+      border-radius: 0 2px 2px 0px;
+
+      .anticon {
+        padding: 12px 3px;
+      }
+    }
+
+    .pc-setting-tools {
+      height: calc(100vh - 48px);
+      width: 300px;
+      background: #ffffff;
+      overflow-y: auto;
+      overflow-x: hidden;
+      padding-bottom: 50px;
+
+      .normal-view {
+        display: none;
+      }
+
+      > .ant-collapse {
+        background-color: #ffffff;
+        .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.hidden {
+    left: -300px;
+  }
+  .mob-shell {
+    margin: 0 auto;
+    background: #000000;
+    background-size: 100% 100%;
+    padding: 25px 13px 40px;
+    border-radius: 30px;
+  }
+  .menu-control {
+    position: fixed;
+    right: 0;
+    top: 48px;
+    height: calc(100vh - 48px);
+    background: #ffffff;
+    z-index: 10;
+    transition: right 0.3s;
+    width: 145px;
+
+    .draw {
+      position: absolute;
+      z-index: 1;
+      background: #ffffff;
+      left: -21px;
+      top: 0px;
+      box-shadow: 0 0 1px #959595;
+      border-radius: 0 2px 2px 0px;
+
+      .anticon {
+        padding: 12px 3px;
+      }
+    }
+
+    div:not(.draw), button:not(.ant-switch) {
+      display: block!important;
+      margin-bottom: 15px;
+      width: 100%;
+    }
+    .wrap {
+      height: 100%;
+      padding: 20px 10px;
+    }
+  }
+  
+  .menu-control.hidden {
+    right: -145px;
+  }
+
+  .menu-body {
+    width: 100vw;
+    height: 100vh;
+    overflow-x: hidden;
+    position: relative;
+    background: #959595;
+    padding: 50px 0px 0px;
+    overflow-y: auto;
+
+  }
+  .menu-body::-webkit-scrollbar {
+    width: 7px;
+  }
+  .menu-body::-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-body::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+    border-radius: 3px;
+    border: 1px solid rgba(0, 0, 0, 0.07);
+    background: rgba(0, 0, 0, 0);
+  }
+
+  .instant-message {
+    width: 100%;
+    height: 100%;
+    background-color: #ededed;
+    padding-top: 40px;
+    padding-bottom: 50px;
+    background-position: center;
+    position: relative;
+  
+    .header {
+      position: absolute;
+      top: 0px;
+      width: 100%;
+      height: 40px;
+      line-height: 40px;
+      background: #ffffff;
+      box-shadow: 0 0 3px #d9d9d9;
+      text-align: center;
+      font-size: 16px;
+      z-index: 1;
+  
+      .anticon-left {
+        position: absolute;
+        left: 0px;
+        padding: 10px 13px;
+        font-size: 18px;
+      }
+    }
+  
+    .mk-content-wrap {
+      height: calc(100% - 90px);
+      overflow-y: auto;
+      padding-bottom: 10px;
+      padding-top: 5px;
+    }
+    .mk-content-wrap.friend {
+      .line-wrap:not(.right) {
+        .title {
+          display: none;
+        }
+        .words::after {
+          top: 10px;
+        }
+      }
+    }
+    .line-wrap {
+      margin-bottom: 10px;
+      .time-line {
+        text-align: center;
+        margin-bottom: 10px;
+        color: #757575;
+        font-size: 12px;
+      }
+      .line-msg {
+        display: flex;
+        width: calc(100% - 50px);
+        .portrait {
+          width: 50px;
+          text-align: center;
+          .img {
+            width: 32px;
+            height: 32px;
+            background-color: #bcbcbc;
+            display: inline-block;
+            background-repeat: no-repeat;
+            background-size: cover;
+            background-position: center;
+            line-height: 32px;
+            font-size: 16px;
+          }
+        }
+        .msg {
+          flex: 1;
+          .title {
+            font-size: 12px;
+            color: rgba(0,0,0,0.35);
+            margin-bottom: 3px;
+            margin-top: -5px;
+          }
+          .words {
+            position: relative;
+            display: inline-block;
+            padding: 5px 10px;
+            background: #ffffff;
+            border-radius: 3px;
+            min-height: 32px;
+            font-size: 14px;
+            text-align: left;
+          }
+          .words::after {
+            position: absolute;
+            content: ' ';
+            display: block;
+            width: 10px;
+            height: 10px;
+            transform: rotate(45deg);
+            background: #ffffff;
+            top: 4px;
+            left: -2px;
+          }
+        }
+      }
+    }
+    .line-msg.right {
+      margin-left: 50px;
+      .msg {
+        text-align: right;
+        .words {
+          background: #93ED6C;
+          color: #000000;
+        }
+        .words::after {
+          background: #93ED6C;
+          top: 10px;
+          left: auto;
+          right: -2px;
+        }
+      }
+    }
+  
+    .send-wrap {
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      right: 0;
+      background-color: #f7f7f7;
+      border-top: 1px solid #e9e9e9;
+      height: 50px;
+      line-height: 50px;
+      display: flex;
+  
+      .adm-input {
+        padding: 4px 10px;
+        background: #ffffff;
+        margin: 7px 10px;
+        flex: 1;
+      }
+      .send {
+        width: 75px;
+      }
+      .ant-btn {
+        padding: 2px 15px;
+        height: 32px;
+        margin: 9px 5px 0px 0px;
+        border-color: #26C281;
+        background-color: #26C281;
+        color: #ffffff;
+      }
+    }
+  }
+}
+
+body {
+  overflow-y: hidden;
+}
\ No newline at end of file
diff --git a/src/views/imdesign/menuform/index.jsx b/src/views/imdesign/menuform/index.jsx
new file mode 100644
index 0000000..0fb6e84
--- /dev/null
+++ b/src/views/imdesign/menuform/index.jsx
@@ -0,0 +1,77 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input } from 'antd'
+
+import './index.scss'
+
+class CustomMenuForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object, // 瀛楀吀椤�
+    config: PropTypes.object,
+    MenuId: PropTypes.string,
+    adapters: PropTypes.array,
+    updateConfig: PropTypes.func
+  }
+
+  state = {}
+
+  // 鑿滃崟鍚嶇О
+  changeName = (e) => {
+    this.props.updateConfig({...this.props.config, MenuName: e.target.value})
+  }
+
+  // 鑿滃崟鍙傛暟
+  changeNo = (e) => {
+    this.props.updateConfig({...this.props.config, MenuNo: e.target.value})
+  }
+
+  render() {
+    const { dict, config } = this.props
+    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="custom-menu-form">
+        <Row>
+          <Col span={24}>
+            <Form.Item label={dict['mob.menu'] + dict['mob.name']}>
+              {getFieldDecorator('MenuName', {
+                initialValue: config.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: config.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>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(CustomMenuForm)
\ No newline at end of file
diff --git a/src/views/imdesign/menuform/index.scss b/src/views/imdesign/menuform/index.scss
new file mode 100644
index 0000000..6bfb57a
--- /dev/null
+++ b/src/views/imdesign/menuform/index.scss
@@ -0,0 +1,25 @@
+.custom-menu-form {
+  .ant-form-item {
+    height: 50px;
+    .ant-form-explain {
+      font-size: 12px;
+    }
+  }
+  .ant-radio-group {
+    white-space: nowrap;
+  }
+  .mk-source-wrap .mk-source-item-info .anticon-delete {
+    color: #ff4d4f;
+  }
+  .status-bar {
+    .ant-form-item-control {
+      padding-top: 7px;
+      .color-sketch-block-box {
+        width: calc(100% - 140px);
+      }
+      .color-sketch-value {
+        width: 140px;
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/views/imdesign/options.jsx b/src/views/imdesign/options.jsx
new file mode 100644
index 0000000..4ae841b
--- /dev/null
+++ b/src/views/imdesign/options.jsx
@@ -0,0 +1,29 @@
+/**
+ * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
+ */
+export default function (wrap) {
+  let menulist = sessionStorage.getItem('appMenus')
+
+  if (menulist) {
+    try {
+      menulist = JSON.parse(menulist)
+    } catch (e) {
+      menulist = []
+    }
+  } else {
+    menulist = []
+  }
+
+  const WrapForm = [
+    {
+      type: 'select',
+      field: 'linkmenu',
+      label: '鍏宠仈鑿滃崟',
+      initval: wrap.linkmenu || '',
+      required: false,
+      options: menulist,
+    },
+  ]
+
+  return WrapForm
+} 
\ No newline at end of file
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index 76a8309..0862e1d 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -17,6 +17,7 @@
 import MKEmitter from '@/utils/events.js'
 import MenuUtils from '@/utils/utils-custom.js'
 import asyncComponent from '@/utils/asyncComponent'
+import backurl from '@/assets/img/back.jpg'
 
 import './index.scss'
 
@@ -72,7 +73,8 @@
     settingshow: true,
     controlshow: true,
     comloading: false,
-    adapters: []
+    adapters: [],
+    viewType: 'menu'
   }
 
   UNSAFE_componentWillMount() {
@@ -89,6 +91,8 @@
         sessionStorage.setItem('typename', param.typename || 'mob')
         sessionStorage.setItem('adapter', param.adapter || '')
         sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
+        sessionStorage.setItem('userbind', param.userbind || '')
+        sessionStorage.setItem('instantMessage', param.instantMessage || '')
 
         this.setState({
           localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
@@ -117,7 +121,8 @@
 
         this.setState({
           adapters,
-          MenuId: param.MenuID
+          MenuId: param.MenuID,
+          viewType: /^userbind/.test(param.MenuID) ? 'userbind' : 'menu'
         }, () => {
           this.getMenuParam(param)
         })
@@ -444,10 +449,7 @@
 
     if (!config) {
       window.close()
-      return
-    }
-
-    if (!oriConfig || !is(fromJS(oriConfig), fromJS(config))) {
+    } else if (!oriConfig || !is(fromJS(oriConfig), fromJS(config))) {
       confirm({
         title: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾鍏抽棴鍚楋紵',
         content: '',
@@ -458,6 +460,25 @@
       })
     } else {
       window.close()
+    }
+  }
+
+  backView = () => {
+    const { oriConfig, config } = this.state
+
+    if (!config) {
+      window.history.back()
+    } else if (!oriConfig || !is(fromJS(oriConfig), fromJS(config))) {
+      confirm({
+        title: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾鍚庨��鍚楋紵',
+        content: '',
+        onOk() {
+          window.history.back()
+        },
+        onCancel() {}
+      })
+    } else {
+      window.history.back()
     }
   }
 
@@ -491,6 +512,11 @@
         } catch (e) {
           console.warn('Parse Failure')
           config = null
+        }
+
+        if (/^userbind/.test(MenuId)) {
+          this.setUserBindMenu(config, result)
+          return
         }
 
         if (!config) {
@@ -541,6 +567,88 @@
     this.getAppMenus()
   }
 
+  setUserBindMenu = (config, result) => {
+    const { MenuId } = this.state
+    let isCreate = !config
+
+    if (!config) {
+      config = {
+        version: 1.0,
+        uuid: MenuId,
+        MenuID: MenuId,
+        Template: 'webPage',
+        enabled: false,
+        MenuName: '鐢ㄦ埛缁戝畾',
+        MenuNo: 'user_bind',
+        tables: [],
+        components: [],
+        viewType: 'userbind',
+        statusBarbgColor: sessionStorage.getItem('sysBgColor') || '#ffffff',
+        style: {
+          backgroundColor: sessionStorage.getItem('sysBgColor') || '#ffffff', backgroundImage: ''
+        }
+      }
+
+      config.components.push({
+        subcards:[
+          {
+            uuid: Utils.getuuid(), setting: {width:24, primaryId: '', click: ''}, style: {}, backStyle: {},
+            elements: [{maxWidth: 135, datatype: 'static', width: 24, marks: null, url: 'http://cloud.mk9h.cn/Content/images/20220120/cb5cd13a-2ef4-41cc-ab6a-a202f1c04da5.png', style: {borderRadius: '50%'}, eleType: 'picture', link: '', uuid: Utils.getuuid(), lenWidRadio: '1:1', $type: ''}],
+            backElements: []
+          }
+        ],
+        headerStyle: {}, parentId: '', width: 24, scripts: [], btnlog: [], pageable: false,
+        wrap: {name: 'logo', width: 24, datatype: 'static', cardType: '', blacklist: []},
+        name: 'logo', floor: 1, switchable: true,
+        setting:{interType: 'system'}, tabId: '', style:{paddingTop: '10vh', paddingBottom: '10vh'}, dataName: Utils.getuuid(), format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
+      })
+
+      config.components.push({
+        uuid: Utils.getuuid(),
+        type: 'login',
+        floor: 1,
+        tabId: '',
+        parentId: '',
+        dataName: '',
+        width: 24,
+        name: '鐢ㄦ埛缁戝畾',
+        subtype: 'bindlogin',
+        wrap: { name: '鐢ㄦ埛缁戝畾', width: 24, loginWays: ['uname_pwd'], shortcut: 'none', height: '45vh' },
+        style: {},
+        loginWays: [
+          {type: 'uname_pwd', label: '璐﹀彿鐧诲綍', shortcut: 'none'},
+          {type: 'sms_vcode', label: '鐭俊鐧诲綍'},
+        ]
+      })
+
+      config.components.push({
+        subcards:[
+          {
+            uuid: Utils.getuuid(), setting: {width:24, primaryId: '', click: ''}, style: {}, backStyle: {},
+            elements: [{datatype: 'static', width: 24, marks: null, height: null, value: 'Power by Minkesoft', style: { fontSize: '13px', textAlign: 'center'}, eleType: 'text', link: '', uuid: Utils.getuuid(), $type: ''}],
+            backElements: []
+          }
+        ],
+        headerStyle: {}, parentId: '', width: 24, scripts: [], btnlog: [], pageable: false,
+        wrap: {name: 'Power', width: 24, datatype: 'static', cardType: '', blacklist: []},
+        name: 'Power', floor: 1, switchable: true,
+        setting:{interType: 'system'}, tabId: '', style:{}, dataName: Utils.getuuid(), format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
+      })
+    }
+    
+    config.uuid = MenuId
+    config.MenuID = MenuId
+    config.open_edition = result.open_edition || ''
+
+    this.setState({
+      oriConfig: isCreate ? null : config,
+      config: fromJS(config).toJS(),
+      activeKey: isCreate ? 'basedata' : 'component',
+      loading: false
+    })
+    window.GLOB.customMenu = config
+  }
+
   getAppMenus = () => {
     let _param = {
       func: 's_get_app_menus',
@@ -565,6 +673,13 @@
       let appIndeList = sessionStorage.getItem('appViewList')
       appIndeList = JSON.parse(appIndeList)
       appIndeList = appIndeList.map(item => (item.keys_type !== 'index' ? item.keys_id : '')).join(',')
+
+      if (sessionStorage.getItem('userbind')) {
+        appIndeList = appIndeList + ',' + sessionStorage.getItem('userbind')
+      }
+      if (sessionStorage.getItem('instantMessage')) {
+        appIndeList = appIndeList + ',' + sessionStorage.getItem('instantMessage')
+      }
 
       let menus = res.menus.filter(item => appIndeList.indexOf(item.MenuID) === -1)
       menus = menus.map(item => {
@@ -1247,7 +1362,7 @@
   }
 
   verifyConfig = (show) => {
-    const { config } = this.state
+    const { config, viewType } = this.state
     let error = ''
     let searchSum = 0
     let swipes = []
@@ -1313,6 +1428,10 @@
     }
 
     check(config.components)
+
+    if (!error && viewType === 'userbind' && config.components.filter(item => item.type === 'login').length === 0) {
+      error = '鐢ㄦ埛缁戝畾椤甸潰蹇呴』娣诲姞鐧诲綍銆�'
+    }
 
     if (!error && searchSum > 1) {
       error = '鎼滅储缁勪欢涓庡鑸爮鐨勬悳绱㈠姛鑳戒笉鍙悓鏃朵娇鐢ㄣ��'
@@ -1540,11 +1659,11 @@
 
 
   render () {
-    const { localedict, comloading, loading, settingshow, controlshow, activeKey, dict, MenuId, config, menuloading, customComponents, adapters } = this.state
+    const { viewType, localedict, comloading, loading, settingshow, controlshow, activeKey, dict, MenuId, config, menuloading, customComponents, adapters } = this.state
 
     return (
       <ConfigProvider locale={localedict}>
-        <div className="mk-mob-view" id="mk-mob-design-view">
+        <div className={'mk-mob-view ' + viewType} id="mk-mob-design-view">
           <Header changeView={this.changeView}/>
           {loading ? <Spin className="view-spin" size="large" /> : null}
           <DndProvider backend={HTML5Backend}>
@@ -1556,7 +1675,7 @@
               <div className="pc-setting-tools">
                 <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
                   {/* 鍩烘湰淇℃伅 */}
-                  <Panel header={dict['mob.basemsg']} forceRender key="basedata">
+                  <Panel header={dict['mob.basemsg']} forceRender className="basedata" key="basedata">
                     {/* 鑿滃崟淇℃伅 */}
                     {config ? <MenuForm
                       dict={dict}
@@ -1571,10 +1690,10 @@
                     {config ? <Paragraph style={{padding: '15px 0px 0px 18px'}} copyable={{ text: MenuId }}>鑿滃崟ID</Paragraph> : null}
                   </Panel>
                   {/* 缁勪欢娣诲姞 */}
-                  <Panel header={dict['mob.component']} key="component">
+                  <Panel header={dict['mob.component']} className="component" key="component">
                     <SourceWrap />
                   </Panel>
-                  {customComponents && customComponents.length ? <Panel header="鑷畾涔夌粍浠�" key="cuscomponent">
+                  {customComponents && customComponents.length ? <Panel header="鑷畾涔夌粍浠�" className="cuscomponent" key="cuscomponent">
                     <SourceWrap components={customComponents} />
                   </Panel> : null}
                   <Panel header={'椤甸潰鏍峰紡'} key="background">
@@ -1591,14 +1710,15 @@
               <div className="wrap">
                 <Button type="primary" onClick={this.submitConfig} id="save-config" loading={menuloading}>{dict['mob.save']}</Button>
                 <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config && config.enabled} onChange={this.onEnabledChange} />
+                <img title="鍚庨��" className="back-view" onClick={this.backView} src={backurl} alt=""/>
                 <CreateView resetmenu={this.getAppMenus} />
                 <PasteController insert={this.insert} />
                 <StyleCombControlButton menu={config} />
                 <SysInterface config={config} updateConfig={this.updateConfig}/>
                 <PictureController/>
                 <Quotecomponent config={config} updateConfig={this.updateConfig}/>
-                <Button className="mk-border-green" onClick={this.setHomeView}><HomeOutlined /> 璁句负棣栭〉</Button>
-                <Button className="mk-border-purple" onClick={this.setLoginView}><LoginOutlined /> 璁句负鐧诲綍椤�</Button>
+                <Button className="mk-border-green set-home" onClick={this.setHomeView}><HomeOutlined /> 璁句负棣栭〉</Button>
+                <Button className="mk-border-purple set-login" onClick={this.setLoginView}><LoginOutlined /> 璁句负鐧诲綍椤�</Button>
                 <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                 <Transfer MenuID={MenuId} />
                 <Versions MenuId={MenuId} open_edition={config ? config.open_edition : ''}/>
diff --git a/src/views/mobdesign/index.scss b/src/views/mobdesign/index.scss
index 5392b98..d9f3125 100644
--- a/src/views/mobdesign/index.scss
+++ b/src/views/mobdesign/index.scss
@@ -7,6 +7,17 @@
     left: calc(50% - 16px);
     top: calc(50vh - 70px);
   }
+  .back-view {
+    width: 28px;
+    float: right;
+    margin-right: 10px;
+    cursor: pointer;
+    filter: opacity(0.7);
+    transition: filter 0.3s;
+  }
+  .back-view:hover {
+    filter: opacity(0.9);
+  }
   .modal-form-board {
     padding-top: 0;
   }
@@ -243,6 +254,41 @@
   }
 }
 
+.mk-mob-view.userbind {
+  .pc-setting-tools {
+    .ant-collapse-item.basedata {
+      .custom-menu-form > .ant-row {
+        > .ant-col {
+          display: none;
+        }
+        > .ant-col:nth-child(1), > .ant-col:nth-child(2) {
+          display: block;
+        }
+      }
+      .url-field-component, .model-table-tablemanage-view, .ant-typography {
+        display: none;
+      }
+    }
+
+    .ant-collapse-item.component {
+      .menu-source-item {
+        display: none;
+      }
+      .menu-source-item.card-propcard, .menu-source-item.balcony-balcony, .menu-source-item.login-normallogin {
+        display: block;
+      }
+    }
+    .ant-collapse-item.cuscomponent {
+      display: none;
+    }
+  }
+  .menu-control {
+    .back-view, .mk-view-paste, .quote-wrap, .mk-sys-interface, .set-home, .set-login, .mk-replace-field {
+      display: none!important;
+    }
+  }
+}
+
 body {
   overflow-y: hidden;
 }
\ No newline at end of file
diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx
index 174afee..7f0144d 100644
--- a/src/views/pcdesign/index.jsx
+++ b/src/views/pcdesign/index.jsx
@@ -17,6 +17,7 @@
 import MKEmitter from '@/utils/events.js'
 import MenuUtils from '@/utils/utils-custom.js'
 import asyncComponent from '@/utils/asyncComponent'
+import backurl from '@/assets/img/back.jpg'
 
 import './index.scss'
 
@@ -546,10 +547,7 @@
 
     if (!config) {
       window.close()
-      return
-    }
-
-    if (!oriConfig || !is(fromJS(oriConfig), fromJS(config))) {
+    } else if (!oriConfig || !is(fromJS(oriConfig), fromJS(config))) {
       confirm({
         title: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾鍏抽棴鍚楋紵',
         content: '',
@@ -560,6 +558,25 @@
       })
     } else {
       window.close()
+    }
+  }
+
+  backView = () => {
+    const { oriConfig, config } = this.state
+
+    if (!config) {
+      window.history.back()
+    } else if (!oriConfig || !is(fromJS(oriConfig), fromJS(config))) {
+      confirm({
+        title: '閰嶇疆淇℃伅鏈繚瀛橈紝纭畾鍚庨��鍚楋紵',
+        content: '',
+        onOk() {
+          window.history.back()
+        },
+        onCancel() {}
+      })
+    } else {
+      window.history.back()
     }
   }
 
@@ -1761,6 +1778,7 @@
               <div className="wrap">
                 <Button type="primary" id="save-config" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button>
                 <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config && config.enabled} onChange={this.onEnabledChange} />
+                <img title="鍚庨��" className="back-view" onClick={this.backView} src={backurl} alt=""/>
                 <CreateView resetmenu={this.getAppMenus} />
                 <PasteController insert={this.insert} />
                 <StyleCombControlButton menu={config} />
diff --git a/src/views/pcdesign/index.scss b/src/views/pcdesign/index.scss
index b1e76e6..c6a8f6a 100644
--- a/src/views/pcdesign/index.scss
+++ b/src/views/pcdesign/index.scss
@@ -11,6 +11,17 @@
     left: calc(50% - 16px);
     top: calc(50vh - 70px);
   }
+  .back-view {
+    width: 28px;
+    float: right;
+    margin-right: 10px;
+    cursor: pointer;
+    filter: opacity(0.7);
+    transition: filter 0.3s;
+  }
+  .back-view:hover {
+    filter: opacity(0.9);
+  }
   .modal-form-board {
     padding-top: 0;
   }
diff --git a/src/views/rolemanage/index.jsx b/src/views/rolemanage/index.jsx
index 8277f73..06a4db8 100644
--- a/src/views/rolemanage/index.jsx
+++ b/src/views/rolemanage/index.jsx
@@ -34,7 +34,15 @@
         align: 'center',
         render: (text, record) => (
           <div>
-            <Button type="link" onClick={() => this.deleteMenu(record)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button>
+            {record.type !== 'none' ?
+              <Button type="link" onClick={() => this.deleteMenu(record)} style={{color: '#ff4d4f'}}>鍒犻櫎</Button> :
+              <Button type="link" onClick={() => {
+                notification.warning({
+                  top: 92,
+                  message: '褰撳墠绯荤粺鑿滃崟灏氭湭鍒涘缓銆�',
+                  duration: 5
+                })
+              }} style={{color: '#ff4d4f', opacity: '0.5'}}>鍒犻櫎</Button>}
             <Button type="link" onClick={() => this.jumpApp(record)} style={{color: '#1890ff', marginLeft: '5px'}}>缂栬緫</Button>
           </div>
         ),
@@ -112,26 +120,48 @@
 
     Api.getCloudConfig(param).then(result => {
       if (result.status) {
-        this.setState({
-          menulist: result.menus.map(item => {
-            item.nodes = ''
-            item.type = 'view'
-            if (item.menus_rolelist) {
-              try {
-                let pageParam = JSON.parse(window.decodeURIComponent(window.atob(item.menus_rolelist)))
-                item.nodes = pageParam
-                if (pageParam.login) {
-                  item.nodes = ''
-                } else if (pageParam.type === 'navbar') {
-                  item.type = 'navbar'
-                }
-              } catch (e) {
+        let ub = app.user_binding === 'true' && app.userbind ? false : true
+        let im = app.instantMessage ? false : true
+
+        let menus = result.menus.map(item => {
+          item.nodes = ''
+          item.type = 'view'
+          if (item.menus_rolelist) {
+            try {
+              let pageParam = JSON.parse(window.decodeURIComponent(window.atob(item.menus_rolelist)))
+              item.nodes = pageParam
+              if (pageParam.login) {
+                item.nodes = ''
+              } else if (pageParam.type === 'navbar') {
+                item.type = 'navbar'
+              } else if (pageParam.type === 'im') {
+                item.type = 'im'
                 item.nodes = ''
               }
+            } catch (e) {
+              item.nodes = ''
             }
-            
-            return item
-          })
+          }
+
+          if (!ub && app.userbind === item.MenuID) {
+            ub = true
+          }
+          if (!im && app.instantMessage === item.MenuID) {
+            im = true
+          }
+          
+          return item
+        })
+
+        if (!im) {
+          menus.push({nodes: '', type: 'none', MenuID: app.instantMessage, MenuName: '鍗虫椂閫氫俊'})
+        }
+        if (!ub) {
+          menus.push({nodes: '', type: 'none', MenuID: app.userbind, MenuName: '鐢ㄦ埛缁戝畾'})
+        }
+
+        this.setState({
+          menulist: menus
         }, () => {
           if (reset && (!this.oriTrees || this.oriTrees.length === 0)) {
             this.initMenutree()
@@ -818,6 +848,10 @@
       return
     }
 
+    if (app.instantMessage && item.MenuID === app.instantMessage) {
+      route = 'imdesign'
+    }
+
     window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify({...app, MenuID: item.MenuID, type: 'app'})))}`))
   }
 

--
Gitblit v1.8.0