From 2404d8a1bed5509432652f11aba6a1efa04aa160 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期五, 18 九月 2020 19:24:26 +0800
Subject: [PATCH] 2020-09-18

---
 src/templates/sharecomponent/columncomponent/colspanform/index.scss |    5 
 src/utils/utils-datamanage.js                                       |   93 +++++++
 src/templates/modalconfig/index.jsx                                 |    2 
 src/templates/sharecomponent/columncomponent/index.jsx              |   10 
 src/templates/sharecomponent/columncomponent/colspanform/index.jsx  |   32 ++
 src/tabviews/subtable/index.jsx                                     |  135 ++++++++--
 src/tabviews/subtabtable/index.jsx                                  |  121 +++++++--
 src/templates/zshare/formconfig.jsx                                 |   30 ++
 src/tabviews/commontable/index.jsx                                  |  116 +++++++--
 src/tabviews/zshare/normalTable/index.jsx                           |  125 +++++++++-
 src/tabviews/zshare/normalTable/index.scss                          |   26 +
 src/templates/sharecomponent/columncomponent/columnform/index.jsx   |   11 
 12 files changed, 583 insertions(+), 123 deletions(-)

diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index 4d7f825..d3c1c80 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -72,7 +72,9 @@
     refreshtabs: null,    // 闇�瑕佸埛鏂扮殑鏍囩闆�
     triggerBtn: null,     // 鐐瑰嚮琛ㄦ牸涓垨蹇嵎閿Е鍙戠殑鎸夐挳
     tabActive: null,      // 鏍囩椤靛睍寮�鎺у埗
-    chartId: ''           // 灞曞紑鍥捐〃ID
+    chartId: '',          // 灞曞紑鍥捐〃ID
+    statFields: [],       // 鍚堣瀛楁
+    statFValue: []        // 鍚堣鍊�
   }
 
   /**
@@ -223,34 +225,36 @@
       config.setting.execute = config.setting.default !== 'false'     // 榛樿sql鏄惁鎵ц锛岃浆涓篵oolean 缁熶竴鏍煎紡
       config.setting.customScript = ''                                // 鑷畾涔夎剼鏈�
 
-      if (config.setting.scripts && config.setting.scripts.length > 0) {
-        let _customScript = ''
-        config.setting.scripts.forEach(item => {
-          if (item.status === 'false') return
-          _customScript += `
-            ${item.sql}
-          `
-        })
-        config.setting.customScript = _customScript
-      }
-
-      if (!config.setting.execute) { // 榛樿sql 涓嶆墽琛屾椂 缃┖
-        config.setting.dataresource = ''
-      } else {
-        config.setting.dataresource = config.setting.dataresource || ''
-      }
-      if (/\s/.test(config.setting.dataresource)) {
-        config.setting.dataresource = '(' + config.setting.dataresource + ') tb'
-      }
-
-      if (this.props.dataManager) { // 鏁版嵁鏉冮檺
-        config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
-        config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
-        config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
-        config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
-      } else {
-        config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
-        config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
+      if (config.setting.interType === 'system') {
+        if (config.setting.scripts && config.setting.scripts.length > 0) {
+          let _customScript = ''
+          config.setting.scripts.forEach(item => {
+            if (item.status === 'false') return
+            _customScript += `
+              ${item.sql}
+            `
+          })
+          config.setting.customScript = _customScript
+        }
+  
+        if (!config.setting.execute) { // 榛樿sql 涓嶆墽琛屾椂 缃┖
+          config.setting.dataresource = ''
+        } else {
+          config.setting.dataresource = config.setting.dataresource || ''
+        }
+        if (/\s/.test(config.setting.dataresource)) {
+          config.setting.dataresource = '(' + config.setting.dataresource + ') tb'
+        }
+  
+        if (this.props.dataManager) { // 鏁版嵁鏉冮檺
+          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
+          config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
+          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
+          config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
+        } else {
+          config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
+          config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
+        }
       }
 
       if (_curUserConfig) {
@@ -293,6 +297,7 @@
       let _logcolumns = []   // 鏃ュ織鏄剧ず鍒�
       let _hideCol = []      // 闅愯棌鍙婂悎骞跺垪涓瓧娈电殑uuid闆�
       let colMap = new Map() // 鐢ㄤ簬瀛楁杩囨护
+      let statFields = []    // 鍚堣瀛楁淇℃伅
 
       let _actions = []      // 宸ュ叿鏍忔寜閽�
       let _operations = []   // 鎿嶄綔鍒楁寜閽紙瀛樺湪鏃讹級
@@ -316,6 +321,9 @@
           _logcolumns.push(col)
 
           col.nameField && _arrField.push(col.nameField) // 閾炬帴鍚嶅瓧娈�
+          if (col.Hide !== 'true' && col.type === 'number' && col.sum === 'true') {
+            statFields.push(col)
+          }
         }
         if (col.type === 'colspan' && col.sublist) { // 绛涢�夐殣钘忓垪
           _hideCol = _hideCol.concat(col.sublist)
@@ -385,6 +393,7 @@
         loadingview: false,
         chartId: chartId,
         config: config,
+        statFields: statFields,
         tabActive: _tabActive,
         userConfig: userConfig,
         setting: config.setting,
@@ -397,6 +406,7 @@
       }, () => {
         if (config.setting.onload !== 'false' && valid) { // 鍒濆鍖栧彲鍔犺浇
           this.loadmaindata()
+          this.getStatFieldsValue()
         }
         this.setShortcut()
       })
@@ -564,6 +574,50 @@
   }
 
   /**
+   * @description 鑾峰彇鍚堣瀛楁鍊�
+   */
+  getStatFieldsValue = () => {
+    const { setting, search, BID, orderBy, statFields } = this.state
+
+    if (statFields.length === 0 || setting.interType !== 'system' || !setting.dataresource) return
+
+    let requireFields = search.filter(item => item.required && (!item.value || item.value.length === 0))
+    if (requireFields.length > 0) {
+      return
+    }
+
+    let _orderBy = orderBy || setting.order
+    let param = UtilsDM.getStatQueryDataParams(setting, statFields, search, _orderBy, BID, this.props.menuType, this.props.dataManager)
+
+    Api.genericInterface(param).then(res => {
+      if (res.status) {
+        let _data = res.data[0]
+        let values = []
+
+        if (_data) {
+          statFields.forEach(item => {
+            if (_data[item.field] || _data[item.field] === 0) {
+              values.push({label: item.label, value: _data[item.field]})
+            }
+          })
+        }
+        this.setState({
+          statFValue: values
+        })
+      } else {
+        this.setState({
+          statFValue: []
+        })
+        notification.error({
+          top: 92,
+          message: res.message,
+          duration: 10
+        })
+      }
+    })
+  }
+
+  /**
    * @description 鎼滅储鏉′欢鏀瑰彉鏃讹紝閲嶇疆琛ㄦ牸鏁版嵁
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
@@ -577,6 +631,7 @@
         setting: {...setting, onload: 'true'}
       }, () => {
         this.loadmaindata()
+        this.getStatFieldsValue()
       })
     } else {
       this.setState({
@@ -586,6 +641,7 @@
         search: searches
       }, () => {
         this.loadmaindata()
+        this.getStatFieldsValue()
       })
     }
   }
@@ -622,6 +678,7 @@
       pageIndex: 1
     }, () => {
       this.loadmaindata()
+      this.getStatFieldsValue()
     })
   }
 
@@ -918,6 +975,7 @@
                       total={this.state.total}
                       MenuID={this.props.MenuID}
                       loading={this.state.loading}
+                      statFValue={this.state.statFValue}
                       refreshdata={this.refreshbytable}
                       buttonTrigger={this.buttonTrigger}
                       handleTableId={this.handleTableId}
diff --git a/src/tabviews/subtable/index.jsx b/src/tabviews/subtable/index.jsx
index 982e15b..5f57a90 100644
--- a/src/tabviews/subtable/index.jsx
+++ b/src/tabviews/subtable/index.jsx
@@ -64,7 +64,9 @@
     search: [],           // 鎼滅储鏉′欢鏁扮粍锛屼娇鐢ㄦ椂闇�鍒嗗満鏅鐞�
     pickup: false,        // 瀛愯〃鏁版嵁闅愯棌鏄剧ず鍒囨崲
     triggerBtn: null,     // 鎸夐挳瑙﹀彂
-    chartId: ''           // 灞曞紑鍥捐〃ID
+    chartId: '',          // 灞曞紑鍥捐〃ID
+    statFields: [],       // 鍚堣瀛楁
+    statFValue: []        // 鍚堣鍊�
   }
 
   /**
@@ -79,6 +81,7 @@
       }, () => {
         if (this.state.setting) {
           this.loadmaindata(nextProps.BID, 'refresh')
+          this.getStatFieldsValue(nextProps.BID, 'refresh')
         }
       })
     } else if (this.state.config && nextProps.refreshtabs && nextProps.refreshtabs.includes(this.props.Tab.uuid)) {
@@ -95,6 +98,7 @@
       if (this.state.setting) {
         this.setState({}, () => {
           this.loadmaindata()
+          this.getStatFieldsValue()
         })
       }
     }
@@ -145,6 +149,7 @@
       let _logcolumns = []   // 鏃ュ織鏄剧ず鍒�
       let _hideCol = []      // 闅愯棌鍙婂悎骞跺垪涓瓧娈电殑uuid闆�
       let colMap = new Map()
+      let statFields = []    // 鍚堣瀛楁淇℃伅
 
       // 鐗堟湰鍏煎
       config = UtilsUpdate.updateSubTable(config)
@@ -241,6 +246,9 @@
           _logcolumns.push(col)
 
           col.nameField && _arrField.push(col.nameField) // 閾炬帴鍚嶅瓧娈�
+          if (col.Hide !== 'true' && col.type === 'number' && col.sum === 'true') {
+            statFields.push(col)
+          }
         }
         if (col.type === 'colspan' && col.sublist) { // 绛涢�夐殣钘忓垪
           _hideCol = _hideCol.concat(col.sublist)
@@ -324,40 +332,43 @@
       config.setting.execute = config.setting.default !== 'false'     // 榛樿sql鏄惁鎵ц锛岃浆涓篵oolean 缁熶竴鏍煎紡
       config.setting.customScript = ''                                // 鑷畾涔夎剼鏈�
 
-      if (config.setting.scripts && config.setting.scripts.length > 0) {
-        let _customScript = ''
-        config.setting.scripts.forEach(item => {
-          if (item.status === 'false') return
-          _customScript += `
-            ${item.sql}
-          `
-        })
-        config.setting.customScript = _customScript
-      }
-
-      if (!config.setting.execute) { // 榛樿sql 涓嶆墽琛屾椂 缃┖
-        config.setting.dataresource = ''
-      } else {
-        config.setting.dataresource = config.setting.dataresource || ''
-      }
-      if (/\s/.test(config.setting.dataresource)) {
-        config.setting.dataresource = '(' + config.setting.dataresource + ') tb'
-      }
-
-      if (this.props.dataManager) { // 鏁版嵁鏉冮檺
-        config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
-        config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
-        config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
-        config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
-      } else {
-        config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
-        config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
+      if (config.setting.interType === 'system') {
+        if (config.setting.scripts && config.setting.scripts.length > 0) {
+          let _customScript = ''
+          config.setting.scripts.forEach(item => {
+            if (item.status === 'false') return
+            _customScript += `
+              ${item.sql}
+            `
+          })
+          config.setting.customScript = _customScript
+        }
+  
+        if (!config.setting.execute) { // 榛樿sql 涓嶆墽琛屾椂 缃┖
+          config.setting.dataresource = ''
+        } else {
+          config.setting.dataresource = config.setting.dataresource || ''
+        }
+        if (/\s/.test(config.setting.dataresource)) {
+          config.setting.dataresource = '(' + config.setting.dataresource + ') tb'
+        }
+  
+        if (this.props.dataManager) { // 鏁版嵁鏉冮檺
+          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
+          config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
+          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
+          config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
+        } else {
+          config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
+          config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
+        }
       }
 
       this.setState({
         loadingview: false,
         chartId: chartId,
         config: config,
+        statFields: statFields,
         setting: config.setting,
         searchlist: config.search,
         actions: _actions,
@@ -368,6 +379,7 @@
       }, () => {
         if (config.setting.onload !== 'false' && (!Tab.supMenu || BID || Tab.isTreeNode) && valid) { // 鍒濆鍖栧彲鍔犺浇
           this.loadmaindata()
+          this.getStatFieldsValue()
         }
       })
     } else {
@@ -458,6 +470,68 @@
   }
 
   /**
+   * @description 鑾峰彇鍚堣瀛楁鍊�
+   */
+  getStatFieldsValue = (bid, type) => {
+    const { mainSearch } = this.props
+    const { setting, search, orderBy, statFields } = this.state
+
+    let _BID = this.props.BID
+    let searches = fromJS(search).toJS()
+    if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
+      searches = [...mainSearch, ...searches]
+    }
+
+    if (statFields.length === 0 || setting.interType !== 'system' || !setting.dataresource) return
+
+    let requireFields = search.filter(item => item.required && (!item.value || item.value.length === 0))
+    if (requireFields.length > 0) {
+      return
+    }
+
+    if (type === 'refresh') {
+      if (!bid) { // 涓昏〃ID涓嶅瓨鍦ㄦ椂锛屼笉鏌ヨ瀛愯〃鍚堣鍊�
+        this.setState({
+          statFValue: []
+        })
+        return
+      } else {
+        _BID = bid
+      }
+    }
+
+    let _orderBy = orderBy || setting.order
+    let param = UtilsDM.getStatQueryDataParams(setting, statFields, searches, _orderBy, _BID, this.props.menuType, this.props.dataManager)
+
+    Api.genericInterface(param).then(res => {
+      if (res.status) {
+        let _data = res.data[0]
+        let values = []
+
+        if (_data) {
+          statFields.forEach(item => {
+            if (_data[item.field] || _data[item.field] === 0) {
+              values.push({label: item.label, value: _data[item.field]})
+            }
+          })
+        }
+        this.setState({
+          statFValue: values
+        })
+      } else {
+        this.setState({
+          statFValue: []
+        })
+        notification.error({
+          top: 92,
+          message: res.message,
+          duration: 10
+        })
+      }
+    })
+  }
+
+  /**
    * @description 鎼滅储鏉′欢鏀瑰彉鏃讹紝閲嶇疆琛ㄦ牸鏁版嵁
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
@@ -469,6 +543,7 @@
       selectedData: [],
     }, () => {
       this.loadmaindata()
+      this.getStatFieldsValue()
     })
   }
 
@@ -504,6 +579,7 @@
       resetTable: !this.state.resetTable
     }, () => {
       this.loadmaindata()
+      this.getStatFieldsValue()
     })
   }
 
@@ -689,6 +765,7 @@
                       total={this.state.total}
                       MenuID={this.props.MenuID}
                       loading={this.state.loading}
+                      statFValue={this.state.statFValue}
                       refreshdata={this.refreshbytable}
                       buttonTrigger={this.buttonTrigger}
                       handleTableId={this.handleTableId}
diff --git a/src/tabviews/subtabtable/index.jsx b/src/tabviews/subtabtable/index.jsx
index 2d2de9c..26635f0 100644
--- a/src/tabviews/subtabtable/index.jsx
+++ b/src/tabviews/subtabtable/index.jsx
@@ -59,7 +59,9 @@
     orderBy: '',          // 鎺掑簭
     search: '',           // 鎼滅储鏉′欢鏁扮粍锛屼娇鐢ㄦ椂闇�鍒嗗満鏅鐞�
     triggerBtn: null,     // 鎸夐挳瑙﹀彂
-    chartId: ''           // 灞曞紑鍥捐〃ID
+    chartId: '',          // 灞曞紑鍥捐〃ID
+    statFields: [],       // 鍚堣瀛楁
+    statFValue: []        // 鍚堣鍊�
   }
 
   /**
@@ -107,6 +109,7 @@
       let _logcolumns = []   // 鏃ュ織鏄剧ず鍒�
       let _hideCol = []      // 闅愯棌鍙婂悎骞跺垪涓瓧娈电殑uuid闆�
       let colMap = new Map()
+      let statFields = []    // 鍚堣瀛楁淇℃伅
 
       // 鐗堟湰鍏煎
       config = UtilsUpdate.updateSubTable(config)
@@ -182,6 +185,9 @@
           _logcolumns.push(col)
 
           col.nameField && _arrField.push(col.nameField) // 閾炬帴鍚嶅瓧娈�
+          if (col.Hide !== 'true' && col.type === 'number' && col.sum === 'true') {
+            statFields.push(col)
+          }
         }
         if (col.type === 'colspan' && col.sublist) { // 绛涢�夐殣钘忓垪
           _hideCol = _hideCol.concat(col.sublist)
@@ -247,40 +253,43 @@
       config.setting.execute = config.setting.default !== 'false'     // 榛樿sql鏄惁鎵ц锛岃浆涓篵oolean 缁熶竴鏍煎紡
       config.setting.customScript = ''                                // 鑷畾涔夎剼鏈�
 
-      if (config.setting.scripts && config.setting.scripts.length > 0) {
-        let _customScript = ''
-        config.setting.scripts.forEach(item => {
-          if (item.status === 'false') return
-          _customScript += `
-            ${item.sql}
-          `
-        })
-        config.setting.customScript = _customScript
-      }
-
-      if (!config.setting.execute) { // 榛樿sql 涓嶆墽琛屾椂 缃┖
-        config.setting.dataresource = ''
-      } else {
-        config.setting.dataresource = config.setting.dataresource || ''
-      }
-      if (/\s/.test(config.setting.dataresource)) {
-        config.setting.dataresource = '(' + config.setting.dataresource + ') tb'
-      }
-
-      if (this.props.dataManager) { // 鏁版嵁鏉冮檺
-        config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
-        config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
-        config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
-        config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
-      } else {
-        config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
-        config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
+      if (config.setting.interType === 'system') {
+        if (config.setting.scripts && config.setting.scripts.length > 0) {
+          let _customScript = ''
+          config.setting.scripts.forEach(item => {
+            if (item.status === 'false') return
+            _customScript += `
+              ${item.sql}
+            `
+          })
+          config.setting.customScript = _customScript
+        }
+  
+        if (!config.setting.execute) { // 榛樿sql 涓嶆墽琛屾椂 缃┖
+          config.setting.dataresource = ''
+        } else {
+          config.setting.dataresource = config.setting.dataresource || ''
+        }
+        if (/\s/.test(config.setting.dataresource)) {
+          config.setting.dataresource = '(' + config.setting.dataresource + ') tb'
+        }
+  
+        if (this.props.dataManager) { // 鏁版嵁鏉冮檺
+          config.setting.dataresource = config.setting.dataresource.replace(/\$@/ig, '/*')
+          config.setting.dataresource = config.setting.dataresource.replace(/@\$/ig, '*/')
+          config.setting.customScript = config.setting.customScript.replace(/\$@/ig, '/*')
+          config.setting.customScript = config.setting.customScript.replace(/@\$/ig, '*/')
+        } else {
+          config.setting.dataresource = config.setting.dataresource.replace(/@\$|\$@/ig, '')
+          config.setting.customScript = config.setting.customScript.replace(/@\$|\$@/ig, '')
+        }
       }
 
       this.setState({
         loadingview: false,
         chartId: chartId,
         config: config,
+        statFields: statFields,
         setting: config.setting,
         searchlist: config.search,
         actions: _actions,
@@ -291,6 +300,7 @@
       }, () => {
         if (config.setting.onload !== 'false' && valid) { // 鍒濆鍖栧彲鍔犺浇
           this.loadmaindata()
+          this.getStatFieldsValue()
         }
       })
     } else {
@@ -362,6 +372,56 @@
   }
 
   /**
+   * @description 鑾峰彇鍚堣瀛楁鍊�
+   */
+  getStatFieldsValue = () => {
+    const { mainSearch, BID } = this.props
+    const { setting, search, orderBy, statFields } = this.state
+
+    let searches = fromJS(search).toJS()
+    if (mainSearch && mainSearch.length > 0) { // 涓昏〃鎼滅储鏉′欢
+      searches = [...mainSearch, ...searches]
+    }
+
+    if (statFields.length === 0 || setting.interType !== 'system' || !setting.dataresource) return
+
+    let requireFields = search.filter(item => item.required && (!item.value || item.value.length === 0))
+    if (requireFields.length > 0) {
+      return
+    }
+
+    let _orderBy = orderBy || setting.order
+    let param = UtilsDM.getStatQueryDataParams(setting, statFields, searches, _orderBy, BID, this.props.menuType, this.props.dataManager)
+
+    Api.genericInterface(param).then(res => {
+      if (res.status) {
+        let _data = res.data[0]
+        let values = []
+
+        if (_data) {
+          statFields.forEach(item => {
+            if (_data[item.field] || _data[item.field] === 0) {
+              values.push({label: item.label, value: _data[item.field]})
+            }
+          })
+        }
+        this.setState({
+          statFValue: values
+        })
+      } else {
+        this.setState({
+          statFValue: []
+        })
+        notification.error({
+          top: 92,
+          message: res.message,
+          duration: 10
+        })
+      }
+    })
+  }
+
+  /**
    * @description 鎼滅储鏉′欢鏀瑰彉鏃讹紝閲嶇疆琛ㄦ牸鏁版嵁
    * 鍚湁鍒濆涓嶅姞杞界殑椤甸潰锛屼慨鏀硅缃�
    */
@@ -373,6 +433,7 @@
       resetTable: !this.state.resetTable
     }, () => {
       this.loadmaindata()
+      this.getStatFieldsValue()
     })
   }
 
@@ -408,6 +469,7 @@
       resetTable: !this.state.resetTable
     }, () => {
       this.loadmaindata()
+      this.getStatFieldsValue()
     })
   }
 
@@ -561,6 +623,7 @@
                     total={this.state.total}
                     MenuID={this.props.MenuID}
                     loading={this.state.loading}
+                    statFValue={this.state.statFValue}
                     refreshdata={this.refreshbytable}
                     buttonTrigger={this.buttonTrigger}
                     resetTable={this.state.resetTable}
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index d5b303d..e207ef6 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -5,6 +5,7 @@
 import {connect} from 'react-redux'
 import { Table, message, Affix, Button, Typography, Modal, Icon } from 'antd'
 
+import Utils from '@/utils/utils.js'
 import { modifyTabview } from '@/store/action'
 import '@/assets/css/table.scss'
 import './index.scss'
@@ -19,6 +20,7 @@
   static propTpyes = {
     tableId: PropTypes.string,     // 鍒楄〃Id
     resetTable: PropTypes.bool,    // 琛ㄦ牸閲嶇疆
+    statFValue: PropTypes.any,     // 鍚堣瀛楁鏁版嵁
     pageSize: PropTypes.any,       // 姣忛〉鏁版嵁
     dict: PropTypes.object,        // 瀛楀吀椤�
     config: PropTypes.object,      // 椤甸潰閰嶇疆
@@ -44,7 +46,8 @@
     imgSrc: '',           // 鍥剧墖璺緞
     lineMarks: null,      // 琛屾爣璁�
     colMap: null,         // 鍒椾俊鎭紙鍏ㄩ儴锛�
-    activeIndex: null     // 鏍囪褰撳墠閫変腑琛�
+    activeIndex: null,    // 鏍囪褰撳墠閫変腑琛�
+    rowspan: null         // 琛屽悎骞跺瓧娈典俊鎭�
   }
 
   UNSAFE_componentWillMount () {
@@ -55,6 +58,7 @@
     let colMap = new Map() // 鐢ㄤ簬鑾峰彇瀛楁淇℃伅
     let radio = 5          // 铏氬寲姣斾緥
     let _format = false    // 鏄惁铏氬寲澶勭悊
+    let rowspan = null
 
     if (window.GLOB.dataFormat && menuType !== 'HS' && memberLevel) {
       _format = true
@@ -110,17 +114,45 @@
         }
       }
 
-      let cell = {
-        align: item.Align,
-        dataIndex: item.field || item.uuid,
-        title: item.label,
-        sorter: item.field && item.IsSort === 'true',
-        width: item.Width || 120,
-        render: (text, record) => {
-          return this.getContent(item, record)
+      let cell = null
+
+      if (item.type === 'colspan' && item.unfold === 'true') {
+        cell = {title: item.label, children: []}
+
+        item.subColumn.forEach(col => {
+
+          if (col.rowspan === 'true') {
+            rowspan = col
+          }
+
+          cell.children.push({
+            align: col.Align,
+            title: col.label,
+            dataIndex: col.field || col.uuid,
+            key: col.uuid,
+            width: col.Width || 120,
+            render: (text, record) => {
+              return this.getContent(col, record)
+            }
+          })
+        })
+      } else {
+        if (item.rowspan === 'true') {
+          rowspan = item
+        }
+
+        cell = {
+          align: item.Align,
+          dataIndex: item.field || item.uuid,
+          title: item.label,
+          sorter: item.field && item.IsSort === 'true',
+          width: item.Width || 120,
+          render: (text, record) => {
+            return this.getContent(item, record)
+          }
         }
       }
-
+      
       if (item.fixed === true || item.fixed === 'true') {
         if (index < columns.length / 2) {
           cell.fixed = 'left'
@@ -136,7 +168,8 @@
       columns: _columns,
       pageSize: pageSize ? pageSize : 10,
       lineMarks: lineMarks,
-      colMap: colMap
+      colMap: colMap,
+      rowspan: rowspan
     })
   }
 
@@ -330,6 +363,21 @@
       }
 
       if (item.linkThdMenu) {
+        if (item.rowspan === 'true') {
+          return {
+            children: (
+              <div className={className}>
+                <div className="baseboard link-menu" onDoubleClick={() => this.triggerLink(item, record)}></div>
+                <div className="content link-menu" style={{ minWidth: (item.Width || 120) + 'px' }} onDoubleClick={() => this.triggerLink(item, record)}>
+                  {content}
+                </div>
+              </div>
+            ),
+            props: {
+              rowSpan: record.$$rowspan,
+            }
+          }
+        }
         return (
           <div className={className}>
             <div className="baseboard link-menu" onDoubleClick={() => this.triggerLink(item, record)}></div>
@@ -339,6 +387,21 @@
           </div>
         )
       } else {
+        if (item.rowspan === 'true') {
+          return {
+            children: (
+              <div className={className}>
+                <div className="baseboard"></div>
+                <div className="content" style={{ minWidth: (item.Width || 120) + 'px' }}>
+                  {content}
+                </div>
+              </div>
+            ),
+            props: {
+              rowSpan: record.$$rowspan,
+            }
+          }
+        }
         return (
           <div className={className}>
             <div className="baseboard"></div>
@@ -872,8 +935,8 @@
   }
 
   render() {
-    const { setting, pickup } = this.props
-    const { selectedRowKeys, lineMarks, colMap, activeIndex } = this.state
+    const { setting, pickup, statFValue } = this.props
+    const { selectedRowKeys, lineMarks, colMap, activeIndex, rowspan } = this.state
 
     // 璁剧疆琛ㄦ牸閫夋嫨灞炴�э細鍗曢�夈�佸閫夈�佷笉鍙��
     let rowSelection = null
@@ -907,6 +970,35 @@
       _data = _data.filter((item, index) => selectedRowKeys.includes(index))
     }
 
+    if (rowspan) {
+      let marks = {}
+      let premark = {val: '', mark: ''}
+      _data = _data.map(item => {
+        if (item[rowspan.field]) {
+          if (item[rowspan.field] !== premark.val) {
+            premark = {val: item[rowspan.field], mark: Utils.getuuid()}
+
+            marks[premark.mark] = 1
+            item.$$mark = premark.mark
+          } else {
+            marks[premark.mark]++
+            item.$$mark = premark.mark
+          }
+        } else {
+          item.$$rowspan = 1
+        }
+        return item
+      })
+
+      _data = _data.map(item => {
+        if (item.$$mark) {
+          item.$$rowspan = marks[item.$$mark]
+          marks[item.$$mark] = 0
+        }
+        return item
+      })
+    }
+
     let _pagination = false
     if (setting.laypage !== 'false') {
       _pagination = {
@@ -917,6 +1009,12 @@
         total: this.props.total,
         showTotal: (total, range) => `${range[0]}-${range[1]} ${this.props.dict['main.pagination.of']} ${total} ${this.props.dict['main.pagination.items']}`
       }
+    }
+
+    let _footer = ''
+
+    if (statFValue && statFValue.length > 0) {
+      _footer = statFValue.map(f => `${f.label}(鍚堣)锛�${f.value}`).join('锛�')
     }
 
     return (
@@ -1006,6 +1104,7 @@
           onChange={this.changeTable}
           pagination={_pagination}
         />
+        {_footer ? <div className={'normal-table-footer ' + (_pagination ? 'pagination' : '')}>{_footer}</div> : null}
         <Modal
           className="image-scale-modal"
           visible={this.state.imgShow}
diff --git a/src/tabviews/zshare/normalTable/index.scss b/src/tabviews/zshare/normalTable/index.scss
index 3dbaa8b..94d01db 100644
--- a/src/tabviews/zshare/normalTable/index.scss
+++ b/src/tabviews/zshare/normalTable/index.scss
@@ -1,5 +1,20 @@
 .normal-data-table {
+  position: relative;
   padding: 0 0px 30px;
+
+  .normal-table-footer {
+    padding: 10px 0px;
+    color: rgba(0, 0, 0, 0.65);
+  }
+  .normal-table-footer.pagination {
+    position: absolute;
+    bottom: 40px;
+  }
+  >.ant-table-wrapper {
+    position: relative;
+    z-index: 1;
+  }
+
   table {
     max-width: 100%;
     width: 100%;
@@ -40,18 +55,7 @@
   .ant-table-body {
     overflow-x: auto!important;
     min-height: 90px;
-    border: 1px solid #e8e8e8;
-    border-radius: 4px;
-    border-top: none;
-    border-bottom: none;
     table {
-      border-left: 0;
-      .ant-table-thead > tr > th:last-child {
-        border-right: 0;
-      }
-      .ant-table-tbody > tr > td:last-child {
-        border-right: 0;
-      }
       .ant-table-tbody > tr > td {
         vertical-align: top;
         .content {
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index 4cec9e0..a369e07 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -399,8 +399,6 @@
     if (type === 'copy') {
       card.originUuid = card.uuid
       card.uuid = Utils.getuuid()
-      card.label = card.label + '(copy)'
-      card.field = card.field + '(copy)'
       card.focus = true
 
       // 澶嶅埗鍒板壀鍒囨澘
diff --git a/src/templates/sharecomponent/columncomponent/colspanform/index.jsx b/src/templates/sharecomponent/columncomponent/colspanform/index.jsx
index 2364967..8474416 100644
--- a/src/templates/sharecomponent/columncomponent/colspanform/index.jsx
+++ b/src/templates/sharecomponent/columncomponent/colspanform/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, InputNumber, Select, Radio } from 'antd'
+import { Form, Row, Col, Input, InputNumber, Select, Radio, Tooltip, Icon } from 'antd'
 import { formRule } from '@/utils/option.js'
 import TransferForm from '@/templates/zshare/transferform'
 import './index.scss'
@@ -62,6 +62,7 @@
   }
 
   render() {
+    const { card } = this.props
     const { getFieldDecorator } = this.props.form
     const formItemLayout = {
       labelCol: {
@@ -79,7 +80,7 @@
           <Col span={12}>
             <Form.Item label={this.props.dict['model.name']}>
               {getFieldDecorator('label', {
-                initialValue: this.props.card.label,
+                initialValue: card.label,
                 rules: [
                   {
                     required: true,
@@ -109,7 +110,7 @@
           <Col span={12}>
             <Form.Item label={this.props.dict['model.form.align']}>
               {getFieldDecorator('Align', {
-                initialValue: this.props.card.Align,
+                initialValue: card.Align,
                 rules: [
                   {
                     required: true,
@@ -130,7 +131,7 @@
           <Col span={12}>
             <Form.Item label={this.props.dict['model.form.columnWidth']}>
               {getFieldDecorator('Width', {
-                initialValue: this.props.card.Width,
+                initialValue: card.Width,
                 rules: [
                   {
                     required: true,
@@ -141,9 +142,26 @@
             </Form.Item>
           </Col>
           <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="閫夋嫨鏄剧ず鍒嗙粍锛岃〃鏍间細灞曞紑娣诲姞鍒嗙粍鐨勫瓙鍒楋紝姝ゆ椂鎺掑垪鏂瑰紡浼氬け鏁堛��">
+                <Icon type="question-circle" />
+                鏄剧ず鍒嗙粍
+              </Tooltip>
+            }>
+              {getFieldDecorator('unfold', {
+                initialValue: card.unfold || 'false'
+              })(
+                <Radio.Group>
+                  <Radio value="true">{this.props.dict['model.true']}</Radio>
+                  <Radio value="false">{this.props.dict['model.false']}</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
             <Form.Item label={this.props.dict['model.hidden']}>
               {getFieldDecorator('Hide', {
-                initialValue: this.props.card.Hide || 'false',
+                initialValue: card.Hide || 'false',
                 rules: [
                   {
                     required: true,
@@ -161,7 +179,7 @@
           <Col span={12}>
             <Form.Item label={this.props.dict['header.form.order']}>
               {getFieldDecorator('order', {
-                initialValue: this.props.card.order,
+                initialValue: card.order,
                 rules: [
                   {
                     required: true,
@@ -182,7 +200,7 @@
             </Form.Item>
           </Col>
           <Col span={24}>
-            <TransferForm columns={this.props.columns} ref="column-transfer" selected={this.props.card.sublist}/>
+            <TransferForm columns={this.props.columns} ref="column-transfer" selected={card.sublist}/>
           </Col>
         </Row>
       </Form>
diff --git a/src/templates/sharecomponent/columncomponent/colspanform/index.scss b/src/templates/sharecomponent/columncomponent/colspanform/index.scss
index d6690dc..d39b484 100644
--- a/src/templates/sharecomponent/columncomponent/colspanform/index.scss
+++ b/src/templates/sharecomponent/columncomponent/colspanform/index.scss
@@ -5,4 +5,9 @@
       width: 100%;
     }
   }
+  .anticon-question-circle {
+    color: #c49f47;
+    position: relative;
+    left: -3px;
+  }
 }
\ No newline at end of file
diff --git a/src/templates/sharecomponent/columncomponent/columnform/index.jsx b/src/templates/sharecomponent/columncomponent/columnform/index.jsx
index 7affa3b..0deb323 100644
--- a/src/templates/sharecomponent/columncomponent/columnform/index.jsx
+++ b/src/templates/sharecomponent/columncomponent/columnform/index.jsx
@@ -8,8 +8,8 @@
 import './index.scss'
 
 const columnTypeOptions = {
-  text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'fieldlength', 'blacklist', 'linkmenu'],
-  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'linkmenu'],
+  text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'fieldlength', 'blacklist', 'linkmenu', 'rowspan'],
+  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'linkmenu', 'sum'],
   link: ['label', 'field', 'type', 'nameField', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'fieldlength', 'blacklist'],
   textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'fieldlength', 'blacklist'],
   picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'maxHeight']
@@ -191,7 +191,12 @@
       } else if (item.type === 'radio') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.label}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
diff --git a/src/templates/sharecomponent/columncomponent/index.jsx b/src/templates/sharecomponent/columncomponent/index.jsx
index 30538c5..42e2e79 100644
--- a/src/templates/sharecomponent/columncomponent/index.jsx
+++ b/src/templates/sharecomponent/columncomponent/index.jsx
@@ -229,6 +229,7 @@
       this.columnFormRef.handleConfirm().then(res => {
         let fieldrepet = false // 瀛楁閲嶅
         let labelrepet = false // 鎻愮ず鏂囧瓧閲嶅
+        let rowspanLabel = ''  // 宸插瓨鍦ㄧ殑琛屽悎骞跺瓧娈�
 
         _columnlist = _columnlist.filter(item => !item.origin || item.uuid === res.uuid) // 鍘婚櫎鍒濆鍒�
 
@@ -238,6 +239,8 @@
               fieldrepet = true
             } else if (item.label === res.label) {
               labelrepet = true
+            } else if (res.rowspan === 'true' && item.rowspan === 'true') {
+              rowspanLabel = item.label
             }
           }
 
@@ -262,6 +265,13 @@
             duration: 5
           })
           return
+        } else if (rowspanLabel) {
+          notification.warning({
+            top: 92,
+            message: `宸插瓨鍦ㄨ鍚堝苟瀛楁銆�${rowspanLabel}銆�!`,
+            duration: 5
+          })
+          return
         }
 
         if (!card.focus && (card.type !== res.type || (res.field && card.field !== res.field))) {
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index 6eec582..060c858 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -1144,6 +1144,36 @@
       }]
     },
     {
+      type: 'radio',
+      key: 'rowspan',
+      label: '琛屽悎骞�',
+      initVal: card.rowspan || 'false',
+      tooltip: '鐩搁偦琛屼俊鎭浉鍚屾椂锛屽崟鍏冩牸鍚堝苟銆傛敞锛氫负闃叉琛ㄦ牸淇℃伅閿欎贡锛岃鍚堝苟鍙兘娣诲姞涓�涓瓧娈点��',
+      required: false,
+      options: [{
+        value: 'true',
+        text: Formdict['model.true']
+      }, {
+        value: 'false',
+        text: Formdict['model.false']
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'sum',
+      label: '鏄剧ず鍚堣',
+      initVal: card.sum || 'false',
+      tooltip: '鍚堣淇℃伅鍙湪浣跨敤绯荤粺鏁版嵁婧愶紝涓斿綋鍓嶅垪鏈殣钘忔椂鏈夋晥銆�',
+      required: false,
+      options: [{
+        value: 'true',
+        text: Formdict['model.true']
+      }, {
+        value: 'false',
+        text: Formdict['model.false']
+      }]
+    },
+    {
       type: 'number',
       key: 'decimal',
       min: 0,
diff --git a/src/utils/utils-datamanage.js b/src/utils/utils-datamanage.js
index 3aac834..ebfef57 100644
--- a/src/utils/utils-datamanage.js
+++ b/src/utils/utils-datamanage.js
@@ -183,4 +183,97 @@
 
     return param
   }
+
+  /**
+   * @description 鑾峰彇绯荤粺瀛樺偍杩囩▼ sPC_Get_TableData 鍚堣鍊肩殑鍙傛暟
+   */
+  static getStatQueryDataParams (setting, statFields, search, orderBy, pageIndex, pageSize, menuType, dataManager) {
+    let param = {
+      func: 'sPC_Get_TableData',
+      obj_name: 'data',
+      arr_field: statFields.map(col => col.field).join(','),
+      default_sql: setting.execute ? 'true' : 'false'
+    }
+    
+    let _dataresource = setting.dataresource
+    let _customScript = ''
+    
+    if (setting.customScript) {
+      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000) select @ErrorCode='',@retmsg =''
+        ${setting.customScript}
+      `
+    }
+
+    let regoptions = null
+    if (setting.queryType === 'statistics' || _customScript) {
+      let allSearch = Utils.getAllSearchOptions(search)
+
+      regoptions = allSearch.map(item => {
+        return {
+          reg: new RegExp('@' + item.key + '@', 'ig'),
+          value: `'${item.value}'`
+        }
+      })
+      regoptions.push({
+        reg: new RegExp('@orderBy@', 'ig'),
+        value: orderBy
+      }, {
+        reg: new RegExp('@pageSize@', 'ig'),
+        value: 999999
+      }, {
+        reg: new RegExp('@pageIndex@', 'ig'),
+        value: 1
+      })
+    }
+
+    let _search = Utils.joinMainSearchkey(search)
+    if (_search) {
+      _search = 'where ' + _search
+    }
+    
+    if (setting.queryType === 'statistics') { // 缁熻鏁版嵁婧愶紝鍐呭鏇挎崲
+      regoptions.forEach(item => {
+        _dataresource = _dataresource.replace(item.reg, item.value)
+      })
+    }
+
+    if (_customScript) {
+      regoptions.forEach(item => {
+        _customScript = _customScript.replace(item.reg, item.value)
+      })
+    }
+
+    let LText = ` select ${statFields.map(col => `sum(${col.field}) as ${col.field}`).join(',')} from ${_dataresource} ${_search} `
+
+    if (_customScript) {
+      LText = `${LText}
+        aaa:
+        if @ErrorCode!=''
+          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@ 
+      `
+    }
+
+    // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
+    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
+      _customScript &&  console.log(`${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
+      LText &&  console.log(LText)
+    }
+    
+    param.custom_script = Utils.formatOptions(_customScript)
+    param.LText = Utils.formatOptions(LText)
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+    param.DateCount = ''
+
+    if (menuType === 'HS') { // 浜戠鏁版嵁楠岃瘉
+      param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp)
+    }
+
+    // 鏁版嵁绠$悊鏉冮檺
+    if (dataManager) {
+      param.dataM = 'Y'
+    }
+
+    return param
+  }
 }
\ No newline at end of file

--
Gitblit v1.8.0