From ee32a69f9a7f25c37757325dc28ac7b5127dceca Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期二, 15 十月 2019 22:23:36 +0800
Subject: [PATCH] datamanage-update

---
 src/components/tabview/index.jsx                  |   21 
 src/index.js                                      |    1 
 src/tabviews/tabform/index.scss                   |   15 
 src/locales/zh-CN/main.js                         |   10 
 src/components/sidemenu/index.scss                |    1 
 src/tabviews/rolemanage/index.jsx                 |    3 
 src/store/reducer.js                              |    8 
 src/store/action-type.js                          |    5 
 src/router/index.js                               |    2 
 src/tabviews/datamanage/modules/action/index.jsx  |  379 ++++++++++++++++++----
 src/tabviews/datamanage/modules/search/index.jsx  |    8 
 src/tabviews/datamanage/modules/table/index.jsx   |   30 
 src/components/mutilform/index.scss               |    6 
 src/tabviews/datamanage/modules/table/index.scss  |    7 
 src/store/action.js                               |    8 
 src/api/index.js                                  |   15 
 src/tabviews/tabform/index.jsx                    |  139 ++++++++
 src/tabviews/datamanage/index.jsx                 |  100 ++++-
 src/locales/en-US/main.js                         |    6 
 src/components/sidemenu/index.jsx                 |    4 
 src/tabviews/commontable/index.jsx                |    3 
 src/tabviews/datamanage/modules/action/index.scss |    8 
 src/components/mutilform/index.jsx                |  193 ++++++-----
 src/assets/css/main.scss                          |   40 ++
 24 files changed, 799 insertions(+), 213 deletions(-)

diff --git a/src/api/index.js b/src/api/index.js
index b494a97..78d5efd 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -205,6 +205,21 @@
       data: param
     })
   }
+
+  /**
+   * @description 閫氱敤鎺ュ彛(鎻愪氦)
+   * @param {Object} param 鏌ヨ鍙婃彁浜ゅ弬鏁�
+   */
+  submitInterface (param) {
+    param.userid = sessionStorage.getItem('UserID')
+    param.lang = localStorage.getItem('lang') || ''
+    param.SessionUid = sessionStorage.getItem('SessionUid') || ''
+    param.LoginUID = sessionStorage.getItem('LoginUID') || ''
+    return axios({
+      url: '/webapi/dostar',
+      data: param
+    })
+  }
 }
 
 export default new Api()
\ No newline at end of file
diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss
index 09d453b..bce8f01 100644
--- a/src/assets/css/main.scss
+++ b/src/assets/css/main.scss
@@ -84,3 +84,43 @@
   top: 50px;
   z-index: 1080;
 }
+
+// 閲嶇疆鏃堕棿鎻掍欢鏃堕棿婊氬姩鏉�
+.ant-calendar-time-picker-select:hover::-webkit-scrollbar {
+  width: 7px;
+}
+.ant-calendar-time-picker-select:hover::-webkit-scrollbar-thumb {
+  border-radius: 5px;
+  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+  background: rgba(0, 0, 0, 0.13);
+}
+.ant-calendar-time-picker-select:hover::-webkit-scrollbar-track {
+  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+  border-radius: 3px;
+  border: 1px solid rgba(0, 0, 0, 0.07);
+  background: rgba(0, 0, 0, 0);
+}
+.ant-modal-mask {
+  z-index: 1080!important;
+}
+.ant-modal-wrap {
+  z-index: 1080!important;
+}
+.ant-form-item-children {
+  width: 100%;
+  display: inline-block;
+  .ant-calendar-picker {
+    width: 100%;
+  }
+}
+.ant-calendar-picker-container {
+  z-index: 1090!important;
+}
+.ant-notification {
+  z-index: 1100!important;
+}
+
+// 纭鎻愮ず妗嗛珮搴�
+.ant-modal {
+  top: 38vh!important;
+}
\ No newline at end of file
diff --git a/src/components/mutilform/index.jsx b/src/components/mutilform/index.jsx
index d0a3e9e..667ec75 100644
--- a/src/components/mutilform/index.jsx
+++ b/src/components/mutilform/index.jsx
@@ -1,42 +1,39 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Select, DatePicker } from 'antd'
+import { Form, Row, Col, Input, InputNumber, Select, DatePicker } from 'antd'
 import moment from 'moment'
-import Utils from '@/utils/utils.js'
 import './index.scss'
 
-const {MonthPicker, WeekPicker} = DatePicker
 const dateFormat = 'YYYY-MM-DD'
-const weekFormat = 'YYYYMMDD'
-const monthFormat = 'YYYY-MM'
+const timeFormat = 'YYYY-MM-DD HH:mm:ss'
 
 class MainSearch extends Component {
   static propTpyes = {
     formlist: PropTypes.array, // 鎼滅储鏉′欢鍒楄〃
     dict: PropTypes.object, // 瀛楀吀椤�
-    data: PropTypes.object // 琛ㄦ牸鏁版嵁
+    data: PropTypes.any, // 琛ㄦ牸鏁版嵁
+    cols: PropTypes.number
   }
 
   state = {
     formats: null, // 浜嬩欢鏍¢獙瑙勫垯
-    match: null // 鎼滅储鏉′欢鍖归厤瑙勫垯
+    datatype: null
   }
 
   UNSAFE_componentWillMount () {
     let formats = {}
-    let match = {}
+    let datatype = {}
     this.props.formlist.forEach(item => {
-      if (item.Type === 'date') {
-        // formats[item.FieldName] = dateFormat
-        formats[item.FieldName] = weekFormat
-      } else if (item.ID === 'WHE1400200905') {
-        formats[item.FieldName] = monthFormat
+      if (item.InputType === 'date') {
+        formats[item.FieldName] = dateFormat
+      } else if (item.InputType === 'datetime') {
+        formats[item.FieldName] = timeFormat
       }
-      match[item.FieldName] = item.Op
+      datatype[item.FieldName] = item.InputType
     })
     this.setState({
       formats: formats,
-      match: match
+      datatype: datatype
     })
   }
 
@@ -44,31 +41,61 @@
     const { getFieldDecorator } = this.props.form
     const fields = []
     this.props.formlist.forEach((item, index) => {
-      if (item.InputType === 'text' || item.InputType === 'string') { // 鏂囨湰鎼滅储
+      if (item.Hide !== 'false') return // input闅愯棌
+
+      let validate = item.Validate ? JSON.parse(item.Validate) : {} // 妫�楠屾槸鍚﹀繀濉�
+      let _required = validate.required || false
+      if (item.InputType === 'text') { // 鏂囨湰鎼滅储
         fields.push(
-          <Col span={12} key={index}>
+          <Col span={24 / this.props.cols} key={index}>
             <Form.Item label={item.Label}>
               {getFieldDecorator(item.FieldName, {
-                initialValue: this.props.data[item.FieldName],
+                initialValue: this.props.data ? this.props.data[item.FieldName] : item.InitVal,
                 rules: [
                   {
-                    required: item.required,
+                    required: _required,
                     message: this.props.dict['main.form.required.input'] + item.Label + '!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" disabled={item.ReadOnly === 'true'} />)}
+              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} />)}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.InputType === 'spinner') { // 鏁板瓧
+        validate.min = (validate.min || validate.min === 0) ? validate.min : -Infinity
+        validate.max = (validate.max || validate.max === 0) ? validate.max : Infinity
+        validate.precision = (validate.precision || validate.precision === 0) ? validate.precision : ''
+        let _initval = (this.props.data ? this.props.data[item.FieldName] : item.InitVal) || 0
+        let model = <InputNumber initialValue={_initval} disabled={item.readonly} min={validate.min} max={validate.max} />
+
+        if (validate.precision === +validate.precision) { // 鏁版嵁绮惧害
+          model = <InputNumber initialValue={_initval} disabled={item.readonly} min={validate.min} max={validate.max} precision={validate.precision} />
+        }
+        
+        fields.push(
+          <Col span={24 / this.props.cols} key={index}>
+            <Form.Item label={item.Label}>
+              {getFieldDecorator(item.FieldName, {
+                initialValue: _initval,
+                rules: [
+                  {
+                    required: _required,
+                    message: this.props.dict['main.form.required.input'] + item.Label + '!'
+                  }
+                ]
+              })(model)}
             </Form.Item>
           </Col>
         )
       } else if (item.InputType === 'select') { // 涓嬫媺鎼滅储
         fields.push(
-          <Col span={12} key={index}>
+          <Col span={24 / this.props.cols} key={index}>
             <Form.Item label={item.Label}>
               {getFieldDecorator(item.FieldName, {
-                initialValue: this.props.data[item.FieldName],
+                initialValue: this.props.data ? this.props.data[item.FieldName] : item.InitVal,
                 rules: [
                   {
-                    required: item.required,
+                    required: _required,
                     message: this.props.dict['main.form.required.select'] + item.Label + '!'
                   }
                 ]
@@ -76,6 +103,7 @@
                 <Select
                   showSearch
                   filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  getPopupContainer={() => document.getElementById('form-box')}
                 >
                   {item.DynOptions.map(option =>
                     <Select.Option id={option.id} title={option.text} key={option.id} value={option.id}>{option.text}</Select.Option>
@@ -86,37 +114,43 @@
           </Col>
         )
       } else if (item.InputType === 'date') { // 鏃堕棿鎼滅储
-        if (item.ID === 'WHE14002009024') {
-          fields.push(
-            <Col span={12} key={index}>
-              <Form.Item label={item.Label}>
-                {getFieldDecorator(item.FieldName, {initialValue: moment('2019-09-14', dateFormat) })(
-                  <DatePicker format={dateFormat} />
-                )}
-              </Form.Item>
-            </Col>
-          )
-        } else if (item.ID === 'WHE1400200905') {
-          fields.push(
-            <Col span={12} key={index}>
-              <Form.Item label={item.Label}>
-                {getFieldDecorator(item.FieldName, {initialValue: moment('2019-09', monthFormat) })(
-                  <MonthPicker format={monthFormat} />
-                )}
-              </Form.Item>
-            </Col>
-          )
-        } else if (item.ID === 'WHE1400200902') {
-          fields.push(
-            <Col span={12} key={index}>
-              <Form.Item label={item.Label}>
-                {getFieldDecorator(item.FieldName, {initialValue: moment('20190906', weekFormat) })(
-                  <WeekPicker />
-                )}
-              </Form.Item>
-            </Col>
-          )
-        }
+        let _initval = this.props.data ? this.props.data[item.FieldName] : item.InitVal
+        fields.push(
+          <Col span={24 / this.props.cols} key={index}>
+            <Form.Item label={item.Label}>
+              {getFieldDecorator(item.FieldName, {
+                initialValue: _initval ? moment(_initval, dateFormat) : null,
+                rules: [
+                  {
+                    required: _required,
+                    message: this.props.dict['main.form.required.select'] + item.Label + '!'
+                  }
+                ]
+              })(
+                <DatePicker getCalendarContainer={() => document.getElementById('form-box')} format={dateFormat} />
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.InputType === 'datetime') {
+        let _initval = this.props.data ? this.props.data[item.FieldName] : item.InitVal
+        fields.push(
+          <Col span={24 / this.props.cols} key={index}>
+            <Form.Item label={item.Label}>
+              {getFieldDecorator(item.FieldName, {
+                initialValue: _initval ? moment(_initval, timeFormat) : null,
+                rules: [
+                  {
+                    required: _required,
+                    message: this.props.dict['main.form.required.select'] + item.Label + '!'
+                  }
+                ]
+              })(
+                <DatePicker showTime format={timeFormat} />
+              )}
+            </Form.Item>
+          </Col>
+        )
       }
     })
     
@@ -128,7 +162,21 @@
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
-          resolve(values)
+          let formdata = {}
+          Object.keys(values).forEach(key => {
+            if (values[key] && typeof(values[key]) === 'object') {
+              formdata[key] = moment(values[key]).format(this.state.formats[key])
+            } else if (values[key] || values[key] === 0) {
+              if (this.state.datatype[key] === 'spinner') {
+                formdata[key] = parseFloat(values[key])
+              } else {
+                formdata[key] = values[key].replace(/\t|\v|\n|\r/g,'')
+              }
+            } else {
+              formdata[key] = ''
+            }
+          })
+          resolve(formdata)
         } else {
           reject(err)
         }
@@ -139,39 +187,6 @@
   handleReset = () => {
     // 閲嶇疆
     this.props.form.resetFields()
-  }
-
-  getFieldsValues = (searches) => {
-    // 鑾峰彇鎼滅储鏉′欢鍊�
-    let search = []
-    Object.keys(searches).forEach(key => {
-      if (searches[key] && typeof(searches[key]) === 'object') {
-        if (this.state.formats[key] === weekFormat) {
-          search.push({
-            type: 'date',
-            key: key,
-            value: moment(searches[key]).startOf('week').format(this.state.formats[key]) + ' ' + moment(searches[key]).endOf('week').format(this.state.formats[key]),
-            op: this.state.match[key]
-          })
-        } else {
-          search.push({
-            type: 'date',
-            key: key,
-            value: moment(searches[key]).format(this.state.formats[key]),
-            op: this.state.match[key]
-          })
-        }
-      } else if (searches[key] && searches[key] !== '-1') {
-        search.push({
-          type: 'text',
-          key: key,
-          value: searches[key],
-          op: this.state.match[key]
-        })
-      }
-    })
-    search = Utils.jointsearchkey(search)
-    this.props.refreshdata(search)
   }
 
   render() {
@@ -186,7 +201,7 @@
       }
     }
     return (
-      <Form {...formItemLayout} className="ant-advanced-search-form">
+      <Form {...formItemLayout} className="ant-advanced-search-form" id="form-box">
         <Row gutter={24}>{this.getFields()}</Row>
       </Form>
     )
diff --git a/src/components/mutilform/index.scss b/src/components/mutilform/index.scss
index 34418e4..838b936 100644
--- a/src/components/mutilform/index.scss
+++ b/src/components/mutilform/index.scss
@@ -11,4 +11,10 @@
   .ant-form-item-label {
     width: 100px;
   }
+}
+.ant-advanced-search-form {
+  position: relative;
+}
+.ant-advanced-search-form .ant-input-number {
+  width: 100%;
 }
\ No newline at end of file
diff --git a/src/components/sidemenu/index.jsx b/src/components/sidemenu/index.jsx
index 6d3366e..c56c0fb 100644
--- a/src/components/sidemenu/index.jsx
+++ b/src/components/sidemenu/index.jsx
@@ -29,7 +29,7 @@
     let result = await Api.getSubMenuData(menu.MenuID)
     if (result.status) {
       let param = sessionStorage.getItem('view_param') // 鏄惁涓烘墦寮�鏂伴〉闈�
-      let msg = sessionStorage.getItem('UserID')
+      let msg = sessionStorage.getItem('UserID') + '&' + sessionStorage.getItem('SessionUid') + '&' + sessionStorage.getItem('LoginUID')
       let submenuindex = 0 // 灞曞紑浜岀骇鑿滃崟绱㈠紩
       let tabindex = null // 鎵撳紑鐨則ab椤�
       if (param) {
@@ -48,7 +48,7 @@
               child.src = '#/main/' + _msg
               if (child.LinkUrl === 'CommonTable') {
                 child.type = 'CommonTable'
-              } else if (child.LinkUrl === 'DataManage') {
+              } else if (child.LinkUrl === 'DataManage' || child.LinkUrl === 'Main/Index?MenuNo=sProcExcepM') {
                 child.type = 'DataManage'
               } else if (child.LinkUrl === 'bda/rdt?pageno=rolemenus&MenuNo=RoleMenuM') {
                 child.type = 'RoleManage'
diff --git a/src/components/sidemenu/index.scss b/src/components/sidemenu/index.scss
index cc53193..e5e38ac 100644
--- a/src/components/sidemenu/index.scss
+++ b/src/components/sidemenu/index.scss
@@ -1,5 +1,4 @@
 @import '../../assets/css/iconfont.css';
-@import '../../assets/css/minkeicon.css';
 @import '../../assets/css/global.scss';
 
 .side-menu {
diff --git a/src/components/tabview/index.jsx b/src/components/tabview/index.jsx
index 1fa9c17..d494727 100644
--- a/src/components/tabview/index.jsx
+++ b/src/components/tabview/index.jsx
@@ -39,7 +39,11 @@
       } else {
         tab.selected = false
       }
-      return tab.MenuID !== menu.MenuID
+      if (menu.type === 'TabForm' || menu.type === 'iframe') {
+        return tab.MenuID !== menu.MenuID
+      } else {
+        return tab.MenuNo !== menu.MenuNo
+      }
     })
     if (menu.MenuID === this.state.selectedTabId) {
       tabs[0] && (tabs[0].selected = true)
@@ -59,11 +63,13 @@
   selectcomponent (view) {
     // 鏍规嵁tab椤典腑鑿滃崟淇℃伅锛岄�夋嫨鎵�闇�鐨勭粍浠�
     if (view.type === 'CommonTable') {
-      return (<Comps.CommonTable MenuNo={view.MenuNo} key={view.MenuID}/>)
+      return (<Comps.CommonTable MenuNo={view.MenuNo} MenuID={view.MenuID} key={view.MenuID}/>)
     } else if (view.type === 'DataManage') {
-      return (<Comps.DataManage MenuNo={view.MenuNo} key={view.MenuID}/>)
+      return (<Comps.DataManage MenuNo={view.MenuNo} MenuID={view.MenuID} key={view.MenuID}/>)
     } else if (view.type === 'RoleManage') {
-      return (<Comps.RoleManage MenuNo={view.MenuNo} key={view.MenuID}/>)
+      return (<Comps.RoleManage MenuNo={view.MenuNo} MenuID={view.MenuID} key={view.MenuID}/>)
+    } else if (view.type === 'TabForm') {
+      return (<Comps.TabForm MenuNo={view.MenuNo} MenuID={view.MenuID} key={view.MenuID} param={view.param}/>)
     } else if (view.type === 'iframe') {
       return (<Comps.Iframe key={view.MenuID} title={view.MenuName} url={'http://qingqiumarket.cn/MKWMS/zh-CN/' + view.LinkUrl}/>)
     } else {
@@ -111,15 +117,18 @@
       // tab绐楀彛椤靛鍔犳垨鍒犻櫎
       if (nextProps.tabviews.length > this.props.tabviews.length) {
         // 鏌ョ湅鏂皌ab椤甸渶瑕佺粍浠舵槸鍚﹀姞杞�
-        let newtab = nextProps.tabviews[nextProps.tabviews.length - 1]
+        let MenuIDs = this.props.tabviews.map(tab => {return tab.MenuID})
+        let newtab = nextProps.tabviews.filter(tab => !MenuIDs.includes(tab.MenuID))[0]
         if (!Comps.CommonTable && newtab.type === 'CommonTable') {
           Comps.CommonTable = asyncComponent(() => import('@/tabviews/commontable'))
         } else if (!Comps.Iframe && newtab.type === 'iframe') {
           Comps.Iframe = asyncComponent(() => import('@/tabviews/iframe'))
         } else if (!Comps.DataManage && newtab.type === 'DataManage') {
           Comps.DataManage = asyncComponent(() => import('@/tabviews/datamanage'))
-        } else if (!Comps.DataManage && newtab.type === 'RoleManage') {
+        } else if (!Comps.RoleManage && newtab.type === 'RoleManage') {
           Comps.RoleManage = asyncComponent(() => import('@/tabviews/rolemanage'))
+        } else if (!Comps.TabForm && newtab.type === 'TabForm') {
+          Comps.TabForm = asyncComponent(() => import('@/tabviews/tabform'))
         }
       }
 
diff --git a/src/index.js b/src/index.js
index e6799be..cad9ff0 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,6 +6,7 @@
 import * as serviceWorker from './serviceWorker'
 import '@/assets/css/main.scss'
 import '@/assets/css/action.scss'
+import '@/assets/css/minkeicon.css';
 
 const render  = Component => {
   ReactDOM.render(
diff --git a/src/locales/en-US/main.js b/src/locales/en-US/main.js
index c954445..09fcd8b 100644
--- a/src/locales/en-US/main.js
+++ b/src/locales/en-US/main.js
@@ -1,13 +1,19 @@
 export default {
   'main.search': 'Search',
   'main.reset': 'Reset',
+  'main.confirm': 'OK',
+  'main.return': 'Cancel',
   'main.copy.success': 'Copy success',
   'main.pagination.of': 'of',
   'main.pagination.items': 'items',
+  'main.action.settingerror': 'Button setting error!',
   'main.action.confirm.tip': 'Do you want to execute?',
   'main.action.confirm.success': 'Execute successfully!',
   'main.action.confirm.selectline': 'Please select a line!',
   'main.action.confirm.selectSingleLine': 'Please select a single row of data!',
+  'main.action.primarykey.required': 'Primary key not set!',
+  'main.action.primarykey.repetition': 'There are multiple primary keys!',
+  'main.action.primarykey.repetitionbid': 'There are multiple BID!',
   'main.form.required.input': 'Please input ',
   'main.form.required.select': 'Please select '
 }
\ No newline at end of file
diff --git a/src/locales/zh-CN/main.js b/src/locales/zh-CN/main.js
index 85018dc..c3d4968 100644
--- a/src/locales/zh-CN/main.js
+++ b/src/locales/zh-CN/main.js
@@ -1,13 +1,19 @@
 export default {
   'main.search': '鎼滅储',
   'main.reset': '閲嶇疆',
+  'main.confirm': '纭畾',
+  'main.return': '杩斿洖',
   'main.copy.success': '澶嶅埗鎴愬姛',
   'main.pagination.of': '鍏�',
   'main.pagination.items': '鏉�',
+  'main.action.settingerror': '鎸夐挳璁剧疆閿欒锛�',
   'main.action.confirm.tip': '纭畾瑕佹墽琛屽悧?',
   'main.action.confirm.success': '鎵ц鎴愬姛锛�',
-  'main.action.confirm.selectline': '璇烽�夋嫨琛�!',
-  'main.action.confirm.selectSingleLine': '璇烽�夋嫨鍗曡鏁版嵁!',
+  'main.action.confirm.selectline': '璇烽�夋嫨琛岋紒',
+  'main.action.confirm.selectSingleLine': '璇烽�夋嫨鍗曡鏁版嵁锛�',
+  'main.action.primarykey.required': '鏈缃富閿紒',
+  'main.action.primarykey.repetition': '瀛樺湪澶氫釜涓婚敭锛�',
+  'main.action.primarykey.repetitionbid': '瀛樺湪澶氫釜BID锛�',
   'main.form.required.input': '璇疯緭鍏�',
   'main.form.required.select': '璇烽�夋嫨'
 }
\ No newline at end of file
diff --git a/src/router/index.js b/src/router/index.js
index a28c284..1833c7e 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -38,6 +38,8 @@
       if (param) {
         param = param.split('&')
         sessionStorage.setItem('UserID', param[3])
+        sessionStorage.setItem('SessionUid', param[4])
+        sessionStorage.setItem('LoginUID', param[5])
         return (<item.component {...props}/>)
       } else {
         return (<Redirect to={{ pathname: '/login', state: {from: props.location}}}/>)
diff --git a/src/store/action-type.js b/src/store/action-type.js
index 83e8c0e..09a24bb 100644
--- a/src/store/action-type.js
+++ b/src/store/action-type.js
@@ -14,4 +14,7 @@
 export const RESET_STATE = 'RESET_STATE'
 
 // 淇敼缂栬緫妯″紡
-export const RESET_DEBUG = 'RESET_DEBUG'
\ No newline at end of file
+export const RESET_DEBUG = 'RESET_DEBUG'
+
+// 鍒锋柊tab椤甸潰
+export const REFRESH_TABVIEW = 'REFRESH_TABVIEW'
\ No newline at end of file
diff --git a/src/store/action.js b/src/store/action.js
index 2f9efce..f5e70b6 100644
--- a/src/store/action.js
+++ b/src/store/action.js
@@ -44,4 +44,12 @@
   return {
     type: user.RESET_DEBUG
   }
+}
+
+// 鍒锋柊tab椤甸潰
+export const refreshTabView = (refreshTab) => {
+  return {
+    type: user.REFRESH_TABVIEW,
+    refreshTab
+  }
 }
\ No newline at end of file
diff --git a/src/store/reducer.js b/src/store/reducer.js
index 7ef0bcf..add72a8 100644
--- a/src/store/reducer.js
+++ b/src/store/reducer.js
@@ -5,7 +5,8 @@
   tabviews: [], // 瀵艰埅鏍�
   collapse: false, // 鏄惁鏀惰捣渚ц竟鏍忓鑸�
   isiframe: false, // 鏄惁涓篿frame绐楀彛
-  debug: false // 鐭ュ惁鍙互澶嶅埗鑿滃崟鍙傛暟
+  debug: false, // 鐭ュ惁鍙互澶嶅埗鑿滃崟鍙傛暟
+  refreshTab: null // 鍒锋柊tabview椤甸潰淇℃伅
 }
 
 // 鐢ㄦ埛娑堟伅
@@ -46,6 +47,11 @@
         ...state,
         debug: true
       }
+    case Type.REFRESH_TABVIEW:
+      return {
+        ...state,
+        refreshTab: action.refreshTab
+      }
     default:
       return state
   }
diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index f9a9948..1cc7d63 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -13,7 +13,8 @@
 
 export default class NormalTable extends Component {
   static propTpyes = {
-    MenuNo: PropTypes.string // 鏍囩椤垫暟缁�
+    MenuNo: PropTypes.string, // 鑿滃崟鍙傛暟
+    MenuID: PropTypes.string // 鑿滃崟Id
   }
 
   state = {
diff --git a/src/tabviews/datamanage/index.jsx b/src/tabviews/datamanage/index.jsx
index c61ee55..444dbf5 100644
--- a/src/tabviews/datamanage/index.jsx
+++ b/src/tabviews/datamanage/index.jsx
@@ -1,7 +1,9 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
+import {connect} from 'react-redux'
 import { BackTop, notification } from 'antd'
+import {refreshTabView} from '@/store/action'
 import Api from '@/api'
 import DataSearch from './modules/search'
 import DataAction from './modules/action'
@@ -11,9 +13,10 @@
 import enUS from '@/locales/en-US/main.js'
 import './index.scss'
 
-export default class DataManage extends Component {
+class DataManage extends Component {
   static propTpyes = {
-    MenuNo: PropTypes.string // 鏍囩椤垫暟缁�
+    MenuNo: PropTypes.string, // 鑿滃崟鍙傛暟
+    MenuID: PropTypes.string // 鑿滃崟Id
   }
 
   state = {
@@ -22,18 +25,12 @@
     searchparam: null, // 鎼滅储鍙傛暟
     actions: null, // 鎸夐挳
     columns: null, // 鏄剧ず鍒�
+    mainKey: null, // 涓婚敭
     selectable: false, // 琛ㄦ牸鏄惁鍙��
     datafunc: null, // 鑾峰彇鏁版嵁鍙婃樉绀哄垪鐨勫瓨鍌ㄨ繃绋嬪悕绉�
     data: null,
     total: 0,
-    loading: true,
-    param: {
-      pageIndex: 1,
-      pageSize: 10,
-      orderColumn: '',
-      orderType: '',
-      search: ''
-    }
+    loading: true
   }
 
   async loadconfig () {
@@ -48,15 +45,23 @@
         newconfig.searchlist = result.sWheredata
       }
       if (result.sMenusdata && result.sMenusdata.length > 0) {
-        newconfig.actions = result.sMenusdata
+        newconfig.actions = result.sMenusdata.map(action => {
+          let width = +action.PopWidth
+          if (width > 100 || !width) {
+            width = 62
+          }
+          action.PopWidth = width / 100
+          return action
+        })
       }
-      newconfig.selectable = result.CheckBox === 'true'
+      newconfig.selectable = result.CheckBox !== 'true'
       newconfig.datafunc = result.sWhereAction
       this.setState(newconfig)
     } else {
       notification.warning({
         top: 92,
-        message: result.message
+        message: result.message,
+        duration: 10
       })
     }
   }
@@ -73,13 +78,13 @@
     }
     let result = await Api.commonInterface(param)
     if (result.status) {
-      result.sGriddata.length = 4
       this.setState({
         columns: result.sGriddata,
         data: result.data.map((item, index) => {
           item.key = index
           return item
         }),
+        mainKey: result.sGriddata.filter(grid => grid.IDField === '1' || grid.IDField === '2'),
         total: result.Total,
         searchparam: searches,
         loading: false
@@ -87,7 +92,8 @@
     } else {
       notification.warning({
         top: 92,
-        message: result.message
+        message: result.message,
+        duration: 10
       })
       this.setState({
         searchparam: searches,
@@ -128,13 +134,28 @@
     })
   }
 
-  refreshbyaction = () => {
+  refreshbyaction = (type) => {
     // 鎸夐挳鎿嶄綔鍚庡埛鏂拌〃鏍�,閲嶇疆椤电爜鍙婇�夋嫨椤�
-    this.refs.dataTable.resetTable()
-    this.loadDbdata(this.state.searchparam)
-    this.setState({
-      loading: true
-    })
+    if (type === 'grid') {
+      this.refs.dataTable.resetTable()
+      this.loadDbdata(this.state.searchparam)
+      this.setState({
+        loading: true
+      })
+    } else if (type === 'all') {
+      this.setState({
+        searchlist: null,
+        searchparam: null,
+        actions: null,
+        columns: null,
+        mainKey: null,
+        selectable: false,
+        datafunc: null,
+        data: null,
+        total: 0
+      })
+      this.loadconfig()
+    }
   }
 
   gettableselected = () => {
@@ -146,13 +167,27 @@
     return data
   }
 
+  switchview = (param) => {
+    console.log(param)
+  }
+
   UNSAFE_componentWillMount () {
     // 缁勪欢鍔犺浇鏃讹紝鑾峰彇鑿滃崟鏁版嵁
     this.loadconfig()
   }
 
   shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+    if (!is(fromJS(this.props.refreshTab), fromJS(nextProps.refreshTab)) && nextProps.refreshTab && this.props.MenuNo === nextProps.refreshTab.MenuNo) {
+      // 鎺ユ敹鍒板埛鏂板懡浠わ紝涓斿埛鏂颁俊鎭腑鑿滃崟鍙傛暟涓庡綋鍓嶉〉闈㈢浉鍚�
+      this.props.refreshTabView(null)
+      this.refreshbyaction(nextProps.refreshTab.ReloadForm)
+      return false
+    } else if (!is(fromJS(this.props.refreshTab), fromJS(nextProps.refreshTab)) && !(nextProps.refreshTab && this.props.MenuNo === nextProps.refreshTab.MenuNo)) {
+      // 鏈帴鏀跺埌鍒锋柊鍛戒护锛屾垨鍒锋柊淇℃伅涓彍鍗曞弬鏁颁笌褰撳墠椤甸潰涓嶅悓
+      return false
+    } else {
+      return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+    }
   }
 
   render() {
@@ -166,10 +201,13 @@
             dict={this.state.dict}
           />
         }
-        {this.state.actions &&
+        {this.state.actions && this.state.columns &&
           <DataAction
             MenuNo={this.props.MenuNo}
+            columns={this.state.columns}
+            mainKey={this.state.mainKey}
             refreshdata={this.refreshbyaction}
+            switchview={this.switchview}
             gettableselected={this.gettableselected}
             actions={this.state.actions}
             dict={this.state.dict}
@@ -198,4 +236,18 @@
       </div>
     )
   }
-}
\ No newline at end of file
+}
+
+const mapStateToProps = (state) => {
+  return {
+    refreshTab: state.refreshTab
+  }
+}
+
+const mapDispatchToProps = (dispatch) => {
+  return {
+    refreshTabView: (refreshTab) => dispatch(refreshTabView(refreshTab))
+  }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(DataManage)
\ No newline at end of file
diff --git a/src/tabviews/datamanage/modules/action/index.jsx b/src/tabviews/datamanage/modules/action/index.jsx
index bcfedc3..84b092d 100644
--- a/src/tabviews/datamanage/modules/action/index.jsx
+++ b/src/tabviews/datamanage/modules/action/index.jsx
@@ -1,8 +1,9 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-// import { is, fromJS } from 'immutable'
+import {connect} from 'react-redux'
 import { Button, Affix, Modal, notification } from 'antd'
 import MutilForm from '@/components/mutilform'
+import {modifyTabview} from '@/store/action'
 import Api from '@/api'
 import './index.scss'
 
@@ -10,102 +11,314 @@
 
 class MainAction extends Component {
   static propTpyes = {
-    MenuNo: PropTypes.string,
+    MenuNo: PropTypes.string, // 鑿滃崟鍙傛暟
+    columns: PropTypes.array, // 鏄剧ず鍒楃敤浜庤〃鍗曞垪
     actions: PropTypes.array, // 鎼滅储鏉′欢鍒楄〃
-    dict: PropTypes.object // 瀛楀吀椤�
+    dict: PropTypes.object, // 瀛楀吀椤�
+    mainKey: PropTypes.array
   }
 
   state = {
-    visible: false,
-    formdata: null,
-    tabledata: null,
-    confirmLoading: false,
-    execAction: null
+    visible: false, // 寮圭獥鏄惁鏄剧ず
+    formdata: null, // 琛ㄥ崟鏄剧ず鍒楁暟鎹�
+    tabledata: null, // 鍒楄〃閫夋嫨鏁版嵁
+    confirmLoading: false, // 纭涓�
+    execAction: null, // 鎵ц鎸夐挳灞炴��
+    primarykey: null, // 涓婚敭
+    bidkey: null, // BID
+    defaultproc: { // 榛樿娣诲姞銆佷慨鏀广�佸垹闄ゅ瓨鍌ㄨ繃绋�
+      Add: 'sDataManageAdd',
+      Update: 'sDataManageUpt',
+      Delete: 'sDataManageDel'
+    }
   }
   
-  refreshdata = () => {
-    this.props.refreshdata()
+  submitaction = (action, datalist, primarykey, bidkey) => {
+    if (action.Ot === 'requiredSgl' || action.Ot === 'requiredOnce') { // 閫夋嫨鍗曡鎴栧琛宨d鎷兼帴鎵ц
+      let ids = datalist.map(data => {
+        return data[primarykey]
+      })
+      let bids = null
+      if (bidkey) {
+        bids = datalist.map(data => {
+          return data[bidkey] || ''
+        })
+      }
+      return Api.submitInterface({
+        func: action.AuditProc || this.state.defaultproc[action.Action],
+        ID: ids.join(','), // 涓婚敭瀛楁
+        BID: bids ? bids.join(',') : '' // BID瀛楁
+      })
+    } else if (action.Ot === 'required') { // 鍙�夊琛岋紝寰幆鎵ц
+      let deffers = datalist.map(data => {
+        return new Promise((resolve, reject) => {
+          Api.submitInterface({
+            func: action.AuditProc || this.state.defaultproc[action.Action],
+            ID: data[primarykey], // 涓婚敭瀛楁
+            BID: data[bidkey] || '' // BID瀛楁
+          }).then(res => {
+            resolve(res)
+          })
+        })
+      })
+      return Promise.all(deffers)
+    } else { // 涓嶉�夎
+      return Api.submitInterface({
+        func: action.AuditProc || this.state.defaultproc[action.Action],
+        ID: '', // 涓婚敭瀛楁
+        BID: '' // BID瀛楁
+      })
+    }
   }
   actionTrigger = (item) => {
     let _this = this
-    let data = this.props.gettableselected() || []
-    if (item.Ot === 'required' && data.length === 0) {
+    let datalist = this.props.gettableselected() || []
+
+    /************* 鏍¢獙鍒楄〃鏁版嵁閫夋嫨鏄惁姝g‘ **************/
+
+    if ((item.Ot === 'requiredSgl' || item.Ot === 'required' || item.Ot === 'requiredOnce') && datalist.length === 0) {
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
-        message: this.props.dict['main.action.confirm.selectline']
+        message: this.props.dict['main.action.confirm.selectline'],
+        duration: 10
       })
       return
-    } else if (item.Ot === 'pop' && data.length !== 1) {
-      if (data.length === 0) {
-        // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
+    } else if (item.Ot === 'requiredSgl' && datalist.length > 1) {
+      // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
+      notification.warning({
+        top: 92,
+        message: this.props.dict['main.action.confirm.selectSingleLine'],
+        duration: 10
+      })
+      return
+    }
+
+    /************* 鏍¢獙涓婚敭涓嶣ID **************/
+    let ID = []
+    let BID = []
+    if (item.Ot === 'requiredSgl' || item.Ot === 'required' || item.Ot === 'requiredOnce') {
+      this.props.mainKey.forEach(key => {
+        if (key.IDField === '1') {
+          ID.push(key.FieldName)
+        } else {
+          BID.push(key.FieldName)
+        }
+      })
+  
+      if (ID.length === 0) { // 涓婚敭鏍¢獙
         notification.warning({
           top: 92,
-          message: this.props.dict['main.action.confirm.selectline']
+          message: this.props.dict['main.action.primarykey.required'],
+          duration: 10
         })
         return
-      } else {
-        // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
+      } else if (ID.length > 1) {
         notification.warning({
           top: 92,
-          message: this.props.dict['main.action.confirm.selectSingleLine']
+          message: this.props.dict['main.action.primarykey.repetition'],
+          duration: 10
+        })
+        return
+      }
+  
+      if (BID.length > 1) { // BID鏍¢獙
+        notification.warning({
+          top: 92,
+          message: this.props.dict['main.action.primarykey.repetitionbid'],
+          duration: 10
         })
         return
       }
     }
 
-    if (item.Action === 'Prompt' || item.Action === 'Delete') {
+    /********************* 鎿嶄綔澶勭悊 **********************/
+
+    if (item.OpenType === 'prompt') { // 纭妗�
       confirm({
         title: this.props.dict['main.action.confirm.tip'],
         onOk() {
-          return Api.setActionSubmit({
-            func: 'SetActionSubmitSuccess'
-            // func: 'SetActionSubmitError'
-          }).then((res) => {
-            if (res.status) {
-              notification.success({
-                top: 92,
-                message: _this.props.dict['main.action.confirm.success']
-                // duration: 0
-                // description:
-              })
-              _this.refreshdata()
-            } else {
-              notification.error({
-                top: 92,
-                message: res.message
-              })
-            }
-          })
+          return _this.submitaction(item, datalist, ID[0], (BID.length === 1 ? BID[0] : ''))
+            .then(res => {
+              if (Array.isArray(res)) {
+                let iserror = false
+                res.forEach(result => {
+                  if (!result.status && !iserror) {
+                    notification.error({
+                      top: 92,
+                      message: result.message,
+                      duration: 15
+                    })
+                    iserror = true
+                  }
+                })
+                if (!iserror) {
+                  notification.success({
+                    top: 92,
+                    message: _this.props.dict['main.action.confirm.success']
+                  })
+                  if (item.ReloadForm && item.ReloadForm !== 'false' && item.ReloadForm !== 'singlegrid') {
+                    _this.props.refreshdata(item.ReloadForm)
+                  }
+                }
+              } else {
+                if (res.status) {
+                  notification.success({
+                    top: 92,
+                    message: _this.props.dict['main.action.confirm.success']
+                  })
+                  if (item.ReloadForm && item.ReloadForm !== 'false' && item.ReloadForm !== 'singlegrid') {
+                    _this.props.refreshdata(item.ReloadForm)
+                  }
+                } else {
+                  notification.error({
+                    top: 92,
+                    message: res.message,
+                    duration: 15
+                  })
+                }
+              }
+            })
         },
         onCancel() {}
       })
-    } else if (item.Action === 'Update') {
-      Api.getModelFormData(item.MenuID).then(res => {
-        if (res.status) {
-          this.setState({
-            formdata: res.data.map(input => {
-              let validate = input.Validate && JSON.parse(input.Validate)
-              input.DynOptions = JSON.parse(input.DynOptions)
-              input.required = (validate && validate.required) || false
-              return input
-            }),
-            visible: true,
-            execAction: item,
-            tabledata: data[0]
-          })
+    } else if (item.OpenType === 'execproc') { // 鐩存帴鎵ц
+      this.submitaction(item, datalist, ID[0], (BID.length === 1 ? BID[0] : ''))
+        .then(res => {
+          if (Array.isArray(res)) {
+            let iserror = false
+            res.forEach(result => {
+              if (!result.status && !iserror) {
+                notification.error({
+                  top: 92,
+                  message: result.message,
+                  duration: 15
+                })
+                iserror = true
+              }
+            })
+            if (!iserror) {
+              notification.success({
+                top: 92,
+                message: this.props.dict['main.action.confirm.success']
+              })
+              if (item.ReloadForm && item.ReloadForm !== 'false' && item.ReloadForm !== 'singlegrid') {
+                this.props.refreshdata(item.ReloadForm)
+              }
+            }
+          } else {
+            if (res.status) {
+              notification.success({
+                top: 92,
+                message: this.props.dict['main.action.confirm.success']
+              })
+              if (item.ReloadForm && item.ReloadForm !== 'false' && item.ReloadForm !== 'singlegrid') {
+                this.props.refreshdata(item.ReloadForm)
+              }
+            } else {
+              notification.error({
+                top: 92,
+                message: res.message,
+                duration: 15
+              })
+            }
+          }
+        })
+    } else if (item.OpenType === 'newpage') { // 鎵撳紑鏂伴〉闈�
+      let src = '#/' + item.LinkUrl + '?param=' + window.btoa(JSON.stringify({UserId: sessionStorage.getItem('UserID'), ID: datalist[0][ID[0]], BID: BID.length === 1 ? datalist[0][BID[0]] : ''}))
+      window.open(src)
+    } else if (item.OpenType === 'pop') {
+      this.setState({
+        formdata: this.props.columns.map(column => {
+          column.readonly = false
+          if (column.ReadOnly.includes(item.MenuID)) {
+            column.readonly = true
+          }
+          return column
+        }),
+        visible: true,
+        execAction: item,
+        primarykey: ID[0],
+        bidkey: BID.length === 1 ? BID[0] : '',
+        tabledata: datalist[0] || ''
+      })
+    } else if (item.OpenType === 'tab') {
+      let menu = {
+        MenuNo: this.props.MenuNo,
+        MenuID: item.MenuID,
+        MenuName: item.MenuName,
+        type: 'TabForm',
+        param: {
+          formdata: this.props.columns.map(column => {
+            column.readonly = false
+            if (column.ReadOnly.includes(item.MenuID)) {
+              column.readonly = true
+            }
+            return column
+          }),
+          execAction: item,
+          primarykey: ID[0],
+          bidkey: BID.length === 1 ? BID[0] : '',
+          tabledata: datalist[0] || '',
+          defaultproc: this.state.defaultproc,
+          dict: this.props.dict
         }
+      }
+      let tabs = JSON.parse(JSON.stringify(this.props.tabviews))
+      let _index = null
+      let isexit = false
+      tabs = tabs.map((tab, index) => {
+        tab.selected = false
+        if (tab.MenuNo === this.props.MenuNo && tab.MenuID === item.MenuID) {
+          isexit = true
+          tab.selected = true
+          tab.param = menu.param
+        } else if (tab.MenuNo === this.props.MenuNo && tab.type !== 'TabForm') {
+          _index = index
+          menu.MenuName = tab.MenuName + '-' + menu.MenuName
+          menu.selected = true
+        }
+        return tab
+      })
+      if (!isexit) {
+        tabs.splice(_index + 1, 0, menu)
+      }
+      this.props.modifyTabview(tabs)
+    } else if (item.OpenType === 'blank') {
+      this.props.switchview(item)
+    } else {
+      notification.warning({
+        top: 92,
+        message: this.props.dict['main.action.settingerror'],
+        duration: 10
       })
     }
   }
 
+  changemenu(e) {
+    let menu = {}
+    let tabs = JSON.parse(JSON.stringify(this.props.tabviews))
+    tabs = tabs.filter(tab => {
+      tab.selected = false
+      return tab.MenuID !== menu.MenuID
+    })
+    menu.selected = true
+    tabs.push(menu)
+    this.props.modifyTabview(tabs)
+  }
+
   getModels = () => {
+    if (!this.state.execAction) return
+    let cols = +this.state.execAction.FormLineQty
+    if (![1, 2, 3].includes(cols)) {
+      cols = 2
+    }
     return (
       <Modal
         wrapClassName='action-modal'
-        title={(this.state.execAction && this.state.execAction.MenuName) || ''}
+        title={this.state.execAction.MenuName || ''}
         visible={this.state.visible}
-        width={(this.state.execAction && +this.state.execAction.PopWidth) || 520}
+        width={document.body.clientWidth * this.state.execAction.PopWidth}
         onOk={this.handleOk}
         confirmLoading={this.state.confirmLoading}
         onCancel={this.handleCancel}
@@ -115,6 +328,7 @@
             dict={this.props.dict}
             formlist={this.state.formdata}
             data={this.state.tabledata}
+            cols={cols}
             wrappedComponentRef={(inst) => this.formRef = inst}
           />}
       </Modal>
@@ -126,11 +340,25 @@
       this.setState({
         confirmLoading: true
       })
-      console.log(res)
-      Api.setActionSubmit({
-        func: 'SetActionSubmitSuccess'
-      }).then((res) => {
-        if (res.status) {
+      let values = []
+      this.props.columns.forEach(column => {
+        let value = ''
+        if (res[column.FieldName] || res[column.FieldName] === 0) { // 渚濇閫夊彇琛ㄥ崟鍊笺�佽〃鏍兼暟鎹�笺�佸垵濮嬪��
+          value = res[column.FieldName]
+        } else if (this.state.tabledata && this.state.tabledata[column.FieldName]) {
+          value = this.state.tabledata[column.FieldName]
+        } else if (column.InitVal) {
+          value = column.InitVal
+        }
+        values.push(value)
+      })
+      Api.submitInterface({
+        func: this.state.execAction.AuditProc || this.state.defaultproc[this.state.execAction.Action],
+        AddLongText: values.join(','), // 琛ㄥ崟鏁版嵁
+        ID: (this.state.tabledata && this.state.primarykey) ? this.state.tabledata[this.state.primarykey] : '', // 涓婚敭瀛楁
+        BID: (this.state.tabledata && this.state.bidkey) ? this.state.tabledata[this.state.bidkey] : '' // BID瀛楁
+      }).then(result => {
+        if (result.status) {
           notification.success({
             top: 92,
             message: this.props.dict['main.action.confirm.success']
@@ -139,10 +367,17 @@
             confirmLoading: false,
             visible: false
           })
+          if (this.state.execAction.ReloadForm && this.state.execAction.ReloadForm !== 'false' && this.state.execAction.ReloadForm !== 'singlegrid') {
+            this.props.refreshdata(this.state.execAction.ReloadForm)
+          }
         } else {
+          this.setState({
+            confirmLoading: false
+          })
           notification.error({
             top: 92,
-            message: res.message
+            message: result.message,
+            duration: 15
           })
         }
       })
@@ -151,6 +386,7 @@
 
   handleCancel = () => {
     this.setState({
+      confirmLoading: false,
       visible: false
     })
     this.formRef.handleReset()
@@ -159,11 +395,6 @@
   UNSAFE_componentWillMount () {
 
   }
-
-  // shouldComponentUpdate (nextProps, nextState) {
-  //   console.log(!is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)))
-  //   return true
-  // }
 
   render() {
     return (
@@ -186,4 +417,16 @@
   }
 }
 
-export default MainAction
\ No newline at end of file
+const mapStateToProps = (state) => {
+  return {
+    tabviews: state.tabviews
+  }
+}
+
+const mapDispatchToProps = (dispatch) => {
+  return {
+    modifyTabview: (tabviews) => dispatch(modifyTabview(tabviews))
+  }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(MainAction)
\ No newline at end of file
diff --git a/src/tabviews/datamanage/modules/action/index.scss b/src/tabviews/datamanage/modules/action/index.scss
index 215e88d..d5333a3 100644
--- a/src/tabviews/datamanage/modules/action/index.scss
+++ b/src/tabviews/datamanage/modules/action/index.scss
@@ -5,6 +5,9 @@
     margin-right: 15px;
     margin-bottom: 10px;
   }
+  .ant-btn > .anticon + span {
+    margin-left: 5px;
+  }
 }
 // 璁剧疆妯℃�佹鏍峰紡锛岃瀹氭渶澶ф渶灏忛珮搴︼紝閲嶇疆婊氬姩鏉�
 .action-modal {
@@ -32,4 +35,9 @@
     border: 1px solid rgba(0, 0, 0, 0.07);
     background: rgba(0, 0, 0, 0);
   }
+  .ant-modal-footer {
+    .ant-btn {
+      margin-right: 25px;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/tabviews/datamanage/modules/search/index.jsx b/src/tabviews/datamanage/modules/search/index.jsx
index 7d288db..e832982 100644
--- a/src/tabviews/datamanage/modules/search/index.jsx
+++ b/src/tabviews/datamanage/modules/search/index.jsx
@@ -51,16 +51,20 @@
           </Col>
         )
       } else if (item.Type === 'select') { // 涓嬫媺鎼滅储
+        let initval = item.FromField.filter(field => field.Selected === 'Selected')[0]
+        if (!initval) {
+          initval = item.FromField[0]
+        }
         fields.push(
           <Col span={6} key={index}>
             <Form.Item label={item.label}>
-              {getFieldDecorator(item.FieldName, {initialValue: item.FromField[0].id })(
+              {getFieldDecorator(item.FieldName, {initialValue: initval.IdField })(
                 <Select
                   showSearch
                   filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                 >
                   {item.FromField.map(option =>
-                    <Select.Option id={option.id} title={option.text} key={option.id} value={option.id}>{option.text}</Select.Option>
+                    <Select.Option id={option.IdField} title={option.TextField} key={option.IdField} value={option.IdField}>{option.TextField}</Select.Option>
                   )}
                 </Select>
               )}
diff --git a/src/tabviews/datamanage/modules/table/index.jsx b/src/tabviews/datamanage/modules/table/index.jsx
index 4817382..9339e95 100644
--- a/src/tabviews/datamanage/modules/table/index.jsx
+++ b/src/tabviews/datamanage/modules/table/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-// import { is, fromJS } from 'immutable'
 import { Table, message, Affix } from 'antd'
 import './index.scss'
 
@@ -23,17 +22,22 @@
     selectedRowKeys: [],
     pageIndex: 1,
     pageSize: 10,
-    columns: this.props.columns.map((item, index) => {
+    columns: this.props.columns.map(item => {
       let _width = parseInt(item.Width) || 50
+      // if (/ID$/.test(item.FieldName) || item.FieldName.includes('PassWord')) {
+      //   _width = _width * 3
+      // } else if (item.FieldName.includes('Date')) {
+      //   _width = _width * 2
+      // }
       return {
         align: item.Align,
         dataIndex: item.FieldName,
         title: item.Label,
         sorter: item.IsSort === 'true',
         width: _width,
-        render: (text, record) => (
+        render: (text) => (
           <div style={{ wordWrap: 'break-word', wordBreak: 'break-word', minWidth: _width + 'px' }}>
-            {item.Type === 'image' ? text : text}
+            {item.Type === 'Image' ? <img width={_width * 0.9} src={text} alt={text}/> : text}
           </div>
         )
         // onHeaderCell: () => ({style:{textAlign: 'center'}})
@@ -59,22 +63,17 @@
   }
 
   changeRow = (record, index) => {
-    // 鐐瑰嚮鏁磋锛岃Е鍙戝垏鎹紝鍒ゆ柇鏄惁鍙�夛紝鍗曢�夋垨澶氶�夛紝杩涜瀵瑰簲鎿嶄綔
-    if (!this.props.select || !this.props.select.selectable) return
+    // 鐐瑰嚮鏁磋锛岃Е鍙戝垏鎹紝鍒ゆ柇鏄惁鍙�夛紝杩涜瀵瑰簲鎿嶄綔
+    if (!this.props.selectable) return
 
     let newkeys = JSON.parse(JSON.stringify(this.state.selectedRowKeys))
-    let _re = newkeys.includes(index)
 
-    if (this.props.select.selectType === 'radio') {
-      this.setState({ selectedRowKeys: [index] })
+    if (newkeys.includes(index)) {
+      newkeys = newkeys.filter(item => item !== index)
     } else {
-      if (_re) {
-        newkeys = newkeys.filter(item => item !== index)
-      } else {
-        newkeys.push(index)
-      }
-      this.setState({ selectedRowKeys: newkeys })
+      newkeys.push(index)
     }
+    this.setState({ selectedRowKeys: newkeys })
   }
 
   changeTable = (pagination, filters, sorter) => {
@@ -127,6 +126,7 @@
           />
         </Affix>}
         <Table
+          className={this.state.fixed ? 'fixed' : ''}
           bordered={true}
           rowSelection={rowSelection}
           size="middle"
diff --git a/src/tabviews/datamanage/modules/table/index.scss b/src/tabviews/datamanage/modules/table/index.scss
index fb65cc0..39babb8 100644
--- a/src/tabviews/datamanage/modules/table/index.scss
+++ b/src/tabviews/datamanage/modules/table/index.scss
@@ -14,6 +14,9 @@
     .ant-table-tbody > tr.ant-table-row-selected td {
       background-color: #c4ebfd;
     }
+    .ant-table-tbody > tr:hover.ant-table-row-selected td {
+      background-color: #c4ebfd;
+    }
   }
   .ant-table-body {
     overflow-x: auto!important;
@@ -76,4 +79,8 @@
       background: #fafafa;
     }
   }
+  // 琛ㄦ牸娌℃湁妯悜婊氬姩鏉℃椂
+  .ant-table-wrapper.fixed .ant-table-body {
+    min-height: unset;
+  }
 }
\ No newline at end of file
diff --git a/src/tabviews/rolemanage/index.jsx b/src/tabviews/rolemanage/index.jsx
index a4232a7..2c13a08 100644
--- a/src/tabviews/rolemanage/index.jsx
+++ b/src/tabviews/rolemanage/index.jsx
@@ -10,7 +10,8 @@
 
 export default class RoleManage extends Component {
   static propTpyes = {
-    MenuNo: PropTypes.string // 鏍囩椤垫暟缁�
+    MenuNo: PropTypes.string, // 鑿滃崟鍙傛暟
+    MenuID: PropTypes.string // 鑿滃崟Id
   }
 
   state = {
diff --git a/src/tabviews/tabform/index.jsx b/src/tabviews/tabform/index.jsx
new file mode 100644
index 0000000..48fefca
--- /dev/null
+++ b/src/tabviews/tabform/index.jsx
@@ -0,0 +1,139 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import {connect} from 'react-redux'
+import { is, fromJS } from 'immutable'
+import { Button, BackTop, notification } from 'antd'
+import {refreshTabView, modifyTabview} from '@/store/action'
+import MutilForm from '@/components/mutilform'
+import Api from '@/api'
+import './index.scss'
+
+class TabForm extends Component {
+  static propTpyes = {
+    MenuNo: PropTypes.string, // 鑿滃崟鍙傛暟
+    MenuID: PropTypes.string, // 鑿滃崟Id
+    param: PropTypes.object // 鑿滃崟鍙傛暟
+  }
+
+  state = {
+    loading: false
+  }
+
+  handleOk = () => {
+    this.setState({
+      loading: true
+    })
+    this.formRef.handleConfirm().then(res => {
+      let values = []
+      this.props.param.formdata.forEach(column => {
+        let value = ''
+        if (res[column.FieldName] || res[column.FieldName] === 0) { // 渚濇閫夊彇琛ㄥ崟鍊笺�佽〃鏍兼暟鎹�笺�佸垵濮嬪��
+          value = res[column.FieldName]
+        } else if (this.state.tabledata && this.state.tabledata[column.FieldName]) {
+          value = this.state.tabledata[column.FieldName]
+        } else if (column.InitVal) {
+          value = column.InitVal
+        }
+        values.push(column.FieldName + 'equal\'' + value + '\'')
+      })
+      Api.submitInterface({
+        func: this.props.param.execAction.AuditProc || this.props.param.defaultproc[this.props.param.execAction.Action],
+        UptLongText: values.join(','), // 琛ㄥ崟鏁版嵁
+        ID: (this.props.param.tabledata && this.props.param.primarykey) ? this.props.param.tabledata[this.props.param.primarykey] : '', // 涓婚敭瀛楁
+        BID: (this.props.param.tabledata && this.props.param.bidkey) ? this.props.param.tabledata[this.props.param.bidkey] : '' // BID瀛楁
+      }).then(result => {
+        if (result.status) {
+          notification.success({
+            top: 92,
+            message: this.props.param.dict['main.action.confirm.success']
+          })
+          
+          // 鍒锋柊涓诲垪琛ㄩ〉闈�
+          if (this.props.param.execAction.ReloadForm && this.props.param.execAction.ReloadForm !== 'false' && this.props.param.execAction.ReloadForm !== 'singlegrid') {
+            this.props.refreshTabView({
+              MenuNo: this.props.MenuNo,
+              ReloadForm: this.props.param.execAction.ReloadForm
+            })
+          }
+
+          this.handleCancel()
+        } else {
+          notification.error({
+            top: 92,
+            message: result.message,
+            duration: 15
+          })
+        }
+        this.setState({
+          loading: false
+        })
+      })
+    }, () => {})
+  }
+
+  handleCancel = () => {
+    // 鍏抽棴褰撳墠绐楀彛锛岃繑鍥炲師鍒楄〃椤�
+    let tabs = JSON.parse(JSON.stringify(this.props.tabviews))
+    tabs = tabs.filter(tab => {
+      if (tab.MenuNo === this.props.MenuNo && tab.type !== 'TabForm') {
+        tab.selected = true
+      } else {
+        tab.selected = false
+      }
+      return tab.MenuID !== this.props.MenuID
+    })
+    this.props.modifyTabview(tabs)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  render() {
+    let cols = +this.props.param.execAction.FormLineQty
+    if (![1, 2, 3].includes(cols)) {
+      cols = 2
+    }
+    return (
+      <div className="tabform">
+        <MutilForm
+          dict={this.props.param.dict}
+          formlist={this.props.param.formdata}
+          data={this.props.param.tabledata}
+          cols={cols}
+          wrappedComponentRef={(inst) => this.formRef = inst}
+        />
+        <div className="operation">
+          <Button type="primary" htmlType="submit" onClick={() => {this.handleOk()}} loading={this.state.loading}>
+            {this.props.param.dict['main.confirm']}
+          </Button>
+          <Button onClick={() => {this.handleCancel()}}>
+            {this.props.param.dict['main.return']}
+          </Button>
+        </div>
+        <BackTop>
+          <div className="ant-back-top">
+            <div className="ant-back-top-content">
+              <div className="ant-back-top-icon"></div>
+            </div>
+          </div>
+        </BackTop>
+      </div>
+    )
+  }
+}
+
+const mapStateToProps = (state) => {
+  return {
+    tabviews: state.tabviews
+  }
+}
+
+const mapDispatchToProps = (dispatch) => {
+  return {
+    refreshTabView: (refreshTab) => dispatch(refreshTabView(refreshTab)),
+    modifyTabview: (tabviews) => dispatch(modifyTabview(tabviews))
+  }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(TabForm)
\ No newline at end of file
diff --git a/src/tabviews/tabform/index.scss b/src/tabviews/tabform/index.scss
new file mode 100644
index 0000000..ebdaef0
--- /dev/null
+++ b/src/tabviews/tabform/index.scss
@@ -0,0 +1,15 @@
+.tabform {
+  padding: 25px 25px 120px;
+  .operation {
+    text-align: center;
+    margin: 20px 0;
+    .ant-btn {
+      height: 40px;
+      padding: 0 30px;
+      font-size: 16px;
+    }
+    .ant-btn-primary {
+      margin-right: 40px;
+    }
+  }
+}
\ No newline at end of file

--
Gitblit v1.8.0