From 400fee62fb40006a9839f1c3a8244b82566b5057 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 08 五月 2025 16:30:39 +0800
Subject: [PATCH] Merge branch 'develop'

---
 src/views/design/header/index.jsx                              |    5 
 src/views/login/loginform.jsx                                  |   91 +++
 src/menu/components/table/normal-table/options.jsx             |   10 
 src/components/header/index.jsx                                |    6 
 src/tabviews/zshare/topSearch/index.jsx                        |    4 
 src/tabviews/custom/components/card/double-data-card/index.jsx |   37 +
 src/menu/components/form/formaction/actionform/index.jsx       |   10 
 src/utils/utils-custom.js                                      |  435 +++++++++++++++-
 src/templates/sharecomponent/searchcomponent/index.jsx         |    2 
 src/views/design/header/transmenu/index.jsx                    |   15 
 src/views/menudesign/printmenuform/index.jsx                   |   29 +
 src/menu/components/table/edit-table/options.jsx               |   10 
 src/tabviews/basetable/index.jsx                               |    4 
 src/views/systemfunc/index.jsx                                 |    1 
 src/api/index.js                                               |    6 
 src/tabviews/zshare/actionList/newpagebutton/index.jsx         |   18 
 src/tabviews/zshare/topSearch/index.scss                       |   30 +
 src/views/billprint/index.jsx                                  |   36 +
 src/tabviews/custom/components/form/simple-form/index.jsx      |    8 
 src/tabviews/zshare/actionList/normalbutton/index.jsx          |    6 
 src/menu/components/search/main-search/index.scss              |   25 
 src/menu/components/table/edit-table/index.jsx                 |    8 
 src/menu/datasource/verifycard/index.jsx                       |    4 
 src/index.js                                                   |    8 
 src/menu/replaceField/settingform/index.jsx                    |    5 
 public/manifest.json                                           |    2 
 src/menu/components/table/base-table/options.jsx               |   10 
 src/menu/datasource/verifycard/settingform/index.jsx           |    2 
 src/menu/replaceField/index.jsx                                |  528 ++++++++++++++------
 src/menu/components/search/main-search/index.jsx               |    2 
 src/menu/lowerField/index.jsx                                  |    9 
 src/tabviews/custom/components/form/step-form/index.jsx        |   16 
 src/tabviews/custom/index.jsx                                  |    4 
 src/views/login/index.scss                                     |   35 +
 src/views/appmanage/index.jsx                                  |    2 
 src/menu/debug/index.jsx                                       |    2 
 src/menu/components/table/normal-table/index.jsx               |    8 
 src/menu/components/search/main-search/options.jsx             |   10 
 src/templates/sharecomponent/searchcomponent/index.scss        |   25 
 src/views/login/index.jsx                                      |   69 +
 40 files changed, 1,226 insertions(+), 311 deletions(-)

diff --git a/public/manifest.json b/public/manifest.json
index a87928a..809cb78 100644
--- a/public/manifest.json
+++ b/public/manifest.json
@@ -6,5 +6,5 @@
   "display": "standalone",
   "theme_color": "#000000",
   "background_color": "#ffffff",
-  "mk_version": "20250402"
+  "mk_version": "20250502"
 }
diff --git a/src/api/index.js b/src/api/index.js
index 3295b09..a90161b 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -269,7 +269,8 @@
       login_id_address: sessionStorage.getItem('ipAddress') || '',
       kei_id: window.btoa(window.encodeURIComponent(window.GLOB.host)),
       device_id: localStorage.getItem('SessionUid'),
-      appkey: window.GLOB.appkey || ''
+      appkey: window.GLOB.appkey || '',
+      lang: sessionStorage.getItem('lang') || ''
     }
 
     let url = '/webapi/dologon'
@@ -307,7 +308,8 @@
       kei_id: window.btoa(window.encodeURIComponent(window.GLOB.host)),
       device_id: localStorage.getItem('SessionUid'),
       timestamp: moment().add(shim, 'seconds').format('YYYY-MM-DD HH:mm:ss'),
-      appkey: window.GLOB.appkey || ''
+      appkey: window.GLOB.appkey || '',
+      lang: sessionStorage.getItem('lang') || ''
     }
     
     // Type: 'S' 鏃�
diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index 1a792aa..7c11089 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -148,8 +148,10 @@
       cancelText: dict['cancel'] || '鍙栨秷',
       onOk() {
         sessionStorage.clear()
-        that.props.history.replace('/login')
-        window.location.reload()
+        setTimeout(() => {
+          that.props.history.replace('/login')
+          window.location.reload()
+        }, 100)
       },
       onCancel() {}
     })
diff --git a/src/index.js b/src/index.js
index aae8007..079c949 100644
--- a/src/index.js
+++ b/src/index.js
@@ -95,10 +95,10 @@
       GLOB.externalDatabase = null
     }
 
-    if (config.probation && /^20\d{2}-\d{2}-\d{2}$/.test(config.probation) && new Date(config.probation).getTime() > new Date().getTime()) {
+    if (config.probation && /^[1-9]\d{3}-\d{2}-\d{2}$/.test(config.probation) && new Date(config.probation).getTime() > new Date().getTime()) {
       GLOB.probation = true
     }
-    if (config.forcedUpdate && /^20\d{2}-\d{2}-\d{2}$/.test(config.forcedUpdate) && new Date(config.forcedUpdate).getTime() > new Date().getTime()) {
+    if (config.forcedUpdate && /^[1-9]\d{3}-\d{2}-\d{2}$/.test(config.forcedUpdate) && new Date(config.forcedUpdate).getTime() > new Date().getTime()) {
       GLOB.forcedUpdate = true
     }
 
@@ -243,6 +243,8 @@
         GLOB.mainlogo = _systemMsg.mainlogo
         GLOB.doclogo = _systemMsg.doclogo
         GLOB.webSite = _systemMsg.webSite
+        GLOB.prolType = _systemMsg.prolType || ''
+        GLOB.prolCont = _systemMsg.prolCont || ''
         GLOB.style = _systemMsg.style || 'bg_black_style_blue'
         GLOB.showline = _systemMsg.showline || ''
         GLOB.navBar = _systemMsg.navBar || 'shutter'
@@ -287,7 +289,7 @@
 
     document.title = GLOB.platTitle || ''
 
-    if (config.filter === 'true' || (/^20\d{2}-\d{2}-\d{2}$/.test(config.filter) && new Date(config.filter).getTime() + 86400000 >= new Date().getTime())) {
+    if (config.filter === 'true' || (/^[1-9]\d{3}-\d{2}-\d{2}$/.test(config.filter) && new Date(config.filter).getTime() + 86400000 >= new Date().getTime())) {
       GLOB.filter = true
     }
 
diff --git a/src/menu/components/form/formaction/actionform/index.jsx b/src/menu/components/form/formaction/actionform/index.jsx
index 92c414f..7514e22 100644
--- a/src/menu/components/form/formaction/actionform/index.jsx
+++ b/src/menu/components/form/formaction/actionform/index.jsx
@@ -54,9 +54,17 @@
 
     if (this.record.type === 'prev') {
       shows = ['typeName', 'label', 'actionType']
+      if (this.record.actionType === 'close') {
+        shows.push('refreshTab', 'reload')
+      }
     } else if (this.record.type === 'next') {
       shows = ['typeName', 'label', 'actionType']
-    } else if (this.record.type === 'close' || this.record.type === 'reset') {
+      if (this.record.actionType === 'close') {
+        shows.push('refreshTab', 'reload')
+      }
+    } else if (this.record.type === 'close') {
+      shows = ['typeName', 'label', 'refreshTab', 'reload']
+    } else if (this.record.type === 'reset') {
       shows = ['typeName', 'label']
     } else {
       shows = ['typeName', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'output', 'reload', 'preButton', 'refreshTab'] // 閫夐」鍒楄〃
diff --git a/src/menu/components/search/main-search/index.jsx b/src/menu/components/search/main-search/index.jsx
index c87bbd9..281ea26 100644
--- a/src/menu/components/search/main-search/index.jsx
+++ b/src/menu/components/search/main-search/index.jsx
@@ -392,7 +392,7 @@
     let _style = resetStyle(card.style)
 
     return (
-      <div className={`main-search-edit-list ${card.wrap.float} ${showField ? 'show-field' : ''} mk-size-${card.wrap.searchSize || ''}`} onClick={this.clickComponent} id={card.uuid} style={_style}>
+      <div className={`main-search-edit-list ${card.wrap.float} ${showField ? 'show-field' : ''} mk-order-${card.wrap.searchSize || ''}`} onClick={this.clickComponent} id={card.uuid} style={_style}>
         <FieldsComponent config={card} type="search" />
         <Switch checkedChildren="寮�" size="small" unCheckedChildren="鍏�" defaultChecked={showField} onChange={this.onFieldChange} />
         <DragElement
diff --git a/src/menu/components/search/main-search/index.scss b/src/menu/components/search/main-search/index.scss
index b5a03a5..b7f1fe6 100644
--- a/src/menu/components/search/main-search/index.scss
+++ b/src/menu/components/search/main-search/index.scss
@@ -157,7 +157,7 @@
   }
 }
 
-.main-search-edit-list.mk-size-small {
+.main-search-edit-list.mk-order-small {
   .page-card {
     height: 45px;
   }
@@ -167,6 +167,29 @@
     }
   }
 }
+.main-search-edit-list.mk-order-updown {
+  .mk-search-item-wrap {
+    .page-card {
+      height: auto;
+    }
+    .ant-form-item {
+      display: block;
+      .ant-form-item-label {
+        display: block;
+        width: 100% !important;
+        text-align: left;
+        float: none;
+        line-height: 2;
+        height: 24px;
+      }
+      .ant-form-item-control-wrapper {
+        display: block;
+        width: 100% !important;
+        float: none;
+      }
+    }
+  }
+}
 
 .main-search-edit-list:not(.show-field) {
   .ant-form-explain {
diff --git a/src/menu/components/search/main-search/options.jsx b/src/menu/components/search/main-search/options.jsx
index 6d586f9..0641d23 100644
--- a/src/menu/components/search/main-search/options.jsx
+++ b/src/menu/components/search/main-search/options.jsx
@@ -163,13 +163,13 @@
     {
       type: 'radio',
       field: 'searchSize',
-      label: '鎼滅储闂磋窛',
-      initval: wrap.searchSize || 'middle',
-      tooltip: '鎼滅储鏉′欢鐨勪笂涓嬮棿璺濄��',
+      label: '鎼滅储鏍峰紡',
+      initval: wrap.searchSize === 'middle' ? '' : wrap.searchSize || '',
       required: false,
       options: [
-        {value: 'middle', label: '榛樿'},
-        {value: 'small', label: '灏�'},
+        {value: '', label: '榛樿'},
+        {value: 'small', label: '灏忛棿璺�'},
+        {value: 'updown', label: '涓婁笅鎺掑垪'},
       ],
     },
     {
diff --git a/src/menu/components/table/base-table/options.jsx b/src/menu/components/table/base-table/options.jsx
index 281b215..f88acc1 100644
--- a/src/menu/components/table/base-table/options.jsx
+++ b/src/menu/components/table/base-table/options.jsx
@@ -79,13 +79,13 @@
     {
       type: 'radio',
       field: 'searchSize',
-      label: '鎼滅储闂磋窛',
-      initval: wrap.searchSize || 'middle',
-      tooltip: '鎼滅储鏉′欢鐨勪笂涓嬮棿璺濄��',
+      label: '鎼滅储鏍峰紡',
+      initval: wrap.searchSize === 'middle' ? '' : wrap.searchSize || '',
       required: false,
       options: [
-        {value: 'middle', label: '榛樿'},
-        {value: 'small', label: '灏�'},
+        {value: '', label: '榛樿'},
+        {value: 'small', label: '灏忛棿璺�'},
+        {value: 'updown', label: '涓婁笅鎺掑垪'},
       ],
     },
     {
diff --git a/src/menu/components/table/edit-table/index.jsx b/src/menu/components/table/edit-table/index.jsx
index 7be53fa..4280d24 100644
--- a/src/menu/components/table/edit-table/index.jsx
+++ b/src/menu/components/table/edit-table/index.jsx
@@ -218,7 +218,13 @@
   addSearch = () => {
     const { card } = this.state
 
-    MKEmitter.emit('plusSearch', card.uuid, {uuid: Utils.getuuid(), focus: true, label: 'label', type: 'text', match: '='}, 'simple')
+    let ratio = 6
+
+    if (card.search.length) {
+      ratio = card.search[card.search.length - 1].ratio
+    }
+
+    MKEmitter.emit('plusSearch', card.uuid, {uuid: Utils.getuuid(), focus: true, label: 'label', type: 'text', match: '=', ratio}, 'simple')
   }
 
   addButton = () => {
diff --git a/src/menu/components/table/edit-table/options.jsx b/src/menu/components/table/edit-table/options.jsx
index c6899e7..a239a89 100644
--- a/src/menu/components/table/edit-table/options.jsx
+++ b/src/menu/components/table/edit-table/options.jsx
@@ -131,13 +131,13 @@
     {
       type: 'radio',
       field: 'searchSize',
-      label: '鎼滅储闂磋窛',
-      initval: wrap.searchSize || 'middle',
-      tooltip: '鎼滅储鏉′欢鐨勪笂涓嬮棿璺濄��',
+      label: '鎼滅储鏍峰紡',
+      initval: wrap.searchSize === 'middle' ? '' : wrap.searchSize || '',
       required: false,
       options: [
-        {value: 'middle', label: '榛樿'},
-        {value: 'small', label: '灏�'},
+        {value: '', label: '榛樿'},
+        {value: 'small', label: '灏忛棿璺�'},
+        {value: 'updown', label: '涓婁笅鎺掑垪'},
       ],
     },
     {
diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx
index 7ec4411..5cadab2 100644
--- a/src/menu/components/table/normal-table/index.jsx
+++ b/src/menu/components/table/normal-table/index.jsx
@@ -231,7 +231,13 @@
   addSearch = () => {
     const { card } = this.state
 
-    MKEmitter.emit('plusSearch', card.uuid, {uuid: Utils.getuuid(), focus: true, label: 'label', type: 'text', match: '='}, 'simple')
+    let ratio = 6
+
+    if (card.search.length) {
+      ratio = card.search[card.search.length - 1].ratio
+    }
+
+    MKEmitter.emit('plusSearch', card.uuid, {uuid: Utils.getuuid(), focus: true, label: 'label', type: 'text', match: '=', ratio}, 'simple')
   }
 
   addButton = () => {
diff --git a/src/menu/components/table/normal-table/options.jsx b/src/menu/components/table/normal-table/options.jsx
index 94e0641..62fd279 100644
--- a/src/menu/components/table/normal-table/options.jsx
+++ b/src/menu/components/table/normal-table/options.jsx
@@ -162,13 +162,13 @@
     {
       type: 'radio',
       field: 'searchSize',
-      label: '鎼滅储闂磋窛',
-      initval: wrap.searchSize || 'middle',
-      tooltip: '鎼滅储鏉′欢鐨勪笂涓嬮棿璺濄��',
+      label: '鎼滅储鏍峰紡',
+      initval: wrap.searchSize === 'middle' ? '' : wrap.searchSize || '',
       required: false,
       options: [
-        {value: 'middle', label: '榛樿'},
-        {value: 'small', label: '灏�'},
+        {value: '', label: '榛樿'},
+        {value: 'small', label: '灏忛棿璺�'},
+        {value: 'updown', label: '涓婁笅鎺掑垪'},
       ],
       forbid: appType === 'mob'
     },
diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx
index 58eef7d..72c8e18 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -730,7 +730,7 @@
 
     if ((setting.interType === 'system' && setting.execute !== 'false') || _scripts.length > 0) {
       let _columns = columns
-      if (config.subtype === 'dualdatacard') {
+      if (config.subtype === 'dualdatacard' && setting.subdata !== 'sub_data_string') {
         _columns = [...columns, ...subColumns]
       }
 
@@ -1117,7 +1117,7 @@
 
     drop table #${setting.tableName || 'tb'}${extend}
     
-    select top 99999 @mk_total as mk_total * from #${setting.tableName || 'tb'} order by sort_id`
+    select top 99999 @mk_total as mk_total, * from #${setting.tableName || 'tb'} order by sort_id`
 
     document.body.appendChild(oInput)
     oInput.select()
diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx
index 7f567b1..786e56e 100644
--- a/src/menu/datasource/verifycard/settingform/index.jsx
+++ b/src/menu/datasource/verifycard/settingform/index.jsx
@@ -679,7 +679,7 @@
             </Col> : null}
             {config.subtype === 'dualdatacard' ? <Col span={8}>
               <Form.Item label={
-                <Tooltip placement="topLeft" title="瀛愯〃鍦ㄤ富琛ㄤ腑鐨勬暟鎹泦鍚嶇О銆�">
+                <Tooltip placement="topLeft" title="瀛愯〃鍦ㄤ富琛ㄤ腑鐨勬暟鎹泦鍚嶇О锛屼娇鐢� sub_data_string 鏃舵暟鎹互 JSON 瀛楃涓插舰寮忚繑鍥烇紙瀛楁闆嗕腑闇�娣诲姞 sub_data_string 瀛楁锛夈��">
                   <QuestionCircleOutlined className="mk-form-tip" />
                   瀛愯〃瀛楁
                 </Tooltip>
diff --git a/src/menu/debug/index.jsx b/src/menu/debug/index.jsx
index dfd426f..55a6b56 100644
--- a/src/menu/debug/index.jsx
+++ b/src/menu/debug/index.jsx
@@ -2471,7 +2471,7 @@
     searches = formatSearch(searches)
 
     let _columns = []
-    if (item.subtype === 'dualdatacard') {
+    if (item.subtype === 'dualdatacard' && item.setting.subdata !== 'sub_data_string') {
       _columns = [...item.columns, ...item.subColumns]
     } else if (item.columns) {
       _columns = [...item.columns]
diff --git a/src/menu/lowerField/index.jsx b/src/menu/lowerField/index.jsx
index 3b0516c..e99f2af 100644
--- a/src/menu/lowerField/index.jsx
+++ b/src/menu/lowerField/index.jsx
@@ -79,8 +79,13 @@
         m.linkurl = m.linkurl.toLowerCase()
       }
       if (m.modal && m.modal.fields) {
-        if (m.modal.setting && m.modal.setting.focus) {
-          m.modal.setting.focus = m.modal.setting.focus.toLowerCase()
+        if (m.modal.setting) {
+          if (m.modal.setting.focus) {
+            m.modal.setting.focus = m.modal.setting.focus.toLowerCase()
+          }
+          if (m.modal.setting.errFocus) {
+            m.modal.setting.errFocus = m.modal.setting.errFocus.toLowerCase()
+          }
         }
         m.modal.fields = m.modal.fields.map(col => {
           resetForm(col)
diff --git a/src/menu/replaceField/index.jsx b/src/menu/replaceField/index.jsx
index 81403fe..fbca31e 100644
--- a/src/menu/replaceField/index.jsx
+++ b/src/menu/replaceField/index.jsx
@@ -6,6 +6,7 @@
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
+import { setLangSingleTrans } from '@/utils/utils-custom.js'
 import SettingForm from './settingform'
 import { queryTableSql } from '@/utils/option.js'
 import './index.scss'
@@ -104,6 +105,8 @@
   
           this.execLabel(map)
         }
+      } else if (res.resource === 'langs') {
+        this.getDicts()
       } else {
         let param = {func: 'sPC_Get_FieldName', TBName: res.table}
         if (window.GLOB.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
@@ -152,10 +155,226 @@
     })
   }
 
+  getDicts = () => {
+    let sql = `select mother_tongue as reg,translation as value,use_type as type,case when use_type='menu' then '鑿滃崟' when  use_type='button' then '鎸夐挳'  when  use_type='title' then '鏍囬'   when  use_type='list' then '閫夐」' else '鏂囨湰' end as use_type_text from s_app_lang_translation where appkey=@appkey@ and deleted=0 and translation != '' and lang='${sessionStorage.getItem('lang') || ''}'`
+
+    let param = {
+      func: 'sPC_Get_SelectedList',
+      LText: Utils.formatOptions(sql, 'x'),
+      obj_name: 'data',
+      arr_field: 'reg,value,type',
+      exec_type: 'x'
+    }
+
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt('', param.timestamp)
+    param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
+
+    this.$Api.getCloudConfig(param).then(result => {
+      if (!result.status) {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+        this.setState({
+          confirming: false
+        })
+        return
+      } else if (!result.data || result.data.length === 0) {
+        notification.warning({
+          top: 92,
+          message: '鏇挎崲鏁版嵁涓虹┖锛岃妫�鏌ュ綋鍓嶈瑷�涓嬫槸鍚﹀瓨鍦ㄨ瑷�鍖咃紒',
+          duration: 5
+        })
+        this.setState({
+          confirming: false
+        })
+        return
+      }
+
+      let btnDict = {}
+      let titDict = {}
+      let lisDict = {}
+      let menuDict = {}
+      let regs = []
+
+      result.data.forEach(item => {
+        if (item.type === 'button') {
+          btnDict[item.reg] = item.value
+        } else if (item.type === 'title') {
+          titDict[item.reg] = item.value
+        } else if (item.type === 'list') {
+          lisDict[item.reg] = item.value
+        } else if (item.type === 'text') {
+          regs.push({reg: new RegExp(item.reg, 'g'), value: item.value, sort: item.reg.length})
+        } else if (item.type === 'menu') {
+          menuDict[item.reg] = item.value
+        }
+      })
+
+      regs.sort((a, b) => b.sort - a.sort)
+
+      let config = fromJS(this.props.config).toJS()
+
+      setLangSingleTrans(config, btnDict, titDict, lisDict, menuDict, regs)
+
+      this.setState({
+        confirming: false,
+        visible: false
+      })
+  
+      if (is(fromJS(this.props.config), fromJS(config))) {
+        notification.success({
+          top: 92,
+          message: '鏈彂鐜伴渶瑕佹浛鎹㈢殑淇℃伅銆�',
+          duration: 3
+        })
+        return
+      }
+  
+      notification.success({
+        top: 92,
+        message: '鏇挎崲宸插畬鎴愩��',
+        duration: 3
+      })
+      this.props.updateConfig(config)
+    })
+  }
+
   // 渚濇嵁鍘熷瓧娈垫浛鎹负鏂板瓧娈�
   exec = (map) => {
     let config = fromJS(this.props.config).toJS()
 
+    let getVal = (val) => {
+      let _val = val.toLowerCase()
+      if (map[_val]) {
+        return map[_val].FieldName
+      }
+      return val
+    }
+
+    let resetForm = (m) => {
+      if (m.field) {
+        m.field = getVal(m.field)
+      }
+      if (m.type === 'split' && m.splitctrl) {
+        m.splitctrl = getVal(m.splitctrl)
+      }
+      if (m.tabField) {
+        m.tabField = getVal(m.tabField)
+      }
+      if (m.linkField) {
+        m.linkField = getVal(m.linkField)
+      }
+      if (m.supField) {
+        m.supField = getVal(m.supField)
+      }
+      if (m.phoneField) {
+        m.phoneField = getVal(m.phoneField)
+      }
+      if (m.linkSubField) {
+        m.linkSubField = m.linkSubField.map(n => getVal(n))
+        m.linkSubField = Array.from(new Set(m.linkSubField))
+      }
+    }
+    let resetMark = (m) => {
+      m.marks = m.marks.map(n => {
+        if (n.field && Array.isArray(n.field)) {
+          if (n.field[1] === 'static') {
+            n.field[0] = getVal(n.field[0])
+          } else {
+            if (n.field[0]) {
+              n.field[0] = getVal(n.field[0])
+            }
+            if (n.field[2]) {
+              n.field[2] = getVal(n.field[2])
+            }
+          }
+        }
+
+        return n
+      })
+    }
+    let resetElement = (m) => {
+      if (m.field) {
+        m.field = getVal(m.field)
+      }
+      if (m.posterField) {
+        m.posterField = getVal(m.posterField)
+      }
+      if (m.bgImage) {
+        m.bgImage = getVal(m.bgImage)
+      }
+      if (m.linkurl && /^[a-zA-Z0-9_]+$/.test(m.linkurl)) {
+        m.linkurl = getVal(m.linkurl)
+      }
+      if (m.modal && m.modal.fields) {
+        if (m.modal.setting) {
+          if (m.modal.setting.focus) {
+            m.modal.setting.focus = getVal(m.modal.setting.focus)
+          }
+          if (m.modal.setting.errFocus) {
+            m.modal.setting.errFocus = getVal(m.modal.setting.errFocus)
+          }
+        }
+        m.modal.fields = m.modal.fields.map(col => {
+          resetForm(col)
+          return col
+        })
+      }
+      if (m.verify) {
+        if (m.verify.columns) {
+          m.verify.columns = m.verify.columns.map(col => {
+            if (col.Column) {
+              col.Column = getVal(col.Column)
+            }
+            return col
+          })
+        }
+        if (m.verify.uniques) {
+          m.verify.uniques = m.verify.uniques.map(col => {
+            if (col.field) {
+              col.field = col.field.split(',').map(_field => {
+                if (_field === 'BID') return _field
+                return getVal(_field)
+              }).join(',')
+            }
+            return col
+          })
+        }
+        if (m.verify.billcodes) {
+          m.verify.billcodes = m.verify.billcodes.map(col => {
+            if (col.field) {
+              col.field = getVal(col.field)
+            }
+            if (col.linkField && col.linkField !== 'BID') {
+              col.linkField = getVal(col.linkField)
+            }
+            return col
+          })
+        }
+
+        if (m.verify.accountfield && m.verify.accountfield !== 'BID') {
+          m.verify.accountfield = getVal(m.verify.accountfield)
+        }
+        if (m.verify.voucher && m.verify.voucher.linkField && m.verify.voucher.linkField !== 'BID') {
+          m.verify.voucher.linkField = getVal(m.verify.voucher.linkField)
+        }
+      }
+      if (m.controlField) {
+        m.controlField = getVal(m.controlField)
+      }
+
+      if (m.marks && m.marks.length) {
+        resetMark(m)
+      }
+
+      if (m.config && m.config.components) {
+        m.config.components = _replace(m.config.components)
+      }
+    }
+    
     let _replace = (components) => {
       return components.map(item => {
         if (item.type === 'tabs') {
@@ -182,8 +401,8 @@
         }
         if (item.search) {
           item.search = item.search.map(col => {
-            if (col.field && map[col.field.toLowerCase()]) {
-              col.field = map[col.field.toLowerCase()].FieldName
+            if (col.field) {
+              col.field = getVal(col.field)
             }
             return col
           })
@@ -191,163 +410,93 @@
 
         if (item.action) {
           item.action.forEach(m => {
-            if (m.modal && m.modal.fields) {
-              m.modal.fields = m.modal.fields.map(col => {
-                if (col.field && map[col.field.toLowerCase()]) {
-                  col.field = map[col.field.toLowerCase()].FieldName
-                }
-                return col
-              })
-            }
-            if (m.verify && m.verify.columns) {
-              m.verify.columns = m.verify.columns.map(col => {
-                if (col.Column && map[col.Column.toLowerCase()]) {
-                  col.Column = map[col.Column.toLowerCase()].FieldName
-                }
-                return col
-              })
-            }
-            if (m.config && m.config.components) {
-              m.config.components = _replace(m.config.components)
-            }
+            resetElement(m)
           })
         }
 
         if (item.subcards) {
           item.subcards.forEach(card => {
+            if (card.setting) {
+              if (card.setting.controlField) {
+                card.setting.controlField = getVal(card.setting.controlField)
+              }
+              if (card.setting.bgField) {
+                card.setting.bgField = getVal(card.setting.bgField)
+              }
+              if (card.setting.menuType) {
+                card.setting.menuType = getVal(card.setting.menuType)
+              }
+            }
+
             if (card.elements) { // 鍗$墖
               card.elements = card.elements.map(m => {
-                if (m.datatype === 'dynamic' && map[m.field.toLowerCase()]) {
-                  m.field = map[m.field.toLowerCase()].FieldName
-                }
-                if (m.modal && m.modal.fields) {
-                  m.modal.fields = m.modal.fields.map(col => {
-                    if (col.field && map[col.field.toLowerCase()]) {
-                      col.field = map[col.field.toLowerCase()].FieldName
-                    }
-                    return col
-                  })
-                }
-                if (m.verify && m.verify.columns) {
-                  m.verify.columns = m.verify.columns.map(col => {
-                    if (col.Column && map[col.Column.toLowerCase()]) {
-                      col.Column = map[col.Column.toLowerCase()].FieldName
-                    }
-                    return col
-                  })
-                }
-                if (m.config && m.config.components) {
-                  m.config.components = _replace(m.config.components)
-                }
+                resetElement(m)
                 return m
               })
             }
 
             if (card.backElements) { // 鍗$墖
               card.backElements = card.backElements.map(m => {
-                if (m.datatype === 'dynamic' && map[m.field.toLowerCase()]) {
-                  m.field = map[m.field.toLowerCase()].FieldName
-                }
-                if (m.modal && m.modal.fields) {
-                  m.modal.fields = m.modal.fields.map(col => {
-                    if (col.field && map[col.field.toLowerCase()]) {
-                      col.field = map[col.field.toLowerCase()].FieldName
-                    }
-                    return col
-                  })
-                }
-                if (m.verify && m.verify.columns) {
-                  m.verify.columns = m.verify.columns.map(col => {
-                    if (col.Column && map[col.Column.toLowerCase()]) {
-                      col.Column = map[col.Column.toLowerCase()].FieldName
-                    }
-                    return col
-                  })
-                }
-                if (m.config && m.config.components) {
-                  m.config.components = _replace(m.config.components)
-                }
+                resetElement(m)
                 return m
               })
             }
 
             if (card.fields) { // 琛ㄥ崟
               card.fields = card.fields.map(m => {
-                if (m.field && map[m.field.toLowerCase()]) {
-                  m.field = map[m.field.toLowerCase()].FieldName
-                }
+                resetForm(m)
                 return m
               })
+            }
+
+            if (card.subButton) {
+              resetElement(card.subButton)
+
+              if (card.subButton.resetForms) {
+                card.subButton.resetForms = card.subButton.resetForms.map(n => getVal(n))
+              }
             }
           })
         }
 
         if (item.elements) {
           item.elements = item.elements.map(m => {
-            if (m.datatype === 'dynamic' && map[m.field.toLowerCase()]) {
-              m.field = map[m.field.toLowerCase()].FieldName
-            }
-            if (m.modal && m.modal.fields) {
-              m.modal.fields = m.modal.fields.map(col => {
-                if (col.field && map[col.field.toLowerCase()]) {
-                  col.field = map[col.field.toLowerCase()].FieldName
-                }
-                return col
-              })
-            }
-            if (m.verify && m.verify.columns) {
-              m.verify.columns = m.verify.columns.map(col => {
-                if (col.Column && map[col.Column.toLowerCase()]) {
-                  col.Column = map[col.Column.toLowerCase()].FieldName
-                }
-                return col
-              })
-            }
-            if (m.config && m.config.components) {
-              m.config.components = _replace(m.config.components)
-            }
+            resetElement(m)
             return m
           })
         }
 
         if (item.plot) {
-          if (item.plot.Xaxis && map[item.plot.Xaxis.toLowerCase()]) {
-            item.plot.Xaxis = map[item.plot.Xaxis.toLowerCase()].FieldName
+          if (item.plot.Xaxis) {
+            item.plot.Xaxis = getVal(item.plot.Xaxis)
           }
           // 缁熻鍥�
-          if (item.plot.InfoValue && map[item.plot.InfoValue.toLowerCase()]) {
-            item.plot.InfoValue = map[item.plot.InfoValue.toLowerCase()].FieldName
+          if (item.plot.InfoValue) {
+            item.plot.InfoValue = getVal(item.plot.InfoValue)
           }
-          if (item.plot.InfoType && map[item.plot.InfoType.toLowerCase()]) {
-            item.plot.InfoType = map[item.plot.InfoType.toLowerCase()].FieldName
+          if (item.plot.InfoType) {
+            item.plot.InfoType = getVal(item.plot.InfoType)
           }
           // 鍗犳瘮鍥�
-          if (item.plot.valueField && map[item.plot.valueField.toLowerCase()]) {
-            item.plot.valueField = map[item.plot.valueField.toLowerCase()].FieldName
+          if (item.plot.valueField) {
+            item.plot.valueField = getVal(item.plot.valueField)
           }
-          if (item.plot.labelField && map[item.plot.labelField.toLowerCase()]) {
-            item.plot.labelField = map[item.plot.labelField.toLowerCase()].FieldName
+          if (item.plot.labelField) {
+            item.plot.labelField = getVal(item.plot.labelField)
           }
           // 楗煎浘
-          if (item.plot.type && map[item.plot.type.toLowerCase()]) {
-            item.plot.type = map[item.plot.type.toLowerCase()].FieldName
+          if (item.plot.type) {
+            item.plot.type = getVal(item.plot.type)
           }
           // 鏁g偣鍥�
-          if (item.plot.gender && map[item.plot.gender.toLowerCase()]) {
-            item.plot.gender = map[item.plot.gender.toLowerCase()].FieldName
+          if (item.plot.gender) {
+            item.plot.gender = getVal(item.plot.gender)
           }
           if (item.Yaxis) {
             if (Array.isArray(item.Yaxis)) {
-              item.Yaxis = item.Yaxis.map(m => {
-                if (map[m.toLowerCase()]) {
-                  return map[m.toLowerCase()].FieldName
-                }
-                return m
-              })
+              item.Yaxis = item.Yaxis.map(m => getVal(m))
             } else {
-              if (item.Yaxis && map[item.Yaxis.toLowerCase()]) {
-                item.Yaxis = map[item.Yaxis.toLowerCase()].FieldName
-              }
+              item.Yaxis = getVal(item.Yaxis)
             }
           }
         }
@@ -357,40 +506,13 @@
             return cols.map(col => {
               if (col.type === 'custom' && col.elements) {
                 col.elements = col.elements.map(m => {
-                  if (m.eleType === 'button') {
-                    if (m.modal && m.modal.fields) {
-                      m.modal.fields = m.modal.fields.map(col => {
-                        if (col.field && map[col.field.toLowerCase()]) {
-                          col.field = map[col.field.toLowerCase()].FieldName
-                        }
-                        return col
-                      })
-                    }
-                    if (m.verify && m.verify.columns) {
-                      m.verify.columns = m.verify.columns.map(col => {
-                        if (col.Column && map[col.Column.toLowerCase()]) {
-                          col.Column = map[col.Column.toLowerCase()].FieldName
-                        }
-                        return col
-                      })
-                    }
-                    if (m.config && m.config.components) {
-                      m.config.components = _replace(m.config.components)
-                    }
-                  } else {
-                    if (m.datatype === 'dynamic' && map[m.field.toLowerCase()]) {
-                      m.field = map[m.field.toLowerCase()].FieldName
-                    }
-                  }
-
+                  resetElement(m)
                   return m
                 })
               } else if (col.type === 'colspan') {
                 col.subcols = _update(col.subcols)
               } else if (col.field) {
-                if (map[col.field.toLowerCase()]) {
-                  col.field = map[col.field.toLowerCase()].FieldName
-                }
+                col.field = getVal(col.field)
               }
               
               return col
@@ -398,15 +520,100 @@
           }
 
           item.cols = _update(item.cols)
+
+          if (item.lineMarks) {
+            item.lineMarks = item.lineMarks.map(n => {
+              if (n.field && Array.isArray(n.field)) {
+                if (n.field[1] === 'static') {
+                  n.field[0] = getVal(n.field[0])
+                } else {
+                  if (n.field[0]) {
+                    n.field[0] = getVal(n.field[0])
+                  }
+                  if (n.field[2]) {
+                    n.field[2] = getVal(n.field[2])
+                  }
+                }
+              }
+      
+              return n
+            })
+          }
         }
 
-        if (item.subtype === 'basetable') {
-          item.cols = item.cols.map(col => {
-            if (col.field && map[col.field.toLowerCase()]) {
-              col.field = map[col.field.toLowerCase()].FieldName
+        if (item.subMenus) {
+          item.subMenus = item.subMenus.map(m => {
+            if (m.setting && m.setting.tip) {
+              m.setting.tip = getVal(m.setting.tip)
             }
-            return col
+            return m
           })
+        }
+
+        if (item.wrap) {
+          if (item.wrap.field) {
+            item.wrap.field = getVal(item.wrap.field)
+          }
+          if (item.wrap.tipField) {
+            item.wrap.tipField = getVal(item.wrap.tipField)
+          }
+          if (item.wrap.controlField) {
+            item.wrap.controlField = getVal(item.wrap.controlField)
+          }
+          if (item.wrap.valueField) {
+            item.wrap.valueField = getVal(item.wrap.valueField)
+          }
+          if (item.wrap.labelField) {
+            item.wrap.labelField = getVal(item.wrap.labelField)
+          }
+          if (item.wrap.parentField) {
+            item.wrap.parentField = getVal(item.wrap.parentField)
+          }
+          if (item.wrap.broadcast) {
+            item.wrap.broadcast = getVal(item.wrap.broadcast)
+          }
+          if (item.wrap.jumpField) {
+            item.wrap.jumpField = getVal(item.wrap.jumpField)
+          }
+          if (item.wrap.link) {
+            item.wrap.link = getVal(item.wrap.link)
+          }
+          if (item.wrap.linkField) {
+            item.wrap.linkField = getVal(item.wrap.linkField)
+          }
+          if (item.wrap.focus) {
+            item.wrap.focus = getVal(item.wrap.focus)
+          }
+          if (item.wrap.refocus) {
+            item.wrap.refocus = getVal(item.wrap.refocus)
+          }
+          if (item.wrap.statusControl) {
+            item.wrap.statusControl = getVal(item.wrap.statusControl)
+          }
+          if (item.wrap.timeField) {
+            item.wrap.timeField = getVal(item.wrap.timeField)
+          }
+          if (item.wrap.endField) {
+            item.wrap.endField = getVal(item.wrap.endField)
+          }
+          if (item.wrap.remarkField) {
+            item.wrap.remarkField = getVal(item.wrap.remarkField)
+          }
+          if (item.wrap.colorField) {
+            item.wrap.colorField = getVal(item.wrap.colorField)
+          }
+          if (item.wrap.menuType) {
+            item.wrap.menuType = getVal(item.wrap.menuType)
+          }
+
+          if (item.type === 'timeline') {
+            if (item.wrap.label) {
+              item.wrap.label = getVal(item.wrap.label)
+            }
+            if (item.wrap.node) {
+              item.wrap.node = getVal(item.wrap.node)
+            }
+          }
         }
 
         return item
@@ -434,6 +641,15 @@
       confirming: false,
       visible: false
     })
+
+    if (is(fromJS(this.props.config), fromJS(config))) {
+      notification.success({
+        top: 92,
+        message: '鏈煡璇㈠埌闇�瑕佹浛鎹㈢殑瀛楁銆�',
+        duration: 3
+      })
+      return
+    }
 
     notification.success({
       top: 92,
@@ -544,15 +760,6 @@
           item.cols = _update(item.cols)
         }
 
-        if (item.subtype === 'basetable') {
-          item.cols = item.cols.map(col => {
-            if (col.field && map[col.field.toLowerCase()]) {
-              col.label = map[col.field.toLowerCase()].FieldDec
-            }
-            return col
-          })
-        }
-
         return item
       })
     }
@@ -575,6 +782,15 @@
       visible: false
     })
 
+    if (is(fromJS(this.props.config), fromJS(config))) {
+      notification.success({
+        top: 92,
+        message: '鏈煡璇㈠埌闇�瑕佹浛鎹㈢殑瀛楁銆�',
+        duration: 3
+      })
+      return
+    }
+
     notification.success({
       top: 92,
       message: '鏇存柊宸插畬鎴愩��',
diff --git a/src/menu/replaceField/settingform/index.jsx b/src/menu/replaceField/settingform/index.jsx
index 9d20e58..ad41ce6 100644
--- a/src/menu/replaceField/settingform/index.jsx
+++ b/src/menu/replaceField/settingform/index.jsx
@@ -155,11 +155,12 @@
                 <Radio.Group onChange={(e) => {this.setState({resource: e.target.value});this.props.form.setFieldsValue({reType: 'field'})}}>
                   <Radio value="dict">鏁版嵁瀛楀吀</Radio>
                   <Radio value="custom">鑷畾涔�</Radio>
+                  <Radio value="langs">璇█鍖�</Radio>
                 </Radio.Group>
               )}
             </Form.Item>
           </Col>
-          <Col span={20}>
+          {resource !== 'langs' ? <Col span={20}>
             <Form.Item label="鏇挎崲渚濇嵁">
               {getFieldDecorator('reType', {
                 initialValue: 'field'
@@ -170,7 +171,7 @@
                 </Radio.Group>
               )}
             </Form.Item>
-          </Col>
+          </Col> : null}
           {resource === 'dict' ? <Col span={20}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="鐢ㄤ簬瀛楁鏇挎崲鐨勮〃鍚嶃��">
diff --git a/src/tabviews/basetable/index.jsx b/src/tabviews/basetable/index.jsx
index 05e30ac..2c95369 100644
--- a/src/tabviews/basetable/index.jsx
+++ b/src/tabviews/basetable/index.jsx
@@ -55,6 +55,10 @@
       func: 'sPC_Get_LongParam',
       MenuID: MenuID
     }
+
+    if (window.GLOB.mkHS) {
+      _param.lang = 'zh-CN'
+    }
     
     let result = await Api.getCacheConfig(_param)
 
diff --git a/src/tabviews/custom/components/card/double-data-card/index.jsx b/src/tabviews/custom/components/card/double-data-card/index.jsx
index f95fca7..223d05d 100644
--- a/src/tabviews/custom/components/card/double-data-card/index.jsx
+++ b/src/tabviews/custom/components/card/double-data-card/index.jsx
@@ -184,8 +184,10 @@
       })
     }
 
-    _config.setting.sub_field = subconfig.columns.map(col => col.field).join(',')
-    _config.setting.all_field = _config.setting.arr_field + ',' + _config.setting.sub_field
+    if (_config.setting.subdata !== 'sub_data_string') {
+      _config.setting.sub_field = subconfig.columns.map(col => col.field).join(',')
+      _config.setting.all_field = _config.setting.arr_field + ',' + _config.setting.sub_field
+    }
 
     let pageOptions = ['10', '25', '50', '100', '500', '1000']
 
@@ -287,6 +289,10 @@
 
             delete item[config.setting.subdata]
 
+            if (config.setting.subdata === 'sub_data_string') {
+              _children = this.parseSubData(_children)
+            }
+
             _children.forEach((cell, i) => {
               cell.key = i
               cell.$$uuid = cell[config.setting.subKey] || ''
@@ -345,6 +351,21 @@
         this.loadData()
       }, config.setting.delay || 0)
     }
+  }
+
+  parseSubData = (data) => {
+    try {
+      data = JSON.parse(data)
+      if (typeof(data) !== 'object') {
+        data = []
+      } else if (!Array.isArray(data)) {
+        data = [data]
+      }
+    } catch(e) {
+      console.warn('Data parsing error.')
+      data = []
+    }
+    return data
   }
 
   autoExec = (times) => {
@@ -663,6 +684,10 @@
             let _children = item[config.setting.subdata]
 
             delete item[config.setting.subdata]
+
+            if (config.setting.subdata === 'sub_data_string') {
+              _children = this.parseSubData(_children)
+            }
             
             _children.forEach((cell, i) => {
               cell.key = i
@@ -703,6 +728,10 @@
             let _children = item[config.setting.subdata]
 
             delete item[config.setting.subdata]
+
+            if (config.setting.subdata === 'sub_data_string') {
+              _children = this.parseSubData(_children)
+            }
 
             _children.forEach((cell, i) => {
               cell.key = i
@@ -830,6 +859,10 @@
 
               delete _data[config.setting.subdata]
 
+              if (config.setting.subdata === 'sub_data_string') {
+                _children = this.parseSubData(_children)
+              }
+
               _children.forEach((cell, i) => {
                 cell.key = i
                 cell.$$uuid = cell[config.setting.subKey] || ''
diff --git a/src/tabviews/custom/components/form/simple-form/index.jsx b/src/tabviews/custom/components/form/simple-form/index.jsx
index 2f83c49..c3edeff 100644
--- a/src/tabviews/custom/components/form/simple-form/index.jsx
+++ b/src/tabviews/custom/components/form/simple-form/index.jsx
@@ -419,6 +419,14 @@
     const { group } = this.state
 
     MKEmitter.emit('closeTabView', group.subButton.$MenuID)
+
+    let tabId = ''
+    if (group.closeButton.refreshTab && group.closeButton.refreshTab.length > 0 && window.GLOB.appType !== 'pc') {
+      tabId = group.closeButton.refreshTab[group.closeButton.refreshTab.length - 1]
+    }
+    if (tabId && group.subButton.$MenuID !== tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃舵棤鏁�
+      MKEmitter.emit('reloadMenuView', tabId)
+    }
   }
 
   resetTab = () => {
diff --git a/src/tabviews/custom/components/form/step-form/index.jsx b/src/tabviews/custom/components/form/step-form/index.jsx
index 6f1c40e..cb32043 100644
--- a/src/tabviews/custom/components/form/step-form/index.jsx
+++ b/src/tabviews/custom/components/form/step-form/index.jsx
@@ -440,6 +440,14 @@
 
     if (group.prevButton.actionType === 'close') {
       MKEmitter.emit('closeTabView', group.subButton.$MenuID)
+
+      let tabId = ''
+      if (group.prevButton.refreshTab && group.prevButton.refreshTab.length > 0 && window.GLOB.appType !== 'pc') {
+        tabId = group.prevButton.refreshTab[group.prevButton.refreshTab.length - 1]
+      }
+      if (tabId && group.subButton.$MenuID !== tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃舵棤鏁�
+        MKEmitter.emit('reloadMenuView', tabId)
+      }
       return
     }
 
@@ -455,6 +463,14 @@
 
     if (group.nextButton.actionType === 'close') {
       MKEmitter.emit('closeTabView', group.subButton.$MenuID)
+
+      let tabId = ''
+      if (group.nextButton.refreshTab && group.nextButton.refreshTab.length > 0 && window.GLOB.appType !== 'pc') {
+        tabId = group.nextButton.refreshTab[group.nextButton.refreshTab.length - 1]
+      }
+      if (tabId && group.subButton.$MenuID !== tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃舵棤鏁�
+        MKEmitter.emit('reloadMenuView', tabId)
+      }
       return
     }
 
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index 8234d4a..36e091f 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -88,6 +88,10 @@
       MenuID: MenuID
     }
 
+    if (window.GLOB.mkHS) {
+      _param.lang = 'zh-CN'
+    }
+
     let result = await Api.getCacheConfig(_param)
 
     if (result.status) {
diff --git a/src/tabviews/zshare/actionList/newpagebutton/index.jsx b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
index 3c1c12e..bab817a 100644
--- a/src/tabviews/zshare/actionList/newpagebutton/index.jsx
+++ b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -251,14 +251,16 @@
           let _param = { id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM')}
           let item = data[0]
 
-          Object.keys(item).forEach(key => {
-            if (/^\$/.test(key)) return
-            if (typeof(item[key]) !== 'string' && typeof(item[key]) !== 'number') return
-            if (typeof(item[key]) === 'string' && item[key].length > 50) return
-            if (['id', 'tempid', 'pageid', 'datam'].includes(key.toLowerCase())) return
-
-            _param[key.toLowerCase()] = item[key]
-          })
+          if (item) {
+            Object.keys(item).forEach(key => {
+              if (/^\$/.test(key)) return
+              if (typeof(item[key]) !== 'string' && typeof(item[key]) !== 'number') return
+              if (typeof(item[key]) === 'string' && item[key].length > 50) return
+              if (['id', 'tempid', 'pageid', 'datam'].includes(key.toLowerCase())) return
+  
+              _param[key.toLowerCase()] = item[key]
+            })
+          }
 
           window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify(_param))))
         }
diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx
index f038673..495d224 100644
--- a/src/tabviews/zshare/actionList/normalbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -3030,8 +3030,10 @@
       tabId = btn.refreshTab[btn.refreshTab.length - 1]
     }
 
-    if (window.backend && btn.outerFunc && ['bd_workers_create_user_sso', 's_susers_del', 's_susers_add', 's_susers_update', 's_susers_start', 's_susers_admin'].includes(btn.outerFunc)) {
-      this.clearBackSqlCache()
+    if (window.backend && btn.outerFunc && ['bd_workers_create_user_sso', 's_susers_del', 's_susers_add', 's_susers_update', 's_susers_start', 's_susers_admin'].includes(btn.outerFunc.toLowerCase())) {
+      setTimeout(() => {
+        this.clearBackSqlCache()
+      }, 300)
     }
 
     if (btn.openmenu && Array.isArray(btn.openmenu) && btn.openmenu.length > 0 && sign !== '@no_target_menu@') {
diff --git a/src/tabviews/zshare/topSearch/index.jsx b/src/tabviews/zshare/topSearch/index.jsx
index 6b79f41..6a50820 100644
--- a/src/tabviews/zshare/topSearch/index.jsx
+++ b/src/tabviews/zshare/topSearch/index.jsx
@@ -85,7 +85,7 @@
       _setting.wrapperCol = {style: {width: (100 - _setting.labelwidth) + '%'}}
       _setting.borderRadius = config.wrap.borderRadius
       _setting.resetContrl = config.wrap.resetContrl || 'init'
-      _setting.size = config.wrap.searchSize || ''
+      _setting.order = config.wrap.searchSize || ''
 
       if (config.wrap.searchBtn === 'show') {
         _setting.showBtn = true
@@ -1266,7 +1266,7 @@
 
     return (
       <>
-        <Form {...formItemLayout} className={`mk-search-wrap mk-float-${setting.float} mk-size-${setting.size}`} style={setting.style}>
+        <Form {...formItemLayout} className={`mk-search-wrap mk-float-${setting.float} mk-order-${setting.order}`} style={setting.style}>
           <Row gutter={24}>{this.getFields()}</Row>
           {advanceValues.length && (setting.advanceType !== 'pulldown' || (setting.advanceType === 'pulldown' && !visible)) ? <Row gutter={24}>
             <div className="advanced-list">
diff --git a/src/tabviews/zshare/topSearch/index.scss b/src/tabviews/zshare/topSearch/index.scss
index 021510b..7f921b2 100644
--- a/src/tabviews/zshare/topSearch/index.scss
+++ b/src/tabviews/zshare/topSearch/index.scss
@@ -132,11 +132,39 @@
     text-align: right;
   }
 }
-.mk-search-wrap.mk-size-small {
+.mk-search-wrap.mk-order-small {
   .ant-form-item, .search-button {
     min-height: 45px;
   }
 }
+.mk-search-wrap.mk-order-updown {
+  .mk-search-col {
+    .ant-form-item {
+      display: block;
+      min-height: auto;
+      margin-bottom: 15px;
+
+      .ant-form-item-label {
+        display: block;
+        width: 100% !important;
+        text-align: left;
+        float: none;
+        line-height: 2;
+        height: 24px;
+      }
+      .ant-form-item-control-wrapper {
+        display: block;
+        width: 100% !important;
+        float: none;
+      }
+    }
+  }
+  .mk-search-col:last-child {
+    .ant-form-item {
+      margin-bottom: 20px;
+    }
+  }
+}
 .mk-search-drawer {
   .ant-drawer-wrapper-body {
     position: relative;
diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx
index 16dcefa..5e6ae12 100644
--- a/src/templates/sharecomponent/searchcomponent/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/index.jsx
@@ -339,7 +339,7 @@
 
     let size = ''
     if (config.wrap && config.wrap.searchSize) {
-      size = ' mk-size-' + config.wrap.searchSize
+      size = ' mk-order-' + config.wrap.searchSize
     }
 
     return (
diff --git a/src/templates/sharecomponent/searchcomponent/index.scss b/src/templates/sharecomponent/searchcomponent/index.scss
index b156cdb..b6f619c 100644
--- a/src/templates/sharecomponent/searchcomponent/index.scss
+++ b/src/templates/sharecomponent/searchcomponent/index.scss
@@ -142,7 +142,7 @@
     }
   }
 }
-.model-table-search-list.mk-size-small {
+.model-table-search-list.mk-order-small {
   .page-card {
     height: 45px;
   }
@@ -151,4 +151,27 @@
       height: 45px!important;
     }
   }
+}
+.model-table-search-list.mk-order-updown {
+  .mk-search-item-wrap {
+    .page-card {
+      height: auto;
+    }
+    .ant-form-item {
+      display: block;
+      .ant-form-item-label {
+        display: block;
+        width: 100% !important;
+        text-align: left;
+        float: none;
+        line-height: 2;
+        height: 24px;
+      }
+      .ant-form-item-control-wrapper {
+        display: block;
+        width: 100% !important;
+        float: none;
+      }
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js
index 62635f2..e66d16d 100644
--- a/src/utils/utils-custom.js
+++ b/src/utils/utils-custom.js
@@ -2288,40 +2288,6 @@
       duration: 5
     })
     return false
-  } else if (/,\./ig.test(sql)) {
-    let lines = []
-    sql.split(/\n/).forEach((s, i) => {
-      if (/,\./ig.test(s)) {
-        lines.push(i + 1)
-      }
-    })
-
-    lines = lines.join('銆�')
-    lines = lines ? '(绗�' + lines + '琛�)' : ''
-
-    notification.warning({
-      top: 92,
-      message: label + `${lines}锛屼笉鍙嚭鐜拌嫳鏂囬�楀彿,.`,
-      duration: 5
-    })
-    return false
-  } else if (/\.,/ig.test(sql)) {
-    let lines = []
-    sql.split(/\n/).forEach((s, i) => {
-      if (/\.,/ig.test(s)) {
-        lines.push(i + 1)
-      }
-    })
-
-    lines = lines.join('銆�')
-    lines = lines ? '(绗�' + lines + '琛�)' : ''
-
-    notification.warning({
-      top: 92,
-      message: label + `${lines}锛屼笉鍙嚭鐜拌嫳鏂囬�楀彿.,`,
-      duration: 5
-    })
-    return false
   } else if (/鈥榺鈥�/ig.test(sql)) {
     let lines = []
     sql.split(/\n/).forEach((s, i) => {
@@ -2424,6 +2390,38 @@
       duration: 5
     })
     return false
+  } else if (/,\./ig.test(sql)) {
+    let lines = []
+    sql.split(/\n/).forEach((s, i) => {
+      if (/,\./ig.test(s)) {
+        lines.push(i + 1)
+      }
+    })
+
+    lines = lines.join('銆�')
+    lines = lines ? '(绗�' + lines + '琛�)' : ''
+
+    notification.warning({
+      top: 92,
+      message: label + `${lines}锛屼笉鍙嚭鐜拌嫳鏂囬�楀彿,.`,
+      duration: 5
+    })
+  } else if (/\.,/ig.test(sql)) {
+    let lines = []
+    sql.split(/\n/).forEach((s, i) => {
+      if (/\.,/ig.test(s)) {
+        lines.push(i + 1)
+      }
+    })
+
+    lines = lines.join('銆�')
+    lines = lines ? '(绗�' + lines + '琛�)' : ''
+
+    notification.warning({
+      top: 92,
+      message: label + `${lines}锛屼笉鍙嚭鐜拌嫳鏂囬�楀彿.,`,
+      duration: 5
+    })
   }
 
   return true
@@ -2433,6 +2431,8 @@
  * @description 鑾峰彇璇█杞崲淇℃伅
  */
 export function getLangTrans (config) {
+  if (sessionStorage.getItem('lang') !== 'zh-CN') return ''
+
   let langList = sessionStorage.getItem('langList')
   let appType = sessionStorage.getItem('appType')
 
@@ -2440,18 +2440,19 @@
     langList = sessionStorage.getItem('applangList')
   }
   
-  if (!langList) return
-
-  let defLang = ''
+  if (!langList) return ''
 
   try {
     langList = JSON.parse(langList)
-    defLang = langList[0]
   } catch (e) {
-    defLang = ''
+    langList = ''
   }
 
-  if (!defLang) return ''
+  if (!langList) return ''
+
+  langList = langList.filter(n => n !== 'zh-CN')
+
+  if (langList.length === 0) return ''
 
   let sql = []
   let btn = []
@@ -2486,8 +2487,18 @@
   let filterBtn = (btn) => {
     if (!btn.verify) return
 
+    btn.verify.columns && btn.verify.columns.forEach(col => {
+      if (col.Text) {
+        sql.push(col.Text)
+      }
+    })
+
     btn.verify.customverifys && btn.verify.customverifys.forEach(script => {
       filterSql(script.sql)
+
+      if (script.errmsg) {
+        sql.push(script.errmsg)
+      }
     })
     btn.verify.scripts && btn.verify.scripts.forEach(script => {
       filterSql(script.sql)
@@ -2530,6 +2541,9 @@
       } else {
         if (item.wrap && item.wrap.title) {
           sql.push(item.wrap.title)
+        }
+        if (item.plot && item.plot.title) {
+          sql.push(item.plot.title)
         }
         
         if (item.setting && (!item.wrap || !item.wrap.datatype || item.wrap.datatype === 'dynamic')) {
@@ -2767,8 +2781,6 @@
   let result = []
 
   langList.forEach(lan => {
-    if (lan === defLang) return
-
     list.forEach(n => {
       result.push(`'${lan}',${n}`)
     })
@@ -2901,8 +2913,24 @@
 
     if (!btn.verify) return
 
+    btn.verify.columns && btn.verify.columns.forEach(col => {
+      if (col.Text) {
+        col.Text = replaceTitle(col.Text)
+      }
+    })
+
+    btn.verify.uniques && btn.verify.uniques.forEach(col => {
+      if (col.fieldlabel) {
+        col.fieldlabel = col.fieldlabel.split(',').map(n => replaceTitle(n)).join(',')
+      }
+    })
+    
     btn.verify.customverifys && btn.verify.customverifys.forEach(script => {
       script.sql = filterSql(script.sql)
+
+      if (script.errmsg) {
+        script.errmsg = replaceTitle(script.errmsg)
+      }
     })
     btn.verify.scripts && btn.verify.scripts.forEach(script => {
       script.sql = filterSql(script.sql)
@@ -2993,6 +3021,9 @@
       } else {
         if (item.wrap && item.wrap.title) {
           item.wrap.title = replaceTitle(item.wrap.title)
+        }
+        if (item.plot && item.plot.title) {
+          item.plot.title = replaceTitle(item.plot.title)
         }
         if (item.wrap && (item.wrap.click === 'menu' || item.wrap.click === 'menus')) {
           if (item.wrap.click === 'menu') {
@@ -3085,6 +3116,320 @@
             } else if (card.setting.click === 'menu') {
               resetMenu(card.setting)
             }
+            card.elements && card.elements.forEach(cell => {
+              if (cell.eleType === 'button') {
+                filterBtn(cell)
+                if (cell.OpenType === 'popview' && cell.config) {
+                  traversal(cell.config.components)
+                } else if (cell.OpenType === 'pop') {
+                  if (cell.modal && cell.modal.fields.length) {
+                    cell.modal.fields.forEach(n => {
+                      filterForm(n)
+                    })
+                  }
+                }
+              } else {
+                filterElement(cell)
+              }
+            })
+            card.backElements && card.backElements.forEach(cell => {
+              if (cell.eleType === 'button') {
+                filterBtn(cell)
+                if (cell.OpenType === 'popview' && cell.config) {
+                  traversal(cell.config.components)
+                } else if (cell.OpenType === 'pop') {
+                  if (cell.modal && cell.modal.fields.length) {
+                    cell.modal.fields.forEach(n => {
+                      filterForm(n)
+                    })
+                  }
+                }
+              } else {
+                filterElement(cell)
+              }
+            })
+          })
+        } else if (item.type === 'balcony') {
+          item.elements && item.elements.forEach(cell => {
+            if (cell.eleType === 'button') {
+              filterBtn(cell)
+              if (cell.OpenType === 'popview' && cell.config) {
+                traversal(cell.config.components)
+              } else if (cell.OpenType === 'pop') {
+                if (cell.modal && cell.modal.fields.length) {
+                  cell.modal.fields.forEach(n => {
+                    filterForm(n)
+                  })
+                }
+              }
+            } else {
+              filterElement(cell)
+            }
+          })
+        } else if (item.type === 'table') {
+          let loopCol = (cols) => {
+            cols.forEach(col => {
+              if (col.label) {
+                col.label = replaceTitle(col.label)
+              }
+              if (col.prefix) {
+                col.prefix = replaceTitle(col.prefix)
+              }
+              if (col.postfix) {
+                col.postfix = replaceTitle(col.postfix)
+              }
+              if (col.type === 'colspan') {
+                loopCol(col.subcols)
+              } else if (col.type === 'custom') {
+                col.elements.forEach(cell => {
+                  if (cell.eleType === 'button') {
+                    filterBtn(cell)
+                    if (cell.OpenType === 'popview' && cell.config) {
+                      traversal(cell.config.components)
+                    } else if (cell.OpenType === 'pop') {
+                      if (cell.modal && cell.modal.fields.length) {
+                        cell.modal.fields.forEach(n => {
+                          filterForm(n)
+                        })
+                      }
+                    }
+                  } else {
+                    filterElement(cell)
+                  }
+                })
+              }
+            })
+          }
+          loopCol(item.cols)
+        } else if (item.type === 'form') {
+          item.subcards.forEach(cell => {
+            filterBtn(cell.subButton)
+            cell.fields.forEach(n => {
+              filterForm(n)
+            })
+          })
+        }
+      }
+    })
+  }
+
+  if (config.interfaces) {
+    config.interfaces.forEach(item => {
+      if (item.setting.interType === 'system') {
+        item.setting.dataresource = filterSql(item.setting.dataresource)
+        item.scripts && item.scripts.forEach(script => {
+          script.sql = filterSql(script.sql)
+        })
+      }
+    })
+  }
+
+  traversal(config.components)
+}
+
+/**
+ * @description 璇█杞崲
+ */
+export function setLangSingleTrans (config, btnDict, titDict, lisDict, menuDict, regs) {
+  let filterElement = (card) => {
+    if (card.datatype === 'static' && card.eleType === 'text' && !/@.+@/g.test(card.value)) {
+      if (card.value) {
+        card.value = replaceTitle(card.value)
+      }
+    }
+    if (card.prefix) {
+      card.prefix = replaceTitle(card.prefix)
+    }
+    if (card.postfix) {
+      card.postfix = replaceTitle(card.postfix)
+    }
+  }
+
+  let replaceTitle = (val)聽=> {
+    if聽(/(:|锛�)$/g.test(val)) {
+      let _val = val.replace(/(:|锛�)$/g,聽'')
+      if聽(titDict[_val]) {
+        val = titDict[_val] + val.substr(-1)
+      }聽else if (titDict[val]) {
+        val = titDict[val]
+      }
+    }聽else if (titDict[val]) {
+      val = titDict[val]
+    }
+
+    return val
+  }
+
+  let getuuid = () => {
+    let uuid = []
+    let _options = '0123456789abcdefghigklmnopqrstuv'
+    for (let i = 0; i < 19; i++) {
+      uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
+    }
+    return uuid.join('')
+  }
+
+  let filterSql = (sl) => {
+    if (!sl) return
+
+    let arr = []
+    
+    sl = sl.replace(/\/\*[^*/]+\*\//g, (word) => {
+      let uuid = getuuid()
+      arr.push({id: `/*${uuid}*/`, value: word})
+      return `/*${uuid}*/`
+    })
+
+    regs.forEach(item => {
+      sl = sl.replace(item.reg, item.value)
+    })
+
+    arr.forEach(item => {
+      sl = sl.replace(item.id, item.value)
+    })
+
+    return sl
+  }
+
+  let filterBtn = (btn) => {
+    if (btn.label && btnDict[btn.label]) {
+      btn.label = btnDict[btn.label]
+    }
+
+    if (!btn.verify) return
+
+    btn.verify.columns && btn.verify.columns.forEach(col => {
+      if (col.Text) {
+        col.Text = replaceTitle(col.Text)
+      }
+    })
+
+    btn.verify.uniques && btn.verify.uniques.forEach(col => {
+      if (col.fieldlabel) {
+        col.fieldlabel = col.fieldlabel.split(',').map(n => replaceTitle(n)).join(',')
+      }
+    })
+    
+    btn.verify.customverifys && btn.verify.customverifys.forEach(script => {
+      script.sql = filterSql(script.sql)
+
+      if (script.errmsg) {
+        script.errmsg = replaceTitle(script.errmsg)
+      }
+    })
+    btn.verify.scripts && btn.verify.scripts.forEach(script => {
+      script.sql = filterSql(script.sql)
+    })
+    btn.verify.cbScripts && btn.verify.cbScripts.forEach(script => {
+      script.sql = filterSql(script.sql)
+    })
+
+    if (btn.OpenType === 'funcbutton') {
+      if (btn.intertype === 'system' && btn.verify.dataType === 'custom' && btn.verify.setting) {
+        btn.verify.setting.dataresource = filterSql(btn.verify.setting.dataresource)
+      }
+    } else if (btn.OpenType === 'excelOut' && btn.verify.dataresource) {
+      btn.verify.dataresource = filterSql(btn.verify.dataresource)
+    }
+  }
+
+  let filterForm = (n) => {
+    if (n.label) {
+      n.label = replaceTitle(n.label)
+    }
+    if (n.resourceType === '1') {
+      n.dataSource = filterSql(n.dataSource)
+    } else if (n.options) {
+      n.options.forEach(o => {
+        if (o.Text && lisDict[o.Text]) {
+          o.Text = lisDict[o.Text]
+        }
+      })
+    }
+  }
+
+  let traversal = (components) => {
+    if (!components) return
+
+    components.forEach(item => {
+      if (item.type === 'tabs') {
+        item.subtabs.forEach(tab => {
+          if (tab.label) {
+            tab.label = replaceTitle(tab.label)
+          }
+          traversal(tab.components)
+        })
+      } else if (item.type === 'group') {
+        traversal(item.components)
+      } else {
+        if (item.wrap && item.wrap.title) {
+          item.wrap.title = replaceTitle(item.wrap.title)
+        }
+        if (item.plot && item.plot.title) {
+          item.plot.title = replaceTitle(item.plot.title)
+        }
+        if (item.setting && (!item.wrap || !item.wrap.datatype || item.wrap.datatype === 'dynamic')) {
+          if (item.setting.interType === 'system') {
+            item.setting.dataresource = filterSql(item.setting.dataresource)
+            item.scripts && item.scripts.forEach(script => {
+              script.sql = filterSql(script.sql)
+            })
+          }
+        }
+
+        if (item.columns) {
+          item.columns.forEach(cell => {
+            if (cell.label) {
+              cell.label = replaceTitle(cell.label)
+            }
+          })
+        }
+        if (item.search) {
+          if (item.type === 'topbar') {
+            if (item.search.fields) {
+              item.search.fields.forEach(cell => {
+                filterForm(cell)
+              })
+            }
+            if (item.search.groups) {
+              item.search.groups.forEach(group => {
+                if (group.fields) {
+                  group.fields.forEach(cell => {
+                    filterForm(cell)
+                  })
+                }
+              })
+            }
+          } else {
+            item.search.forEach(cell => {
+              filterForm(cell)
+            })
+          }
+        }
+        if (item.action) {
+          item.action.forEach(cell => {
+            filterBtn(cell)
+            if (cell.OpenType === 'popview' && cell.config) {
+              traversal(cell.config.components)
+            } else if (cell.OpenType === 'pop') {
+              if (cell.modal && cell.modal.fields.length) {
+                cell.modal.fields.forEach(n => {
+                  filterForm(n)
+                })
+              }
+            }
+          })
+        }
+
+        if (item.type === 'menubar') {
+          item.subMenus = item.subMenus.map(cell => {
+            if (cell.setting.name && menuDict[cell.setting.name]) {
+              cell.setting.name = menuDict[cell.setting.name]
+            }
+            return cell
+          })
+        } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
+          item.subcards.forEach(card => {
             card.elements && card.elements.forEach(cell => {
               if (cell.eleType === 'button') {
                 filterBtn(cell)
@@ -5012,7 +5357,7 @@
     let sFields = getSearches(searches)
 
     let _columns = []
-    if (item.subtype === 'dualdatacard') {
+    if (item.subtype === 'dualdatacard' && item.setting.subdata !== 'sub_data_string') {
       _columns = [...item.columns, ...item.subColumns]
     } else if (item.columns) {
       _columns = [...item.columns]
@@ -5128,7 +5473,7 @@
       } else if (item.setting.laypage === 'true' && item.setting.order) {
         LText = `select top @pageSize@ ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by @orderBy@) as rows from ${_dataresource} ${_search}) tmptable where rows > @pageSize@ * (@pageIndex@ - 1) order by tmptable.rows `
         reps.push('pageSize', 'orderBy', 'pageIndex')
-        if (item.subtype === 'dualdatacard') {
+        if (item.subtype === 'dualdatacard' && item.setting.subdata !== 'sub_data_string') {
           DateCount = `select count(1) as total from (select distinct ${item.setting.primaryKey || 'ID'} from ${_dataresource} ${_search})a`
         } else {
           DateCount = `select count(1) as total from ${_dataresource} ${_search}`
@@ -5155,7 +5500,7 @@
     let parid = ''
     let sub_field = ''
 
-    if (item.subtype === 'dualdatacard') {
+    if (item.subtype === 'dualdatacard' && item.setting.subdata !== 'sub_data_string') {
       arr_field = item.columns.map(col => col.field).join(',')
       sub_name = item.setting.subdata
       tabid = item.setting.primaryKey || ''
diff --git a/src/views/appmanage/index.jsx b/src/views/appmanage/index.jsx
index 88bbad2..da7e730 100644
--- a/src/views/appmanage/index.jsx
+++ b/src/views/appmanage/index.jsx
@@ -746,7 +746,6 @@
       })
     }
     if (applangList.length) {
-      applangList.unshift('zh-CN')
       applangList = JSON.stringify(applangList)
     } else {
       applangList = ''
@@ -769,7 +768,6 @@
       })
     }
     if (applangList.length) {
-      applangList.unshift('zh-CN')
       applangList = JSON.stringify(applangList)
     } else {
       applangList = ''
diff --git a/src/views/billprint/index.jsx b/src/views/billprint/index.jsx
index a202327..4f2aa10 100644
--- a/src/views/billprint/index.jsx
+++ b/src/views/billprint/index.jsx
@@ -619,9 +619,10 @@
           params.unshift(_pars)
         } else if (window.backend && config.allSqls && params.length > 0) {
           let data = []
+          let ids = []
           params = params.filter(item => {
             if (!item.$backend || item.public) return true
-
+            ids.push(item.componentId)
             item.data[0].exps.forEach(cell => {
               if (cell.key === 'mk_obj_name') {
                 cell.value = 'mk' + item.componentId.slice(-18)
@@ -635,6 +636,7 @@
               $backend: true,
               $type: 's_Get_TableData',
               componentId: '',
+              componentIds: ids,
               data
             })
           }
@@ -668,6 +670,8 @@
           
           if (params.length === 0 && initInters.length === 0) {
             this.setState({loadingview: false, pages: [config.components]})
+
+            this.autoExec()
           } else if (initInters.length > 0) {
             this.loadinit(initInters, params)
           } else {
@@ -983,6 +987,8 @@
     Promise.all(deffers).then(() => {
       if (params.length === 0) {
         this.setState({loadingview: false, pages: [this.state.config.components]})
+
+        this.autoExec()
       } else {
         this.loadmaindata(params)
       }
@@ -997,7 +1003,9 @@
 
     let deffers = params.map(item => {
       let componentId = item.componentId
+      let ids = item.componentIds
       delete item.componentId
+      delete item.componentIds
       delete item.public
       return new Promise(resolve => {
         Api.genericInterface(item).then(res => {
@@ -1015,6 +1023,20 @@
               })
             }
             resolve(false)
+          } else if (ids) {
+            ids.forEach(id => {
+              let _id = 'mk' + id.slice(-18)
+
+              if (res[_id]) {
+                let _data = { $$empty: true }
+                if (res[_id][0]) {
+                  _data = res[_id][0]
+                }
+                window.GLOB.CacheData.set(id, _data)
+              }
+            })
+
+            resolve(res)
           } else {
             res.componentId = componentId
 
@@ -1185,9 +1207,21 @@
       })
 
       this.setState({loadingview: false, pages, rePos})
+
+      this.autoExec()
     })
   }
 
+  autoExec = () => {
+    const { config } = this.state
+
+    if (config.autoExec !== 'true') return
+
+    setTimeout(() => {
+      this.print()
+    }, config.autoExecSplit || 500)
+  }
+
   reloadTabs = () => {
     if (this.reloading) return
 
diff --git a/src/views/design/header/index.jsx b/src/views/design/header/index.jsx
index 20ba503..dcb9ef0 100644
--- a/src/views/design/header/index.jsx
+++ b/src/views/design/header/index.jsx
@@ -26,7 +26,6 @@
     userName: sessionStorage.getItem('CloudUserName'),
     avatar: Utils.getrealurl(sessionStorage.getItem('CloudAvatar')),
     logo: sessionStorage.getItem('CloudLogo') || MainLogo,
-    subLang: sessionStorage.getItem('subLangList') !== null,
     visible: false,
     loading: false
   }
@@ -412,7 +411,7 @@
 
   render () {
     const { mainMenu, editLevel } = this.props
-    const { menulist, visible, loading, logo, subLang } = this.state
+    const { menulist, visible, loading, logo } = this.state
 
     return (
       <header className={'sys-header-container ant-menu-dark ' + (['level2', 'level3'].includes(editLevel) ? 'mask' : '')} id="main-header-container">
@@ -496,7 +495,7 @@
               缂栬緫
             </Button>
           </div> : null}
-          {window.GLOB.systemType !== 'production' && subLang ? <div className="entrance">
+          {window.GLOB.systemType !== 'production' && sessionStorage.getItem('lang') !== 'zh-CN' ? <div className="entrance">
             <div className="icon"><PlusOutlined /></div>
             <div className="title">鑿滃崟杞崲</div>
             <div className="detail">鍙�夋嫨姣嶈绯荤粺鐨勮彍鍗曪紝蹇�熻浆鎹㈠埌褰撳墠璇█銆傛墦鍗版ā鏉胯鍦℉S涓嬪鍒跺悗锛屽湪姝ゅ閫夋嫨鎸囧畾妯℃澘杩涜璇█杞崲銆�</div>
diff --git a/src/views/design/header/transmenu/index.jsx b/src/views/design/header/transmenu/index.jsx
index 805f411..6ce5336 100644
--- a/src/views/design/header/transmenu/index.jsx
+++ b/src/views/design/header/transmenu/index.jsx
@@ -16,7 +16,6 @@
     visible: false,
     loading: false,
     saveing: false,
-    lang: '',
     type: '',
     dicts: [],
     menus: [],
@@ -31,11 +30,7 @@
   }
 
   trigger = () => {
-    let langs = sessionStorage.getItem('subLangList')
-    langs = JSON.parse(langs)
-
     this.setState({
-      lang: langs[0],
       loading: true,
       visible: true,
       saveing: false,
@@ -45,7 +40,7 @@
     })
     
     this.getDicts()
-    this.getMenus(langs[0])
+    this.getMenus()
   }
   
   getDicts = () => {
@@ -78,7 +73,7 @@
     })
   }
 
-  getMenus = (lang) => {
+  getMenus = () => {
     if (this.state.menus.length > 0) {
       this.setState({loading: false})
       return
@@ -88,7 +83,7 @@
       func: 's_get_pc_menus',
       systemType: window.GLOB.sysType,
       pro_sys: '',
-      lang: lang,
+      lang: 'zh-CN',
       debug: 'Y'
     }
 
@@ -327,12 +322,12 @@
 
   transThdMenu = (menu, reload) => {
     const { menulist } = this.props
-    const { lang, dicts } = this.state
+    const { dicts } = this.state
 
     let _param = {
       func: 'sPC_Get_LongParam',
       MenuID: menu.value,
-      lang: lang
+      lang: 'zh-CN'
     }
 
     let creat = true
diff --git a/src/views/login/index.jsx b/src/views/login/index.jsx
index 850d770..f7dbf17 100644
--- a/src/views/login/index.jsx
+++ b/src/views/login/index.jsx
@@ -27,6 +27,8 @@
     ICP: window.GLOB.ICP || '',
     lineColor: window.GLOB.lineColor || '',
     webSite: window.GLOB.webSite || '',
+    prolType: window.GLOB.prolType || '',
+    prolCont: window.GLOB.prolCont || '',
     langList: [],
     syncApp: false,
     loginWays: null,
@@ -296,7 +298,6 @@
     // md5("/ws/location/v1/ip?callback=callbackFunction&key=key&output=jsonp secret key")
     // md5("/ws/location/v1/ip?callback=callbackFunction&key=BA7BZ-4QB65-LFCIA-QPDA6-4G6O7-MJB4Q&output=jsonpuThL4ZM3XOj642ksEQh76tyHFjh4")
 
-    sessionStorage.removeItem('subLangList')
     sessionStorage.removeItem('langList')
 
     setTimeout(() => {
@@ -627,12 +628,27 @@
               style: res.CSS || '',
               showline: res.split_line_show || 'true',
               webSite: res.WebSite || '',
+              prolType: '',
+              prolCont: '',
               navBar: res.menu_type, // shutter 鐧惧彾绐椼�乴inkage_navigation 鑱斿姩鑿滃崟銆乴inkage 鑱斿姩鑿滃崟_鏃犲鑸爮銆乵enu_board 鑿滃崟闈㈡澘銆乵enu_board_navigation 鑿滃崟闈㈡澘_鏍囩椤�
               app_version: res.app_version,
               Member_Level: 0,
               appname: res.appname || '',
               loginOtop: loginOtop,
               loginOleft: loginOleft
+            }
+
+            if (['every_time', 'once', 'not_required'].includes(res.require_legal_consent) && res.legal_documents) {
+              systemMsg.prolCont = res.legal_documents
+              try {
+                systemMsg.prolCont = window.decodeURIComponent(window.atob(systemMsg.prolCont))
+                if (res.require_legal_consent !== 'not_required') {
+                  systemMsg.prolType = res.require_legal_consent
+                }
+              } catch(e) {
+                systemMsg.prolType = ''
+                systemMsg.prolCont = ''
+              }
             }
 
             if ([10, 20, 30, 40, 50, 60, 70, 80, 90, 100].includes(res.member_level)) {
@@ -724,20 +740,8 @@
             }
 
             if (res.lang_data && res.lang_data.length > 1 && window.GLOB.systemType !== 'production') {
-              let list = res.lang_data.map(item => item.Lang)
-              let lang = 'zh-CN'
-              if (window.GLOB.defLang && list.includes(window.GLOB.defLang)) {
-                lang = window.GLOB.defLang
-              }
-
-              if (list.includes(lang)) {
-                list = [lang, ...list.filter(item => item !== lang)]
-                if (lang === sessionStorage.getItem('lang')) {
-                  sessionStorage.setItem('langList', JSON.stringify(list))
-                } else {
-                  sessionStorage.setItem('subLangList', JSON.stringify(list))
-                }
-              }
+              let list = res.lang_data.map(item => item.Lang).filter(n => n !== 'zh-CN')
+              sessionStorage.setItem('langList', JSON.stringify(list))
             }
 
             if (res.lang_data.length === 1 && res.lang_data[0].Lang !== sessionStorage.getItem('lang')) {
@@ -747,12 +751,16 @@
               return
             }
 
+            let langList = res.lang_data.map(item => ({Lang: item.Lang, LangName: item.LangName}))
+
+            localStorage.setItem(window.GLOB.sysSign + 'langList', JSON.stringify(langList))
+
             window.GLOB.loginOtop = systemMsg.loginOtop
             window.GLOB.loginOleft = systemMsg.loginOleft
             
             this.setState({
               loginWays: login_ways,
-              langList: res.lang_data || [],
+              langList: langList,
               ...systemMsg
             })
 
@@ -820,6 +828,19 @@
 
       this.setState({
         loginWays: loginWays
+      })
+    }
+
+    let langs = localStorage.getItem(window.GLOB.sysSign + 'langList')
+    if (langs) {
+      try {
+        langs = JSON.parse(langs)
+      } catch (e) {
+        langs = []
+      }
+
+      this.setState({
+        langList: langs
       })
     }
   }
@@ -920,7 +941,7 @@
   }
 
   render () {
-    const { lineColor, bgImage, loginlogo, copyRight, webSite, ICP, loginWays } = this.state
+    const { lineColor, bgImage, loginlogo, copyRight, webSite, ICP, loginWays, prolType, prolCont } = this.state
 
     let wrapStyle = {}
 
@@ -945,6 +966,8 @@
             auth={this.state.auth}
             authError={this.state.authError}
             loginWays={loginWays}
+            prolType={prolType}
+            prolCont={prolCont}
             langList={this.state.langList}
             isDisabled={this.state.isDisabled}
             handleSubmit={() => this.handleSubmit()}
@@ -953,11 +976,13 @@
           /> : null}
         </div>
         <div className="login-bottom">
-          {webSite && copyRight ?
-            <a target="_blank" rel="noopener noreferrer" href={webSite} dangerouslySetInnerHTML={{ __html: copyRight.replace(/\s/ig, '&nbsp;') }}></a> :
-            <p dangerouslySetInnerHTML={{ __html: copyRight ? copyRight.replace(/\s/ig, '&nbsp;') : '' }}></p>
-          }
-          <br/>
+          <p>
+            {webSite && copyRight ?
+              <a target="_blank" rel="noopener noreferrer" href={webSite} dangerouslySetInnerHTML={{ __html: copyRight.replace(/\s/ig, '&nbsp;') }}></a> :
+              <span dangerouslySetInnerHTML={{ __html: copyRight ? copyRight.replace(/\s/ig, '&nbsp;') : '' }}></span>
+            }
+            {prolCont && !prolType ? <span style={{marginLeft: '15px'}} dangerouslySetInnerHTML={{ __html: prolCont }}></span> : null}
+          </p>
           {ICP ? <a target="_blank" rel="noopener noreferrer" href="https://beian.miit.gov.cn/#/Integrated/index" dangerouslySetInnerHTML={{ __html: ICP.replace(/\s/ig, '&nbsp;') }}></a> : null}
         </div>
         {/* 缂栬緫鐘舵�佺櫥褰� */}
diff --git a/src/views/login/index.scss b/src/views/login/index.scss
index cb8b3af..e4b51c4 100644
--- a/src/views/login/index.scss
+++ b/src/views/login/index.scss
@@ -48,6 +48,13 @@
       background-color: var(--mk-sys-color5);
       border-color: var(--mk-sys-color5);
     }
+    .login-form-button.disabled {
+      background-color: var(--mk-sys-color5);
+      border-color: var(--mk-sys-color5);
+      color: #ffffff;
+      cursor: not-allowed;
+      opacity: 0.9;
+    }
 
     .login-way-wrap {
       .login-way.active, .login-way:hover {
@@ -159,6 +166,7 @@
       .btn-login {
         margin-bottom: 3vh;
         clear: both;
+        height: auto;
       }
       .register-line {
         font-size: 14px;
@@ -181,6 +189,7 @@
         display: inline-block;
         margin-bottom: 3vh;
         margin-top: -10px;
+        height: 35px;
       }
       .minline.right {
         float: right;
@@ -192,6 +201,28 @@
           .ant-select-selection-selected-value {
             float: right;
             margin-right: 10px;
+          }
+        }
+      }
+      .proline {
+        display: inline-block;
+        margin-bottom: 10px;
+        height: auto;
+        margin-top: calc(-3vh + 10px);
+        font-size: 13px;
+        .ant-form-item-children {
+          display: flex;
+          align-items: flex-start;
+          line-height: 1.5;
+          color: rgba(0, 0, 0, 0.5);
+
+          // .ant-checkbox-inner {
+          //   width: 15px;
+          //   height: 15px;
+          // }
+
+          a {
+            color: var(--mk-sys-color);
           }
         }
       }
@@ -244,9 +275,7 @@
     padding-top: 20px;
     p {
       margin-bottom: 5px;
-    }
-    p + br {
-      display: none;
+      text-align: center;
     }
     a {
       color: var(--mk-sys-font-color);
diff --git a/src/views/login/loginform.jsx b/src/views/login/loginform.jsx
index 55df6ad..508acd3 100644
--- a/src/views/login/loginform.jsx
+++ b/src/views/login/loginform.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Input, Button, Checkbox, Select, Modal, message, AutoComplete } from 'antd'
+import { Form, Input, Button, Checkbox, Select, Modal, message, AutoComplete, Tooltip } from 'antd'
 import { UserOutlined, LockOutlined, QrcodeOutlined, RedoOutlined, CloseCircleOutlined } from '@ant-design/icons'
 import md5 from 'md5'
 import moment from 'moment'
@@ -15,6 +15,23 @@
 const { warning } = Modal
 let LoginVerCodeTimer = null
 const QrCode = asyncLoadComponent(() => import('@/components/qrcode'))
+
+const CheckWrap = ({checked, prolType, onChange, prolCont}) => {
+  const change = (e) => {
+    onChange(e.target.checked)
+
+    if (prolType === 'once') {
+      localStorage.setItem(window.GLOB.sysSign + 'protocol', e.target.checked)
+    }
+  }
+
+  return (
+    <>
+      <Checkbox defaultChecked={checked} onChange={change} style={{marginRight: '8px'}}></Checkbox>
+      <span dangerouslySetInnerHTML={{__html: prolCont}}></span>
+    </>
+  )
+}
 
 class LoginTabForm extends Component {
   static propTpyes = {
@@ -33,6 +50,7 @@
     username: '',
     password: '',
     remember: true,
+    protocol: null,
     delay: null,
     loginWays: [],
     smsId: '',
@@ -48,9 +66,19 @@
 
   timer = null
   splitTime = 0
+  scanParam = null
 
   UNSAFE_componentWillMount () {
-    const { loginWays } = this.props
+    const { loginWays, prolType } = this.props
+
+    let protocol = null
+
+    if (prolType === 'once') {
+      protocol = localStorage.getItem(window.GLOB.sysSign + 'protocol') === 'true'
+    } else if (prolType === 'every_time') {
+      protocol = false
+    }
+
     let remember = true
     
     if (localStorage.getItem(window.GLOB.sysSign + 'remember') === 'false') {
@@ -111,6 +139,7 @@
       scanId: activeKey === 'app_scan' || activeKey === 'weixin_scan' ? Utils.getuuid() : '',
       timeout: false,
       remember,
+      protocol,
       wayLabels,
       hasScan
     })
@@ -124,9 +153,10 @@
   }
 
   checkResult = () => {
-    const { scanId } = this.state
+    const { scanId, protocol, dict } = this.state
 
     this.splitTime += 10000
+    this.scanParam = null
 
     let _param = {
       func: 'webapi_get_binding_key',
@@ -150,6 +180,14 @@
         message.warning(res.message)
         return
       } else if (res.thd_party_appid && res.thd_party_member_id && res.thd_party_openid) {
+        if (protocol === false) {
+          this.scanParam = {
+            ...res,
+            scanId
+          }
+          message.warning(dict['protocol_check'] || '璇烽槄璇诲苟鍚屾剰鍗忚锛�')
+          return
+        }
         this.props.authLogin(res.thd_party_appid, res.thd_party_openid, res.thd_party_member_id, scanId)
       } else {
         this.timer = setTimeout(() => {
@@ -160,7 +198,10 @@
   }
 
   handleConfirm = () => {
-    const { activeKey } = this.state
+    const { activeKey, protocol } = this.state
+
+    if (protocol === false) return Promise.reject()
+
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
@@ -423,6 +464,14 @@
     localStorage.setItem(window.GLOB.sysSign + 'users', window.btoa(window.encodeURIComponent(JSON.stringify(_users))))
   }
 
+  changeAgree = (val) => {
+    this.setState({protocol: val})
+
+    if (this.scanParam && val) {
+      this.props.authLogin(this.scanParam.thd_party_appid, this.scanParam.thd_party_openid, this.scanParam.thd_party_member_id, this.scanParam.scanId)
+    }
+  }
+
   /**
    * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
    */
@@ -434,9 +483,9 @@
   }
 
   render() {
-    const { langList } = this.props
+    const { langList, isDisabled, prolType, prolCont } = this.props
     const { getFieldDecorator } = this.props.form
-    const { activeKey, verdisabled, delay, loginWays, remember, scanId, timeout, hasScan, users, wayLabels, dict, lang, vispwd } = this.state
+    const { activeKey, verdisabled, delay, loginWays, remember, scanId, timeout, hasScan, users, wayLabels, dict, lang, vispwd, protocol } = this.state
 
     return (
       <Form className="login-form" id="login-form" onSubmit={this.handleSubmit}>
@@ -499,10 +548,17 @@
               </Select>
             )}
           </Form.Item> : null}
+          {prolType ? <Form.Item className="proline">
+            <CheckWrap checked={protocol} onChange={(val) => this.setState({protocol: val})} prolCont={prolCont} prolType={prolType}/>
+          </Form.Item> : null}
           <Form.Item className="btn-login">
-            <Button type="primary" htmlType="submit" className="login-form-button" disabled={this.props.isDisabled} loading={this.props.isDisabled}>
-              {dict['log_in'] || '鐧诲綍'}
-            </Button>
+            {protocol === false ? <Tooltip overlayStyle={{maxWidth: 500}} placement="top" trigger="click" title={dict['protocol_check'] || '璇烽槄璇诲苟鍚屾剰鍗忚锛�'}>
+              <Button type="primary" htmlType="submit" className="login-form-button disabled">
+                {dict['log_in'] || '鐧诲綍'}
+              </Button>
+            </Tooltip> : <Button type="primary" htmlType="submit" className="login-form-button" disabled={isDisabled} loading={isDisabled}>
+            {dict['log_in'] || '鐧诲綍'}
+            </Button>}
           </Form.Item>
           {window.GLOB.sysType === 'cloud' && options.cdomain.indexOf('mk9h') > -1 ? <Form.Item className="register-line">
             <a href="http://www.minkesoft.com/signup" target="_blank" rel="noopener noreferrer" className="register">娉ㄥ唽</a>
@@ -556,10 +612,17 @@
               </Select>
             )}
           </Form.Item> : null}
+          {prolType ? <Form.Item className="proline">
+            <CheckWrap checked={protocol} onChange={(val) => this.setState({protocol: val})} prolCont={prolCont} prolType={prolType}/>
+          </Form.Item> : null}
           <Form.Item className="btn-login">
-            <Button type="primary" htmlType="submit" className="login-form-button" disabled={this.props.isDisabled} loading={this.props.isDisabled}>
+            {protocol === false ? <Tooltip overlayStyle={{maxWidth: 500}} placement="top" trigger="click" title={dict['protocol_check'] || '璇烽槄璇诲苟鍚屾剰鍗忚锛�'}>
+              <Button type="primary" htmlType="submit" className="login-form-button disabled">
+                {dict['log_in'] || '鐧诲綍'}
+              </Button>
+            </Tooltip> : <Button type="primary" htmlType="submit" className="login-form-button" disabled={isDisabled} loading={isDisabled}>
               {dict['log_in'] || '鐧诲綍'}
-            </Button>
+            </Button>}
           </Form.Item>
           {window.GLOB.sysType === 'cloud' && options.cdomain.indexOf('mk9h') > -1 ? <Form.Item className="register-line">
             <a href="http://www.minkesoft.com/signup" target="_blank" rel="noopener noreferrer" className="register">娉ㄥ唽</a>
@@ -577,6 +640,9 @@
             </div>
             <img src={wxicon} alt=""/>{dict['wechat_scan'] || '璇蜂娇鐢ㄥ井淇℃壂涓�鎵櫥褰�'}
           </div>
+          {prolType ? <Form.Item className="proline">
+            <CheckWrap checked={protocol} onChange={this.changeAgree} prolCont={prolCont} prolType={prolType}/>
+          </Form.Item> : null}
         </div> : null}
         {activeKey === 'app_scan' ? <div className="form-item-wrap">
           <div className="form-scan-wrap">
@@ -589,6 +655,9 @@
             </div>
             {dict['client_scan'] || '璇蜂娇鐢ㄥ鎴风鎵竴鎵櫥褰�'}
           </div>
+          {prolType ? <Form.Item className="proline">
+            <CheckWrap checked={protocol} onChange={this.changeAgree} prolCont={prolCont} prolType={prolType}/>
+          </Form.Item> : null}
         </div> : null}
         <div className={'login-ways ' + (activeKey === 'app_scan' || activeKey === 'weixin_scan' ? 'center' : '')}>
           {loginWays.map(item => {
diff --git a/src/views/menudesign/printmenuform/index.jsx b/src/views/menudesign/printmenuform/index.jsx
index 5aff337..c015b1e 100644
--- a/src/views/menudesign/printmenuform/index.jsx
+++ b/src/views/menudesign/printmenuform/index.jsx
@@ -245,6 +245,35 @@
               </Form.Item>
             </Col> : null}
             <Col span={24}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鍚敤鏃讹紝鍦ㄨ彍鍗曞畬鎴愭暟鎹姞杞藉悗鑷姩瑙﹀彂鎵撳嵃棰勮銆�">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  鑷姩鎵撳嵃
+                </Tooltip>
+              }>
+                {getFieldDecorator('autoExec', {
+                  initialValue: config.autoExec || 'false'
+                })(
+                  <Radio.Group onChange={(e) => this.selectChange('autoExec', e.target.value)}>
+                    <Radio value="false">涓嶅惎鐢�</Radio>
+                    <Radio value="true">鍚敤</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            {config.autoExec === 'true' ? <Col span={24}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鑷姩瑙﹀彂鎵撳嵃棰勮鐨勫欢杩熸椂闂达紝鍗曚綅姣銆�">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  寤惰繜鏃堕棿
+                </Tooltip>
+              }>
+                {getFieldDecorator('autoExecSplit', {
+                  initialValue: config.autoExecSplit || 500
+                })(<InputNumber min={1} max={9999} precision={0} onChange={(val) => this.selectChange('autoExecSplit', val)}/>)}
+              </Form.Item>
+            </Col> : null}
+            <Col span={24}>
               <Form.Item label="鍥炶皟">
                 {getFieldDecorator('callback', {
                   initialValue: config.callback || 'false'
diff --git a/src/views/systemfunc/index.jsx b/src/views/systemfunc/index.jsx
index 0e28ca3..bf2d296 100644
--- a/src/views/systemfunc/index.jsx
+++ b/src/views/systemfunc/index.jsx
@@ -30,6 +30,7 @@
       document.body.className = 'mk-blue-black'
       window.GLOB.dataFormat = false // 鍘婚櫎姘村嵃
       window.GLOB.mkHS = true
+      window.GLOB.dict = {}
   
       // HS涓嬩笉鍙紑鍚柇鐐硅皟璇�
       window.GLOB.breakpoint = false

--
Gitblit v1.8.0