From 2031a460f6c0827fe80f8c625dd98333d1631d2f Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期五, 08 五月 2020 22:10:48 +0800
Subject: [PATCH] 2020-05-08

---
 src/tabviews/zshare/dategroup/yearpicker/index.jsx                                |  107 ++++
 src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx             |   58 ++
 src/tabviews/zshare/dategroup/quarterpicker/index.jsx                             |  137 +++++
 src/templates/subtableconfig/source.jsx                                           |   30 
 src/tabviews/zshare/topSearch/index.jsx                                           |   10 
 src/tabviews/zshare/normalTable/index.jsx                                         |    8 
 src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx                  |    3 
 src/templates/zshare/verifycard/customscript/index.jsx                            |   50 +
 src/templates/sharecomponent/searchcomponent/index.jsx                            |   24 
 src/templates/sharecomponent/searchcomponent/searchform/index.scss                |   13 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx |   78 +-
 src/tabviews/zshare/topSearch/index.scss                                          |   11 
 src/templates/sharecomponent/settingcomponent/settingform/index.jsx               |   19 
 src/tabviews/commontable/index.jsx                                                |    1 
 src/tabviews/zshare/dategroup/index.scss                                          |   75 +++
 src/templates/formtabconfig/index.scss                                            |    2 
 src/templates/sharecomponent/settingcomponent/settingform/customscript/index.jsx  |   47 
 src/utils/utils.js                                                                |   70 ++
 src/templates/modalconfig/index.scss                                              |    2 
 src/tabviews/zshare/dategroup/yearpicker/index.scss                               |   43 +
 src/templates/sharecomponent/searchcomponent/dategroup/index.scss                 |   31 +
 src/templates/sharecomponent/searchcomponent/searcheditable/index.scss            |    6 
 src/tabviews/zshare/dategroup/index.jsx                                           |  173 ++++++
 src/templates/zshare/formconfig.jsx                                               |   53 ++
 src/tabviews/zshare/dategroup/quarterpicker/index.scss                            |   37 +
 src/templates/comtableconfig/source.jsx                                           |   30 
 src/tabviews/managetable/index.jsx                                                |   29 
 src/templates/sharecomponent/searchcomponent/dategroup/index.jsx                  |   32 +
 src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx                 |   20 
 src/templates/subtableconfig/index.jsx                                            |    9 
 src/templates/zshare/verifycard/customscript/index.scss                           |    5 
 src/templates/subtableconfig/index.scss                                           |    2 
 /dev/null                                                                         |   24 
 src/templates/comtableconfig/index.scss                                           |    2 
 src/utils/option.js                                                               |   24 
 src/templates/sharecomponent/searchcomponent/searchform/index.jsx                 |  206 +++++++-
 36 files changed, 1,260 insertions(+), 211 deletions(-)

diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index 0cec4fd..a8ef6bd 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -567,7 +567,6 @@
   async loadmaindata () {
     const { setting, BIDs, search } = this.state
     let param = ''
-
     let requireFields = search.filter(item => item.required && !item.value)
 
     if (requireFields.length > 0) {
diff --git a/src/tabviews/managetable/index.jsx b/src/tabviews/managetable/index.jsx
index 33ac0d0..9016520 100644
--- a/src/tabviews/managetable/index.jsx
+++ b/src/tabviews/managetable/index.jsx
@@ -159,11 +159,28 @@
         })
       }
 
+      // 鍏煎鏍囩
+      if (!config.tabgroups) {
+        config.tabgroups = [{ uuid: 'tabs', sublist: [] }]
+      } else if (typeof(config.tabgroups[0]) === 'string') {
+        let _tabgroups = []
+        config.tabgroups.forEach(groupId => {
+          let _group = {
+            uuid: groupId,
+            sublist: fromJS(config[groupId]).toJS()
+          }
+  
+          delete config[groupId]
+  
+          _tabgroups.push(_group)
+        })
+  
+        config.tabgroups = _tabgroups
+      }
+
       let custabs = ['1586577325055l2ng7t75g7i4ek2ng8o']
       config.tabgroups.forEach(group => {
-        if (!config[group]) return
-
-        config[group] = config[group].map(tab => {
+        group.sublist = group.sublist.map(tab => {
           if (custabs.includes(tab.linkTab)) {
             tab.type = 'SecretKeyTable'
           }
@@ -882,11 +899,11 @@
           }
           {setting && setting.onload !== 'false' &&
             config.tabgroups.map(group => {
-              if (config[group].length === 0) return null
+              if (group.sublist.length === 0) return null
 
               return (
-                <Tabs defaultActiveKey="0" key={group}>
-                  {config[group].map((_tab, index) => {
+                <Tabs defaultActiveKey="0" key={group.uuid}>
+                  {group.sublist.map((_tab, index) => {
                     return (
                       <TabPane tab={
                         <span>
diff --git a/src/tabviews/zshare/dategroup/index.jsx b/src/tabviews/zshare/dategroup/index.jsx
new file mode 100644
index 0000000..df8a89a
--- /dev/null
+++ b/src/tabviews/zshare/dategroup/index.jsx
@@ -0,0 +1,173 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { DatePicker, Tooltip } from 'antd'
+import moment from 'moment'
+
+import Utils from '@/utils/utils.js'
+import QuarterPicker from './quarterpicker'
+import YearPicker from './yearpicker'
+import './index.scss'
+
+const { MonthPicker, WeekPicker, RangePicker } = DatePicker
+
+class DateGroup extends Component {
+  static propTpyes = {
+    card: PropTypes.object    // 瀛楀吀椤�
+  }
+
+  state = {
+    active: '',
+    quarterId: Utils.getuuid(),
+    yearId: Utils.getuuid(),
+    dateRange: ''
+  }
+
+  UNSAFE_componentWillMount() {
+    const { card } = this.props
+
+    if (card.initval && card.initval[0]) {
+      let _type = card.initval[0]
+      let _val = card.initval[1]
+      let _dateRange = null
+
+      if (_type === 'day') {
+        _dateRange = [moment().subtract(_val, 'days').format('YYYY-MM-DD'),
+          moment().subtract(_val, 'days').format('YYYY-MM-DD')]
+      } else if (_type === 'week') {
+        _dateRange = [moment().subtract(_val * 7, 'days').startOf('week').format('YYYY-MM-DD'),
+          moment().subtract(_val * 7, 'days').endOf('week').format('YYYY-MM-DD')]
+      } else if (_type === 'month') {
+        _dateRange = [moment().subtract(_val, 'month').startOf('month').format('YYYY-MM-DD'),
+          moment().subtract(_val, 'month').endOf('month').format('YYYY-MM-DD')]
+      } else if (_type === 'quarter') {
+        let _differ = parseInt(moment().format('MM')) % 3
+        let _pdiffer = 0
+        let _ndiffer = 0
+
+        // 宸�艰绠�
+        switch(_differ) {
+          case 0:
+            _pdiffer = 2
+            _ndiffer = 0
+            break
+          case 1:
+            _pdiffer = 0
+            _ndiffer = -2
+            break
+          case 2:
+            _pdiffer = 1
+            _ndiffer = -1
+            break
+          default:
+        }
+
+        _dateRange = [moment().subtract(_pdiffer + _val * 3, 'month').startOf('month').format('YYYY-MM-DD'),
+          moment().subtract(_ndiffer + _val * 3, 'month').endOf('month').format('YYYY-MM-DD')]
+      } else if (_type === 'year') {
+        let _year = parseInt(moment().format('YYYY')) - _val
+        _dateRange = [_year + '-01-01', _year + '-12-31']
+      } else if (_type === 'customized') {
+        try {
+          _val = JSON.parse(_val)
+        } catch {
+          _val = [0, 0]
+        }
+        _dateRange = [moment().subtract(_val[0], 'days').format('YYYY-MM-DD'),
+          moment().subtract(_val[1], 'days').format('YYYY-MM-DD')]
+      }
+      this.setState({
+        active: card.initval[0],
+        dateRange: _dateRange
+      })
+    }
+  }
+
+  changeTab = () => {
+
+  }
+
+  onChange = (date, type) => {
+    let values = []
+    if (type === 'day') {
+      values = [moment(date).format('YYYY-MM-DD'), moment(date).format('YYYY-MM-DD')]
+    } else if (type === 'week') {
+      values = [moment(date).startOf('week').format('YYYY-MM-DD'), moment(date).endOf('week').format('YYYY-MM-DD')]
+    } else if (type === 'month') {
+      values = [moment(date).startOf('month').format('YYYY-MM-DD'), moment(date).endOf('month').format('YYYY-MM-DD')]
+    } else if (type === 'quarter') {
+      values = date
+      document.getElementById(this.state.quarterId).click()
+    } else if (type === 'year') {
+      values = date
+      document.getElementById(this.state.yearId).click()
+    } else if (type === 'customized') {
+      values = [moment(date[0]).format('YYYY-MM-DD'), moment(date[1]).format('YYYY-MM-DD')]
+    }
+
+    this.setState({
+      active: type,
+      dateRange: values
+    })
+  }
+
+  render() {
+    const { card } = this.props
+    const { active, quarterId, yearId, dateRange } = this.state
+    let tabs = {day: '鏃�', week: '鍛�', month: '鏈�', quarter: '瀛�', year: '骞�', customized: '鑷畾涔�'}
+
+    return (
+      <div className="table-search-date-group">
+        {card.items.map(tab => {
+          if (tab === 'day') {
+            return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} >
+              {tabs[tab]}
+              <DatePicker allowClear={false} onChange={(date) => this.onChange(date, tab)} />
+            </span>)
+          } else if (tab === 'week') {
+            return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} >
+              {tabs[tab]}
+              <WeekPicker dropdownClassName="group-week-picker" allowClear={false} onChange={(date) => this.onChange(date, tab)} />
+            </span>)
+          } else if (tab === 'month') {
+            return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} >
+              {tabs[tab]}
+              <MonthPicker allowClear={false} onChange={(date) => this.onChange(date, tab)} />
+            </span>)
+          } else if (tab === 'quarter') {
+            return (
+              <Tooltip key={tab} placement="bottomLeft" overlayClassName="quarter-picker-tooltip" trigger="click" title={
+                <div>
+                  <QuarterPicker onChange={(date) => this.onChange(date, tab)}/>
+                </div>
+              }>
+                <span id={quarterId} className={'ant-tag ant-tag-quarter ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} >
+                  {tabs[tab]}
+                </span>
+              </Tooltip>
+            )
+          } else if (tab === 'year') {
+            return (
+              <Tooltip key={tab} placement="bottomLeft" overlayClassName="year-picker-tooltip" trigger="click" title={
+                <div>
+                  <YearPicker onChange={(date) => this.onChange(date, tab)}/>
+                </div>
+              }>
+                <span id={yearId} className={'ant-tag ant-tag-quarter ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} >
+                  {tabs[tab]}
+                </span>
+              </Tooltip>
+            )
+          } else {
+            return (<span key={tab} className={'ant-tag ant-tag-checkable ' + (active === tab ? 'ant-tag-checkable-checked' : '')} >
+              {tabs[tab]}
+              <RangePicker allowClear={false} onChange={(date) => this.onChange(date, tab)} />
+            </span>)
+          }
+        })}
+        <div className="table-search-date-group-value">{dateRange ? dateRange.join(' ~ ') : ''}</div>
+      </div>
+    )
+  }
+}
+
+export default DateGroup
\ No newline at end of file
diff --git a/src/tabviews/zshare/dategroup/index.scss b/src/tabviews/zshare/dategroup/index.scss
new file mode 100644
index 0000000..ada3e16
--- /dev/null
+++ b/src/tabviews/zshare/dategroup/index.scss
@@ -0,0 +1,75 @@
+.table-search-date-group {
+  white-space: nowrap;
+  line-height: 40px;
+  position: relative;
+  z-index: 1;
+
+  .ant-tag {
+    position: relative;
+    cursor: pointer;
+
+    .ant-calendar-picker {
+      cursor: pointer;
+      position: absolute;
+      left: 0;
+      top: 0;
+      bottom: 0;
+      right: 0;
+      opacity: 0;
+      .ant-input {
+        display: none;
+      }
+      .ant-calendar-picker-icon {
+        position: absolute;
+        top: 0;
+        margin: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        width: 100%;
+        height: 100%;
+      }
+      .ant-calendar-picker-input {
+        display: inline-block;
+        height: 28px;
+      }
+    }
+  }
+  .ant-tag.ant-tag-quarter:hover {
+    opacity: 1;
+  }
+  .ant-tag-checkable {
+    border-color: #d1d5d9;
+    border-radius: 2px;
+    margin-right: 2px;
+    padding: 2px 7px;
+  }
+  .ant-tag-checkable-checked {
+    border-color: #1890ff;
+  }
+  .table-search-date-group-value {
+    position: absolute;
+    line-height: 20px;
+    font-size: 12px;
+    bottom: -15px;
+  }
+}
+// .group-week-picker {
+//   .ant-calendar {
+//     margin-top: -15px;
+//   }
+// }
+@media screen and (min-width: 1600px) {
+  .table-search-date-group {
+    .ant-tag-checkable {
+      padding: 2px 9px;
+    }
+  }
+}
+@media screen and (min-width: 1920px) {
+  .table-search-date-group {
+    .ant-tag-checkable {
+      padding: 2px 11px;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/tabviews/zshare/dategroup/quarterpicker/index.jsx b/src/tabviews/zshare/dategroup/quarterpicker/index.jsx
new file mode 100644
index 0000000..c27ae26
--- /dev/null
+++ b/src/tabviews/zshare/dategroup/quarterpicker/index.jsx
@@ -0,0 +1,137 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import moment from 'moment'
+
+import './index.scss'
+
+class QuarterPicker extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,    // 瀛楀吀椤�
+    onChange: PropTypes.func
+  }
+
+  state = {
+    year: moment().format('YYYY'),
+    selectQuarter: null
+  }
+
+  changeYear = (type) => {
+    let _year = this.state.year
+
+    if (type === 'up') {
+      _year--
+    } else {
+      _year++
+    }
+    
+    this.setState({
+      year: _year
+    })
+  }
+
+  changeQuarter = (quarter) => {
+    const { year } = this.state
+
+    let _stime = ''
+    let _etime = ''
+    if (quarter === 1) {
+      _stime = year + '-01-01'
+      _etime = year + '-03-31'
+    } else if (quarter === 2) {
+      _stime = year + '-04-01'
+      _etime = year + '-06-30'
+    } else if (quarter === 3) {
+      _stime = year + '-07-01'
+      _etime = year + '-09-30'
+    } else if (quarter === 2) {
+      _stime = year + '-10-01'
+      _etime = year + '-12-31'
+    }
+
+
+    this.setState({
+      selectQuarter: quarter
+    })
+    this.props.onChange([_stime, _etime])
+  }
+
+  render() {
+    const { year, selectQuarter } = this.state
+
+    return (
+      <div className="ant-calendar-picker-container ant-calendar-quarter-picker">
+        <div className="ant-calendar ant-calendar-month ant-calendar-month-calendar">
+          <div className="ant-calendar-month-calendar-content">
+            <div className="ant-calendar-month-header-wrap">
+              <div className="ant-calendar-header">
+                <div className="ant-calendar-month-panel">
+                  <div>
+                    <div className="ant-calendar-month-panel-header">
+                      <span className="ant-calendar-month-panel-prev-year-btn" onClick={() => this.changeYear('up')} title="涓婁竴骞�"></span>
+                      <span className="ant-calendar-month-panel-year-select">
+                        <span className="ant-calendar-month-panel-year-select-content">{year}</span>
+                      </span>
+                      <span className="ant-calendar-month-panel-next-year-btn" onClick={() => this.changeYear('down')} title="涓嬩竴骞�"></span>
+                    </div>
+                    <div className="ant-calendar-month-panel-body">
+                      <table className="ant-calendar-month-panel-table">
+                        <tbody className="ant-calendar-month-panel-tbody">
+                          <tr onClick={() => this.changeQuarter(1)} className={selectQuarter === 1 ? 'ant-quarter-selected' : ''}>
+                            <td title="涓�鏈�" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">涓�鏈�</span>
+                            </td>
+                            <td title="浜屾湀" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">浜屾湀</span>
+                            </td>
+                            <td title="涓夋湀" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">涓夋湀</span>
+                            </td>
+                          </tr>
+                          <tr onClick={() => this.changeQuarter(2)} className={selectQuarter === 2 ? 'ant-quarter-selected' : ''}>
+                            <td title="鍥涙湀" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">鍥涙湀</span>
+                            </td>
+                            <td title="浜旀湀" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">浜旀湀</span>
+                            </td>
+                            <td title="鍏湀" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">鍏湀</span>
+                            </td>
+                          </tr>
+                          <tr onClick={() => this.changeQuarter(3)} className={selectQuarter === 3 ? 'ant-quarter-selected' : ''}>
+                            <td title="涓冩湀" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">涓冩湀</span>
+                            </td>
+                            <td title="鍏湀" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">鍏湀</span>
+                            </td>
+                            <td title="涔濇湀" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">涔濇湀</span>
+                            </td>
+                          </tr>
+                          <tr onClick={() => this.changeQuarter(4)} className={selectQuarter === 4 ? 'ant-quarter-selected' : ''}>
+                            <td title="鍗佹湀" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">鍗佹湀</span>
+                            </td>
+                            <td title="鍗佷竴鏈�" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">鍗佷竴鏈�</span>
+                            </td>
+                            <td title="鍗佷簩鏈�" className="ant-calendar-month-panel-cell">
+                              <span className="ant-calendar-month-panel-month">鍗佷簩鏈�</span>
+                            </td>
+                          </tr>
+                        </tbody>
+                      </table>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+}
+
+export default QuarterPicker
\ No newline at end of file
diff --git a/src/tabviews/zshare/dategroup/quarterpicker/index.scss b/src/tabviews/zshare/dategroup/quarterpicker/index.scss
new file mode 100644
index 0000000..086f3a7
--- /dev/null
+++ b/src/tabviews/zshare/dategroup/quarterpicker/index.scss
@@ -0,0 +1,37 @@
+.ant-calendar-quarter-picker {
+  top: -30px;
+  left: 0px;
+
+  .ant-calendar-month-panel-next-year-btn, .ant-calendar-month-panel-prev-year-btn {
+    cursor: pointer;
+  }
+
+  tr {
+    background: #ffffff;
+    transition: all 0.3s;
+    cursor: pointer;
+    td {
+      .ant-calendar-month-panel-month:hover {
+        background: transparent;
+      }
+    }
+  }
+  tr:hover {
+    font-weight: bold;
+    background: #e6f7ff;
+  }
+  tr.ant-quarter-selected {
+    font-weight: bold;
+    background: #bae7ff!important;
+  }
+}
+
+.quarter-picker-tooltip {
+  .ant-tooltip-arrow {
+    display: none;
+  }
+  .ant-tooltip-inner {
+    box-shadow: unset;
+    background-color: transparent;
+  }
+}
diff --git a/src/tabviews/zshare/dategroup/yearpicker/index.jsx b/src/tabviews/zshare/dategroup/yearpicker/index.jsx
new file mode 100644
index 0000000..368bc4f
--- /dev/null
+++ b/src/tabviews/zshare/dategroup/yearpicker/index.jsx
@@ -0,0 +1,107 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import moment from 'moment'
+
+import './index.scss'
+
+class QuarterPicker extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,    // 瀛楀吀椤�
+    onChange: PropTypes.func
+  }
+
+  state = {
+    year: Math.floor(moment().format('YYYY') / 10) * 10,
+    selectYear: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { year } = this.state
+
+    this.setState({
+      yearlist: [
+        [{value: year - 1, type: 'up'}, {value: year, type: ''}, {value: year + 1, type: ''}],
+        [{value: year + 2, type: ''}, {value: year + 3, type: ''}, {value: year + 4, type: ''}],
+        [{value: year + 5, type: ''}, {value: year + 6, type: ''}, {value: year + 7, type: ''}],
+        [{value: year + 8, type: ''}, {value: year + 9, type: ''}, {value: year + 10, type: 'down'}],
+      ]
+    })
+  }
+
+  changeYear = (type) => {
+    let _year = this.state.year
+
+    if (type === 'up') {
+      _year -= 10
+    } else {
+      _year += 10
+    }
+    
+    this.setState({
+      year: _year,
+      yearlist: [
+        [{value: _year - 1, type: 'up'}, {value: _year, type: ''}, {value: _year + 1, type: ''}],
+        [{value: _year + 2, type: ''}, {value: _year + 3, type: ''}, {value: _year + 4, type: ''}],
+        [{value: _year + 5, type: ''}, {value: _year + 6, type: ''}, {value: _year + 7, type: ''}],
+        [{value: _year + 8, type: ''}, {value: _year + 9, type: ''}, {value: _year + 10, type: 'down'}],
+      ]
+    })
+  }
+
+  selectTargetYear = (item) => {
+    if (item.type) {
+      this.changeYear(item.type)
+      return
+    }
+
+    this.setState({
+      selectYear: item.value
+    })
+    this.props.onChange([item.value + '-01-01', item.value + '-12-31'])
+  }
+
+  render() {
+    const { year, selectYear, yearlist } = this.state
+
+    return (
+      <div className="ant-calendar-picker-container ant-calendar-year-picker">
+        <div className="ant-calendar ant-calendar-month ant-calendar-month-calendar">
+          <div className="ant-calendar-month-calendar-content">
+            <div className="ant-calendar-month-header-wrap">
+              <div className="ant-calendar-header">
+                <div className="ant-calendar-year-panel">
+                  <div>
+                    <div className="ant-calendar-year-panel-header">
+                      <span className="ant-calendar-year-panel-prev-decade-btn" onClick={() => this.changeYear('up')} title="涓婁竴骞翠唬"></span>
+                      <span className="ant-calendar-year-panel-year-select">
+                        <span className="ant-calendar-year-panel-decade-select-content">{year + '-' + (year + 9)}</span>
+                      </span>
+                      <span className="ant-calendar-year-panel-next-decade-btn" onClick={() => this.changeYear('down')} title="涓嬩竴骞翠唬"></span>
+                    </div>
+                    <div className="ant-calendar-year-panel-body">
+                      <table className="ant-calendar-year-panel-table">
+                        <tbody className="ant-calendar-year-panel-tbody">
+                          {yearlist.map((list, i) => (
+                            <tr key={'line' + i}>
+                              {list.map(item => (
+                                <td key={item.value} title={item.value} className={'ant-calendar-year-panel-cell' + (item.type ? ' ant-calendar-year-panel-last-decade-cell' : '')}>
+                                  <span onClick={() => this.selectTargetYear(item)} className={'ant-calendar-year-panel-year' + (selectYear === item.value ? ' ant-year-selected' : '')}>{item.value}</span>
+                                </td>
+                              ))}
+                            </tr>
+                          ))}
+                        </tbody>
+                      </table>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+}
+
+export default QuarterPicker
\ No newline at end of file
diff --git a/src/tabviews/zshare/dategroup/yearpicker/index.scss b/src/tabviews/zshare/dategroup/yearpicker/index.scss
new file mode 100644
index 0000000..566824c
--- /dev/null
+++ b/src/tabviews/zshare/dategroup/yearpicker/index.scss
@@ -0,0 +1,43 @@
+.ant-calendar-year-picker {
+  top: -30px;
+  left: 0px;
+
+  .ant-calendar-year-panel-prev-decade-btn, .ant-calendar-year-panel-next-decade-btn {
+    cursor: pointer;
+  }
+
+  tr {
+    td {
+      .ant-calendar-year-panel-year {
+        color: rgba(0, 0, 0, 0.65);
+        cursor: pointer;
+        background: #ffffff;
+        transition: all 0.3s;
+      }
+      .ant-calendar-year-panel-year:hover {
+        color: #40a9ff;
+        background: #e6f7ff;
+      }
+      .ant-calendar-year-panel-year.ant-year-selected {
+        color: #fff;
+        background: #1890ff;
+      }
+    }
+    td.ant-calendar-year-panel-last-decade-cell {
+      .ant-calendar-year-panel-year {
+        background: #ffffff;
+        color: rgba(0, 0, 0, 0.25);
+      }
+    }
+  }
+}
+
+.year-picker-tooltip {
+  .ant-tooltip-arrow {
+    display: none;
+  }
+  .ant-tooltip-inner {
+    box-shadow: unset;
+    background-color: transparent;
+  }
+}
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index 8cc455f..b6bf7ec 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -179,6 +179,10 @@
             }
           }
         }
+
+        if (item.format === 'percent') {
+          content = content * 100
+        }
   
         content = content.toFixed(item.decimal || 0)
   
@@ -291,6 +295,10 @@
           }
     
           if (content !== '') {
+            if (item.format === 'percent') {
+              content = content * 100
+            }
+            
             content = content.toFixed(col.decimal || 0)
       
             if (col.format === 'thdSeparator') {
diff --git a/src/tabviews/zshare/topSearch/index.jsx b/src/tabviews/zshare/topSearch/index.jsx
index 30e5a57..2844062 100644
--- a/src/tabviews/zshare/topSearch/index.jsx
+++ b/src/tabviews/zshare/topSearch/index.jsx
@@ -2,6 +2,8 @@
 import PropTypes from 'prop-types'
 import { Form, Row, Col, Input, Button, Select, DatePicker, notification } from 'antd'
 import moment from 'moment'
+
+import DateGroup from '@/tabviews/zshare/dategroup'
 import Utils from '@/utils/utils.js'
 import './index.scss'
 
@@ -338,6 +340,14 @@
             </Form.Item>
           </Col>
         )
+      } else if (item.type === 'group') {
+        fields.push(
+          <Col span={item.ratio || 6} key={index}>
+            <Form.Item label={item.label} className={item.required ? 'group-required' : ''}>
+              <DateGroup card={item} />
+            </Form.Item>
+          </Col>
+        )
       }
     })
 
diff --git a/src/tabviews/zshare/topSearch/index.scss b/src/tabviews/zshare/topSearch/index.scss
index 04d0d16..ee84ed1 100644
--- a/src/tabviews/zshare/topSearch/index.scss
+++ b/src/tabviews/zshare/topSearch/index.scss
@@ -27,4 +27,15 @@
   .ant-calendar-picker-container {
     z-index: 10 !important;
   }
+  .group-required {
+    label::before {
+      display: inline-block;
+      margin-right: 4px;
+      color: #f5222d;
+      font-size: 14px;
+      font-family: SimSun, sans-serif;
+      line-height: 1;
+      content: '*';
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/templates/comtableconfig/index.scss b/src/templates/comtableconfig/index.scss
index f5984e7..1535241 100644
--- a/src/templates/comtableconfig/index.scss
+++ b/src/templates/comtableconfig/index.scss
@@ -25,7 +25,7 @@
     .ant-collapse-item.ant-collapse-item-active {
       border-bottom: 1px solid #d9d9d9;
     }
-    .ant-collapse-header {
+    .ant-collapse .ant-collapse-header {
       padding: 11px 16px 10px 40px;
       border-bottom: 1px solid #d9d9d9;
       background: #1890ff;
diff --git a/src/templates/comtableconfig/source.jsx b/src/templates/comtableconfig/source.jsx
index 502fe78..c7edb97 100644
--- a/src/templates/comtableconfig/source.jsx
+++ b/src/templates/comtableconfig/source.jsx
@@ -205,39 +205,57 @@
   searchItems = [
     {
       type: 'search',
-      label: '鏂囨湰妗�',
+      label: CommonDict['header.form.text'],
       subType: 'text',
       url: ''
     },
     {
       type: 'search',
-      label: '涓嬫媺妗�',
+      label: CommonDict['header.form.select'],
       subType: 'select',
       url: ''
     },
     {
       type: 'search',
-      label: '鏃堕棿妗嗭紙澶╋級',
+      label: CommonDict['header.form.multiselect'],
+      subType: 'multiselect',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: CommonDict['header.form.link'],
+      subType: 'link',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: CommonDict['header.form.dateday'],
       subType: 'date',
       url: ''
     },
     {
       type: 'search',
-      label: '鏃堕棿妗嗭紙鍛級',
+      label: CommonDict['header.form.dateweek'],
       subType: 'dateweek',
       url: ''
     },
     {
       type: 'search',
-      label: '鏃堕棿妗嗭紙鏈堬級',
+      label: CommonDict['header.form.datemonth'],
       subType: 'datemonth',
       url: ''
     },
     {
       type: 'search',
-      label: '鏃堕棿妗嗭紙鍖洪棿锛�',
+      label: CommonDict['header.form.daterange'],
       subType: 'daterange',
       url: ''
+    },
+    {
+      type: 'search',
+      label: '鏃ユ湡锛堢粍鍚堬級',
+      subType: 'group',
+      url: ''
     }
   ]
 
diff --git a/src/templates/formtabconfig/index.scss b/src/templates/formtabconfig/index.scss
index d9647ba..6de600f 100644
--- a/src/templates/formtabconfig/index.scss
+++ b/src/templates/formtabconfig/index.scss
@@ -25,7 +25,7 @@
     .ant-collapse-item.ant-collapse-item-active {
       border-bottom: 1px solid #d9d9d9;
     }
-    .ant-collapse-header {
+    .ant-collapse .ant-collapse-header {
       padding: 11px 16px 10px 40px;
       border-bottom: 1px solid #d9d9d9;
       background: #1890ff;
diff --git a/src/templates/modalconfig/index.scss b/src/templates/modalconfig/index.scss
index 1f2e120..1b1bf93 100644
--- a/src/templates/modalconfig/index.scss
+++ b/src/templates/modalconfig/index.scss
@@ -24,7 +24,7 @@
     .ant-collapse-item.ant-collapse-item-active {
       border-bottom: 1px solid #d9d9d9;
     }
-    .ant-collapse-header {
+    .ant-collapse .ant-collapse-header {
       padding: 11px 16px 10px 40px;
       border-bottom: 1px solid #d9d9d9;
       background: #1890ff;
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
index cbbd0d8..abf8146 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Button, notification, Modal, Menu, Icon, Tooltip, Radio, Dropdown } from 'antd'
+import { Form, Row, Col, Input, Button, notification, Modal, Icon, Tooltip, Radio, Select } from 'antd'
 import moment from 'moment'
 
 import Utils from '@/utils/utils.js'
@@ -153,23 +153,20 @@
     })
   }
 
-  selectScript = (e) => {
-    const { systemScripts, usefulfields, btn } = this.props
+  selectScript = (value, option) => {
+    const { usefulfields, btn } = this.props
 
-    let option = ''
-    if (e.key === 'default') {
+    let _value = ''
+    if (value === 'default') {
       let fields = usefulfields.map(col => col.Column).join(',')
       
       if (fields) {
         fields = fields + ','
       }
 
-      option = {
-        name: '榛樿sql',
-        value: `Insert into ${btn.sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid,@username,@fullname,@BID From @${btn.sheet}`
-      }
+      _value = `Insert into ${btn.sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid,@username,@fullname,@BID From @${btn.sheet}`
     } else {
-      option = systemScripts[+e.key]
+      _value = value
     }
 
     let _sql = this.props.form.getFieldValue('sql')
@@ -180,10 +177,10 @@
     }
 
     _sql = _sql.replace(/\s{6}$/, '')
-    _sql = _sql + `/*${option.name}*/
+    _sql = _sql + `/*${option.props.children}*/
     `
     _sql = _sql.replace(/\s{4}$/, '')
-    _sql = _sql + option.value
+    _sql = _sql + _value
 
     this.props.form.setFieldsValue({
       sql: _sql
@@ -206,8 +203,18 @@
     }
 
     return (
-      <Form {...formItemLayout} className="verify-form" id="verifycard2">
+      <Form {...formItemLayout} className="verify-form" id="verify-excelin-custom-scripts">
         <Row gutter={24}>
+          {btn.sheet ? <Col span={8}>
+            <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
+              {btn.sheet}
+            </Form.Item>
+          </Col> : null}
+          <Col span={16}>
+            <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0}}>
+              errorCode, errmsg
+            </Form.Item>
+          </Col>
           {usefulfields ? <Col span={24} className="sqlfield">
             <Form.Item label={'鍙敤瀛楁'}>
               {usefulfields}
@@ -231,48 +238,29 @@
               )}
             </Form.Item>
           </Col>
-          <Col span={4} style={{lineHeight: '40px', textAlign: 'center'}}>
-            <Dropdown trigger={['click']} overlayClassName="mk-normal-dropdown" overlay={
-              <Menu onClick={this.selectScript}>
-                <Menu.Item key="default">榛樿sql</Menu.Item>
+          <Col span={10}>
+            <Form.Item style={{marginBottom: 0}} label={'蹇嵎娣诲姞'}>
+              <Select
+                showSearch
+                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                onChange={this.selectScript}
+                getPopupContainer={() => document.getElementById('verify-excelin-custom-scripts')}
+              >
+                <Select.Option key="default" value={'default'}>
+                  榛樿sql
+                </Select.Option>
                 {systemScripts.map((option, i) =>
-                  <Menu.Item key={i} value={option.value}>{option.name}</Menu.Item>
-                )}
-                {systemScripts.map((option, i) =>
-                  <Menu.Item key={i + '1'} value={option.value}>{option.name}</Menu.Item>
-                )}
-              </Menu>
-            }>
-              <span style={{color: '#1890ff', display: 'inline-block', cursor: 'pointer'}}>
-                蹇嵎娣诲姞 <Icon type="down" style={{marginRight: '5px'}} />
-              </span>
-            </Dropdown>
-          </Col>
-          {/* <Col span={8}>
-            <Form.Item style={{marginBottom: 0}} label={
-              <Tooltip placement="bottomLeft" title={'浠庣郴缁熷嚱鏁伴泦涓�夋嫨闇�瑕佺殑鍑芥暟锛屽彲蹇�熸坊鍔犺嚦sql涓��'}>
-                <Icon type="question-circle" style={{color: '#c49f47', marginRight: '5px'}} />
-                蹇嵎娣诲姞
-              </Tooltip>
-            }>
-              <Select value="" onChange={this.selectScript}>
-                {systemScripts.map((option, i) =>
-                  <Select.Option title={option.name} key={i} value={option.value}>
+                  <Select.Option key={i} value={option.value}>
                     {option.name}
                   </Select.Option>
                 )}
               </Select>
             </Form.Item>
-          </Col> */}
+          </Col>
           <Col span={4} className="add">
             <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
               淇濆瓨
             </Button>
-          </Col>
-          <Col span={8} style={{textAlign: 'right'}}>
-            {btn.sheet ? <span style={{maxWidth: '100%', display: 'inline-block', position: 'relative', top: '20px', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden'}}>
-              琛ㄥ悕:  {btn.sheet}
-            </span> : null}
           </Col>
           <Col span={24} className="sql">
             <Form.Item label={'sql'}>
diff --git a/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.jsx b/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.jsx
deleted file mode 100644
index 8abe02b..0000000
--- a/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.jsx
+++ /dev/null
@@ -1,265 +0,0 @@
-import React, {Component} from 'react'
-import { is, fromJS } from 'immutable'
-import { Table, Input, Button, Popconfirm, Form, Icon } from 'antd'
-import Utils from '@/utils/utils.js'
-import './index.scss'
-
-const EditableContext = React.createContext()
-
-const EditableRow = ({ form, index, ...props }) => (
-  <EditableContext.Provider value={form}>
-    <tr {...props} />
-  </EditableContext.Provider>
-)
-
-const EditableFormRow = Form.create()(EditableRow)
-
-class EditableCell extends Component {
-  state = {
-    editing: false
-  }
-
-  toggleEdit = () => {
-    const editing = !this.state.editing
-    this.setState({ editing }, () => {
-      if (editing && this.input && this.input.select) {
-        this.input.select()
-      } else if (editing && this.input && this.input.focus) {
-        this.input.focus()
-      }
-    })
-  }
-
-  save = e => {
-    const { record, handleSave } = this.props
-    this.form.validateFields((error, values) => {
-      handleSave({ ...record, ...values })
-      if (error && error[e.currentTarget.id]) {
-        return
-      }
-      this.toggleEdit()
-    })
-  }
-
-  renderCell = form => {
-    this.form = form
-    const { children, dataIndex, record } = this.props
-    const { editing } = this.state
-    return editing ? (
-      <Form.Item style={{ margin: 0 }}>
-        {form.getFieldDecorator(dataIndex, {
-          rules: [
-            {
-              required: true,
-              message: 'NOT NULL.',
-            },
-          ],
-          initialValue: record[dataIndex]
-        })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)}
-      </Form.Item>
-    ) : (
-      <div
-        className="editable-cell-value-wrap"
-        onClick={this.toggleEdit}
-      >
-        {children}
-      </div>
-    )
-  }
-
-  render() {
-    const {
-      editable,
-      dataIndex,
-      title,
-      record,
-      index,
-      handleSave,
-      children,
-      ...restProps
-    } = this.props
-    return (
-      <td {...restProps}>
-        {editable ? (
-          <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer>
-        ) : (
-          children
-        )}
-      </td>
-    )
-  }
-}
-
-class EditTable extends Component {
-  constructor(props) {
-    super(props)
-    let columns = [
-      {
-        title: 'Value',
-        dataIndex: 'Value',
-        width: props.type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: 'Text',
-        dataIndex: 'Text',
-        width: props.type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: 'Action',
-        align: 'center',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
-          ) : null,
-      }
-    ]
-
-    if (props.type === 'link') {
-      columns.unshift({
-        title: 'ParentID',
-        dataIndex: 'ParentID',
-        width: '27%',
-        editable: true
-      })
-    }
-
-    this.state = {
-      columns: columns,
-      dataSource: props.data,
-      count: props.data.length,
-      type: props.type
-    }
-  }
-
-  handleDelete = key => {
-    const dataSource = [...this.state.dataSource]
-    this.setState({ dataSource: dataSource.filter(item => item.key !== key) })
-  }
-
-  handleAdd = () => {
-    const { type, count, dataSource } = this.state
-    const newData = {
-      key: Utils.getuuid(),
-      Value: `${count}`,
-      Text: `${count}`
-    }
-    if (type === 'link') {
-      newData.ParentID = `${count}`
-    }
-    this.setState({
-      dataSource: [...dataSource, newData],
-      count: count + 1
-    })
-  }
-
-  handleSave = row => {
-    const newData = [...this.state.dataSource]
-    const index = newData.findIndex(item => row.key === item.key)
-    const item = newData[index]
-    newData.splice(index, 1, {
-      ...item,
-      ...row
-    })
-    this.setState({ dataSource: newData })
-  }
-
-  resetColumn = (type) => {
-    let columns = [
-      {
-        title: 'Value',
-        dataIndex: 'Value',
-        width: type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: 'Text',
-        dataIndex: 'Text',
-        width: type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: 'Action',
-        align: 'center',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
-          ) : null,
-      }
-    ]
-
-    if (type === 'link') {
-      columns.unshift({
-        title: 'ParentID',
-        dataIndex: 'ParentID',
-        width: '27%',
-        editable: true
-      })
-    }
-
-    this.setState({
-      columns: columns,
-      type: type
-    })
-  }
-
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (this.props.type !== nextProps.type) {
-      this.resetColumn(nextProps.type)
-    } else if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      this.setState({
-        dataSource: nextProps.data,
-        count: nextProps.data.length
-      })
-    }
-  }
-
-  render() {
-    const { dataSource } = this.state
-    const components = {
-      body: {
-        row: EditableFormRow,
-        cell: EditableCell
-      }
-    }
-    const columns = this.state.columns.map(col => {
-      if (!col.editable) {
-        return col
-      }
-      return {
-        ...col,
-        onCell: record => ({
-          record,
-          editable: col.editable,
-          dataIndex: col.dataIndex,
-          title: col.title,
-          handleSave: this.handleSave,
-        })
-      }
-    })
-    return (
-      <div className="common-modal-edit-table">
-        <Button onClick={this.handleAdd} type="primary" className="add-row">
-          Add
-        </Button>
-        <Table
-          components={components}
-          rowClassName={() => 'editable-row'}
-          bordered
-          dataSource={dataSource}
-          columns={columns}
-          pagination={false}
-        />
-      </div>
-    )
-  }
-}
-
-export default EditTable
\ No newline at end of file
diff --git a/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.scss b/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.scss
deleted file mode 100644
index f8f0942..0000000
--- a/src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.scss
+++ /dev/null
@@ -1,36 +0,0 @@
-.common-modal-edit-table {
-  .add-row {
-    position: absolute;
-    z-index: 1;
-    right: 12px;
-    top: -40px;
-  }
-  .ant-table-thead > tr > th {
-    padding: 10px 16px;
-  }
-  .ant-table-tbody > tr > td {
-    padding: 0px 16px;
-  }
-  .editable-cell-value-wrap {
-    cursor: pointer;
-    height: 40px;
-    width: 100px;
-    display: table-cell;
-    vertical-align: middle;
-    word-wrap: break-word;
-    word-break: break-word;
-    .ant-input {
-      height: 30px;
-      padding: 0 11px;
-    }
-  }
-  .ant-form-item-control-wrapper {
-    width: 100%;
-  }
-  .ant-table-placeholder {
-    padding: 5px 16px;
-    .ant-empty-normal {
-      margin: 0;
-    }
-  }
-}
diff --git a/src/templates/sharecomponent/chartgroupcomponent/searchform/index.jsx b/src/templates/sharecomponent/chartgroupcomponent/searchform/index.jsx
deleted file mode 100644
index e7941ec..0000000
--- a/src/templates/sharecomponent/chartgroupcomponent/searchform/index.jsx
+++ /dev/null
@@ -1,475 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber } from 'antd'
-import { dateOptions, matchReg, formRule } from '@/utils/option.js'
-import EditTable from '../searcheditable'
-import Utils from '@/utils/utils.js'
-import './index.scss'
-
-const { TextArea } = Input
-
-class MainSearch extends Component {
-  static propTpyes = {
-    dict: PropTypes.object,     // 瀛楀吀椤�
-    formlist: PropTypes.any,    // 琛ㄥ崟
-    optionLibs: PropTypes.any,  // 鑷畾涔変笅鎷夐泦
-    card: PropTypes.object,     // 鎼滅储鏉′欢淇℃伅
-    inputSubmit: PropTypes.any  // 鍥炶溅鎻愪氦浜嬩欢
-  }
-
-  state = {
-    openType: null,          // 鎼滅储鏉′欢鏄剧ず绫诲瀷
-    resourceType: null,      // 涓嬫媺鎼滅储鏃讹紝閫夐」鏉ユ簮绫诲瀷
-    formlist: null           // 琛ㄥ崟
-  }
-
-  /**
-   * @description 琛ㄥ崟棰勫鐞�
-   * 1銆佹牴鎹〃鍗曠被鍨嬶紝鏄剧ず琛ㄥ崟鍙紪杈戦」
-   * 2銆佷笅鎷夐�夋嫨锛屾牴鎹暟鎹簮绫诲瀷鏄剧ず鐩稿叧閰嶇疆
-   */
-  UNSAFE_componentWillMount () {
-    const { formlist, optionLibs } = this.props
-
-    let type = formlist.filter(cell => cell.key === 'type')[0].initVal
-    let resourceType = formlist.filter(cell => cell.key === 'resourceType')[0].initVal
-    let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required']                // 榛樿鏄剧ず椤�
-
-    if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '0') {        // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓鸿嚜瀹氫箟璧勬簮
-      _options = [..._options, 'resourceType', 'options', 'display', 'quick']
-    } else if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙�
-      _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database']
-    }
-
-    if (type === 'select' || type === 'link') {
-      _options.push('setAll')
-    }
-
-    if (type === 'link') { // 鍏宠仈绫诲瀷銆佸鍔犲叧鑱斾笂绾х殑瀛楁鍚�
-      _options = [..._options, 'linkField']
-    }
-    
-    this.setState({
-      openType: type,
-      resourceType: resourceType,
-      formlist: formlist.map(form => {
-        // 琛ㄥ崟涓哄垵濮嬪�煎瓧娈碉紝涓旀暟鎹被鍨嬪睘浜庢椂闂寸被鍨嬫椂锛岃缃垵濮嬪�间负涓嬫媺閫夋嫨锛屽苟閲嶇疆閫夋嫨椤�
-        if (form.key === 'initval' && dateOptions.hasOwnProperty(type)) {
-          form.options = dateOptions[type]
-          form.type = 'select'
-        }
-        // 琛ㄥ崟涓哄尮閰嶅瓧娈垫椂锛屾牴鎹笉鍚岀殑绫诲瀷锛屾樉绀哄搴旂殑鍖归厤瑙勫垯
-        if (form.key === 'match') {
-          if (type === 'text') {
-            form.options = matchReg.text
-          } else if (type === 'multiselect') {
-            form.options = matchReg.multiselect
-          } else if (type === 'select' || type === 'link') {
-            form.options = matchReg.select
-          } else if (type === 'date') {
-            form.options = matchReg.date
-          } else if (type === 'datemonth') {
-            form.options = matchReg.datemonth
-          } else if (type === 'dateweek' || type === 'daterange') {
-            form.options = matchReg.daterange
-          }
-        } else if (form.key === 'quick') {
-          form.options = [...optionLibs.values()].map(cell => {
-            return {
-              value: cell.uuid,
-              text: cell.label + '(' + cell.parname + ')'
-            }
-          })
-        }
-        form.hidden = !_options.includes(form.key)
-        return form
-      })
-    })
-  }
-
-  componentDidMount () {
-    const { card } = this.props
-
-    if (card.focus) {
-      try {
-        let _form = document.getElementById('label')
-        _form.select()
-      } catch {
-        console.warn('琛ㄥ崟focus澶辫触锛�')
-      }
-    }
-  }
-
-  /**
-   * @description 鎼滅储鏉′欢绫诲瀷鍒囨崲
-   */
-  openTypeChange = (key, value) => {
-    const { resourceType } = this.state
-
-    if (key === 'type') {
-      let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required']
-
-      if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '0') {        // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓鸿嚜瀹氫箟璧勬簮
-        _options = [..._options, 'resourceType', 'options', 'display', 'quick']
-      } else if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙�
-        _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database']
-      }
-
-      if (value === 'select' || value === 'link') {
-        _options.push('setAll')
-      }
-      
-      if (value === 'link') {
-        _options = [..._options, 'linkField']
-      }
-
-      this.setState({
-        openType: value,
-        formlist: this.state.formlist.map(form => {
-          form.hidden = !_options.includes(form.key)            // 闅愯棌琛ㄥ崟
-
-          if (form.key === 'initval') {
-            if (dateOptions.hasOwnProperty(value)) { // 鏍规嵁鎼滅储鏉′欢绫诲瀷锛岄�夋嫨鍒濆鍊肩殑绫诲瀷鍙婃暟鎹�
-              form.options = dateOptions[value]
-              form.type = 'select'
-            } else {
-              form.type = 'text'
-            }
-            form.initVal = ''                                    // 鎼滅储鏉′欢绫诲瀷鍒囨崲鏃讹紝鍒濆鍊肩疆绌�
-            form.hidden = true
-          } else if (form.key === 'match') {                     // 鎼滅储鏉′欢绫诲瀷鍒囨崲鏃讹紝鍖归厤瑙勫垯绫诲瀷瀵瑰簲鍒囨崲
-            if (value === 'text') {
-              form.options = matchReg.text
-            } else if (value === 'multiselect') {
-              form.options = matchReg.multiselect
-            } else if (value === 'select' || value === 'link') {
-              form.options = matchReg.select
-            } else if (value === 'date') {
-              form.options = matchReg.date
-            } else if (value === 'datemonth') {
-              form.options = matchReg.datemonth
-            } else if (value === 'dateweek' || value === 'daterange') {
-              form.options = matchReg.daterange
-            }
-            form.hidden = true
-          }
-
-          return form
-        })
-      }, () => {
-        this.setState({
-          formlist: this.state.formlist.map(form => {
-
-            if (form.key === 'initval') {
-              form.hidden = false
-            } else if (form.key === 'match') {
-              form.initVal = form.options[0].value
-              form.hidden = false
-            }
-
-            return form
-          })
-        })
-      })
-    } else if (key === 'quick') {
-      let option = this.props.optionLibs.get(value)
-
-      this.setState({
-        formlist: this.state.formlist.map(form => {
-          if (form.key === 'options') {
-            form.initVal = option.options
-          }
-
-          return form
-        })
-      })
-    }
-  }
-
-  /**
-   * @description 鏁版嵁婧愮被鍨嬪垏鎹�
-   */
-  onChange = (e, key) => {
-    const { openType } = this.state
-    let value = e.target.value
-
-    if (key === 'resourceType') {
-      let _options = ['label', 'field', 'initval', 'type', 'match', 'resourceType', 'display', 'ratio', 'blacklist', 'required']
-
-      if (value === '0') {
-        _options = [..._options, 'options', 'quick']
-      } else if (value === '1') {
-        _options = [..._options, 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'database']
-      }
-
-      if (openType === 'select' || openType === 'link') {
-        _options.push('setAll')
-      }
-      
-      if (openType === 'link') {
-        _options = [..._options, 'linkField']
-      }
-      
-      this.setState({
-        resourceType: value,
-        formlist: this.state.formlist.map(form => {
-          form.hidden = !_options.includes(form.key)
-          return form
-        })
-      })
-    }
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  getFields() {
-    const { getFieldDecorator } = this.props.form
-    const fields = []
-    this.state.formlist.forEach((item, index) => {
-      if (item.hidden) return
-
-      if (item.type === 'text') { // 鏂囨湰鎼滅储
-        let rules = []
-        if (item.key === 'field') {
-          rules = [{
-            pattern: formRule.field.pattern,
-            message: formRule.field.message
-          }, {
-            max: formRule.field.max,
-            message: formRule.field.maxMessage
-          }]
-        } else {
-          rules = [{
-            max: formRule.input.max,
-            message: formRule.input.message
-          }]
-        }
-        
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <Icon type="question-circle" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || '',
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  },
-                  ...rules
-                ]
-              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'number') {
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <Icon type="question-circle" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || 6,
-                rules: [
-                  {
-                    required: item.required,
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  }
-                ]
-              })(<InputNumber min={item.min} max={item.max} precision={0} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'select') { // 涓嬫媺鎼滅储
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || '',
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <Select
-                  showSearch
-                  filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                  onChange={(value) => {this.openTypeChange(item.key, value)}}
-                  getPopupContainer={() => document.getElementById('commontable-search-form-box')}
-                >
-                  {item.options.map(option =>
-                    <Select.Option id={option.value} title={option.text} key={option.value} value={option.value}>
-                      {item.key === 'icon' && <Icon type={option.text} />} {option.text}
-                    </Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'radio') {
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal,
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}}>
-                  {
-                    item.options.map(option => {
-                      return (
-                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
-                      )
-                    })
-                  }
-                </Radio.Group>,
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'textarea') {
-        fields.push(
-          <Col span={20} offset={4} key={index}>
-            <Form.Item className="text-area">
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal,
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  }
-                ]
-              })(<TextArea rows={4} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'options') {
-        fields.push(
-          <Col span={20} offset={4} key={index}>
-            <EditTable data={item.initVal} type={this.state.openType} ref="editTable"/>
-          </Col>
-        )
-      } else if (item.type === 'multiselect') { // 澶氶��
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || []
-              })(
-                <Select
-                  showSearch
-                  mode="multiple"
-                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                >
-                  {item.options.map((option, i) =>
-                    <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      }
-    })
-
-    return fields
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          let isvalid = true
-          values.uuid = this.props.card.uuid
-          // 涓嬫媺鑿滃崟鎴栧叧鑱旇彍鍗�
-          if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '0') {
-            values.options = this.refs.editTable.state.dataSource
-            values.dataSource = ''
-            let emptys = []
-            if (values.type === 'multiselect' || values.type === 'select') {
-              emptys = values.options.filter(op => !(op.Value && op.Text))
-            } else {
-              emptys = values.options.filter(op => !(op.Value && op.Text && op.ParentID))
-            }
-            if (emptys.length > 0) {
-              isvalid = false
-            }
-          } else if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '1') {
-            values.options = []
-          }
-
-          if (isvalid) {
-            ['linkField', 'valueField', 'valueText', 'orderBy'].forEach(item => {
-              if (values[item]) {
-                values[item] = values[item].replace(/\s* | \t* | \v* | \r*/ig, '')
-              }
-            })
-
-            let error = Utils.verifySql(values.dataSource)
-
-            if (error) {
-              notification.warning({
-                top: 92,
-                message: '鏁版嵁婧愪腑涓嶅彲浣跨敤' + error,
-                duration: 5
-              })
-              return
-            }
-
-            resolve(values)
-          } else {
-            notification.warning({
-              top: 92,
-              message: this.props.dict['header.form.selectItem.error'],
-              duration: 5
-            })
-          }
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  render() {
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-    return (
-      <Form {...formItemLayout} className="ant-advanced-search-form commontable-search-form" id="commontable-search-form-box">
-        <Row gutter={24}>{this.getFields()}</Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/templates/sharecomponent/chartgroupcomponent/searchform/index.scss b/src/templates/sharecomponent/chartgroupcomponent/searchform/index.scss
deleted file mode 100644
index b027f37..0000000
--- a/src/templates/sharecomponent/chartgroupcomponent/searchform/index.scss
+++ /dev/null
@@ -1,24 +0,0 @@
-.ant-advanced-search-form.commontable-search-form {
-  min-height: 180px;
-  .ant-col-offset-4 {
-    padding-left: 6px!important;
-    padding-bottom: 20px;
-  }
-  // .ant-form-item {
-  //   margin-bottom: 10px;
-  // }
-  .ant-form-item.text-area {
-    margin-bottom: 0px;
-    .ant-form-item-control-wrapper {
-      width: 100%;
-    }
-  }
-  .anticon-question-circle {
-    color: #c49f47;
-    position: relative;
-    left: -3px;
-  }
-  .ant-input-number {
-    width: 100%;
-  }
-}
\ No newline at end of file
diff --git a/src/templates/sharecomponent/searchcomponent/dategroup/index.jsx b/src/templates/sharecomponent/searchcomponent/dategroup/index.jsx
new file mode 100644
index 0000000..37b8769
--- /dev/null
+++ b/src/templates/sharecomponent/searchcomponent/dategroup/index.jsx
@@ -0,0 +1,32 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Tag } from 'antd'
+import './index.scss'
+
+const { CheckableTag } = Tag
+
+class DateGroup extends Component {
+  static propTpyes = {
+    card: PropTypes.object    // 瀛楀吀椤�
+  }
+
+  render() {
+    const { card } = this.props
+    let tabs = {day: '鏃�', week: '鍛�', month: '鏈�', quarter: '瀛�', year: '骞�', customized: '鑷畾涔�'}
+
+    return (
+      <div className="model-date-group">
+        {card.items.map(tab => (
+          <CheckableTag
+            key={tab}
+            checked={card.initval && card.initval.includes(tab)}
+          >
+            {tabs[tab]}
+          </CheckableTag>
+        ))}
+      </div>
+    )
+  }
+}
+
+export default DateGroup
\ No newline at end of file
diff --git a/src/templates/sharecomponent/searchcomponent/dategroup/index.scss b/src/templates/sharecomponent/searchcomponent/dategroup/index.scss
new file mode 100644
index 0000000..2698956
--- /dev/null
+++ b/src/templates/sharecomponent/searchcomponent/dategroup/index.scss
@@ -0,0 +1,31 @@
+.model-date-group {
+  white-space: nowrap;
+  line-height: 40px;
+  position: relative;
+  z-index: 1;
+
+  .ant-tag-checkable {
+    border-color: #d1d5d9;
+    border-radius: 2px;
+    margin-right: 2px;
+    padding: 2px 7px;
+  }
+  .ant-tag-checkable-checked {
+    border-color: #1890ff;
+  }
+}
+
+@media screen and (min-width: 1600px) {
+  .model-date-group {
+    .ant-tag-checkable {
+      padding: 2px 9px;
+    }
+  }
+}
+@media screen and (min-width: 1920px) {
+  .model-date-group {
+    .ant-tag-checkable {
+      padding: 2px 11px;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
index 87b61b3..641505b 100644
--- a/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
+++ b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
@@ -2,6 +2,8 @@
 import { useDrag, useDrop } from 'react-dnd'
 import { Icon, Select, DatePicker, Input } from 'antd'
 import moment from 'moment'
+
+import DateGroup from '../dategroup'
 import './index.scss'
 
 const { MonthPicker, WeekPicker, RangePicker } = DatePicker
@@ -88,6 +90,7 @@
                 value={_defaultValue}
               /> : null
             }
+            {card.type === 'group' ? <DateGroup card={card} /> : null }
             <div className="input-mask"></div>
           </div>
         </div>
diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
index 0281328..8dcf32f 100644
--- a/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
@@ -90,6 +90,15 @@
       let newcard = {}
       newcard.uuid = Utils.getuuid()
       newcard.focus = true
+
+      newcard.label = 'label'
+      newcard.initval = ''
+      newcard.type = item.subType
+      newcard.resourceType = '0'
+      newcard.options = []
+      newcard.setAll = 'false'
+      newcard.orderType = 'asc'
+      newcard.display = 'dropdown'
       
       let _match = 'like'
       if (item.subType === 'select' || item.subType === 'link') {
@@ -98,17 +107,12 @@
         _match = '>='
       } else if (item.subType === 'dateweek' || item.subType === 'daterange') {
         _match = 'between'
+      } else if (item.subType === 'group') {
+        _match = 'between'
+        newcard.items = ['day', 'week', 'month', 'quarter', 'year', 'customized']
       }
       
-      newcard.label = 'label'
-      newcard.initval = ''
-      newcard.type = item.subType
-      newcard.resourceType = '0'
-      newcard.options = []
-      newcard.setAll = 'false'
-      newcard.orderType = 'asc'
       newcard.match = _match
-      newcard.display = 'dropdown'
       
       let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
       if (target) {
diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx
index 81d0380..df45ed6 100644
--- a/src/templates/sharecomponent/searchcomponent/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/index.jsx
@@ -126,7 +126,27 @@
 
       _searchlist = _searchlist.map(item => { // 鏁版嵁鏇存柊鍙婇噸澶嶆娴�
         if (item.uuid !== res.uuid && res.field && item.field) {
-          if (item.field === res.field) {
+          let itemFields = []
+          if (item.type === 'text') {
+            itemFields = item.field.split(',')
+          } else if (item.type === 'group') {
+            itemFields = [item.field, item.datefield]
+          } else {
+            itemFields = [item.field]
+          }
+
+          let resFields = []
+          if (res.type === 'text') {
+            resFields = res.field.split(',')
+          } else if (res.type === 'group') {
+            resFields = [res.field, res.datefield]
+          } else {
+            resFields = [res.field]
+          }
+
+          let setFields = Array.from(new Set([...itemFields, ...resFields]))
+
+          if (setFields.length < itemFields.length + resFields.length && (res.type !== 'date' || item.type !== 'date')) {
             fieldrepet = true
           } else if (item.label === res.label) {
             labelrepet = true
@@ -264,7 +284,7 @@
         <Modal
           title={dict['model.searchCriteria'] + '-' + (card && card.copyType === 'search' ?  dict['model.copy'] : dict['model.edit'])}
           visible={visible}
-          width={750}
+          width={850}
           maskClosable={false}
           onOk={this.handleSubmit}
           confirmLoading={sqlVerifing}
diff --git a/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx b/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx
index 8abe02b..cfb435a 100644
--- a/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx
@@ -112,9 +112,18 @@
         dataIndex: 'operation',
         render: (text, record) =>
           this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
+            <div>
+              <span className="operation-btn" title={props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+              <span className="operation-btn" title={props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+              <Popconfirm
+                title={props.dict['header.form.query.delete']}
+                okText={props.dict['model.confirm']}
+                cancelText={props.dict['header.cancel']}
+                onConfirm={() => this.handleDelete(record.key)
+              }>
+                <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
+              </Popconfirm>
+            </div>
           ) : null,
       }
     ]
@@ -134,6 +143,32 @@
       count: props.data.length,
       type: props.type
     }
+  }
+
+  handleUpDown = (record, direction) => {
+    const { dataSource } = this.state
+    let index = 0
+
+    let _data = dataSource.filter((item, i) => {
+      if (item.key === record.key) {
+        index = i
+      }
+
+      return item.key !== record.key
+    })
+    if ((index === 0 && direction === 'up') || (index === dataSource.length - 1 && direction === 'down')) {
+      return
+    }
+
+    if (direction === 'up') {
+      _data.splice(index - 1, 0, record)
+    } else {
+      _data.splice(index + 1, 0, record)
+    }
+
+    this.setState({
+      dataSource: _data
+    })
   }
 
   handleDelete = key => {
@@ -188,9 +223,18 @@
         dataIndex: 'operation',
         render: (text, record) =>
           this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
+            <div>
+              <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+              <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+              <Popconfirm
+                title={this.props.dict['header.form.query.delete']}
+                okText={this.props.dict['model.confirm']}
+                cancelText={this.props.dict['header.cancel']}
+                onConfirm={() => this.handleDelete(record.key)
+              }>
+                <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
+              </Popconfirm>
+            </div>
           ) : null,
       }
     ]
@@ -245,7 +289,7 @@
       }
     })
     return (
-      <div className="common-modal-edit-table">
+      <div className="model-search-edit-table">
         <Button onClick={this.handleAdd} type="primary" className="add-row">
           Add
         </Button>
diff --git a/src/templates/sharecomponent/searchcomponent/searcheditable/index.scss b/src/templates/sharecomponent/searchcomponent/searcheditable/index.scss
index f8f0942..26b012b 100644
--- a/src/templates/sharecomponent/searchcomponent/searcheditable/index.scss
+++ b/src/templates/sharecomponent/searchcomponent/searcheditable/index.scss
@@ -1,4 +1,4 @@
-.common-modal-edit-table {
+.model-search-edit-table {
   .add-row {
     position: absolute;
     z-index: 1;
@@ -33,4 +33,8 @@
       margin: 0;
     }
   }
+  .operation-btn {
+    margin-right: 10px;
+    cursor: pointer;
+  }
 }
diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
index e7941ec..f6c62a0 100644
--- a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -1,12 +1,85 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber } from 'antd'
+import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber, Checkbox, Cascader } from 'antd'
 import { dateOptions, matchReg, formRule } from '@/utils/option.js'
 import EditTable from '../searcheditable'
 import Utils from '@/utils/utils.js'
 import './index.scss'
 
 const { TextArea } = Input
+
+const groupOptions = [
+  {
+    value: 'day',
+    label: '鏃�',
+    children: [
+      {value: '0', label: '褰撳ぉ'},
+      {value: 1, label: '鏄ㄥぉ'},
+      {value: 2, label: '鍓嶅ぉ'},
+      {value: 3, label: '鍓嶄笁澶�'},
+      {value: 7, label: '鍓嶄竷澶�'},
+      {value: 30, label: '鍓�30澶�'},
+      {value: -1, label: '鏄庡ぉ'},
+      {value: -2, label: '鍚庡ぉ'}
+    ]
+  },
+  {
+    value: 'week',
+    label: '鍛�',
+    children: [
+      {value: '0', label: '鏈懆'},
+      {value: 1, label: '涓婂懆'},
+      {value: 3, label: '鍓嶄笁鍛�'},
+      {value: 7, label: '鍓嶄竷鍛�'},
+      {value: -1, label: '涓嬪懆'}
+    ]
+  },
+  {
+    value: 'month',
+    label: '鏈�',
+    children: [
+      {value: '0', label: '鏈湀'},
+      {value: 1, label: '涓婃湀'},
+      {value: 3, label: '鍓嶄笁鏈�'},
+      {value: 7, label: '鍓嶄竷鏈�'},
+      {value: -1, label: '涓嬫湀'}
+    ]
+  },
+  {
+    value: 'quarter',
+    label: '瀛�',
+    children: [
+      {value: '0', label: '鏈搴�'},
+      {value: 1, label: '涓婂搴�'},
+      {value: -1, label: '涓嬪搴�'}
+    ]
+  },
+  {
+    value: 'year',
+    label: '骞�',
+    children: [
+      {value: '0', label: '鏈勾'},
+      {value: 1, label: '鍘诲勾'},
+      {value: -1, label: '鏄庡勾'}
+    ]
+  },
+  {
+    value: 'customized',
+    label: '鑷畾涔�',
+    children: [
+      {value: '[0, 0]', label: '浠婂ぉ'},
+      {value: '[1, 1]', label: '鏄ㄥぉ'},
+      {value: '[3, 0]', label: '杩戜笁澶�'},
+      {value: '[7, 0]', label: '杩戜竷澶�'},
+      {value: '[30, 0]', label: '杩�30澶�'},
+      {value: '[7, -7]', label: '鍓嶅悗涓冨ぉ'},
+      {value: '[30, -30]', label: '鍓嶅悗30澶�'},
+      {value: '[90, -90]', label: '鍓嶅悗90澶�'},
+      {value: '[-1, -1]', label: '鏄庡ぉ'},
+      {value: '[-2, -2]', label: '鍚庡ぉ'}
+    ]
+  },
+]
 
 class MainSearch extends Component {
   static propTpyes = {
@@ -20,7 +93,8 @@
   state = {
     openType: null,          // 鎼滅储鏉′欢鏄剧ず绫诲瀷
     resourceType: null,      // 涓嬫媺鎼滅储鏃讹紝閫夐」鏉ユ簮绫诲瀷
-    formlist: null           // 琛ㄥ崟
+    formlist: null,          // 琛ㄥ崟
+    textTooltip: '瀛楁鍚嶅彲浠ヤ娇鐢ㄩ�楀彿鍒嗛殧锛岃繘琛岀患鍚堟悳绱�',
   }
 
   /**
@@ -29,9 +103,10 @@
    * 2銆佷笅鎷夐�夋嫨锛屾牴鎹暟鎹簮绫诲瀷鏄剧ず鐩稿叧閰嶇疆
    */
   UNSAFE_componentWillMount () {
-    const { formlist, optionLibs } = this.props
+    const { formlist, optionLibs, dict } = this.props
 
     let type = formlist.filter(cell => cell.key === 'type')[0].initVal
+    let _items = formlist.filter(cell => cell.key === 'items')[0].initVal
     let resourceType = formlist.filter(cell => cell.key === 'resourceType')[0].initVal
     let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required']                // 榛樿鏄剧ず椤�
 
@@ -39,6 +114,8 @@
       _options = [..._options, 'resourceType', 'options', 'display', 'quick']
     } else if ((type === 'multiselect' || type === 'select' || type === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙�
       _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database']
+    } else if (type === 'group') {
+      _options = ['label', 'type', 'field', 'datefield', 'initval', 'blacklist', 'ratio', 'items', 'required', 'transfer']
     }
 
     if (type === 'select' || type === 'link') {
@@ -51,15 +128,17 @@
     
     this.setState({
       openType: type,
+      items: _items,
       resourceType: resourceType,
       formlist: formlist.map(form => {
         // 琛ㄥ崟涓哄垵濮嬪�煎瓧娈碉紝涓旀暟鎹被鍨嬪睘浜庢椂闂寸被鍨嬫椂锛岃缃垵濮嬪�间负涓嬫媺閫夋嫨锛屽苟閲嶇疆閫夋嫨椤�
         if (form.key === 'initval' && dateOptions.hasOwnProperty(type)) {
           form.options = dateOptions[type]
           form.type = 'select'
-        }
-        // 琛ㄥ崟涓哄尮閰嶅瓧娈垫椂锛屾牴鎹笉鍚岀殑绫诲瀷锛屾樉绀哄搴旂殑鍖归厤瑙勫垯
-        if (form.key === 'match') {
+        } else if (form.key === 'initval' && type === 'group') {
+          form.options = groupOptions.filter(op => _items.includes(op.value))
+          form.type = 'cascader'
+        } else if (form.key === 'match') { // 琛ㄥ崟涓哄尮閰嶅瓧娈垫椂锛屾牴鎹笉鍚岀殑绫诲瀷锛屾樉绀哄搴旂殑鍖归厤瑙勫垯
           if (type === 'text') {
             form.options = matchReg.text
           } else if (type === 'multiselect') {
@@ -80,6 +159,10 @@
               text: cell.label + '(' + cell.parname + ')'
             }
           })
+        } else if (form.key === 'field' && type === 'text') {
+          form.tooltip = this.state.textTooltip
+        } else if (form.key === 'field' && type === 'group') {
+          form.label = dict['header.form.type'] + dict['header.form.field']
         }
         form.hidden = !_options.includes(form.key)
         return form
@@ -104,7 +187,8 @@
    * @description 鎼滅储鏉′欢绫诲瀷鍒囨崲
    */
   openTypeChange = (key, value) => {
-    const { resourceType } = this.state
+    const { dict } = this.props
+    const { resourceType, items } = this.state
 
     if (key === 'type') {
       let _options = ['label', 'field', 'initval', 'type', 'match', 'ratio', 'blacklist', 'required']
@@ -113,6 +197,8 @@
         _options = [..._options, 'resourceType', 'options', 'display', 'quick']
       } else if ((value === 'multiselect' || value === 'select' || value === 'link') && resourceType === '1') { // 涓嬫媺閫夋嫨绫诲瀷銆侀�夐」涓哄悗鍙版暟鎹簮涓幏鍙�
         _options = [..._options, 'resourceType', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display', 'database']
+      } else if (value === 'group') {
+        _options = ['label', 'type', 'field', 'datefield', 'initval', 'items', 'ratio', 'blacklist', 'required', 'transfer']
       }
 
       if (value === 'select' || value === 'link') {
@@ -123,6 +209,8 @@
         _options = [..._options, 'linkField']
       }
 
+      let matchs = []
+
       this.setState({
         openType: value,
         formlist: this.state.formlist.map(form => {
@@ -132,11 +220,12 @@
             if (dateOptions.hasOwnProperty(value)) { // 鏍规嵁鎼滅储鏉′欢绫诲瀷锛岄�夋嫨鍒濆鍊肩殑绫诲瀷鍙婃暟鎹�
               form.options = dateOptions[value]
               form.type = 'select'
+            } else if (value === 'group') {
+              form.options = groupOptions.filter(op => items.includes(op.value))
+              form.type = 'cascader'
             } else {
               form.type = 'text'
             }
-            form.initVal = ''                                    // 鎼滅储鏉′欢绫诲瀷鍒囨崲鏃讹紝鍒濆鍊肩疆绌�
-            form.hidden = true
           } else if (form.key === 'match') {                     // 鎼滅储鏉′欢绫诲瀷鍒囨崲鏃讹紝鍖归厤瑙勫垯绫诲瀷瀵瑰簲鍒囨崲
             if (value === 'text') {
               form.options = matchReg.text
@@ -151,33 +240,34 @@
             } else if (value === 'dateweek' || value === 'daterange') {
               form.options = matchReg.daterange
             }
-            form.hidden = true
+            matchs = form.options
+          } else if (form.key === 'field') {
+            form.tooltip = ''
+            form.label = dict['header.form.field']
+            if (value === 'text') {
+              form.tooltip = this.state.textTooltip
+            } else if (value === 'group') {
+              form.label = dict['header.form.type'] + dict['header.form.field']
+            }
           }
 
           return form
         })
       }, () => {
-        this.setState({
-          formlist: this.state.formlist.map(form => {
-
-            if (form.key === 'initval') {
-              form.hidden = false
-            } else if (form.key === 'match') {
-              form.initVal = form.options[0].value
-              form.hidden = false
-            }
-
-            return form
-          })
-        })
+        if (this.props.form.getFieldValue('initval') !== undefined) {
+          this.props.form.setFieldsValue({initval: ''})
+        }
+        if (this.props.form.getFieldValue('match') !== undefined) {
+          this.props.form.setFieldsValue({match: matchs[0].value})
+        }
       })
     } else if (key === 'quick') {
-      let option = this.props.optionLibs.get(value)
+      let _option = this.props.optionLibs.get(value)
 
       this.setState({
         formlist: this.state.formlist.map(form => {
           if (form.key === 'options') {
-            form.initVal = option.options
+            form.initVal = _option.options
           }
 
           return form
@@ -220,6 +310,26 @@
     }
   }
 
+  checkChange = (values, key) => {
+    const { openType, formlist } = this.state
+
+    if (key === 'items') {
+      this.setState({
+        items: values,
+        formlist: formlist.map(form => {
+          if (form.key === 'initval' && openType === 'group') {
+            form.options = groupOptions.filter(op => values.includes(op.value))
+          }
+
+          return form
+        })
+      })
+      if (this.props.form.getFieldValue('initval') !== undefined) {
+        this.props.form.setFieldsValue({initval: ''})
+      }
+    }
+  }
+
   handleSubmit = (e) => {
     e.preventDefault()
 
@@ -229,6 +339,7 @@
   }
 
   getFields() {
+    const { openType } = this.state
     const { getFieldDecorator } = this.props.form
     const fields = []
     this.state.formlist.forEach((item, index) => {
@@ -236,9 +347,9 @@
 
       if (item.type === 'text') { // 鏂囨湰鎼滅储
         let rules = []
-        if (item.key === 'field') {
+        if (item.key === 'field' || item.key === 'datefield') {
           rules = [{
-            pattern: formRule.field.pattern,
+            pattern: openType === 'text' ? formRule.field.multipattern : formRule.field.pattern,
             message: formRule.field.message
           }, {
             max: formRule.field.max,
@@ -325,7 +436,12 @@
       } else if (item.type === 'radio') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.label}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -367,7 +483,25 @@
       } else if (item.type === 'options') {
         fields.push(
           <Col span={20} offset={4} key={index}>
-            <EditTable data={item.initVal} type={this.state.openType} ref="editTable"/>
+            <EditTable data={item.initVal} type={this.state.openType} dict={this.props.dict} ref="editTable"/>
+          </Col>
+        )
+      } else if (item.type === 'checkbox') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Checkbox.Group style={{width: '105%'}} options={item.options} onChange={(values) => this.checkChange(values, item.key)}/>
+              )}
+            </Form.Item>
           </Col>
         )
       } else if (item.type === 'multiselect') { // 澶氶��
@@ -386,6 +520,18 @@
                     <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option>
                   )}
                 </Select>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'cascader') { // 澶氶��
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal
+              })(
+                <Cascader options={item.options} placeholder="" />
               )}
             </Form.Item>
           </Col>
@@ -465,7 +611,7 @@
       }
     }
     return (
-      <Form {...formItemLayout} className="ant-advanced-search-form commontable-search-form" id="commontable-search-form-box">
+      <Form {...formItemLayout} className="model-search-edit-form" id="commontable-search-form-box">
         <Row gutter={24}>{this.getFields()}</Row>
       </Form>
     )
diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.scss b/src/templates/sharecomponent/searchcomponent/searchform/index.scss
index b027f37..7afdc2a 100644
--- a/src/templates/sharecomponent/searchcomponent/searchform/index.scss
+++ b/src/templates/sharecomponent/searchcomponent/searchform/index.scss
@@ -1,12 +1,9 @@
-.ant-advanced-search-form.commontable-search-form {
+.model-search-edit-form {
   min-height: 180px;
   .ant-col-offset-4 {
     padding-left: 6px!important;
     padding-bottom: 20px;
   }
-  // .ant-form-item {
-  //   margin-bottom: 10px;
-  // }
   .ant-form-item.text-area {
     margin-bottom: 0px;
     .ant-form-item-control-wrapper {
@@ -21,4 +18,12 @@
   .ant-input-number {
     width: 100%;
   }
+  .ant-checkbox-group {
+    .ant-checkbox-group-item {
+      .ant-checkbox + span {
+        padding-left: 4px;
+        padding-right: 4px;
+      }
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/customscript/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/customscript/index.jsx
index ad8097e..b606b5a 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/customscript/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/customscript/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Button, notification, Modal, Menu, Icon, Radio, Dropdown } from 'antd'
+import { Form, Row, Col, Input, Button, notification, Modal, Select, Radio } from 'antd'
 import moment from 'moment'
 
 import Utils from '@/utils/utils.js'
@@ -129,11 +129,7 @@
     })
   }
 
-  selectScript = (e) => {
-    const { systemScripts } = this.props
-
-    let option = systemScripts[+e.key]
-
+  selectScript = (value, option) => {
     let _sql = this.props.form.getFieldValue('sql')
     if (_sql) {
       _sql = _sql + ` 
@@ -142,10 +138,10 @@
     }
 
     _sql = _sql.replace(/\s{6}$/, '')
-    _sql = _sql + `/*${option.name}*/
+    _sql = _sql + `/*${option.props.children}*/
     `
     _sql = _sql.replace(/\s{4}$/, '')
-    _sql = _sql + option.value
+    _sql = _sql + value
 
     this.props.form.setFieldsValue({
       sql: _sql
@@ -169,6 +165,16 @@
     return (
       <Form {...formItemLayout} className="modal-menu-setting-script">
         <Row gutter={24}>
+          {tableName ? <Col span={8}>
+            <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
+              {tableName}
+            </Form.Item>
+          </Col> : null}
+          <Col span={16}>
+            <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0}}>
+              errorCode, errmsg
+            </Form.Item>
+          </Col>
           <Col span={24} className="sqlfield">
             <Form.Item label={'鍙敤瀛楁'}>
               id, bid, loginuid, sessionuid, userid, appkey
@@ -186,28 +192,23 @@
               )}
             </Form.Item>
           </Col>
-          <Col span={4} style={{lineHeight: '40px', textAlign: 'center'}}>
-            <Dropdown trigger={['click']} overlayClassName="mk-normal-dropdown" overlay={
-              <Menu onClick={this.selectScript}>
+          <Col span={10}>
+            <Form.Item label={'蹇嵎娣诲姞'} style={{marginBottom: 0}}>
+              <Select
+                showSearch
+                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                onChange={this.selectScript}
+              >
                 {systemScripts.map((option, i) =>
-                  <Menu.Item key={i}>{option.name}</Menu.Item>
+                  <Select.Option style={{whiteSpace: 'normal'}} key={i} value={option.value}>{option.name}</Select.Option>
                 )}
-              </Menu>
-            }>
-              <span style={{color: '#1890ff', display: 'inline-block', cursor: 'pointer'}}>
-                蹇嵎娣诲姞 <Icon type="down" style={{marginRight: '5px'}} />
-              </span>
-            </Dropdown>
+              </Select>
+            </Form.Item>
           </Col>
           <Col span={4} className="add">
             <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
               淇濆瓨
             </Button>
-          </Col>
-          <Col span={8} style={{textAlign: 'right'}}>
-            {tableName ? <span style={{maxWidth: '100%', display: 'inline-block', position: 'relative', top: '20px', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden'}}>
-              琛ㄥ悕:  {tableName}
-            </span> : null}
           </Col>
           <Col span={24} className="sql">
             <Form.Item label={'sql'}>
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
index 77f999a..2c73e0c 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
@@ -26,7 +26,10 @@
     formlist: [],
     setting: null,
     view: 'normal',
-    systemScripts: [],
+    systemScripts: [{
+      name: '榛樿sql',
+      value: ''
+    }],
     scriptsColumns: [
       {
         title: 'SQL',
@@ -138,23 +141,17 @@
     
     Api.getSystemConfig(_sParam).then(res => {
       if (res.status) {
-        let _scripts = []
-
-        _scripts.push({
-          name: '榛樿sql',
-          value: ''
-        })
-
-        res.data.forEach(item => {
+        let _scripts = res.data.map(item => {
           let _item = {
             name: item.funcname,
             value: Utils.formatOptions(item.longparam, true)
           }
-          _scripts.push(_item)
+
+          return _item
         })
 
         this.setState({
-          systemScripts: _scripts
+          systemScripts: [...this.state.systemScripts, ..._scripts]
         })
       } else {
         notification.warning({
diff --git a/src/templates/subtableconfig/index.jsx b/src/templates/subtableconfig/index.jsx
index 2747162..87766f5 100644
--- a/src/templates/subtableconfig/index.jsx
+++ b/src/templates/subtableconfig/index.jsx
@@ -267,8 +267,17 @@
   submitConfig = () => {
     const { delActions, thawButtons, originConfig } = this.state
     let config = JSON.parse(JSON.stringify(this.state.config))
+    let copyreg = /\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}$/ig
 
     this.menuformRef.handleConfirm().then(res => {
+      if (copyreg.test(res.MenuNo) || copyreg.test(res.MenuName)) {
+        notification.warning({
+          top: 92,
+          message: '璇蜂慨鏀规爣绛惧悕绉板拰鏍囩鍙傛暟锛屼笉鍙互鏃堕棿鏍煎紡 YYYY-MM-DD HH:mm:ss 缁撳熬锛�',
+          duration: 5
+        })
+        return
+      }
 
       if (originConfig.isAdd) {
         if (config.search[0] && config.search[0].origin) {
diff --git a/src/templates/subtableconfig/index.scss b/src/templates/subtableconfig/index.scss
index 09c3b52..f259da6 100644
--- a/src/templates/subtableconfig/index.scss
+++ b/src/templates/subtableconfig/index.scss
@@ -25,7 +25,7 @@
     .ant-collapse-item.ant-collapse-item-active {
       border-bottom: 1px solid #d9d9d9;
     }
-    .ant-collapse-header {
+    .ant-collapse .ant-collapse-header {
       padding: 11px 16px 10px 40px;
       border-bottom: 1px solid #d9d9d9;
       background: #1890ff;
diff --git a/src/templates/subtableconfig/source.jsx b/src/templates/subtableconfig/source.jsx
index ba636c4..f45159d 100644
--- a/src/templates/subtableconfig/source.jsx
+++ b/src/templates/subtableconfig/source.jsx
@@ -184,39 +184,57 @@
   searchItems = [
     {
       type: 'search',
-      label: '鏂囨湰妗�',
+      label: CommonDict['header.form.text'],
       subType: 'text',
       url: ''
     },
     {
       type: 'search',
-      label: '涓嬫媺妗�',
+      label: CommonDict['header.form.select'],
       subType: 'select',
       url: ''
     },
     {
       type: 'search',
-      label: '鏃堕棿妗嗭紙澶╋級',
+      label: CommonDict['header.form.multiselect'],
+      subType: 'multiselect',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: CommonDict['header.form.link'],
+      subType: 'link',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: CommonDict['header.form.dateday'],
       subType: 'date',
       url: ''
     },
     {
       type: 'search',
-      label: '鏃堕棿妗嗭紙鍛級',
+      label: CommonDict['header.form.dateweek'],
       subType: 'dateweek',
       url: ''
     },
     {
       type: 'search',
-      label: '鏃堕棿妗嗭紙鏈堬級',
+      label: CommonDict['header.form.datemonth'],
       subType: 'datemonth',
       url: ''
     },
     {
       type: 'search',
-      label: '鏃堕棿妗嗭紙鍖洪棿锛�',
+      label: CommonDict['header.form.daterange'],
       subType: 'daterange',
       url: ''
+    },
+    {
+      type: 'search',
+      label: '鏃ユ湡锛堢粍鍚堬級',
+      subType: 'group',
+      url: ''
     }
   ]
 
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index 28f3662..5150a76 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -357,7 +357,6 @@
       key: 'field',
       label: Formdict['header.form.field'],
       initVal: card.field || '',
-      tooltip: '瀛楁鍚嶅彲浠ヤ娇鐢ㄩ�楀彿鍒嗛殧锛岃繘琛屽瀛楁缁煎悎鎼滅储锛屾敞锛氱患鍚堟悳绱粎鍦ㄦ枃鏈被鍨嬫椂鏈夋晥',
       tooltipClass: 'middle',
       required: true,
       readonly: false
@@ -392,7 +391,18 @@
       }, {
         value: 'daterange',
         text: Formdict['header.form.daterange']
+      }, {
+        value: 'group',
+        text: '鏃ユ湡锛堢粍鍚堬級'
       }]
+    },
+    {
+      type: 'text',
+      key: 'datefield',
+      label: '鏃堕棿瀛楁',
+      initVal: card.datefield || '',
+      required: true,
+      readonly: false
     },
     {
       type: 'text',
@@ -443,6 +453,33 @@
       initVal: card.options || [],
       required: true,
       readonly: false
+    },
+    {
+      type: 'checkbox',
+      key: 'items',
+      label: '閫夐」',
+      initVal: card.items || ['day', 'week', 'month', 'quarter', 'year', 'customized'],
+      required: true,
+      readonly: false,
+      options: [{
+        value: 'day',
+        label: '鏃�'
+      }, {
+        value: 'week',
+        label: '鍛�'
+      }, {
+        value: 'month',
+        label: '鏈�'
+      }, {
+        value: 'quarter',
+        label: '瀛�'
+      }, {
+        value: 'year',
+        label: '骞�'
+      }, {
+        value: 'customized',
+        label: '鑷�'
+      }]
     },
     {
       type: 'text',
@@ -577,6 +614,20 @@
       initVal: card.blacklist || [],
       required: false,
       options: roleList || []
+    },
+    {
+      type: 'radio',
+      key: 'transfer',
+      label: '浼犻��',
+      initVal: card.transfer || 'false',
+      tooltip: '鏁版嵁鏌ヨ鏃讹紝绫诲瀷瀛楁鏄惁浣滀负鍙傛暟浼犻�掋��',
+      options: [{
+        value: 'true',
+        text: Formdict['header.form.true']
+      }, {
+        value: 'false',
+        text: Formdict['header.form.false']
+      }]
     }
   ]
 }
diff --git a/src/templates/zshare/verifycard/customscript/index.jsx b/src/templates/zshare/verifycard/customscript/index.jsx
index b1fabe2..04781fd 100644
--- a/src/templates/zshare/verifycard/customscript/index.jsx
+++ b/src/templates/zshare/verifycard/customscript/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Button, notification, Modal, Menu, Tooltip, Icon, Radio, Dropdown } from 'antd'
+import { Form, Row, Col, Input, Button, notification, Modal, Tooltip, Icon, Radio, Select } from 'antd'
 import moment from 'moment'
 
 import Utils from '@/utils/utils.js'
@@ -131,11 +131,7 @@
     })
   }
 
-  selectScript = (e) => {
-    const { systemScripts } = this.props
-
-    let option = systemScripts[+e.key]
-
+  selectScript = (value, option) => {
     let _sql = this.props.form.getFieldValue('sql')
     if (_sql) {
       _sql = _sql + ` 
@@ -144,10 +140,10 @@
     }
 
     _sql = _sql.replace(/\s{6}$/, '')
-    _sql = _sql + `/*${option.name}*/
+    _sql = _sql + `/*${option.props.children}*/
     `
     _sql = _sql.replace(/\s{4}$/, '')
-    _sql = _sql + option.value
+    _sql = _sql + value
 
     this.props.form.setFieldsValue({
       sql: _sql
@@ -169,8 +165,18 @@
     }
 
     return (
-      <Form {...formItemLayout} className="verify-form" id="verifycard2">
+      <Form {...formItemLayout} className="verify-form" id="verify-custom-scripts">
         <Row gutter={24}>
+          {btn.sql ? <Col span={8}>
+            <Form.Item label={'琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
+              {btn.sql}
+            </Form.Item>
+          </Col> : null}
+          <Col span={16}>
+            <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0}}>
+              errorCode, errmsg
+            </Form.Item>
+          </Col>
           {usefulfields ? <Col span={24} className="sqlfield">
             <Form.Item label={'鍙敤瀛楁'}>
               {usefulfields}
@@ -194,28 +200,24 @@
               )}
             </Form.Item>
           </Col>
-          <Col span={4} style={{lineHeight: '40px', textAlign: 'center'}}>
-            <Dropdown trigger={['click']} overlayClassName="mk-normal-dropdown" overlay={
-              <Menu onClick={this.selectScript}>
+          <Col span={10}>
+            <Form.Item label={'蹇嵎娣诲姞'} style={{marginBottom: 0}}>
+              <Select
+                showSearch
+                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                onChange={this.selectScript}
+                getPopupContainer={() => document.getElementById('verify-custom-scripts')}
+              >
                 {systemScripts.map((option, i) =>
-                  <Menu.Item key={i}>{option.name}</Menu.Item>
+                  <Select.Option key={i} value={option.value}>{option.name}</Select.Option>
                 )}
-              </Menu>
-            }>
-              <span style={{color: '#1890ff', display: 'inline-block', cursor: 'pointer'}}>
-                蹇嵎娣诲姞 <Icon type="down" style={{marginRight: '5px'}} />
-              </span>
-            </Dropdown>
+              </Select>
+            </Form.Item>
           </Col>
           <Col span={4} className="add">
             <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
               淇濆瓨
             </Button>
-          </Col>
-          <Col span={8} style={{textAlign: 'right'}}>
-            {btn.sql ? <span style={{maxWidth: '100%', display: 'inline-block', position: 'relative', top: '20px', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden'}}>
-              琛ㄥ悕:  {btn.sql}
-            </span> : null}
           </Col>
           <Col span={24} className="sql">
             <Form.Item label={'sql'}>
diff --git a/src/templates/zshare/verifycard/customscript/index.scss b/src/templates/zshare/verifycard/customscript/index.scss
index e69de29..89791c7 100644
--- a/src/templates/zshare/verifycard/customscript/index.scss
+++ b/src/templates/zshare/verifycard/customscript/index.scss
@@ -0,0 +1,5 @@
+#verify-custom-scripts {
+  .ant-select-dropdown-menu-item {
+    white-space: normal;
+  }
+}
\ No newline at end of file
diff --git a/src/utils/option.js b/src/utils/option.js
index 21e3eea..0315a31 100644
--- a/src/utils/option.js
+++ b/src/utils/option.js
@@ -19,7 +19,8 @@
   },
   field: { // 瀛楁鍚�
     max: 50,
-    pattern: /^[\u4E00-\u9FA50-9a-zA-Z,_-]*$/ig,
+    pattern: /^[\u4E00-\u9FA50-9a-zA-Z_-]*$/ig,
+    multipattern: /^[\u4E00-\u9FA50-9a-zA-Z,_-]*$/ig,
     message: '瀛楁鍚嶅彧鍏佽鍖呭惈鏁板瓧銆佸瓧姣嶃�佹眽瀛椾互鍙奯-',
     maxMessage: '瀛楁鍚嶆渶澶�50涓瓧绗︺��'
   },
@@ -74,24 +75,29 @@
   date: [
     {value: '', text: _dict['date.empty']},
     {value: '0', text: '褰撳ぉ'},
-    {value: 1, text: '鍓嶄竴澶�'},
+    {value: 1, text: '鏄ㄥぉ'},
+    {value: 2, text: '鍓嶅ぉ'},
     {value: 3, text: '鍓嶄笁澶�'},
     {value: 7, text: '鍓嶄竷澶�'},
-    {value: 30, text: '鍓�30澶�'}
+    {value: 30, text: '鍓�30澶�'},
+    {value: -1, text: '鏄庡ぉ'},
+    {value: -2, text: '鍚庡ぉ'}
   ],
   dateweek: [
     {value: '', text: _dict['date.empty']},
     {value: '0', text: '鏈懆'},
     {value: 1, text: '涓婂懆'},
     {value: 3, text: '鍓嶄笁鍛�'},
-    {value: 7, text: '鍓嶄竷鍛�'}
+    {value: 7, text: '鍓嶄竷鍛�'},
+    {value: -1, text: '涓嬪懆'}
   ],
   datemonth: [
     {value: '', text: _dict['date.empty']},
     {value: '0', text: '鏈湀'},
     {value: 1, text: '涓婃湀'},
     {value: 3, text: '鍓嶄笁鏈�'},
-    {value: 7, text: '鍓嶄竷鏈�'}
+    {value: 7, text: '鍓嶄竷鏈�'},
+    {value: -1, text: '涓嬫湀'}
   ],
   daterange: [
     {value: '', text: _dict['date.empty']},
@@ -102,7 +108,9 @@
     {value: '[30, 0]', text: '杩�30澶�'},
     {value: '[7, -7]', text: '鍓嶅悗涓冨ぉ'},
     {value: '[30, -30]', text: '鍓嶅悗30澶�'},
-    {value: '[90, -90]', text: '鍓嶅悗90澶�'}
+    {value: '[90, -90]', text: '鍓嶅悗90澶�'},
+    {value: '[-1, -1]', text: '鏄庡ぉ'},
+    {value: '[-2, -2]', text: '鍚庡ぉ'}
   ],
   datetime: [
     {value: '', text: _dict['date.empty']},
@@ -110,7 +118,9 @@
     {value: 1, text: '鏄ㄥぉ'},
     {value: 3, text: '鍓嶄笁澶�'},
     {value: 7, text: '鍓嶄竷澶�'},
-    {value: 30, text: '鍓�30澶�'}
+    {value: 30, text: '鍓�30澶�'},
+    {value: -1, text: '鏄庡ぉ'},
+    {value: -2, text: '鍚庡ぉ'}
   ]
 }
 
diff --git a/src/utils/utils.js b/src/utils/utils.js
index a08f503..18a6ed2 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -193,7 +193,75 @@
         value: search.initval,
         required: search.required === 'true'
       }
-      if (item.type === 'date') {
+
+      if (item.type === 'group') {
+        let copy = JSON.parse(JSON.stringify(item))
+        copy.key = search.datefield
+
+        item.value = search.initval && search.initval[0] ? search.initval[0] : ''
+        item.match = '='
+        
+        copy.type = 'daterange'
+        copy.match = 'between'
+        copy.value = ''
+
+        if (search.initval && search.initval.length > 0) {
+          let _type = search.initval[0]
+          let _val = search.initval[1]
+
+          if (_type === 'day') {
+            copy.value = [moment().subtract(_val, 'days').format('YYYY-MM-DD'),
+              moment().subtract(_val, 'days').format('YYYY-MM-DD')]
+          } else if (_type === 'week') {
+            copy.value = [moment().subtract(_val * 7, 'days').startOf('week').format('YYYY-MM-DD'),
+              moment().subtract(_val * 7, 'days').endOf('week').format('YYYY-MM-DD')]
+          } else if (_type === 'month') {
+            copy.value = [moment().subtract(_val, 'month').startOf('month').format('YYYY-MM-DD'),
+              moment().subtract(_val, 'month').endOf('month').format('YYYY-MM-DD')]
+          } else if (_type === 'quarter') {
+            let _differ = parseInt(moment().format('MM')) % 3
+            let _pdiffer = 0
+            let _ndiffer = 0
+
+            // 宸�艰绠�
+            switch(_differ) {
+              case 0:
+                _pdiffer = 2
+                _ndiffer = 0
+                break
+              case 1:
+                _pdiffer = 0
+                _ndiffer = -2
+                break
+              case 2:
+                _pdiffer = 1
+                _ndiffer = -1
+                break
+              default:
+            }
+
+            copy.value = [moment().subtract(_pdiffer + _val * 3, 'month').startOf('month').format('YYYY-MM-DD'),
+              moment().subtract(_ndiffer + _val * 3, 'month').endOf('month').format('YYYY-MM-DD')]
+          } else if (_type === 'year') {
+            let _year = parseInt(moment().format('YYYY')) - _val
+            copy.value = [_year + '-01-01', _year + '-12-31']
+          } else if (_type === 'customized') {
+            try {
+              _val = JSON.parse(_val)
+            } catch {
+              _val = [0, 0]
+            }
+            copy.value = [moment().subtract(_val[0], 'days').format('YYYY-MM-DD'),
+              moment().subtract(_val[1], 'days').format('YYYY-MM-DD')]
+          }
+        }
+
+        if (search.transfer === 'true') {
+          newsearches.push(item)
+        }
+        newsearches.push(copy)
+        return
+      } else if (item.type === 'date') {
         item.value = item.value ? moment().subtract(item.value, 'days').format('YYYY-MM-DD') : ''
       } else if (item.type === 'datemonth') {
         item.value = item.value ? moment().subtract(item.value, 'month').format('YYYY-MM') : ''

--
Gitblit v1.8.0