king
2020-05-08 2031a460f6c0827fe80f8c625dd98333d1631d2f
2020-05-08
27个文件已修改
8个文件已添加
4个文件已删除
2241 ■■■■■ 已修改文件
src/tabviews/commontable/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/managetable/index.jsx 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/dategroup/index.jsx 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/dategroup/index.scss 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/dategroup/quarterpicker/index.jsx 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/dategroup/quarterpicker/index.scss 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/dategroup/yearpicker/index.jsx 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/dategroup/yearpicker/index.scss 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/topSearch/index.jsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/topSearch/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/source.jsx 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.jsx 265 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.scss 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/searchform/index.jsx 475 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/searchform/index.scss 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/dategroup/index.jsx 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/dategroup/index.scss 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/index.jsx 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searcheditable/index.jsx 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searcheditable/index.scss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searchform/index.jsx 204 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/searchform/index.scss 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/customscript/index.jsx 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/index.jsx 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/source.jsx 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customscript/index.jsx 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/customscript/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/option.js 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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) {
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>
src/tabviews/zshare/dategroup/index.jsx
New file
@@ -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
src/tabviews/zshare/dategroup/index.scss
New file
@@ -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;
    }
  }
}
src/tabviews/zshare/dategroup/quarterpicker/index.jsx
New file
@@ -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
src/tabviews/zshare/dategroup/quarterpicker/index.scss
New file
@@ -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;
  }
}
src/tabviews/zshare/dategroup/yearpicker/index.jsx
New file
@@ -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
src/tabviews/zshare/dategroup/yearpicker/index.scss
New file
@@ -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;
  }
}
src/tabviews/zshare/normalTable/index.jsx
@@ -180,6 +180,10 @@
          }
        }
  
        if (item.format === 'percent') {
          content = content * 100
        }
        content = content.toFixed(item.decimal || 0)
  
        if (item.format === 'thdSeparator') {
@@ -291,6 +295,10 @@
          }
    
          if (content !== '') {
            if (item.format === 'percent') {
              content = content * 100
            }
            content = content.toFixed(col.decimal || 0)
      
            if (col.format === 'thdSeparator') {
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>
        )
      }
    })
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: '*';
    }
  }
}
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;
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: ''
    }
  ]
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;
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;
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'}>
src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.jsx
File was deleted
src/templates/sharecomponent/chartgroupcomponent/searcheditable/index.scss
File was deleted
src/templates/sharecomponent/chartgroupcomponent/searchform/index.jsx
File was deleted
src/templates/sharecomponent/chartgroupcomponent/searchform/index.scss
File was deleted
src/templates/sharecomponent/searchcomponent/dategroup/index.jsx
New file
@@ -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
src/templates/sharecomponent/searchcomponent/dategroup/index.scss
New file
@@ -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;
    }
  }
}
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>
src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
@@ -91,15 +91,6 @@
      newcard.uuid = Utils.getuuid()
      newcard.focus = true
      
      let _match = 'like'
      if (item.subType === 'select' || item.subType === 'link') {
        _match = '='
      } else if (item.subType === 'date' || item.subType === 'datemonth') {
        _match = '>='
      } else if (item.subType === 'dateweek' || item.subType === 'daterange') {
        _match = 'between'
      }
      newcard.label = 'label'
      newcard.initval = ''
      newcard.type = item.subType
@@ -107,9 +98,22 @@
      newcard.options = []
      newcard.setAll = 'false'
      newcard.orderType = 'asc'
      newcard.match = _match
      newcard.display = 'dropdown'
      
      let _match = 'like'
      if (item.subType === 'select' || item.subType === 'link') {
        _match = '='
      } else if (item.subType === 'date' || item.subType === 'datemonth') {
        _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.match = _match
      let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
      if (target) {
        targetId = target.uuid
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}
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)}>
            <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)}>
            <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>
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;
  }
}
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
        if (this.props.form.getFieldValue('initval') !== undefined) {
          this.props.form.setFieldsValue({initval: ''})
            }
            return form
          })
        })
        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>
    )
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;
      }
    }
  }
}
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'}>
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({
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) {
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;
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: ''
    }
  ]
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']
      }]
    }
  ]
}
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'}>
src/templates/zshare/verifycard/customscript/index.scss
@@ -0,0 +1,5 @@
#verify-custom-scripts {
  .ant-select-dropdown-menu-item {
    white-space: normal;
  }
}
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: '后天'}
  ]
}
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') : ''