From da7068bd48791cdee966c786ce0dfd46f6e03df9 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期五, 08 一月 2021 19:02:24 +0800
Subject: [PATCH] 2021-01-08

---
 src/tabviews/zshare/normalTable/index.jsx | 1122 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 950 insertions(+), 172 deletions(-)

diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index ca4838c..0d1e6dd 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -1,199 +1,776 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Table, message, Affix, Button, Typography } from 'antd'
+import md5 from 'md5'
+import { connect } from 'react-redux'
+import { is, fromJS } from 'immutable'
+import { Table, Affix, Typography, Modal, Icon } from 'antd'
+
+import { modifyTabview } from '@/store/action'
+import asyncComponent from '@/utils/asyncComponent'
+import MKEmitter from '@/utils/events.js'
+import '@/assets/css/table.scss'
 import './index.scss'
 
 const { Paragraph } = Typography
 
-export default class MainTable extends Component {
+const NormalButton = asyncComponent(() => import('@/tabviews/zshare/actionList/normalbutton'))
+const PopupButton = asyncComponent(() => import('@/tabviews/zshare/actionList/popupbutton'))
+const TabButton = asyncComponent(() => import('@/tabviews/zshare/actionList/tabbutton'))
+const NewPageButton = asyncComponent(() => import('@/tabviews/zshare/actionList/newpagebutton'))
+
+class NormalTable extends Component {
   static propTpyes = {
-    tableId: PropTypes.string,     // 鍒楄〃Id
-    dict: PropTypes.object,        // 瀛楀吀椤�
-    MenuID: PropTypes.string,      // 鑿滃崟Id
-    setting: PropTypes.object,     // 琛ㄦ牸鍏ㄥ眬璁剧疆锛歵ableType锛堣〃鏍兼槸鍚﹀彲閫夈�佸崟閫夈�佸閫夛級銆乧olumnfixed锛堝垪鍥哄畾锛夈�乤ctionfixed锛堟寜閽浐瀹氾級
-    pickup: PropTypes.any,         // 鏁版嵁鏀惰捣
-    columns: PropTypes.array,      // 琛ㄦ牸鍒�
-    data: PropTypes.any,           // 琛ㄦ牸鏁版嵁
-    total: PropTypes.number,       // 鎬绘暟
-    loading: PropTypes.bool,       // 琛ㄦ牸鍔犺浇涓�
-    refreshdata: PropTypes.func,   // 琛ㄦ牸涓帓搴忓垪銆侀〉鐮佺殑鍙樺寲鏃跺埛鏂�
-    buttonTrigger: PropTypes.func, // 琛ㄦ牸涓寜閽Е鍙戞搷浣�
-    handleTableId: PropTypes.func  // 鏁版嵁鍒囨崲
+    tableId: PropTypes.string,       // 鍒楄〃Id
+    statFValue: PropTypes.any,       // 鍚堣瀛楁鏁版嵁
+    pageSize: PropTypes.any,         // 姣忛〉鏁版嵁
+    dict: PropTypes.object,          // 瀛楀吀椤�
+    MenuID: PropTypes.string,        // 鑿滃崟Id
+    setting: PropTypes.object,       // 琛ㄦ牸鍏ㄥ眬璁剧疆锛歵ableType锛堣〃鏍兼槸鍚﹀彲閫夈�佸崟閫夈�佸閫夛級銆乧olumnfixed锛堝垪鍥哄畾锛夈�乤ctionfixed锛堟寜閽浐瀹氾級
+    pickup: PropTypes.any,           // 鏁版嵁鏀惰捣
+    columns: PropTypes.array,        // 琛ㄦ牸鍒�
+    fields: PropTypes.array,         // 缁勪欢瀛楁闆�
+    ContainerId: PropTypes.any,      // 鏍囩椤靛灞侷d
+    BData: PropTypes.any,            // 涓昏〃鏁版嵁
+    data: PropTypes.any,             // 琛ㄦ牸鏁版嵁
+    total: PropTypes.any,            // 鎬绘暟
+    loading: PropTypes.bool,         // 琛ㄦ牸鍔犺浇涓�
+    refreshdata: PropTypes.func,     // 琛ㄦ牸涓帓搴忓垪銆侀〉鐮佺殑鍙樺寲鏃跺埛鏂�
+    handleTableId: PropTypes.func,   // 鏁版嵁鍒囨崲
+    chgSelectData: PropTypes.func,   // 鏁版嵁鍒囨崲
   }
 
   state = {
     selectedRowKeys: [],  // 琛ㄦ牸涓�変腑琛�
     pageIndex: 1,         // 鍒濆椤甸潰绱㈠紩
     pageSize: 10,         // 姣忛〉鏁版嵁鏉℃暟
-    columns: null         // 鏄剧ず鍒�
+    columns: null,        // 鏄剧ず鍒�
+    imgShow: false,       // 鍥剧墖鏀惧ぇ妯℃�佹
+    imgSrc: '',           // 鍥剧墖璺緞
+    lineMarks: null,      // 琛屾爣璁�
+    activeIndex: null,    // 鏍囪褰撳墠閫変腑琛�
+    rowspans: null        // 琛屽悎骞跺瓧娈典俊鎭�
   }
 
   UNSAFE_componentWillMount () {
-    const { columns } = this.props
+    const { menuType, memberLevel, pageSize } = this.props
+    let columns = fromJS(this.props.columns).toJS()
+    let lineMarks = []
     let _columns = []
+    let radio = 5          // 铏氬寲姣斾緥
+    let _format = false    // 鏄惁铏氬寲澶勭悊
+    let rowspans = []
+
+    if (window.GLOB.dataFormat && menuType !== 'HS' && memberLevel) {
+      _format = true
+
+      if (memberLevel >= 30) {
+        radio = 20
+      } else if (memberLevel >= 20) {
+        radio = 10
+      }
+    }
+
+    columns.forEach((item, index) => {
+      if (item.hidden === true || item.Hide === 'true') return
+      let cell = null
+
+      if (item.type === 'colspan') {
+        cell = {title: item.label, children: []}
+
+        item.subcols.forEach(col => {
+          if (col.rowspan === 'true') {
+            rowspans.push(col.field)
+          }
+          if (_format && !Math.floor(Math.random() * radio)) {
+            col.blur = true
+          }
+
+          if (col.marks) { // 杩囨护琛屽拰鍗$墖鏍囪
+            col.marks = col.marks.filter(mark => {
+              if (mark.signType === 'line') {
+                lineMarks.push(mark)
+              }
+              return mark.signType !== 'line' && mark.signType !== 'card'
+            })
     
-    columns.forEach(item => {
-      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)
+            if (col.marks.length === 0) {
+              col.marks = ''
+            }
+          }
+
+          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.type === 'old_colspan') {
+        item.subcols.forEach(col => {
+          if (col.marks) { // 杩囨护琛屽拰鍗$墖鏍囪
+            col.marks = col.marks.filter(mark => {
+              if (mark.signType === 'line') {
+                lineMarks.push(mark)
+              }
+              return mark.signType !== 'line' && mark.signType !== 'card'
+            })
+    
+            if (col.marks.length === 0) {
+              col.marks = ''
+            }
+          }
+        })
+
+        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)
+          }
+        }
+      } else {
+        if (item.rowspan === 'true') {
+          rowspans.push(item.field)
+        }
+        if (_format && !Math.floor(Math.random() * radio)) {
+          item.blur = true
+        }
+
+        if (item.marks) { // 杩囨护琛屽拰鍗$墖鏍囪
+          item.marks = item.marks.filter(mark => {
+            if (mark.signType === 'line') {
+              lineMarks.push(mark)
+            }
+            return mark.signType !== 'line' && mark.signType !== 'card'
+          })
+  
+          if (item.marks.length === 0) {
+            item.marks = ''
+          }
+        }
+
+        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'
+        } else {
+          cell.fixed = 'right'
+        }
+      }
+      
       _columns.push(cell)
     })
 
+    if (rowspans.length === 0) {
+      rowspans = null
+    }
+
     this.setState({
-      columns: _columns
+      columns: _columns,
+      pageSize: pageSize ? pageSize : 10,
+      lineMarks,
+      rowspans
     })
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('resetTable', this.resetTable)
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('resetTable', this.resetTable)
+  }
+
+  // 瀛楁閫忚
+  triggerLink = (e, item, record) => {
+    const { tabviews, MenuID, setting } = this.props
+
+    e.stopPropagation()
+
+    if (item.linkThdMenu) {
+      let tabmenu = item.linkThdMenu
+
+      tabmenu.param = {
+        searchkey: item.field,
+        searchval: record[item.field] || '',
+        BID: record[setting.primaryKey]
+      }
+  
+      tabmenu.selected = true
+  
+      let index = 0
+      let isexit = false
+      let tabs = tabviews.map((tab, i) => {
+        tab.selected = false
+  
+        if (tab.MenuID === MenuID) {
+          index = i
+        } else if (tab.MenuID === tabmenu.MenuID) {
+          tab.param = tabmenu.param
+          tab.selected = true
+          isexit = true
+        }
+  
+        return tab
+      })
+  
+      if (!isexit) {
+        tabs.splice(index + 1, 0, tabmenu)
+      }
+  
+      this.props.modifyTabview(tabs)
+    } else {
+      let src = item.linkurl
+
+      if (item.linkurl.indexOf('paramsmain/') > -1) {
+        try {
+          let _url = item.linkurl.split('paramsmain/')[0] + 'paramsmain/'
+          let _param = JSON.parse(window.decodeURIComponent(window.atob(item.linkurl.split('paramsmain/')[1])))
+          let dataparam = {
+            searchkey: item.field,
+            searchval: record[item.field] || '',
+            BID: record[setting.primaryKey]
+          }
+          _param.UserID = sessionStorage.getItem('UserID')
+          _param.LoginUID = sessionStorage.getItem('LoginUID')
+          _param.User_Name = sessionStorage.getItem('User_Name')
+          _param.param = dataparam
+          src = _url + window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
+        } catch {
+          console.warn('鑿滃崟鍙傛暟瑙f瀽閿欒锛�')
+        }
+      }
+
+      window.open(src)
+    }
+  }
+
+  getMark = (record, marks) => {
+    let className = ''
+    let isIcon = false
+    let position = 'back'
+    let icon = ''
+
+    marks.some(mark => {
+      let originVal = record[mark.field] + ''
+      let contrastVal = ''
+      if (mark.contrastType === 'static') {
+        contrastVal = mark.contrastValue + ''
+      } else {
+        contrastVal = record[mark.contrastField] + ''
+      }
+
+      if (mark.match === '=') {
+        className = originVal === contrastVal ? mark.color[1] : ''
+      } else if (mark.match === '!=') {
+        className = originVal !== contrastVal ? mark.color[1] : ''
+      } else if (mark.match === 'like') {
+        className = originVal.indexOf(contrastVal) > -1 ? mark.color[1] : ''
+      } else if (mark.match === '>') {
+        try {
+          originVal = parseFloat(originVal)
+          contrastVal = parseFloat(contrastVal)
+        } catch {
+          originVal = NaN
+        }
+
+        if (!isNaN(originVal) && !isNaN(contrastVal) && originVal > contrastVal) {
+          className = mark.color[1]
+        }
+      } else if (mark.match === '<') {
+        try {
+          originVal = parseFloat(originVal)
+          contrastVal = parseFloat(contrastVal)
+        } catch {
+          originVal = NaN
+        }
+
+        if (!isNaN(originVal) && !isNaN(contrastVal) && originVal < contrastVal) {
+          className = mark.color[1]
+        }
+      }
+
+      if (!className) return false
+
+      if (mark.signType === 'font') {
+        className = 'font ' + className
+      } else if (mark.signType === 'background') {
+        className = 'background ' + className
+      } else if (mark.signType === 'icon') {
+        isIcon = true
+        if (mark.position === 'front') {
+          position = 'front'
+        }
+        icon = <Icon className={'font ' + className} type={mark.icon} />
+        className = ''
+      }
+
+      return true
+    })
+
+    return {
+      className: className,
+      isIcon: isIcon,
+      position: position,
+      icon: icon
+    }
   }
 
   getContent = (item, record) => {
     if (item.type === 'text') {
       let content = ''
-      let match = false
+      let className = ''
       if (item.field && record.hasOwnProperty(item.field)) {
         content = `${record[item.field]}`
       }
 
-      if (content && item.matchVal && content.indexOf(item.matchVal) > 0) {
-        match = true
+      if (content !== '') {
+        if (item.textFormat === 'YYYY-MM-DD' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1])/.test(content)) {
+          content = `${content.substr(0, 4)}-${content.substr(5, 2)}-${content.substr(8, 2)}`
+        } else if (item.textFormat === 'YYYY-MM-DD HH:mm:ss' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1]).([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/.test(content)) {
+          content = `${content.substr(0, 4)}-${content.substr(5, 2)}-${content.substr(8, 2)} ${content.substr(11, 2)}:${content.substr(14, 2)}:${content.substr(17, 2)}`
+        }
+  
+        content = (item.prefix || '') + content + (item.postfix || '')
       }
+      
+      if (item.marks) {
+        let result = this.getMark(record, item.marks)
 
-      content = (item.prefix || '') + content + (item.postfix || '')
-
-      return (
-        <div className={match ? item.color : ''}>
-          <div className="background"></div>
-          <div className="content" style={{ minWidth: (item.Width || 120) + 'px' }}>
-            {content}
-          </div>
-        </div>
-      )
-    } else if (item.type === 'number') {
-      let content = ''
-      let match = false
-      if (item.field && record.hasOwnProperty(item.field)) {
-        content = +record[item.field]
-      }
-
-      if (content && item.match && item.matchVal) {
-        if (item.match === '>') {
-          if (content > item.matchVal) {
-            match = true
-          }
-        } else if (item.match === '<') {
-          if (content < item.matchVal) {
-            match = true
-          }
-        } else if (item.match === '>=') {
-          if (content >= item.matchVal) {
-            match = true
-          }
-        } else if (item.match === '<=') {
-          if (content <= item.matchVal) {
-            match = true
+        if (result.className) {
+          className = result.className
+        } else if (result.isIcon) {
+          if (result.position === 'front') {
+            content = <span>{result.icon} {content}</span>
+          } else {
+            content = <span>{content} {result.icon}</span>
           }
         }
       }
 
-      if (content && item.format === 'thdSeparator') {
-        content = `${content}`
-        content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
+      if (item.blur) {
+        className = ''
+        content = md5(content)
       }
 
-      content = (item.prefix || '') + content + (item.postfix || '')
-
-      return (
-        <div className={match ? item.color : ''}>
-          <div className={'background'}></div>
-          <div className="content" style={{ minWidth: (item.Width || 120) + 'px' }}>
-            {content}
+      if (item.linkThdMenu || item.linkurl) {
+        if (item.rowspan === 'true') {
+          return {
+            children: (
+              <div className={className}>
+                <div className="baseboard link-menu" onDoubleClick={(e) => this.triggerLink(e, item, record)}></div>
+                <div className="content link-menu" onDoubleClick={(e) => this.triggerLink(e, item, record)}>
+                  {content}
+                </div>
+              </div>
+            ),
+            props: {
+              rowSpan: record['$$' + item.field],
+            }
+          }
+        }
+        return (
+          <div className={className}>
+            <div className="baseboard link-menu" onDoubleClick={(e) => this.triggerLink(e, item, record)}></div>
+            <div className="content link-menu" onDoubleClick={(e) => this.triggerLink(e, item, record)}>
+              {content}
+            </div>
           </div>
-        </div>
-      )
+        )
+      } else {
+        if (item.rowspan === 'true') {
+          return {
+            children: (
+              <div className={className}>
+                <div className="baseboard"></div>
+                <div className="content">
+                  {content}
+                </div>
+              </div>
+            ),
+            props: {
+              rowSpan: record['$$' + item.field],
+            }
+          }
+        }
+        return (
+          <div className={className}>
+            <div className="baseboard"></div>
+            <div className="content">
+              {content}
+            </div>
+          </div>
+        )
+      }
+    } else if (item.type === 'number') {
+      let content = ''
+      let className = ''
+
+      if (item.field && record.hasOwnProperty(item.field)) {
+        try {
+          content = parseFloat(record[item.field])
+          if (isNaN(content)) {
+            content = ''
+          }
+        } catch {
+          content = ''
+        }
+      }
+
+      if (content !== '') {
+        let decimal = item.decimal || 0
+        if (item.format === 'percent') {
+          content = content * 100
+          decimal = decimal > 2 ? decimal - 2 : 0
+        }
+  
+        content = content.toFixed(decimal)
+  
+        if (item.format === 'thdSeparator') {
+          content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
+        }
+  
+        content = (item.prefix || '') + content + (item.postfix || '')
+      }
+
+      if (item.marks) {
+        let result = this.getMark(record, item.marks)
+
+        if (result.className) {
+          className = result.className
+        } else if (result.isIcon) {
+          if (result.position === 'front') {
+            content = <span>{result.icon} {content}</span>
+          } else {
+            content = <span>{content} {result.icon}</span>
+          }
+        }
+      }
+
+      if (item.blur) {
+        className = ''
+        content = md5(content)
+      }
+
+      if (item.linkThdMenu || item.linkurl) {
+        return (
+          <div className={className}>
+            <div className="baseboard link-menu" onDoubleClick={(e) => this.triggerLink(e, item, record)}></div>
+            <div className="content link-menu" onDoubleClick={(e) => this.triggerLink(e, item, record)}>
+              {content}
+            </div>
+          </div>
+        )
+      } else {
+        return (
+          <div className={className}>
+            <div className="baseboard"></div>
+            <div className="content">
+              {content}
+            </div>
+          </div>
+        )
+      }
     } else if (item.type === 'picture') {
       let photos = ''
       if (item.field && record.hasOwnProperty(item.field)) {
-        photos = record[item.field].split(',')
+        photos = record[item.field] + ''
+        photos = photos.split(',')
       } else {
         photos = ''
       }
+
+      let maxHeight = item.maxHeight || 128
       return (
-        <div className="picture-col" style={{ minWidth: (item.Width || 120) + 'px' }}>
+        <div className="picture-col">
           {photos && photos.map((url, i) => {
-            return <img key={`${i}`} src={url} alt=""/>
+            if (item.scale === 'true') {
+              return <img style={{maxHeight: maxHeight}} className="image-scale" onClick={this.imgScale} key={`${i}`} src={url} alt=""/>
+            } else {
+              return <img style={{maxHeight: maxHeight}} key={`${i}`} src={url} alt=""/>
+            }
           })}
         </div>
       )
     } else if (item.type === 'textarea') {
       let content = ''
-      let match = false
+
       if (item.field && record.hasOwnProperty(item.field)) {
         content = `${record[item.field]}`
       }
 
-      if (content && item.matchVal && content.indexOf(item.matchVal) > 0) {
-        match = true
+      content = content ? (item.prefix || '') + content + (item.postfix || '') : ''
+
+      if (item.blur) {
+        content = md5(content)
       }
 
-      content = (item.prefix || '') + content + (item.postfix || '')
+      return (
+        <div>
+          <div className="content">
+            {content ? <Paragraph copyable ellipsis={{ rows: 3, expandable: true }}>{content}</Paragraph> : null }
+          </div>
+        </div>
+      )
+    } else if (item.type === 'link') {
+      let content = ''
+      let _href = record[item.field] || ''
+
+      if (item.nameField && record.hasOwnProperty(item.nameField)) {
+        content = record[item.nameField]
+      }
+
+      if (!content && _href) {
+        content = _href
+      } else if (!_href) {
+        content = ''
+      }
+
+      if (item.joint === 'true' && _href) {
+        let _quary = `id=${record[this.props.setting.primaryKey]}&userid=${sessionStorage.getItem('UserID')}&appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`
+        let _param = ''
+        
+        try {
+          _param = window.btoa(_quary)
+        } catch {
+          _param = window.btoa(window.encodeURIComponent(_quary))
+        }
+        
+        _href += '?' + _param
+      }
+
+      if (item.blur) {
+        content = md5(content)
+      }
 
       return (
-        <div className={match ? item.color : ''}>
-          <div className="background"></div>
-          <div className="content" style={{ minWidth: (item.Width || 120) + 'px' }}>
-            {content ? <Paragraph copyable ellipsis={{ rows: 3, expandable: true }}>{content}</Paragraph> : null }
+        <div>
+          <div className="content">
+            {content ? <a href={_href} target="_blank" rel="noopener noreferrer">{content}</a> : null }
           </div>
         </div>
       )
     } else if (item.type === 'action') {
       return (
-        <div className={item.style} style={{ minWidth: (item.Width || 120) + 'px' }}>
+        <div className="action-col">
           {item.operations.map(btn => {
-            return <Button
-              className={'mk-btn mk-' + btn.class}
-              icon={btn.icon}
-              key={btn.uuid}
-              onClick={(e) => {this.actionTrigger(e, btn, record)}}
-            >{btn.label}</Button>
+            if (['exec', 'prompt', 'pop'].includes(btn.OpenType)) {
+              return (
+                <NormalButton
+                  key={btn.uuid}
+                  btn={btn}
+                  BID={record.$$BID}
+                  selectedData={[record]}
+                  BData={this.props.BData}
+                  setting={this.props.setting}
+                  columns={this.props.fields || this.props.columns}
+                  ContainerId={this.props.ContainerId}
+                />
+              )
+            } else if (btn.OpenType === 'popview') {
+              return (
+                <PopupButton
+                  key={btn.uuid}
+                  btn={btn}
+                  BID={record.$$BID}
+                  selectedData={[record]}
+                  BData={this.props.BData}
+                  setting={this.props.setting}
+                />
+              )
+            } else if (btn.OpenType === 'tab' || btn.OpenType === 'blank') {
+              return (
+                <TabButton
+                  key={btn.uuid}
+                  btn={btn}
+                  selectedData={[record]}
+                  MenuID={this.props.MenuID}
+                  setting={this.props.setting}
+                />
+              )
+            } else if (btn.OpenType === 'innerpage' || btn.OpenType === 'outerpage') {
+              return (
+                <NewPageButton
+                  key={btn.uuid}
+                  btn={btn}
+                  selectedData={[record]}
+                  setting={this.props.setting}
+                />
+              )
+            }
+            return null
           })}
         </div>
       )
-    } else if (item.type === 'colspan') {
-      if (item.subColumn.length === 0) return ''
+    } else if (item.type === 'old_colspan') {
+      if (item.subcols.length === 0) return ''
       let ordertype = item.order
       let contents = []
       let images = []
 
-      item.subColumn.forEach(col => {
+      item.subcols.forEach(col => {
         if (!col.field || !record.hasOwnProperty(col.field)) return
         
-        if (col.type === 'number' && typeof(record[col.field]) === 'number') {
-          let content = record[col.field]
+        if (col.type === 'number') {
+          let content = ''
+          try {
+            content = parseFloat(record[col.field])
+            if (isNaN(content)) {
+              content = ''
+            }
+          } catch {
+            content = ''
+          }
+    
+          if (content !== '') {
+            let decimal = col.decimal || 0
+            if (col.format === 'percent') {
+              content = content * 100
+              decimal = decimal > 2 ? decimal - 2 : 0
+            }
 
-          if (col.format === 'thdSeparator') {
-            content = `${content}`
-            content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
+            content = content.toFixed(decimal)
+      
+            if (col.format === 'thdSeparator') {
+              content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
+            }
+
+            content = (col.prefix || '') + content + (col.postfix || '')
           }
 
-          content = (col.prefix || '') + content + (col.postfix || '')
+          if (col.marks) {
+            let result = this.getMark(record, col.marks)
+    
+            if (result.className && result.className.indexOf('font') > -1) {
+              content = <span className={result.className}>{content}</span>
+            } else if (result.isIcon) {
+              if (result.position === 'front') {
+                content = <span>{result.icon} {content}</span>
+              } else {
+                content = <span>{content} {result.icon}</span>
+              }
+            }
+          }
 
-          contents.push(content)
+          if (item.blur) {
+            content = md5(content)
+          }
+
+          contents.push({content, align: col.Align})
         } else if (col.type === 'picture') {
           let photos = []
           try {
-            photos = record[col.field].split(',')
+            photos = record[col.field] + ''
+            photos = photos.split(',')
           } catch {
             photos = []
           }
 
-          images.push(...photos)
+          photos.forEach(photo => {
+            images.push({url: photo, align: col.Align, scale: col.scale === 'true', maxHeight: col.maxHeight || 128})
+          })
+        } else if (col.type === 'text') {
+          let content = record[col.field]
+
+          if (content !== '') {
+            if (col.textFormat === 'YYYY-MM-DD' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1])/.test(content)) {
+              content = `${content.substr(0, 4)}-${content.substr(5, 2)}-${content.substr(8, 2)}`
+            } else if (col.textFormat === 'YYYY-MM-DD HH:mm:ss' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1]).([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/.test(content)) {
+              content = `${content.substr(0, 4)}-${content.substr(5, 2)}-${content.substr(8, 2)} ${content.substr(11, 2)}:${content.substr(14, 2)}:${content.substr(17, 2)}`
+            }
+
+            content = (col.prefix || '') + content + (col.postfix || '')
+          }
+
+          if (col.marks) {
+            let result = this.getMark(record, col.marks)
+    
+            if (result.className && result.className.indexOf('font') > -1) {
+              content = <span className={result.className}>{content}</span>
+            } else if (result.isIcon) {
+              if (result.position === 'front') {
+                content = <span>{result.icon} {content}</span>
+              } else {
+                content = <span>{content} {result.icon}</span>
+              }
+            }
+          }
+
+          if (item.blur) {
+            content = md5(content)
+          }
+
+          contents.push({content, align: col.Align})
+        } else if (col.type === 'link') {
+          let content = col.nameField ? record[col.nameField] : ''
+          let _href = record[col.field] || ''
+
+          if (!content && _href) {
+            content = _href
+          } else if (!_href) {
+            content = ''
+          }
+
+          if (col.joint === 'true' && _href) {
+            let _quary = `id=${record[this.props.setting.primaryKey]}&userid=${sessionStorage.getItem('UserID')}&appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`
+            let _param = ''
+
+            try {
+              _param = window.btoa(_quary)
+            } catch {
+              _param = window.btoa(window.encodeURIComponent(_quary))
+            }
+
+            _href += '?' + _param
+          }
+
+          if (item.blur) {
+            content = md5(content)
+          }
+
+          content = _href ? <a href={_href} target="_blank" rel="noopener noreferrer">{content}</a> : null
+
+          contents.push({content, align: col.Align})
         } else {
-          contents.push((col.prefix || '') + record[col.field] + (col.postfix || ''))
+          let content = record[col.field]
+
+          if (content !== '') {
+            content = (col.prefix || '') + record[col.field] + (col.postfix || '')
+          }
+
+          if (item.blur) {
+            content = md5(content)
+          }
+
+          contents.push({content, align: col.Align})
         }
       })
 
@@ -203,7 +780,7 @@
 
       return (
         <div>
-          <div className="content" style={{ minWidth: (item.Width || 120) + 'px' }}>
+          <div className="content">
             {this.getCospanContent(ordertype, contents, images)}
           </div>
         </div>
@@ -213,29 +790,29 @@
 
   getCospanContent = (type, contents, images) => {
     if (type === 'vertical') {
-      return contents.map((content, index) => {
-        return (<p key={index}>{content}</p>)
+      return contents.map((cont, index) => {
+        return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
       })
     } else if (type === 'horizontal') {
-      return contents.map((content, index) => {
-        return (<span key={index}>{content}</span>)
+      return contents.map((cont, index) => {
+        return (<span key={index}>{cont.content}</span>)
       })
     } else if (type === 'vertical2') {
       return (
         <div className="content-fence">
           <div className="content-fence-left">
-            {contents.map((content, index) => {
+            {contents.map((cont, index) => {
               if (index % 2 === 0) {
-                return (<p key={index}>{content}</p>)
+                return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
               } else {
                 return ''
               }
             })}
           </div>
           <div className="content-fence-right">
-            {contents.map((content, index) => {
+            {contents.map((cont, index) => {
               if (index % 2 === 1) {
-                return (<p key={index}>{content}</p>)
+                return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
               } else {
                 return ''
               }
@@ -246,15 +823,19 @@
     } else if (type === 'topPicBottomText') {
       return (
         <div className="content-fence">
-          <div className="content-fence-top">
-            {images.map((url, index) => {
-              if (!url) return ''
-              return (<img key={`${index}`} src={url} alt=""/>)
+          <div className="content-fence-top" style={images[0] ? {textAlign: images[0].align} : null}>
+            {images.map((_img, index) => {
+              if (!_img.url) return ''
+              if (_img.scale) {
+                return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={this.imgScale} key={`${index}`} src={_img.url} alt=""/>
+              } else {
+                return (<img style={{maxHeight: _img.maxHeight}} key={`${index}`} src={_img.url} alt=""/>)
+              }
             })}
           </div>
           <div className="content-fence-bottom">
-            {contents.map((content, index) => {
-              return (<p key={index}>{content}</p>)
+            {contents.map((cont, index) => {
+              return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
             })}
           </div>
         </div>
@@ -262,15 +843,19 @@
     } else if (type === 'leftPicRightText') {
       return (
         <div className="content-fence">
-          <div className="content-fence-left">
-            {images.map((url, index) => {
-              if (!url) return ''
-              return (<img key={`${index}`} src={url} alt=""/>)
+          <div className="content-fence-left" style={images[0] ? {textAlign: images[0].align} : null}>
+            {images.map((_img, index) => {
+              if (!_img.url) return ''
+              if (_img.scale) {
+                return <img style={{maxHeight: _img.maxHeight}} className="image-scale" onClick={this.imgScale} key={`${index}`} src={_img.url} alt=""/>
+              } else {
+                return (<img style={{maxHeight: _img.maxHeight}} key={`${index}`} src={_img.url} alt=""/>)
+              }
             })}
           </div>
           <div className="content-fence-right">
-            {contents.map((content, index) => {
-              return (<p key={index}>{content}</p>)
+            {contents.map((cont, index) => {
+              return (<p key={index} style={{textAlign: cont.align}}>{cont.content}</p>)
             })}
           </div>
         </div>
@@ -278,71 +863,94 @@
     }
   }
 
-  actionTrigger = (e, btn, record) => {
-    e.stopPropagation()
-    this.props.buttonTrigger(btn, record)
+  /**
+   * @description 鍥剧墖缂╂斁
+   */
+  imgScaleClose = () => {
+    this.setState({
+     imgShow: false
+    })
+  }
+  imgScale = (e) => {
+    if (e.target.nodeName === 'IMG') {
+      this.setState({
+        imgShow: true,
+        imgSrc: e.target.src
+      })
+    }
   }
 
-  copycontent = (e, content) => {
-    // 琛ㄦ牸涓唴瀹瑰鍒�
-    e.stopPropagation()
-    let oInput = document.createElement('input')
-    oInput.value = content
-    document.body.appendChild(oInput)
-    oInput.select()
-    document.execCommand('Copy')
-    oInput.className = 'oInput'
-    oInput.style.display='none'
-    message.success(this.props.dict['main.copy.success'])
-  }
-
+  /**
+   * 
+   */
   onSelectChange = selectedRowKeys => {
+    const { setting } = this.props
+
     let index = ''
+    let _activeIndex = null
     if (selectedRowKeys.length > 0) {
-      index = selectedRowKeys[selectedRowKeys.length - 1]
+      index = selectedRowKeys.slice(-1)[0]
+    }
+
+    if (setting.tableType === 'checkbox') {
+      _activeIndex = index === '' ? null : index
     }
 
     this.changedata(index)
 
-    this.setState({ selectedRowKeys })
+    this.setState({ selectedRowKeys, activeIndex: _activeIndex })
+
+    let selects = this.props.data.filter((item, _index) => selectedRowKeys.includes(_index))
+
+    this.props.chgSelectData(selects)
   }
 
+  /**
+   * @description 鐐瑰嚮鏁磋锛岃Е鍙戝垏鎹紝 鍒ゆ柇鏄惁鍙�夛紝鍗曢�夋垨澶氶�夛紝杩涜瀵瑰簲鎿嶄綔
+   */
   changeRow = (record, index) => {
-    // 鐐瑰嚮鏁磋锛岃Е鍙戝垏鎹紝鍒ゆ柇鏄惁鍙�夛紝鍗曢�夋垨澶氶�夛紝杩涜瀵瑰簲鎿嶄綔
     if (!this.props.setting.tableType || this.props.pickup) return
     
-    let newkeys = JSON.parse(JSON.stringify(this.state.selectedRowKeys))
-    let _re = newkeys.includes(index)
+    let newkeys = fromJS(this.state.selectedRowKeys).toJS()
 
     if (this.props.setting.tableType === 'radio') {
+      newkeys = [index]
       this.changedata(index)
-      this.setState({ selectedRowKeys: [index] })
+      this.setState({ selectedRowKeys: newkeys })
     } else {
-      if (_re) {
+      let _index = ''
+      if (newkeys.includes(index)) {
         newkeys = newkeys.filter(item => item !== index)
-        this.changedata('')
+        if (newkeys.length > 0) {
+          _index = newkeys.slice(-1)[0]
+        }
+        this.changedata(_index)
       } else {
+        _index = index
         newkeys.push(index)
         this.changedata(index)
       }
 
-      this.setState({ selectedRowKeys: newkeys })
+      this.setState({ selectedRowKeys: newkeys, activeIndex: _index !== '' ? _index : null })
     }
+
+    let selects = this.props.data.filter((item, _index) => newkeys.includes(_index))
+    
+    this.props.chgSelectData(selects)
   }
 
   changeTable = (pagination, filters, sorter) => {
     this.setState({
       pageIndex: pagination.current,
       pageSize: pagination.pageSize,
-      selectedRowKeys: []
+      selectedRowKeys: [],
+      activeIndex: null
     })
     this.props.refreshdata(pagination, filters, sorter)
   }
 
   changedata = (index) => {
     const { data, setting } = this.props
-
-    if (!this.props.tableId) return
 
     let _id = ''
     let _data = ''
@@ -355,16 +963,90 @@
     this.props.handleTableId(this.props.tableId, _id, _data)
   }
 
-  resetTable = () => {
-    this.setState({
-      pageIndex: 1,
-      selectedRowKeys: []
+  resetTable = (id, repage) => {
+    const { MenuID, tableId } = this.props
+
+    if (id !== (MenuID + tableId)) return
+
+    if (repage === 'false') {
+      this.setState({
+        selectedRowKeys: [],
+        activeIndex: null
+      })
+    } else {
+      this.setState({
+        pageIndex: 1,
+        selectedRowKeys: [],
+        activeIndex: null
+      })
+    }
+  }
+
+  handleRowspan = (data) => {
+    const { rowspans } = this.state
+
+    if (!rowspans || data.length === 0) return data
+
+    data = fromJS(data).toJS()
+    data = data.reverse()
+    data.forEach((item, index) => {
+      if (index === 0) {
+        rowspans.forEach(cell => {
+          item['$' + cell] = 1
+        })
+      } else {
+        let preItem = data[index - 1]
+        rowspans.forEach((cell, i) => {
+          if (i === 0) {
+            if ((item[cell] || item[cell] === 0) && preItem[cell] === item[cell]) {
+              item['$' + cell] = preItem['$' + cell] + 1
+            } else {
+              item['$' + cell] = 1
+            }
+          } else {
+            if ((item[cell] || item[cell] === 0) && preItem[cell] === item[cell]) {
+              item['$' + cell] = preItem['$' + cell] + 1
+            } else {
+              item['$' + cell] = 1
+            }
+            if (item['$' + cell] > item['$' + rowspans[i - 1]]) {
+              item['$' + cell] = 1
+            }
+          }
+        })
+      }
     })
+    data = data.reverse()
+    data.forEach((item, index) => {
+      if (index === 0) {
+        rowspans.forEach(cell => {
+          item['$$' + cell] = item['$' + cell]
+        })
+      } else {
+        let preItem = data[index - 1]
+        rowspans.forEach(cell => {
+          if (preItem['$' + cell] > 1) {
+            item['$$' + cell] = 0
+          } else {
+            item['$$' + cell] = item['$' + cell]
+          }
+        })
+      }
+    })
+    return data
+  }
+
+  doubleClickLine = (record) => {
+    const { setting } = this.props
+
+    if (!setting.doubleClick) return
+
+    MKEmitter.emit('triggerBtnId', setting.doubleClick, [record])
   }
 
   render() {
-    const { setting, pickup } = this.props
-    let { selectedRowKeys } = this.state
+    const { setting, pickup, statFValue } = this.props
+    const { selectedRowKeys, lineMarks, activeIndex } = this.state
 
     // 璁剧疆琛ㄦ牸閫夋嫨灞炴�э細鍗曢�夈�佸閫夈�佷笉鍙��
     let rowSelection = null
@@ -398,12 +1080,32 @@
       _data = _data.filter((item, index) => selectedRowKeys.includes(index))
     }
 
+    _data = this.handleRowspan(_data)
+    
+    let _pagination = false
+    if (setting.laypage !== 'false' && setting.laypage !== false) {
+      _pagination = {
+        current: this.state.pageIndex,
+        pageSize: this.state.pageSize,
+        pageSizeOptions: ['10', '25', '50', '100', '500', '1000'],
+        showSizeChanger: true,
+        total: this.props.total || 0,
+        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 (
-      <div className="normal-data-table">
+      <div className="normal-data-table mingke-table">
         {offset && <Affix offsetTop={offset} className="fix-header">
           <Table
             size="middle"
-            bordered={true}
+            bordered={setting.bordered !== 'false'}
             rowSelection={rowSelection}
             columns={this.state.columns.map(column => {
               return {
@@ -417,28 +1119,104 @@
         </Affix>}
         <Table
           size="middle"
-          bordered={true}
+          bordered={setting.bordered !== 'false'}
           rowSelection={rowSelection}
           columns={this.state.columns}
           dataSource={_data}
+          rowClassName={(record) => {
+            let className = ''
+            if (setting.tableType === 'checkbox' && record.key === activeIndex) {
+              className = 'mk-row-active '
+            }
+
+            if (lineMarks.length === 0) return className
+
+            lineMarks.some(mark => {
+              let originVal = record[mark.field] + ''
+              let contrastVal = ''
+              if (mark.contrastType === 'static') {
+                contrastVal = mark.contrastValue + ''
+              } else {
+                contrastVal = record[mark.contrastField] + ''
+              }
+
+              if (mark.match === '=') {
+                className = originVal === contrastVal ? 'background ' + mark.color[1] : ''
+              } else if (mark.match === '!=') {
+                className = originVal !== contrastVal ? 'background ' + mark.color[1] : ''
+              } else if (mark.match === 'like') {
+                className = originVal.indexOf(contrastVal) > -1 ? 'background ' + mark.color[1] : ''
+              } else if (mark.match === '>') {
+                try {
+                  originVal = parseFloat(originVal)
+                  contrastVal = parseFloat(contrastVal)
+                } catch {
+                  originVal = NaN
+                }
+        
+                if (!isNaN(originVal) && !isNaN(contrastVal) && originVal > contrastVal) {
+                  className = 'background ' + mark.color[1]
+                }
+              } else if (mark.match === '<') {
+                try {
+                  originVal = parseFloat(originVal)
+                  contrastVal = parseFloat(contrastVal)
+                } catch {
+                  originVal = NaN
+                }
+        
+                if (!isNaN(originVal) && !isNaN(contrastVal) && originVal < contrastVal) {
+                  className = 'background ' + mark.color[1]
+                }
+              }
+
+              if (!className) return false
+              return true
+            })
+
+            return className
+          }}
           loading={this.props.loading}
           scroll={{ x: '100%', y: false }}
           onRow={(record, index) => {
             return {
-              onClick: () => {this.changeRow(record, index)}
+              onClick: () => {this.changeRow(record, index)},
+              onDoubleClick: () => {this.doubleClickLine(record)}
             }
           }}
           onChange={this.changeTable}
-          pagination={{
-            current: this.state.pageIndex,
-            pageSize: this.state.pageSize,
-            pageSizeOptions: ['10', '25', '50', '100', '500', '1000'],
-            showSizeChanger: true,
-            total: this.props.total,
-            showTotal: (total, range) => `${range[0]}-${range[1]} ${this.props.dict['main.pagination.of']} ${total} ${this.props.dict['main.pagination.items']}`
-          }}
+          pagination={_pagination}
         />
+        {_footer ? <div className={'normal-table-footer ' + (_pagination ? 'pagination' : '')}>{_footer}</div> : null}
+        <Modal
+          className="image-scale-modal"
+          visible={this.state.imgShow}
+          width="70vw"
+          maskClosable={true}
+          onCancel={this.imgScaleClose}
+          title={this.props.dict['main.form.picture.check']}
+          footer={[<span key="close" onClick={this.imgScaleClose}>{this.props.dict['main.close']}</span>]}
+          destroyOnClose
+        >
+         <img style={{maxWidth:'100%'}} src={this.state.imgSrc} alt="" />
+        </Modal>
       </div>
     )
   }
 }
+
+const mapStateToProps = (state) => {
+  return {
+    menuType: state.editLevel,
+    tabviews: state.tabviews,
+    memberLevel: state.memberLevel
+  }
+}
+
+const mapDispatchToProps = (dispatch) => {
+  return {
+    modifyTabview: (tabviews) => dispatch(modifyTabview(tabviews))
+  }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(NormalTable)
\ No newline at end of file

--
Gitblit v1.8.0