king
2023-07-06 fa8f1b1320fd2ad21884ccd6df792bf88270e2a1
2023-07-06
24个文件已修改
4个文件已添加
1541 ■■■■■ 已修改文件
src/assets/css/main.scss 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/breadview/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tabview/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/calendar/board/index.jsx 288 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/calendar/board/index.scss 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/calendar/index.jsx 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/calendar/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/calendar/options.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/groupcomponents/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/group/paste/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/actionform/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/dragaction/card.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/formconfig.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/editColumn/formconfig.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/paste/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/card.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/pastecontroller/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/calendar/board/index.jsx 513 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/calendar/board/index.scss 237 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/calendar/index.jsx 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/calendar/index.scss 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/group/normal-group/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/share/tabtransfer/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/timeline/normal-timeline/index.jsx 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/popview/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss
@@ -519,4 +519,20 @@
  .ant-dropdown-menu-item:hover, .ant-dropdown-menu-submenu-title:hover {
    background-color: var(--mk-sys-color1);
  }
}
.ant-radio-group {
  .ant-radio-button-wrapper.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled) {
    color: var(--mk-sys-color);
    border-color: var(--mk-sys-color);
    box-shadow: -1px 0 0 0 var(--mk-sys-color);
  }
  .ant-radio-button-wrapper.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover {
    color: var(--mk-sys-color);
    border-color: var(--mk-sys-color);
    box-shadow: -1px 0 0 0 var(--mk-sys-color);
  }
  .ant-radio-button-wrapper:not(.ant-radio-button-wrapper-checked):not(.ant-radio-button-wrapper-disabled):hover {
    color: var(--mk-sys-color);
  }
}
src/components/breadview/index.jsx
@@ -20,6 +20,8 @@
const RoleManage = asyncComponent(() => import('@/tabviews/rolemanage'))
const FormTab = asyncComponent(() => import('@/tabviews/formtab'))
moment.locale('zh-cn')
class BreadView extends Component {
  state = {
    tabview: null, // 标签
@@ -108,12 +110,6 @@
  }
  UNSAFE_componentWillMount () {
    if (!sessionStorage.getItem('lang') || sessionStorage.getItem('lang') === 'zh-CN') {
      moment.locale('zh-cn')
    } else {
      moment.locale('en')
    }
    let home = {
      MenuID: 'home_page_id',
      MenuName: '首页',
src/components/tabview/index.jsx
@@ -24,6 +24,8 @@
const FormTab = asyncComponent(() => import('@/tabviews/formtab'))
const Calendar = asyncComponent(() => import('@/tabviews/calendar'))
moment.locale('zh-cn')
class TabViews extends Component {
  static propTpyes = {
    collapse: PropTypes.bool
@@ -217,12 +219,6 @@
  }
  UNSAFE_componentWillMount () {
    if (!sessionStorage.getItem('lang') || sessionStorage.getItem('lang') === 'zh-CN') {
      moment.locale('zh-cn')
    } else {
      moment.locale('en')
    }
    if (sessionStorage.getItem('isEditState') !== 'true') {
      this.setState({
        activeId: 'home_page_id',
src/menu/components/calendar/board/index.jsx
@@ -1,12 +1,15 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Select, Radio, Row, Col, Badge } from 'antd'
import { Select, Radio, Row, Col } from 'antd'
import moment from 'moment'
import 'moment/locale/zh-cn'
import './index.scss'
const { Option } = Select
moment.locale('zh-cn')
class CalendarBoard extends Component {
  static propTpyes = {
@@ -31,7 +34,7 @@
    let _selectYear = +this.state.selectYear
    yearlist.push(`${_selectYear}`)
    
    for (let i = 1; i <= 50; i++) {
    for (let i = 1; i <= 10; i++) {
      yearlist.unshift(`${_selectYear - i}`)
      yearlist.push(`${_selectYear + i}`)
    }
@@ -40,11 +43,7 @@
    let _levels = config.wrap.levels
    let level = _levels[0]
    let monthlist = null
    if (_levels.includes('month')) {
      monthlist = datelist.filter(item => item.month === moment().format('MM'))[0]
    }
    let monthlist = datelist.filter(item => item.month === moment().format('MM'))[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
    this.setState({
      yearlist,
@@ -58,7 +57,8 @@
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (!is(fromJS(this.props.config.wrap), fromJS(nextProps.config.wrap))) {
      this.setState({
        levels: nextProps.config.wrap.levels
        levels: nextProps.config.wrap.levels,
        level: nextProps.config.wrap.levels[0]
      })
    }
  }
@@ -67,11 +67,7 @@
    return !is(fromJS(this.state), fromJS(nextState))
  }
  getNongLi = (nyear, nmonth, nday) => {
    let jq = this.getjq(nyear, nmonth, nday)
    if (jq) return jq
  getNongLi = (nyear, nmonth, nday, week) => {
    let lmonth;
    let lday;
    let lleap; //农历参数
@@ -180,11 +176,93 @@
      lmonth = '闰' + lmonth
    }
    if (lday === '初一') {
      return lmonth + '月'
    lmonth = lmonth + '月'
    if (!week) {
      return lmonth + lday
    }
    return lday
    let jq = this.getjq(nyear, nmonth, nday)
    let nl = lday
    if (lday === '初一') {
      nl = lmonth
    }
    if (jq) {
      nl = jq
    }
    let sign = '班'
    if (week > 5) {
      sign = '休'
    }
    let jr = ''
    let gr = '' + nmonth + '-' + nday
    let nr = lmonth + lday
    if (gr === '1-1') {
      jr = '元旦'
      sign = '休'
    } else if (nr === '正月初一') {
      jr = '春节'
      sign = '休'
    } else if (nr === '正月十五') {
      jr = '元宵节'
    } else if (jq === '清明') {
      sign = '休'
    } else if (gr === '3-8') {
      jr = '妇女节'
    } else if (gr === '5-1') {
      jr = '劳动节'
      sign = '休'
    } else if (nr === '五月初五') {
      jr = '端午节'
      sign = '休'
    } else if (nr === '七月初七') {
      jr = '七夕节'
    } else if (nr === '七月十五') {
      jr = '中元节'
    } else if (nr === '八月十五') {
      jr = '中秋节'
      sign = '休'
    } else if (gr === '7-1') {
      jr = '建党节'
    } else if (gr === '8-1') {
      jr = '建军节'
    } else if (gr === '9-10') {
      jr = '教师节'
    } else if (gr === '10-1') {
      jr = '国庆节'
      sign = '休'
    } else if (nr === '九月初九') {
      jr = '重阳节'
    } else if (nr === '十二月三十') {
      jr = '除夕'
      sign = '休'
    } else if (['正月初二', '正月初三', '正月初四', '正月初五', '正月初六'].includes(nr)) {
      sign = '休'
    } else if (['10-2', '10-3'].includes(gr)) {
      sign = '休'
    } else if (nr === '十二月廿九') {
      let tis = moment(`${nyear}${nmonth < 10 ? '0' + nmonth : nmonth}${nday < 10 ?  '0' + nday : nday}`, 'YYYYMMDD').add(1, 'days').format('YYYY-MM-DD').split('-')
      let nd = this.getNongLi(+tis[0], +tis[1], +tis[2])
      if (nd === '正月初一') {
        jr = '除夕'
        sign = '休'
      }
    }
    return {
      nlday: lday,
      nlmonth: lmonth,
      nljq: jq,
      nl: nl,
      jr: jr,
      week: week,
      sign: sign
    }
  }
  getjq = (yyyy, mm, dd) => {
@@ -207,22 +285,6 @@
    return solarTerms
  }
  getStyle = (item ) => {
    if (!item || !item.color) return null
    let style = {background: item.color}
    if (/rgb/ig.test(item.color)) {
      try {
        let colors = item.color.match(/\d+/g)
        if ((colors[0] * 0.299 + colors[1] * 0.578 + colors[2] * 0.114) * colors[3] < 192) {
          style.color = '#ffffff'
        }
      } catch (e) {}
    }
    return style
  }
  getDateList = (selectYear) => {
    let datelist = []
    let months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
@@ -232,43 +294,81 @@
    }
    months.forEach(month => {
      let _weeklist = [{week: 1, sublist: []}]
      let _weeklist = []
      let weekday = moment(`${selectYear}${month}01`, 'YYYYMMDD').weekday()
      let end = +moment(`${selectYear}${month}`, 'YYYYMM').endOf('month').format('DD')
      for (let i = 0; i < weekday; i++) {
        _weeklist[0].sublist.push(null)
      let children = []
      if (weekday > 0) {
        let times = moment(`${selectYear}${month}01`, 'YYYYMMDD').subtract(1, 'days').format('YYYY-MM-DD').split('-')
        for (let i = 0; i < weekday; i++) {
          let _day = times[2] - i
          let nl = this.getNongLi(+times[0], +times[1], +_day, weekday - i)
          let item = {
            day: _day,
            time: times[0] + times[1] + _day,
            label: _day,
            subData: [],
            $disable: true,
            ...nl
          }
          children.unshift(item)
        }
      }
      for (let i = 1; i <= end; i++) {
        let _day = i < 10 ? `0${i}` : `${i}`
        let nl = this.getNongLi(+selectYear, +month, +_day, children.length + 1)
        let item = {
          day: _day,
          time: selectYear + month + _day,
          nltime: this.getNongLi(+selectYear, +month, +_day),
          label: i,
          subData: []
          subData: [],
          ...nl
        }
        if (_weeklist[_weeklist.length - 1].sublist.length < 7) {
          _weeklist[_weeklist.length - 1].sublist.push(item)
        } else {
          let _week = {week: _weeklist.length + 1, sublist: [item]}
          _weeklist.push(_week)
        children.push(item)
        if (children.length === 7) {
          _weeklist.push({
            children: [...children]
          })
          children = []
        }
      }
      let re = 7 - _weeklist.slice(-1)[0].sublist.length
      for (let i = 0; i < re; i++) {
        _weeklist[_weeklist.length - 1].sublist.push(null)
      let times = moment(`${selectYear}${month}`, 'YYYYMM').endOf('month').add(1, 'days').format('YYYY-MM-DD').split('-')
      let tick = 42 - _weeklist.length * 7 - children.length
      for (let i = 1; i <= tick; i++) {
        let _day = i < 10 ? '0' + i : i
        let nl = this.getNongLi(+times[0], +times[1], +_day, children.length + 1)
        let item = {
          day: _day,
          time: times[0] + times[1] + _day,
          label: i,
          subData: [],
          $disable: true,
          ...nl
        }
        children.push(item)
        if (children.length === 7) {
          _weeklist.push({
            children: [...children]
          })
          children = []
        }
      }
      datelist.push({
        month: month,
        time: selectYear + month,
        label: monthName[month],
        sublist: _weeklist,
        children: _weeklist,
        subData: []
      })
    })
@@ -281,20 +381,30 @@
  }
  yearChange = (value) => {
    const { levels, selectMonth } = this.state
    const { selectMonth } = this.state
    let datelist = this.getDateList(value)
    let monthlist = null
    if (levels.includes('month')) {
      monthlist = datelist.filter(item => item.month === selectMonth)[0]
    }
    let monthlist = datelist.filter(item => item.month === selectMonth)[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
    this.setState({ selectYear: value, datelist, monthlist })
  }
  monthChange = (value) => {
    const { datelist, levels } = this.state
    if (!levels.includes('month')) {
      return
    }
    this.setState({
      level: 'month',
      selectMonth: value,
      monthlist: datelist.filter(item => item.month === value)[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
    })
  }
  render() {
    const { level, selectYear, yearlist, levels, datelist, monthlist } = this.state
    const _levelName = {day: '日', month: '月'}
    const { level, selectYear, selectMonth, yearlist, levels, datelist, monthlist } = this.state
    const _levelName = {day: '日', month: '月', year: '年'}
    return (
      <div className="mk-calendar">
@@ -302,6 +412,20 @@
          <Select value={selectYear} onChange={this.yearChange}>
            {yearlist.map(item => (<Option key={item} value={item}>{item}年</Option>))}
          </Select>
          {level === 'month' ? <Select value={selectMonth} onChange={this.monthChange}>
            <Option value="01">1月</Option>
            <Option value="02">2月</Option>
            <Option value="03">3月</Option>
            <Option value="04">4月</Option>
            <Option value="05">5月</Option>
            <Option value="06">6月</Option>
            <Option value="07">7月</Option>
            <Option value="08">8月</Option>
            <Option value="09">9月</Option>
            <Option value="10">10月</Option>
            <Option value="11">11月</Option>
            <Option value="12">12月</Option>
          </Select> : null}
          {levels.length > 1 ? <Radio.Group value={level} onChange={this.levelChange}>
            {levels.map(item => (<Radio.Button key={item} value={item}>{_levelName[item]}</Radio.Button>))}
          </Radio.Group> : null}
@@ -320,13 +444,13 @@
                    </tr>
                  </thead>
                  <tbody>
                    {item.sublist.map(cell => (
                      <tr key={cell.week}>
                        {cell.sublist.map((d, i) => (
                    {item.children.map((cell, m) => (
                      <tr key={m}>
                        {cell.children.map((d, i) => (
                          <td key={i}>
                            {d ? <div className="day-wrap" style={d.style || null}>
                            <div className={'day-wrap' + (d.$disable ? ' disabled' : '')}>
                              {d.label}
                            </div> : null }
                            </div>
                          </td>
                        ))}
                      </tr>
@@ -336,20 +460,46 @@
              </Col>
            ))}
          </Row> : null}
          {level === 'month' && monthlist ? <Row className="year-calendar">
          {level === 'month' && monthlist ? <div className="month-calendar">
            <table>
              <thead>
                <tr>
                  <th>星期一</th><th>星期二</th><th>星期三</th><th>星期四</th><th>星期五</th><th>星期六</th><th>星期日</th>
                </tr>
              </thead>
              <tbody>
                {monthlist.map((cell, m) => (
                  <tr key={m}>
                    {cell.children.map((d, i) => (
                      <td key={i}>
                        <div className={'month-wrap' + (d.$disable ? ' disabled' : '')}>
                          <div className="header">
                            <div className="message">
                              {d.label}
                              <span className={'right' + (d.sign === '休' ? ' danger' : '')}>{d.sign}</span>
                            </div>
                            <div className="message">
                              {d.nl}
                              <span className="right">{d.jr}</span>
                            </div>
                          </div>
                          <ul className="content"></ul>
                        </div>
                      </td>
                    ))}
                  </tr>
                ))}
              </tbody>
            </table>
          </div>: null}
          {level === 'year' ? <Row className="year-calendar">
            {datelist.map(item => (
              <Col span={8} key={item.month}>
                <div className="year-wrap" style={item.style || null}>
                  <div className="header" style={item.style ? null : {color: '#1890ff'}}>
                <div className="year-wrap">
                  <div className="header" style={{color: '#1890ff'}}>
                    {item.label}
                  </div>
                  <ul className="content">
                    {item.subData.map((data, index) => (
                      <li key={index} className="message">
                        <Badge color={item.style ? (data.color === item.style.background ? '#ffffff' : data.color) : data.color} text={`${data.remark} (${data.startTime} ~ ${data.endTime})`}/>
                      </li>
                    ))}
                  </ul>
                  <ul className="content"></ul>
                </div>
              </Col>
            ))}
src/menu/components/calendar/board/index.scss
@@ -2,6 +2,7 @@
  position: relative;
  width: 100%;
  padding: 20px;
  color: rgba(0, 0, 0, 0.85);
  .loading-data {
    position: absolute;
@@ -23,6 +24,9 @@
    .ant-select {
      width: 90px;
      margin-right: 15px;
    }
    .ant-select + .ant-select {
      width: 80px;
    }
  }
  .mk-calendar-content {
@@ -58,7 +62,11 @@
                  height: 100%;
                }
              }
              .day-wrap:hover {
              .day-wrap.disabled {
                cursor: default;
                color: rgba(0, 0, 0, 0.35);
              }
              .day-wrap:not(.disabled):hover {
                background: #bae7ff;
              }
            }
@@ -71,7 +79,7 @@
        width: 100%;
        thead {
          text-align: center;
          color: #1890ff;
          // color: #1890ff;
          font-size: 16px;
          tr {
            height: 35px;
@@ -90,12 +98,21 @@
                margin-bottom: 2px;
                box-shadow: 0px 0px 3px #bae7ff;
                .header {
                  text-align: center;
                  font-size: 16px;
                  padding: 5px 10px;
                  .message {
                    .right {
                      float: right;
                    }
                    .right.danger {
                      color: #ff4d4f;
                    }
                  }
                }
                .content {
                  padding: 0 10px 10px;
                  height: 90px;
                  height: 70px;
                  overflow-y: auto;
                  position: absolute;
                  left: 0;
@@ -122,7 +139,20 @@
                  background: rgba(0, 0, 0, 0);
                }
              }
              .month-wrap:hover {
              .month-wrap.disabled {
                cursor: default;
                color: rgba(0, 0, 0, 0.35);
                .header {
                  .message {
                    .right.danger {
                      color: rgba(0, 0, 0, 0.35);
                    }
                  }
                }
              }
              .month-wrap:not(.disabled):hover {
                background: #e6f7ff;
              }
            }
src/menu/components/calendar/index.jsx
@@ -15,6 +15,7 @@
const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
const SearchComponent = asyncComponent(() => import('@/templates/sharecomponent/searchcomponent'))
const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
const CalendarBoard = asyncComponent(() => import('./board'))
@@ -34,6 +35,7 @@
    const { card } = this.props
    if (card.isNew) {
      let btnId = Utils.getuuid()
      let _card = {
        uuid: card.uuid,
        type: card.type,
@@ -44,12 +46,40 @@
        name: card.name,
        subtype: card.subtype,
        setting: { interType: 'system' },
        wrap: { title: '', name: card.name, width: card.width || 24, levels: ['day', 'month'] },
        wrap: { title: '', name: card.name, width: card.width || 24, levels: ['day', 'month', 'year'] },
        style: { marginLeft: '0px', marginRight: '0px', marginTop: '0px', marginBottom: '0px' },
        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
        search: [],
        columns: [],
        scripts: [],
        action: [{
          $fixed: true,
          uuid: btnId,
          label: '添加',
          OpenType: 'popview',
          popClose: 'grid',
          display: 'modal',
          icon: '',
          class: 'green',
          ratio: 85,
          style: {
            color: 'rgb(255, 255, 255)',
            background: 'rgb(38, 194, 129)',
            marginRight: '15px'
          },
          config: {
            uuid: btnId,
            MenuID: btnId,
            ParentId: card.uuid,
            enabled: false,
            MenuName: '添加',
            tables: [],
            Template: 'CustomPage',
            components: [],
            viewType: 'popview',
            style: { backgroundColor: '#ffffff', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
          }
        }]
      }
      if (card.config) {
@@ -164,6 +194,15 @@
    this.updateComponent({...card, wrap: res})
  }
  setSubConfig = (item) => {
    const { card } = this.state
    let btn = fromJS(item).toJS()
    if (btn.OpenType === 'popview') {
      MKEmitter.emit('changePopview', card, btn)
    }
  }
  render() {
    const { card } = this.state
@@ -187,6 +226,7 @@
          <ToolOutlined />
        </Popover>
        <SearchComponent config={card} updatesearch={this.updateComponent}/>
        <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
        <CalendarBoard config={card} />
        <div className="component-name">
          <div className="center">
src/menu/components/calendar/index.scss
@@ -54,6 +54,14 @@
    }
  }
  .model-menu-action-list {
    .page-card {
      position: absolute;
      top: 20px;
      z-index: 1;
    }
  }
  >.anticon-tool {
    position: absolute;
    z-index: 2;
src/menu/components/calendar/options.jsx
@@ -61,8 +61,9 @@
      initval: wrap.levels || [],
      required: true,
      options: [
        {value: 'day', label: '天'},
        {value: 'day', label: '日'},
        {value: 'month', label: '月'},
        {value: 'year', label: '年'},
      ]
    },
    {
src/menu/components/group/groupcomponents/card.jsx
@@ -27,6 +27,7 @@
const AntvG6 = asyncComponent(() => import('@/menu/components/chart/antv-G6'))
const AntvX6 = asyncComponent(() => import('@/menu/components/chart/antv-X6'))
const DoubleDataCard = asyncComponent(() => import('@/menu/components/card/double-data-card'))
const Calendar = asyncComponent(() => import('@/menu/components/calendar'))
const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
  const originalIndex = findCard(id).index
@@ -112,6 +113,8 @@
      return (<AntvG6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'antvX6') {
      return (<AntvX6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'calendar') {
      return (<Calendar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
src/menu/components/group/paste/index.jsx
@@ -33,7 +33,7 @@
    }
    if (appType !== 'mob') {
      options.push('editable', 'antvG6', 'antvX6', 'tree', 'dashboard', 'chart')
      options.push('editable', 'antvG6', 'antvX6', 'calendar', 'tree', 'dashboard', 'chart')
    }
    this.pasteFormRef.handleConfirm().then(res => {
src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -964,6 +964,7 @@
          values.verify = card.verify || null
          values.modal = card.modal || null
          values.config = card.config || null
          values.$fixed = card.$fixed || false
          if (card.OpenType === 'excelOut' && values.OpenType === 'excelIn') {
            if (values.verify && values.verify.columns && values.verify.columns.length > 0) {
src/menu/components/share/actioncomponent/dragaction/card.jsx
@@ -106,9 +106,9 @@
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
      <div className="mk-popover-control">
        <EditOutlined className="edit" onClick={() => editCard(id)} />
        <CopyOutlined className="copy" onClick={() => copyCard(id)} />
        <CloseOutlined className="close" onClick={() => delCard(id)} />
        {type !== 'datacard' && type !== 'basetable' ? <FontColorsOutlined className="style" title="调整样式" onClick={() => changeStyle(id)}/> : ''}
        {!card.$fixed ? <CopyOutlined className="copy" onClick={() => copyCard(id)} /> : null}
        {!card.$fixed ? <CloseOutlined className="close" onClick={() => delCard(id)} /> : null}
        {type !== 'datacard' && type !== 'basetable' && !card.$fixed ? <FontColorsOutlined className="style" title="调整样式" onClick={() => changeStyle(id)}/> : ''}
        {hasProfile ? <ProfileOutlined className="profile" title="验证" onClick={() => profileCard(id)} /> : null}
        {updateTime}
      </div>
src/menu/components/share/actioncomponent/formconfig.jsx
@@ -165,6 +165,10 @@
    }
  }
  if (card.$fixed) {
    opentypes = opentypes.filter(item => item.value === card.OpenType)
  }
  if (card.funcType === 'changeuser') { // 原类型支持
    funTypes.unshift({ value: 'changeuser', text: '切换用户' })
  }
src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -239,7 +239,7 @@
        value: 'false',
        text: '否'
      }],
      forbid: card.isSub
      forbid: card.isSub || card.sum !== 'true'
    },
    {
      type: 'number',
src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -231,7 +231,7 @@
        value: 'false',
        text: '否'
      }],
      forbid: card.isSub
      forbid: card.isSub || card.sum !== 'true'
    },
    {
      type: 'number',
src/menu/components/tabs/paste/index.jsx
@@ -63,7 +63,7 @@
    if (appType === 'mob') {
      options.push('menubar')
    } else {
      options.push('editable', 'antvG6', 'antvX6', 'tree', 'dashboard', 'chart')
      options.push('editable', 'antvG6', 'antvX6', 'calendar', 'tree', 'dashboard', 'chart')
    }
    this.pasteFormRef.handleConfirm().then(res => {
src/menu/components/tabs/tabcomponents/card.jsx
@@ -30,6 +30,7 @@
const AntvG6 = asyncComponent(() => import('@/menu/components/chart/antv-G6'))
const AntvX6 = asyncComponent(() => import('@/menu/components/chart/antv-X6'))
const DoubleDataCard = asyncComponent(() => import('@/menu/components/card/double-data-card'))
const Calendar = asyncComponent(() => import('@/menu/components/calendar'))
const Card = ({ id, card, moveCard, findCard, delCard, unGroup, updateConfig }) => {
  const originalIndex = findCard(id).index
@@ -121,6 +122,8 @@
      return (<AntvG6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'antvX6') {
      return (<AntvX6 card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    } else if (card.type === 'calendar') {
      return (<Calendar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
    }
  }
src/menu/components/tabs/tabcomponents/index.jsx
@@ -118,6 +118,7 @@
        timeline: '时间轴',
        antvG6: '树图',
        antvX6: '流程图',
        calendar: '日历',
        card: '卡片'
      }
      let i = 1
src/menu/pastecontroller/index.jsx
@@ -63,7 +63,7 @@
        options.push('menubar', 'singleSearch')
      }
    } else {
      options.push('editable', 'mainsearch', 'antvG6', 'antvX6', 'tree', 'dashboard', 'chart')
      options.push('editable', 'mainsearch', 'antvG6', 'antvX6', 'calendar', 'tree', 'dashboard', 'chart')
    }
    this.pasteFormRef.handleConfirm().then(res => {
src/tabviews/custom/components/calendar/board/index.jsx
New file
@@ -0,0 +1,513 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Select, Radio, Row, Col } from 'antd'
import moment from 'moment'
import 'moment/locale/zh-cn'
import './index.scss'
const { Option } = Select
moment.locale('zh-cn')
class CalendarBoard extends Component {
  static propTpyes = {
    data: PropTypes.any,            // 事件数据
    config: PropTypes.any
  }
  state = {
    level: 'day',
    levels: null,
    yearlist: null,
    selectYear: moment().format('YYYY'),
    selectMonth: moment().format('MM'),
    datelist: null,
    monthlist: null
  }
  UNSAFE_componentWillMount() {
    const { config } = this.props
    let yearlist = []
    let _selectYear = +this.state.selectYear
    yearlist.push(`${_selectYear}`)
    for (let i = 1; i <= 10; i++) {
      yearlist.unshift(`${_selectYear - i}`)
      yearlist.push(`${_selectYear + i}`)
    }
    let datelist = this.getDateList(this.state.selectYear)
    let _levels = config.wrap.levels
    let level = _levels[0]
    let monthlist = datelist.filter(item => item.month === moment().format('MM'))[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
    this.setState({
      yearlist,
      datelist,
      monthlist,
      level,
      levels: _levels
    })
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (!is(fromJS(this.props.config.wrap), fromJS(nextProps.config.wrap))) {
      this.setState({
        levels: nextProps.config.wrap.levels,
        level: nextProps.config.wrap.levels[0]
      })
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  getNongLi = (nyear, nmonth, nday, week) => {
    let lmonth;
    let lday;
    let lleap; //农历参数
    //阴历函数开始
    // eslint-disable-next-line
    let lunarInfo = new Array(0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0,
      0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, 0x14b63)
    let lYearDays = (y) => {
      let i, sum = 348;
      for (i = 0x8000; i > 0x8; i >>= 1) {
        sum += (lunarInfo[y - 1900] & i) ? 1 : 0
      }
      return (sum + leapDays(y))
    }
    let leapDays = (y) => {
      if (leapMonth(y)) return ((lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
      return 0
    }
    let leapMonth = (y) => {
      return (lunarInfo[y - 1900] & 0xf)
    }
    let monthDays = (y, m) => {
      return ((lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
    }
    let Lunar = (y, m, d) => {
      let i, leap = 0, temp = 0;
      let offset = (Date.UTC(y, m, d) - Date.UTC(1900, 0, 31)) / 86400000;
      for (i = 1900; i < 2050 && offset > 0; i++) {
        temp = lYearDays(i)
        offset -= temp
      }
      if (offset < 0) {
        offset += temp
        i--
      }
      let year = i
      leap = leapMonth(i)
      let isLeap = false
      for (i = 1; i < 13 && offset > 0; i++) {
        if (leap > 0 && i === (leap + 1) && isLeap === false) {
          --i
          isLeap = true
          temp = leapDays(year)
        } else {
          temp = monthDays(year, i)
        }
        if (isLeap === true && i === (leap + 1)) {
          isLeap = false
        }
        offset -= temp
      }
      if (offset === 0 && leap > 0 && i === leap + 1) {
        if (isLeap) {
          isLeap = false
        } else {
          isLeap = true
          --i
        }
      }
      if (offset < 0) {
        offset += temp
        --i
      }
      return {
        month: i,
        day: offset + 1,
        isLeap: isLeap
      }
    }
    let nStr1 = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二']
    let nStr2 = ['初', '十', '廿', '卅']
    let GetcDay = (d) => {
      let s
      switch (d) {
        case 10:
          s = '初十'
          break
        case 20:
          s = '二十'
          break
        case 30:
          s = '三十'
          break
        default:
          s = nStr2[Math.floor(d / 10)]
          s += nStr1[d % 10]
          break
      }
      return s
    }
    let GetcMon = (m) => {
      if (m === 1) return '正'
      return nStr1[m]
    }
    let lObj = Lunar(nyear, nmonth - 1, nday)
    lmonth = GetcMon(lObj.month)
    lday = GetcDay(lObj.day)
    lleap = lObj.isLeap
    if (lleap === 1) {
      lmonth = '闰' + lmonth
    }
    lmonth = lmonth + '月'
    if (!week) {
      return lmonth + lday
    }
    let jq = this.getjq(nyear, nmonth, nday)
    let nl = lday
    if (lday === '初一') {
      nl = lmonth
    }
    if (jq) {
      nl = jq
    }
    let sign = '班'
    if (week > 5) {
      sign = '休'
    }
    let jr = ''
    let gr = '' + nmonth + '-' + nday
    let nr = lmonth + lday
    if (gr === '1-1') {
      jr = '元旦'
      sign = '休'
    } else if (nr === '正月初一') {
      jr = '春节'
      sign = '休'
    } else if (nr === '正月十五') {
      jr = '元宵节'
    } else if (jq === '清明') {
      sign = '休'
    } else if (gr === '3-8') {
      jr = '妇女节'
    } else if (gr === '5-1') {
      jr = '劳动节'
      sign = '休'
    } else if (nr === '五月初五') {
      jr = '端午节'
      sign = '休'
    } else if (nr === '七月初七') {
      jr = '七夕节'
    } else if (nr === '七月十五') {
      jr = '中元节'
    } else if (nr === '八月十五') {
      jr = '中秋节'
      sign = '休'
    } else if (gr === '7-1') {
      jr = '建党节'
    } else if (gr === '8-1') {
      jr = '建军节'
    } else if (gr === '9-10') {
      jr = '教师节'
    } else if (gr === '10-1') {
      jr = '国庆节'
      sign = '休'
    } else if (nr === '九月初九') {
      jr = '重阳节'
    } else if (nr === '十二月三十') {
      jr = '除夕'
      sign = '休'
    } else if (['正月初二', '正月初三', '正月初四', '正月初五', '正月初六'].includes(nr)) {
      sign = '休'
    } else if (['10-2', '10-3'].includes(gr)) {
      sign = '休'
    } else if (nr === '十二月廿九') {
      let tis = moment(`${nyear}${nmonth < 10 ? '0' + nmonth : nmonth}${nday < 10 ?  '0' + nday : nday}`, 'YYYYMMDD').add(1, 'days').format('YYYY-MM-DD').split('-')
      let nd = this.getNongLi(+tis[0], +tis[1], +tis[2])
      if (nd === '正月初一') {
        jr = '除夕'
        sign = '休'
      }
    }
    return {
      nlday: lday,
      nlmonth: lmonth,
      nljq: jq,
      nl: nl,
      jr: jr,
      week: week,
      sign: sign
    }
  }
  getjq = (yyyy, mm, dd) => {
    mm = mm - 1
    // eslint-disable-next-line
    let sTermInfo = new Array(0,21208,42467,63836,85337,107014,128867,150921,173149,195551,218072,240693,263343,285989,308563,331033,353350,375494,397447,419210,440795,462224,483532,504758)
    let solarTerm = ['小寒', '大寒', '立春', '雨水', '惊蛰', '春分', '清明', '谷雨', '立夏', '小满', '芒种', '夏至', '小暑', '大暑', '立秋', '处暑', '白露', '秋分', '寒露', '霜降', '立冬', '小雪', '大雪', '冬至']
    let tmp1 = new Date((31556925974.7 * (yyyy - 1900) + sTermInfo[mm * 2 + 1] * 60000) + Date.UTC(1900, 0, 6, 2, 5))
    let tmp2 = tmp1.getUTCDate()
    let solarTerms = ''
    if (tmp2 === dd) {
      solarTerms = solarTerm[mm * 2 + 1]
    }
    tmp1 = new Date((31556925974.7 * (yyyy - 1900) + sTermInfo[mm * 2] * 60000) + Date.UTC(1900, 0, 6, 2, 5))
    tmp2= tmp1.getUTCDate()
    if (tmp2 === dd) {
      solarTerms = solarTerm[mm * 2]
    }
    return solarTerms
  }
  getDateList = (selectYear) => {
    let datelist = []
    let months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
    let monthName = {
      '01': '一月', '02': '二月', '03': '三月', '04': '四月', '05': '五月', '06': '六月',
      '07': '七月', '08': '八月', '09': '九月', '10': '十月', '11': '十一月', '12': '十二月'
    }
    months.forEach(month => {
      let _weeklist = []
      let weekday = moment(`${selectYear}${month}01`, 'YYYYMMDD').weekday()
      let end = +moment(`${selectYear}${month}`, 'YYYYMM').endOf('month').format('DD')
      let children = []
      if (weekday > 0) {
        let times = moment(`${selectYear}${month}01`, 'YYYYMMDD').subtract(1, 'days').format('YYYY-MM-DD').split('-')
        for (let i = 0; i < weekday; i++) {
          let _day = times[2] - i
          let nl = this.getNongLi(+times[0], +times[1], +_day, weekday - i)
          let item = {
            day: _day,
            time: times[0] + times[1] + _day,
            label: _day,
            subData: [],
            $disable: true,
            ...nl
          }
          children.unshift(item)
        }
      }
      for (let i = 1; i <= end; i++) {
        let _day = i < 10 ? `0${i}` : `${i}`
        let nl = this.getNongLi(+selectYear, +month, +_day, children.length + 1)
        let item = {
          day: _day,
          time: selectYear + month + _day,
          label: i,
          subData: [],
          ...nl
        }
        children.push(item)
        if (children.length === 7) {
          _weeklist.push({
            children: [...children]
          })
          children = []
        }
      }
      let times = moment(`${selectYear}${month}`, 'YYYYMM').endOf('month').add(1, 'days').format('YYYY-MM-DD').split('-')
      let tick = 42 - _weeklist.length * 7 - children.length
      for (let i = 1; i <= tick; i++) {
        let _day = i < 10 ? '0' + i : i
        let nl = this.getNongLi(+times[0], +times[1], +_day, children.length + 1)
        let item = {
          day: _day,
          time: times[0] + times[1] + _day,
          label: i,
          subData: [],
          $disable: true,
          ...nl
        }
        children.push(item)
        if (children.length === 7) {
          _weeklist.push({
            children: [...children]
          })
          children = []
        }
      }
      datelist.push({
        month: month,
        time: selectYear + month,
        label: monthName[month],
        children: _weeklist,
        subData: []
      })
    })
    return datelist
  }
  levelChange = (e) => {
    this.setState({ level: e.target.value })
  }
  yearChange = (value) => {
    const { selectMonth } = this.state
    let datelist = this.getDateList(value)
    let monthlist = datelist.filter(item => item.month === selectMonth)[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
    this.setState({ selectYear: value, datelist, monthlist })
  }
  monthChange = (value) => {
    const { datelist, levels } = this.state
    if (!levels.includes('month')) {
      return
    }
    this.setState({
      level: 'month',
      selectMonth: value,
      monthlist: datelist.filter(item => item.month === value)[0].children.filter(cell => !cell.children[0].$disable || !cell.children[6].$disable)
    })
  }
  render() {
    const { level, selectYear, selectMonth, yearlist, levels, datelist, monthlist } = this.state
    const _levelName = {day: '日', month: '月', year: '年'}
    return (
      <div className="mk-calendar">
        <div className="mk-calendar-control">
          <Select value={selectYear} onChange={this.yearChange}>
            {yearlist.map(item => (<Option key={item} value={item}>{item}年</Option>))}
          </Select>
          {level === 'month' ? <Select value={selectMonth} onChange={this.monthChange}>
            <Option value="01">1月</Option>
            <Option value="02">2月</Option>
            <Option value="03">3月</Option>
            <Option value="04">4月</Option>
            <Option value="05">5月</Option>
            <Option value="06">6月</Option>
            <Option value="07">7月</Option>
            <Option value="08">8月</Option>
            <Option value="09">9月</Option>
            <Option value="10">10月</Option>
            <Option value="11">11月</Option>
            <Option value="12">12月</Option>
          </Select> : null}
          {levels.length > 1 ? <Radio.Group value={level} onChange={this.levelChange}>
            {levels.map(item => (<Radio.Button key={item} value={item}>{_levelName[item]}</Radio.Button>))}
          </Radio.Group> : null}
        </div>
        <div className="mk-calendar-content">
          {level === 'day' ? <Row className="day-calendar" gutter={16}>
            {datelist.map(item => (
              <Col span={4} key={item.month}>
                <table>
                  <thead>
                    <tr>
                      <th colSpan="7">{item.label}</th>
                    </tr>
                    <tr>
                      <th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th><th>日</th>
                    </tr>
                  </thead>
                  <tbody>
                    {item.children.map((cell, m) => (
                      <tr key={m}>
                        {cell.children.map((d, i) => (
                          <td key={i}>
                            <div className={'day-wrap' + (d.$disable ? ' disabled' : '')}>
                              {d.label}
                            </div>
                          </td>
                        ))}
                      </tr>
                    ))}
                  </tbody>
                </table>
              </Col>
            ))}
          </Row> : null}
          {level === 'month' && monthlist ? <div className="month-calendar">
            <table>
              <thead>
                <tr>
                  <th>星期一</th><th>星期二</th><th>星期三</th><th>星期四</th><th>星期五</th><th>星期六</th><th>星期日</th>
                </tr>
              </thead>
              <tbody>
                {monthlist.map((cell, m) => (
                  <tr key={m}>
                    {cell.children.map((d, i) => (
                      <td key={i}>
                        <div className={'month-wrap' + (d.$disable ? ' disabled' : '')}>
                          <div className="header">
                            <div className="message">
                              {d.label}
                              <span className={'right' + (d.sign === '休' ? ' danger' : '')}>{d.sign}</span>
                            </div>
                            <div className="message">
                              {d.nl}
                              <span className="right">{d.jr}</span>
                            </div>
                          </div>
                          <ul className="content"></ul>
                        </div>
                      </td>
                    ))}
                  </tr>
                ))}
              </tbody>
            </table>
          </div>: null}
          {level === 'year' ? <Row className="year-calendar">
            {datelist.map(item => (
              <Col span={8} key={item.month}>
                <div className="year-wrap">
                  <div className="header">
                    {item.label}
                  </div>
                  <ul className="content"></ul>
                </div>
              </Col>
            ))}
          </Row>: null}
        </div>
      </div>
    )
  }
}
export default CalendarBoard
src/tabviews/custom/components/calendar/board/index.scss
New file
@@ -0,0 +1,237 @@
.mk-calendar {
  position: relative;
  width: 100%;
  padding: 20px;
  color: rgba(0, 0, 0, 0.85);
  .loading-data {
    position: absolute;
    top: 0;
    left: 20px;
    right: 20px;
    bottom: 0;
    z-index: 2;
    opacity: 0.5;
    background: #ffffff;
    .ant-spin-spinning {
      position: absolute;
      left: 50%;
      top: 270px;
    }
  }
  .mk-calendar-control {
    text-align: right;
    .ant-select {
      width: 90px;
      margin-right: 15px;
    }
    .ant-select + .ant-select {
      width: 80px;
    }
  }
  .mk-calendar-content {
    margin-top: 10px;
    .day-calendar .ant-col {
      min-height: 235px;
      table {
        width: 100%;
        thead {
          text-align: center;
          color: var(--mk-sys-color);
          tr {
            height: 30px;
          }
          tr:first-child {
            th {
              font-weight: 600;
              font-size: 16px;
            }
          }
        }
        tbody {
          text-align: center;
          tr {
            height: 28px;
            td {
              .day-wrap {
                cursor: pointer;
                transition: background 0.1s;
                span {
                  display: inline-block;
                  width: 100%;
                  height: 100%;
                }
              }
              .day-wrap.disabled {
                cursor: default;
                color: rgba(0, 0, 0, 0.35);
              }
              .day-wrap:not(.disabled):hover {
                background: var(--mk-sys-color2);
              }
            }
          }
        }
      }
    }
    .month-calendar {
      table {
        width: 100%;
        thead {
          text-align: center;
          font-size: 16px;
          tr {
            height: 35px;
          }
        }
        tbody {
          tr {
            td {
              position: relative;
              width: 14.2%;
              .month-wrap {
                cursor: pointer;
                height: 120px;
                width: calc(100% - 2px);
                transition: background 0.1s;
                margin-bottom: 2px;
                box-shadow: 0px 0px 3px var(--mk-sys-color2);
                .header {
                  font-size: 16px;
                  padding: 5px 10px;
                  .message {
                    .right {
                      float: right;
                    }
                    .right.danger {
                      color: #ff4d4f;
                    }
                  }
                }
                .content {
                  padding: 0 10px 10px;
                  height: 70px;
                  overflow-y: auto;
                  position: absolute;
                  left: 0;
                  right: 0;
                  .message {
                    width: 100%;
                    .ant-badge-status-text {
                      color: inherit;
                    }
                  }
                }
                .content::-webkit-scrollbar {
                  width: 5px;
                }
                .content::-webkit-scrollbar-thumb {
                  border-radius: 5px;
                  box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.7);
                  background: rgba(255, 255, 255, 0.7);
                }
                .content::-webkit-scrollbar-track {
                  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
                  border-radius: 3px;
                  border: 1px solid rgba(0, 0, 0, 0.07);
                  background: rgba(0, 0, 0, 0);
                }
              }
              .month-wrap.disabled {
                cursor: default;
                color: rgba(0, 0, 0, 0.35);
                .header {
                  .message {
                    .right.danger {
                      color: rgba(0, 0, 0, 0.35);
                    }
                  }
                }
              }
              .month-wrap:not(.disabled):hover {
                background: var(--mk-sys-color1);
              }
            }
          }
        }
      }
    }
    .year-calendar {
      .year-wrap {
        width: calc(100% - 2px);
        box-shadow: 0px 0px 3px var(--mk-sys-color2);
        cursor: pointer;
        transition: background 0.1s;
        .header {
          text-align: center;
          font-size: 16px;
          color: var(--mk-sys-color);
        }
        .content {
          padding: 5px 15px 10px;
          height: 110px;
          overflow-y: auto;
          margin-bottom: 2px;
          .ant-badge-status-text {
            color: inherit;
          }
          .message {
            width: 100%;
            overflow: hidden;
            margin-bottom: 5px;
            text-overflow: ellipsis;
          }
        }
        .content::-webkit-scrollbar {
          width: 5px;
        }
        .content::-webkit-scrollbar-thumb {
          border-radius: 5px;
          box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.7);
          background: rgba(255, 255, 255, 0.7);
        }
        .content::-webkit-scrollbar-track {
          box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
          border-radius: 3px;
          border: 1px solid rgba(0, 0, 0, 0.07);
          background: rgba(0, 0, 0, 0);
        }
      }
      .year-wrap:hover {
        background: var(--mk-sys-color1);
      }
    }
  }
}
.calendar-day-pop {
  .message {
    .ant-badge-status-text {
      display: inline-block;
      min-width: 200px;
      max-width: 350px;
      vertical-align: middle;
    }
  }
  .ant-popover-inner-content {
    min-height: 100px;
    max-height: 200px;
    overflow-y: auto;
  }
  .ant-popover-inner-content::-webkit-scrollbar {
    width: 5px;
  }
  .ant-popover-inner-content::-webkit-scrollbar-thumb {
    border-radius: 5px;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.09);
    background: rgba(0, 0, 0, 0.09);
  }
  .ant-popover-inner-content::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
    border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(0, 0, 0, 0);
  }
}
src/tabviews/custom/components/calendar/index.jsx
New file
@@ -0,0 +1,268 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Spin, notification, Modal } from 'antd'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import asyncComponent from '@/utils/asyncComponent'
import UtilsDM from '@/utils/utils-datamanage.js'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch'))
const PopupButton = asyncComponent(() => import('@/tabviews/zshare/actionList/popupbutton'))
const CalendarBoard = asyncComponent(() => import('./board'))
class NormalCalendar extends Component {
  static propTpyes = {
    config: PropTypes.object,        // 组件配置信息
    mainSearch: PropTypes.any,       // 外层搜索条件
  }
  state = {
    BID: '',                   // 上级ID
    config: null,              // 图表配置信息
    loading: false,            // 数据加载状态
    data: null,                // 数据
    search: '',
    BData: ''
  }
  loaded = false
  /**
   * @description 初始化处理
   */
  UNSAFE_componentWillMount () {
    let _config = fromJS(this.props.config).toJS()
    let BData = ''
    if (_config.setting.supModule) {
      BData = window.GLOB.CacheData.get(_config.setting.supModule)
    } else {
      BData = window.GLOB.CacheData.get(_config.$pageId)
    }
    this.setState({
      BID: BData ? (BData.$BID || '') : '',
      BData: BData,
      config: _config,
      arr_field: _config.columns.map(col => col.field).join(','),
      search: Utils.initMainSearch(_config.search) // 搜索条件初始化(含有时间格式,需要转化)
    }, () => {
      if (_config.setting.onload === 'true') {
        setTimeout(() => {
          this.loadData()
        }, _config.setting.delay || 0)
      }
    })
  }
  componentDidMount () {
    const { config } = this.state
    MKEmitter.addListener('reloadData', this.reloadData)
    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
    MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
    if (config.$cache && !this.loaded) {
      Api.getLCacheConfig(config.uuid).then(res => {
        if (!res || this.loaded) return
        this.setState({data: res.map((item, index) => {
          item.key = index
          item.$$uuid = item[config.setting.primaryKey] || ''
          item.$Index = index + 1 + ''
          return item
        })})
      })
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  componentWillUnmount () {
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('reloadData', this.reloadData)
    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
    MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
  }
  /**
   * @description 图表数据更新,刷新内容
   */
  UNSAFE_componentWillReceiveProps (nextProps) {
    const { config } = this.state
    if (config.setting.useMSearch && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
      this.setState({}, () => {
        this.loadData()
      })
    }
  }
  /**
   * @description 按钮执行完成后页面刷新
   * @param {*} menuId     // 菜单Id
   * @param {*} position   // 刷新位置
   * @param {*} btn        // 执行的按钮
   */
  refreshByButtonResult = (menuId, position, btn) => {
    const { config, BID } = this.state
    if (config.uuid !== menuId) return
    if (position === 'mainline' && config.setting.supModule && BID) { // 刷新源组件时,附带刷新上级行与当前组件
      MKEmitter.emit('reloadData', config.setting.supModule, BID)
    } else {
      this.loadData()
    }
  }
  resetParentParam = (MenuID, id, data) => {
    const { config } = this.state
    if (!config.setting.supModule || config.setting.supModule !== MenuID) return
    if (id !== this.state.BID || id !== '') {
      this.setState({ BID: id, BData: data }, () => {
        this.loadData()
      })
    }
  }
  reloadData = (menuId) => {
    const { config } = this.state
    if (config.uuid !== menuId) return
    this.loadData()
  }
  async loadData () {
    const { mainSearch } = this.props
    const { config, arr_field, BID, search } = this.state
    if (config.setting.supModule && !BID) { // BID 不存在时,不做查询
      this.setState({
        data: [],
      })
      this.loaded = true
      return
    }
    let searches = fromJS(search).toJS()
    if (config.setting.useMSearch && mainSearch && mainSearch.length > 0) { // 主表搜索条件
      let keys = searches.map(item => item.key.toLowerCase())
      mainSearch.forEach(item => {
        if (!keys.includes(item.key.toLowerCase())) {
          searches.push(item)
        }
      })
    }
    let requireFields = searches.filter(item => item.required && item.value === '')
    if (requireFields.length > 0) {
      return
    }
    this.setState({
      loading: true
    })
    let _orderBy = config.setting.order || ''
    let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 99999, BID)
    let result = await Api.genericInterface(param)
    if (result.status) {
      this.loaded = true
      if (config.$cache && config.setting.onload !== 'false') {
        Api.writeCacheConfig(config.uuid, result.data || '')
      }
      let data = result.data.map((item, index) => {
        item.key = index
        item.$$uuid = item[config.setting.primaryKey] || ''
        item.$$BID = BID || ''
        return item
      })
      this.setState({
        data: data,
        loading: false
      })
      if (result.message) {
        if (result.ErrCode === 'Y') {
          Modal.success({
            title: result.message
          })
        } else if (result.ErrCode === 'S') {
          notification.success({
            top: 92,
            message: result.message,
            duration: 2
          })
        }
      }
    } else {
      this.setState({
        loading: false
      })
      if (!result.message) return
      if (result.ErrCode === 'N') {
        Modal.error({
          title: result.message,
        })
      } else if (result.ErrCode !== '-2') {
        notification.error({
          top: 92,
          message: result.message,
          duration: 10
        })
      }
    }
  }
  refreshbysearch = (searches) => {
    this.setState({
      search: searches
    }, () => {
      this.loadData()
    })
  }
  render() {
    const { config, loading, data, BID, BData } = this.state
    return (
      <div className="normal-calendar-box" id={'anchor' + config.uuid} style={{...config.style}}>
        {loading ?
          <div className="loading-mask">
            {data ? <div className="ant-spin-blur"></div> : null}
            <Spin />
          </div> : null
        }
        <NormalHeader config={config} />
        {config.search.length ?
          <MainSearch BID={BID} config={config} refreshdata={this.refreshbysearch}/> : null
        }
        {config.action[0] ?
          <PopupButton disabled={false} BID={BID} btn={config.action[0]} BData={BData} setting={config.setting} selectedData={[]}/> : null
        }
        <CalendarBoard config={config} />
      </div>
    )
  }
}
export default NormalCalendar
src/tabviews/custom/components/calendar/index.scss
New file
@@ -0,0 +1,38 @@
.normal-calendar-box {
  background: #ffffff;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 100px;
  position: relative;
  >.ant-btn {
    display: none;
  }
  .loading-mask {
    position: absolute;
    left: 0px;
    top: 0;
    right: 0px;
    bottom: 0px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: justify;
    z-index: 1;
    .ant-spin-blur {
      position: absolute;
      width: 100%;
      height: 100%;
      opacity: 0.5;
      background: #ffffff;
    }
  }
}
.normal-calendar-box::after {
  content: ' ';
  display: block;
  clear: both;
}
src/tabviews/custom/components/group/normal-group/index.jsx
@@ -36,6 +36,7 @@
const CustomChart = asyncComponent(() => import('@/tabviews/custom/components/chart/custom-chart'))
const AntvG6 = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-G6'))
const AntvX6 = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-X6'))
const Calendar = asyncComponent(() => import('@/tabviews/custom/components/calendar'))
class TabTransfer extends Component {
  static propTpyes = {
@@ -255,6 +256,12 @@
            <NormalTree config={item} data={data} mainSearch={mainSearch}/>
          </Col>
        )
      } else if (item.type === 'calendar') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>
            <Calendar config={item} mainSearch={mainSearch}/>
          </Col>
        )
      } else if (item.type === 'editor') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>
src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -40,6 +40,7 @@
const MkBaseTable = asyncComponent(() => import('@/tabviews/custom/components/table/base-table'))
const AntvG6 = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-G6'))
const AntvX6 = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-X6'))
const Calendar = asyncComponent(() => import('@/tabviews/custom/components/calendar'))
class TabTransfer extends Component {
  static propTpyes = {
@@ -310,6 +311,12 @@
            <NormalTree config={item} data={data} mainSearch={mainSearch}/>
          </Col>
        )
      } else if (item.type === 'calendar') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>
            <Calendar config={item} mainSearch={mainSearch}/>
          </Col>
        )
      } else if (item.type === 'editor') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>
src/tabviews/custom/components/timeline/normal-timeline/index.jsx
@@ -238,22 +238,6 @@
    }
  }
  refreshLineData = (menuId, btn, uuid, count) => {
    const { config, data } = this.state
    if (config.uuid !== menuId) return
    let _data = fromJS(data).toJS().forEach(item => {
      if (item.$$uuid === uuid) {
        item[btn.field] = count
      }
    })
    this.setState({
      data: _data
    })
  }
  reloadData = (menuId) => {
    const { config } = this.state
src/tabviews/custom/index.jsx
@@ -44,6 +44,7 @@
const Voucher = asyncComponent(() => import('./components/module/voucher'))
const Account = asyncComponent(() => import('./components/module/account'))
const Iframe = asyncComponent(() => import('./components/iframe'))
const Calendar = asyncComponent(() => import('./components/calendar'))
const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
const TableNodes = asyncComponent(() => import('@/tabviews/zshare/tablenodes'))
const MkInterfaces = asyncComponent(() => import('@/tabviews/custom/components/interfaces'))
@@ -1422,6 +1423,12 @@
            <NormalTree config={item} data={data} mainSearch={mainSearch}/>
          </Col>
        )
      } else if (item.type === 'calendar') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>
            <Calendar config={item} mainSearch={mainSearch}/>
          </Col>
        )
      } else if (item.type === 'code') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>
src/tabviews/custom/popview/index.jsx
@@ -40,6 +40,7 @@
const TimeLine = asyncComponent(() => import('../components/timeline/normal-timeline'))
const Voucher = asyncComponent(() => import('../components/module/voucher'))
const Iframe = asyncComponent(() => import('../components/iframe'))
const Calendar = asyncComponent(() => import('../components/calendar'))
const AntvG6 = asyncComponent(() => import('../components/chart/antv-G6'))
const AntvX6 = asyncComponent(() => import('../components/chart/antv-X6'))
@@ -1055,6 +1056,12 @@
            <NormalTree config={item} data={data} mainSearch={mainSearch}/>
          </Col>
        )
      } else if (item.type === 'calendar') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>
            <Calendar config={item} mainSearch={mainSearch}/>
          </Col>
        )
      } else if (item.type === 'code') {
        return (
          <Col span={item.width} style={style} key={item.uuid}>