# MCalendar 日历

- 来源：[E10 UI 组件库](https://www.e-cology.com.cn/ui/mobile/calendar/freepass)
- 平台：移动端
- 维护者：屈正巍
- 设计稿：http://pd.e-cology.com.cn/pd/E10/interface/e10xiaoguotu/H5/ch/rili/
- Issue：http://gitlab.ecology10.cn/FRONTEND/weapp-ui/-/issues?state=all&search=[MCalendar]

## 代码演示

### 基础用法

```jsx
import { Component } from 'react';
import { MCalendar, SlideTabs } from '@weapp/ui';

const data = [
  { id: 'month', content: '月', },
  { id: 'week', content: '周' },
  { id: 'doubleWeek', content: '双周', },
]

interface State {
  mode: any
}

class MCalendarDemo extends Component<any, State> {

  state = {
    mode: 'month' as any,
    // mode: 'week' as any
  }

  onSlideChange = (value: any) => {
    this.setState({ mode: value })
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  render() {
    const { mode } = this.state
    return (
      <div>
        <SlideTabs
          data={data}
          value={mode}
          onChange={this.onSlideChange}
        />
        <MCalendar
          mode={mode}
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 通过date控制面板

```jsx
import { Component } from 'react';
import { MButton, MCalendar, MDateTimePicker, MRadio, SlideTabs } from '@weapp/ui';

const data = [
  { id: 'month', content: '月', },
  { id: 'week', content: '周' },
  { id: 'doubleWeek', content: '双周', },
]

class MCalendarDemo extends Component<any> {

  ref: any;
  getRef = (dom: any) => this.ref = dom;

  state = {
    mode: 'month' as any,
    date: new Date(),
    calendarDate: new Date(),
    monthChangeAutoSelectFirstDate: true,
    pageChangeAnimation: true
  }

  onSlideChange = (value: any) => {
    this.setState({ mode: value })
  }

  onMDateTimePickerChange = (date: any) => {
    this.setState({ date })
  }

  toCustomDate = () => {
    this.setState({ calendarDate: this.state.date })
  }

  toLastMonth = () => {
    this.ref?.panelRef?.onLastMonth()
  }
  toNextMonth = () => {
    this.ref?.panelRef?.onNextMonth()
  }

  onMRadioChange = (value: any) => {
    this.setState({ monthChangeAutoSelectFirstDate: value })
  }

  onMRadioChange2 = (value: any) => {
    this.setState({ pageChangeAnimation: value })
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    this.setState({ calendarDate: new Date(month[0]) })
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  render() {
    const { mode, date, calendarDate, monthChangeAutoSelectFirstDate, pageChangeAnimation } = this.state
    return (
      <div>
        <MDateTimePicker placeholder={'选择准备跳转的日期'} onChange={this.onMDateTimePickerChange} value={date} type={'day'} />
        <MButton onClick={this.toCustomDate} type={'default'}>点击改变date到选中日期</MButton>
        <MButton onClick={this.toLastMonth} >跳转前一个月</MButton>
        <MButton onClick={this.toNextMonth}>跳转后一个月</MButton>
        <MRadio value={monthChangeAutoSelectFirstDate} onChange={this.onMRadioChange}>翻页是否自动选中第一天</MRadio>
        <MRadio value={pageChangeAnimation} onChange={this.onMRadioChange2}>开启翻页动画</MRadio>
        <SlideTabs
          data={data}
          value={mode}
          onChange={this.onSlideChange}
        />
        <MCalendar
          mode={mode}
          ref={this.getRef}
          date={calendarDate}
          weekStart={2}
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          monthChangeAutoSelectFirstDate={monthChangeAutoSelectFirstDate}
          monthChangePreventOnCellClick
          pageChangeAnimation={pageChangeAnimation}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 通过ref控制面板

```jsx
import { Component } from 'react';
import { MButton, MCalendar, MDateTimePicker, MRadio, SlideTabs } from '@weapp/ui';

const data = [
  { id: 'month', content: '月', },
  { id: 'week', content: '周' },
  { id: 'doubleWeek', content: '双周', },
]
class MCalendarDemo extends Component<any> {

  ref: any;
  getRef = (dom: any) => this.ref = dom;

  state = {
    mode: 'month' as any,
    date: new Date(),
    monthChangeAutoSelectFirstDate: true,
    pageChangeAnimation: true
  }

  onSlideChange = (value: any) => {
    this.setState({ mode: value })
  }

  consoleRef = () => {
    console.info('this.ref', this.ref)
    console.info('this.ref?.panelRef', this.ref?.panelRef)
  }

  onMDateTimePickerChange = (date: any) => {
    this.setState({ date })
  }

  toCustomDate = () => {
    this.ref?.panelRef?.toCustomDate(this.state.date)
  }

  toLastMonth = () => {
    this.ref?.panelRef?.onLastMonth()
  }
  toNextMonth = () => {
    this.ref?.panelRef?.onNextMonth()
  }

  onMRadioChange = (value: any) => {
    this.setState({ monthChangeAutoSelectFirstDate: value })
  }

  onMRadioChange2 = (value: any) => {
    this.setState({ pageChangeAnimation: value })
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  render() {
    const { mode, date, monthChangeAutoSelectFirstDate, pageChangeAnimation } = this.state
    return (
      <div>
        <MButton onClick={this.consoleRef} type={'default'}>点击输出日历ref</MButton>
        <MDateTimePicker placeholder={'选择准备跳转的日期'} onChange={this.onMDateTimePickerChange} value={date} type={'day'} />
        <MButton onClick={this.toCustomDate} type={'default'}>点击选择到选中的日期</MButton>
        <MButton onClick={this.toLastMonth} >跳转前一个月</MButton>
        <MButton onClick={this.toNextMonth}>跳转后一个月</MButton>
        <MRadio value={monthChangeAutoSelectFirstDate} onChange={this.onMRadioChange}>翻页是否自动选中第一天</MRadio>
        <MRadio value={pageChangeAnimation} onChange={this.onMRadioChange2}>开启翻页动画</MRadio>
        <SlideTabs
          data={data}
          value={mode}
          onChange={this.onSlideChange}
        />
        <MCalendar
          mode={mode}
          ref={this.getRef}
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          monthChangeAutoSelectFirstDate={monthChangeAutoSelectFirstDate}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 基础用法(双周)

```jsx
import { Component } from 'react';
import { MCalendar } from '@weapp/ui';

class MCalendarDemo extends Component<any, any> {

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  render() {
    return (
      <div>
        <p>初始面板为月，切换到双周模式</p>
        <MCalendar
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          mode={'month'}
          weekMode={'doubleWeek'}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 周导航栏与周起始日

```jsx
import { Component } from 'react';
import { MCalendar, MSelect, MRadio } from '@weapp/ui';

const options = [
  { id: '0', content: '周天' },
  { id: '1', content: '周一' },
  { id: '2', content: '周二' },
  { id: '3', content: '周三' },
  { id: '4', content: '周四' },
  { id: '5', content: '周五' },
  { id: '6', content: '周六' },
]

class MCalendarDemo extends Component<any, any> {

  state = {
    weekStart: '3',
    isShowWeekBar: true
  }

  onMRadioChange = (value: any) => {
    this.setState({ isShowWeekBar: value })
  }

  onMSelectChange = (data: any) => {
    this.setState({ weekStart: data })
  }

  render() {
    const { weekStart, isShowWeekBar } = this.state
    return (
      <div>
        <p>如果没有传入weekStart则读取后台配置</p>
        <p>自定义周起始日</p>
        <div style={{ background: '#fff' }}>
          <MSelect
            data={options}
            onChange={this.onMSelectChange}
            value={weekStart}
          />
        </div>
        <MRadio value={isShowWeekBar} onChange={this.onMRadioChange}>是否开启周导航栏</MRadio>
        <MCalendar
          isShowWeekBar={isShowWeekBar}
          weekStart={Number(weekStart)}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 禁止上下左右滑动

```jsx
import { Component } from 'react';
import { MCalendar } from '@weapp/ui';

class MCalendarDemo extends Component<any, any> {

  render() {
    return (
      <div>
        <p>通过disableScrollX和disableScrollY控制是否能滑动</p>
        <MCalendar
          disableScrollX
          disableScrollY
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 自定义列

```jsx
import { Component } from 'react';
import { MCalendar, MSelect } from '@weapp/ui';

const options = [
  { id: '1', content: '一列' },
  { id: '2', content: '两列' },
  { id: '3', content: '三列' },
  { id: '4', content: '四列' },
  { id: '5', content: '五列' },
  { id: '6', content: '六列' },
  { id: '7', content: '七列' },
]

class MCalendarDemo extends Component<any> {

  state = {
    customColumn: '5'
  }

  onMSelectChange = (data: any) => {
    this.setState({ customColumn: data })
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  render() {
    const { customColumn } = this.state
    return (
      <div>
        <h4>注意：当customColumn生效时，disabledChangeMode属性默认开启</h4>
        <h4>注意：当customColumn生效且不为7时，isShowWeekStartBar属性默认关闭</h4>
        <p>选择自定义列数</p>
        <MSelect
          data={options}
          onChange={this.onMSelectChange}
          value={customColumn}
        />
        <p>基础用法</p>
        <MCalendar
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          onCellClick={this.onCellClick}
          customColumn={Number(customColumn)}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 自定义头部底部

```jsx
import { Component } from 'react';
import { MCalendar } from '@weapp/ui';

class MCalendarDemo extends Component<any> {

  renderHeader = () => {
    return <div style={{ border: '1px solid red', display: 'flex', justifyContent: 'center' }}>自定义渲染头部</div>
  }
  renderFooter = () => {
    return <div style={{ border: '1px solid red', display: 'flex', justifyContent: 'center' }}>自定义渲染底部</div>
  }

  render() {
    return (
      <div>
        <p>自定义渲染</p>
        <MCalendar
          renderHeader={this.renderHeader}
          renderFooter={this.renderFooter}
        />
        <p>自定义标题</p>
        <MCalendar
          extraTitle={'日历标题自定义'}
        />
        <p>隐藏头部</p>
        <MCalendar
          hideHeader
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 自定义渲染指定日期

```jsx
import { Component } from 'react';
import { MCalendar, Button } from '@weapp/ui';

const dateExtra = {
  '2024-05-16': { info: true, sign: { text: '休', color: 'green' } },
  '2024-05-17': { info: true, sign: { text: '班', textIcon: 'Icon-WeChat03-o', color: '#FAAD14' } },
  '2024-05-18': { info: true, sign: { textIcon: 'Icon-robot', color: '#5d9cec' } },
}

class MCalendarDemo extends Component<any, any> {

  constructor(props: any) {
    super(props);
    this.state = {
      dateExtra: {
        '2024-05-15': { info: true, sign: { text: '班' }, cellRender: this.cellRender },
      },
    }
  }

  cellRender = (el: any) => {
    return (
      <div style={{ border: '1px solid red' }}>
        {el.children}
      </div>
    )
  }

  getDateExtra = () => {
    const newData = Object.assign({}, this.state.dateExtra, dateExtra)
    this.setState({ dateExtra: newData })
  }

  render() {
    const { dateExtra } = this.state
    return (
      <div>
        <Button onClick={this.getDateExtra}>点击异步获取dateExtra</Button>
        <MCalendar
          date={'2024-05-02'}
          dateExtra={dateExtra}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 自定义渲染每个单元格

```jsx
import { Component } from 'react';
import { MCalendar } from '@weapp/ui';

class MCalendarDemo extends Component<any> {

  renderCellItem = (el: any) => {
    console.info('renderCellItem el: ', el)
    return (
      <div style={{ border: '1px solid red' }}>
        {el.children}
      </div>
    )
  }

  render() {
    return (
      <div>
        <MCalendar
          renderCellItem={this.renderCellItem}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### H5高度塌陷问题测试

```jsx
import { Component } from 'react';
import { MCalendar } from '@weapp/ui';

class MCalendarDemo extends Component<any> {

  render() {
    return (
      <div>
        <p>111111</p>
        <p>222222</p>
        <p>333333</p>
        <p>444444</p>
        <p>555555</p>
        <p>666666</p>
        <p>777777</p>
        <p>888888</p>
        <p>999999</p>
        <p>111111</p>
        <p>222222</p>
        <p>333333</p>
        <p>444444</p>
        <p>555555</p>
        <p>666666</p>
        <p>777777</p>
        <p>888888</p>
        <p>999999</p>
        <p>111111</p>
        <p>222222</p>
        <p>333333</p>
        <p>444444</p>
        <p>555555</p>
        <p>666666</p>
        <p>777777</p>
        <p>888888</p>
        <p>999999</p>
        <MCalendar />
        <p>111111</p>
        <p>222222</p>
        <p>333333</p>
        <p>444444</p>
        <p>555555</p>
        <p>666666</p>
        <p>777777</p>
        <p>888888</p>
        <p>999999</p>
        <p>111111</p>
        <p>222222</p>
        <p>333333</p>
        <p>444444</p>
        <p>555555</p>
        <p>666666</p>
        <p>777777</p>
        <p>888888</p>
        <p>999999</p>
        <p>111111</p>
        <p>222222</p>
        <p>333333</p>
        <p>444444</p>
        <p>555555</p>
        <p>666666</p>
        <p>777777</p>
        <p>888888</p>
        <p>999999</p>
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 宽度不够横向滚动

```jsx
import { Component } from 'react';
import { MCalendar } from '@weapp/ui';

class MCalendarDemo extends Component<any, any> {

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  render() {
    return (
      <div style={{ border: '1px solid red' }}>
        <p>h5端测试滚动效果不太明显，具体可以移步pc端的Calendar组件【h5日历面板】demo进行测试</p>
        <MCalendar
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 农历与节气

```jsx
import { Component } from 'react';
import { MCalendar, MRadio } from '@weapp/ui';

class MCalendarDemo extends Component<any> {

  state = {
    hideLunar: true,
    showSolarTerm: true
  }

  onMRadioChange1 = (value: any) => {
    this.setState({ hideLunar: value })
  }

  onMRadioChange2 = (value: any) => {
    this.setState({ showSolarTerm: value })
  }

  render() {
    const { hideLunar, showSolarTerm } = this.state
    return (
      <div>
        <MRadio value={hideLunar} onChange={this.onMRadioChange1}>是否隐藏农历（注意在非中文模式下会自动开启此api）</MRadio>
        <MRadio value={showSolarTerm} onChange={this.onMRadioChange2}>是否展示节气</MRadio>
        <p>使用hideLunar隐藏农历 注意在非中文模式下会自动开启此api</p>
        <MCalendar
          hideLunar={hideLunar}
          showSolarTerm={showSolarTerm}
        />
        <p>可以自定义农历展示</p>
        <MCalendar
          solarFestival={['0301 三月一号', '0302 三月二号', '0303 三月三号', '0304 三月四号', '0305 三月五号']}
          lunarFestival={['0301 三月初一', '0302 三月初二', '0303 三月初三', '0304 三月初四', '0305 三月初五']}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 头部导航栏拓展

```jsx
import { Component } from 'react';
import { MCalendar, SlideTabs } from '@weapp/ui';

const data = [
  { id: 'month', content: '月', },
  { id: 'week', content: '周' },
  { id: 'doubleWeek', content: '双周', },
]

interface State {
  mode: any
}

class MCalendarDemo extends Component<any, State> {

  state = {
    mode: 'month' as any,
    // mode: 'week' as any
  }

  onSlideChange = (value: any) => {
    this.setState({ mode: value })
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  render() {
    const { mode } = this.state
    return (
      <div>
        <SlideTabs
          data={data}
          value={mode}
          onChange={this.onSlideChange}
        />
        <MCalendar
          mode={mode}
        // onCellClick={this.onCellClick}
        // onMonthChange={this.onMonthChange}
        // onPanelChange={this.onPanelChange}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 范围选择

```jsx
import { Component } from 'react';
import { MCalendar, MSelect } from '@weapp/ui';

const options1 = [
  { id: '1', content: '一列' },
  { id: '2', content: '两列' },
  { id: '3', content: '三列' },
  { id: '4', content: '四列' },
  { id: '5', content: '五列' },
  { id: '6', content: '六列' },
  { id: '7', content: '七列' },
]

const options2 = [
  { id: '0', content: '周天' },
  { id: '1', content: '周一' },
  { id: '2', content: '周二' },
  { id: '3', content: '周三' },
  { id: '4', content: '周四' },
  { id: '5', content: '周五' },
  { id: '6', content: '周六' },
]

interface State {
  rangeSelectedDate: string[]
  customColumn: string
  weekStart: string
}

class MCalendarDemo extends Component<any, State> {
  constructor(props: any) {
    super(props);
    this.state = {
      // rangeSelectedDate: ['2024-05-11', '2024-05-20'],
      rangeSelectedDate: ['2024-05-27', '2024-05-28'],
      customColumn: '7',
      weekStart: '1'
    }
  }

  onMSelectChange1 = (data: any) => {
    this.setState({ customColumn: data })
  }

  onMSelectChange2 = (data: any) => {
    this.setState({ weekStart: data })
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  render() {
    const { customColumn, weekStart, rangeSelectedDate } = this.state
    return (
      <div>
        <p>选择自定义列数</p>
        <MSelect
          data={options1}
          onChange={this.onMSelectChange1}
          value={customColumn}
        />
        <p>选择自定义周起始日</p>
        <MSelect
          data={options2}
          onChange={this.onMSelectChange2}
          value={weekStart}
        />
        <MCalendar
          type={'range'}
          date={'2024-05'}
          customColumn={Number(customColumn)}
          weekStart={Number(weekStart)}
          rangeSelectedDate={rangeSelectedDate}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          onCellClick={this.onCellClick}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 范围选择(双周)

```jsx
import { Component } from 'react';
import { MCalendar, MSelect } from '@weapp/ui';

const options1 = [
  { id: '1', content: '一列' },
  { id: '2', content: '两列' },
  { id: '3', content: '三列' },
  { id: '4', content: '四列' },
  { id: '5', content: '五列' },
  { id: '6', content: '六列' },
  { id: '7', content: '七列' },
]

const options2 = [
  { id: '0', content: '周天' },
  { id: '1', content: '周一' },
  { id: '2', content: '周二' },
  { id: '3', content: '周三' },
  { id: '4', content: '周四' },
  { id: '5', content: '周五' },
  { id: '6', content: '周六' },
]

interface State {
  rangeSelectedDate: string[]
  customColumn: string
  weekStart: string
}

class MCalendarDemo extends Component<any, State> {
  constructor(props: any) {
    super(props);
    this.state = {
      // rangeSelectedDate: ['2024-05-11', '2024-05-20'],
      rangeSelectedDate: ['2024-05-27', '2024-05-28'],
      customColumn: '7',
      weekStart: '1'
    }
  }

  onMSelectChange1 = (data: any) => {
    this.setState({ customColumn: data })
  }

  onMSelectChange2 = (data: any) => {
    this.setState({ weekStart: data })
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  render() {
    const { customColumn, weekStart, rangeSelectedDate } = this.state
    return (
      <div>
        <p>选择自定义列数</p>
        <MSelect
          data={options1}
          onChange={this.onMSelectChange1}
          value={customColumn}
        />
        <p>选择自定义周起始日</p>
        <MSelect
          data={options2}
          onChange={this.onMSelectChange2}
          value={weekStart}
        />
        <MCalendar
          type={'range'}
          date={'2024-05'}
          customColumn={Number(customColumn)}
          weekStart={Number(weekStart)}
          rangeSelectedDate={rangeSelectedDate}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          onCellClick={this.onCellClick}
          weekMode={'doubleWeek'}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 多选日期

```jsx
import { Component } from 'react';
import { MCalendar, MSelect } from '@weapp/ui';

const options1 = [
  { id: '1', content: '一列' },
  { id: '2', content: '两列' },
  { id: '3', content: '三列' },
  { id: '4', content: '四列' },
  { id: '5', content: '五列' },
  { id: '6', content: '六列' },
  { id: '7', content: '七列' },
]

const options2 = [
  { id: '0', content: '周天' },
  { id: '1', content: '周一' },
  { id: '2', content: '周二' },
  { id: '3', content: '周三' },
  { id: '4', content: '周四' },
  { id: '5', content: '周五' },
  { id: '6', content: '周六' },
]

interface State {
  multipleSelectedDate: string[]
  customColumn: string
  weekStart: string
}

class MCalendarDemo extends Component<any, State> {
  constructor(props: any) {
    super(props);
    this.state = {
      multipleSelectedDate: ['2024-04-01', '2024-04-30', '2024-05-01', '2024-05-03', '2024-05-09', '2024-05-11', '2024-05-30', '2024-06-01', '2024-06-30'],
      customColumn: '7',
      weekStart: '1'
    }
  }

  onMSelectChange1 = (data: any) => {
    this.setState({ customColumn: data })
  }

  onMSelectChange2 = (data: any) => {
    this.setState({ weekStart: data })
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  render() {
    const { customColumn, weekStart, multipleSelectedDate } = this.state
    return (
      <div>
        <p>选择自定义列数</p>
        <MSelect
          data={options1}
          onChange={this.onMSelectChange1}
          value={customColumn}
        />
        <p>选择自定义周起始日</p>
        <MSelect
          data={options2}
          onChange={this.onMSelectChange2}
          value={weekStart}
        />
        <MCalendar
          type={'multiple'}
          date={'2024-05'}
          customColumn={Number(customColumn)}
          weekStart={Number(weekStart)}
          multipleSelectedDate={multipleSelectedDate}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          onCellClick={this.onCellClick}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 多选日期(双周)

```jsx
import { Component } from 'react';
import { MCalendar, MSelect } from '@weapp/ui';

const options1 = [
  { id: '1', content: '一列' },
  { id: '2', content: '两列' },
  { id: '3', content: '三列' },
  { id: '4', content: '四列' },
  { id: '5', content: '五列' },
  { id: '6', content: '六列' },
  { id: '7', content: '七列' },
]

const options2 = [
  { id: '0', content: '周天' },
  { id: '1', content: '周一' },
  { id: '2', content: '周二' },
  { id: '3', content: '周三' },
  { id: '4', content: '周四' },
  { id: '5', content: '周五' },
  { id: '6', content: '周六' },
]

interface State {
  multipleSelectedDate: string[]
  customColumn: string
  weekStart: string
}

class MCalendarDemo extends Component<any, State> {
  constructor(props: any) {
    super(props);
    this.state = {
      multipleSelectedDate: ['2024-04-01', '2024-04-30', '2024-05-01', '2024-05-03', '2024-05-09', '2024-05-11', '2024-05-30', '2024-06-01', '2024-06-30'],
      customColumn: '7',
      weekStart: '1'
    }
  }

  onMSelectChange1 = (data: any) => {
    this.setState({ customColumn: data })
  }

  onMSelectChange2 = (data: any) => {
    this.setState({ weekStart: data })
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  render() {
    const { customColumn, weekStart, multipleSelectedDate } = this.state
    return (
      <div>
        <p>选择自定义列数</p>
        <MSelect
          data={options1}
          onChange={this.onMSelectChange1}
          value={customColumn}
        />
        <p>选择自定义周起始日</p>
        <MSelect
          data={options2}
          onChange={this.onMSelectChange2}
          value={weekStart}
        />
        <MCalendar
          type={'multiple'}
          date={'2024-05'}
          customColumn={Number(customColumn)}
          weekStart={Number(weekStart)}
          multipleSelectedDate={multipleSelectedDate}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          onCellClick={this.onCellClick}
          weekMode={'doubleWeek'}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 周模式

```jsx
import { Component } from 'react';
import { MCalendar, MRadio } from '@weapp/ui';

class MCalendarDemo extends Component<any, any> {

  state = {
    monthChangeAutoSelectFirstDate: true
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  onMRadioChange = (value: any) => {
    this.setState({ monthChangeAutoSelectFirstDate: value })
  }

  render() {
    const { monthChangeAutoSelectFirstDate } = this.state
    return (
      <div>
        <MRadio value={monthChangeAutoSelectFirstDate} onChange={this.onMRadioChange}>翻页是否自动选中第一天</MRadio>
        <p>周模式</p>
        <MCalendar
          monthChangeAutoSelectFirstDate={monthChangeAutoSelectFirstDate}
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          mode={'week'}

        />
        <p>开启周导航栏</p>
        <MCalendar
          monthChangeAutoSelectFirstDate={monthChangeAutoSelectFirstDate}
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          isShowWeekBar
          mode={'week'}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 双周模式

```jsx
import { Component } from 'react';
import { MCalendar, MRadio } from '@weapp/ui';

class MCalendarDemo extends Component<any, any> {

  state = {
    monthChangeAutoSelectFirstDate: true
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  onMRadioChange = (value: any) => {
    this.setState({ monthChangeAutoSelectFirstDate: value })
  }

  render() {
    const { monthChangeAutoSelectFirstDate } = this.state
    return (
      <div>
        <MRadio value={monthChangeAutoSelectFirstDate} onChange={this.onMRadioChange}>翻页是否自动选中第一天</MRadio>
        <p>双周模式</p>
        <MCalendar
          monthChangeAutoSelectFirstDate={monthChangeAutoSelectFirstDate}
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          mode={'doubleWeek'}

        />
        <p>开启周导航栏</p>
        <MCalendar
          monthChangeAutoSelectFirstDate={monthChangeAutoSelectFirstDate}
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          isShowWeekBar
          mode={'doubleWeek'}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

### 接入考勤数据

```jsx
import { Component } from 'react';
import { MCalendar, SlideTabs, Switch } from '@weapp/ui';

const data = [
  { id: 'month', content: '月', },
  { id: 'week', content: '周' },
  { id: 'doubleWeek', content: '双周', },
]

interface State {
  mode: any
  useAttendanceHoliday: boolean
  useAttendanceSameViewHoliday: boolean
  dateExtra: any
}

class MCalendarDemo extends Component<any, State> {

  state = {
    mode: 'month' as any,
    useAttendanceHoliday: true,
    useAttendanceSameViewHoliday: false,
    dateExtra: {
      "2025-05-02": {
        "info": true,
        "count": 1
      },
      "2025-05-12": {
        "info": true,
        "count": 1
      },
      "2025-06-01": {
        "info": true,
        "count": 1
      },
      "2025-05-14": {
        "info": true,
        "count": 1
      },
      "2025-05-19": {
        "info": true,
        "count": 1
      },
      "2025-05-15": {
        "info": true,
        "count": 2
      },
      "2025-05-20": {
        "info": true,
        "count": 1
      },
      "2025-05-13": {
        "info": true,
        "count": 1
      },
      "2025-05-01": {
        "info": true,
        "count": 1
      },
      "2025-05-31": {
        "info": true,
        "count": 1
      }
    }
  }

  onCellClick = (date: Date) => {
    console.info('onCellClick', date)
  }

  onMonthChange = (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => {
    console.info('面板月份', month)
    console.info('当前展示面板的开始和结束日期', range)
    console.info('当前标题', title)
    console.info('当前模式', mode)
    console.info('当前区间选择的开始和结束日期', selectRange)
  }

  onPanelChange = (data: any) => {
    console.info('onPanelChange', data)
  }

  onSlideChange = (value: any) => this.setState({ mode: value })
  onUseAttendanceHolidayChange = (value: any) => this.setState({ useAttendanceHoliday: value })
  onUseAttendanceSameViewHolidayChange = (value: any) => this.setState({ useAttendanceSameViewHoliday: value })

  render() {
    const { mode, useAttendanceHoliday, useAttendanceSameViewHoliday, dateExtra } = this.state
    return (
      <div>
        <div style={{ display: 'flex', minHeight: 40, alignItems: 'center' }}>
          <span>是否同步考勤接口数据：</span>
          <Switch value={useAttendanceHoliday} onChange={this.onUseAttendanceHolidayChange} />
        </div>
        <div style={{ display: 'flex', minHeight: 40, alignItems: 'center' }}>
          <span>是否仅显示当前面板同数据：</span>
          <Switch value={useAttendanceSameViewHoliday} onChange={this.onUseAttendanceSameViewHolidayChange} />
        </div>
        <SlideTabs
          data={data}
          value={mode}
          onChange={this.onSlideChange}
        />
        <MCalendar
          mode={mode}
          dateExtra={dateExtra}
          onCellClick={this.onCellClick}
          onMonthChange={this.onMonthChange}
          onPanelChange={this.onPanelChange}
          useAttendanceHoliday={useAttendanceHoliday}
          useAttendanceSameViewHoliday={useAttendanceSameViewHoliday}
        />
      </div>
    );
  }
}

export default MCalendarDemo;
```

## API

### 新版日历注意：

```typescript
1.历史的onMonthChange方法参数传递不太完善要逐渐废弃，后续将采用onPanelChange方法
2.如果需要自定义改变面板的，可以采用面板ref抛出的 panelRef?.toCustomDate 方法来改变，具体可以参考demo2
```

### dataExtra说明：

```typescript
按照以下下数据为例
const dateExtra =  {
        '2021-05-15': { info: true, sign: { text: '班' }, cellRender: this.cellRender },
        '2021-05-16': { info: true, sign: { text: '休', color: 'green' } },
        '2021-05-17': { info: true, sign: { text: '班', textIcon: 'Icon-WeChat03-o', color: '#FAAD14' } },
        '2021-05-18': { info: true, sign: { textIcon: 'Icon-robot', color: '#5d9cec' } },
      }
1.sign表示开启额外数据展示
2.当sign中的text存在时，开启月模式单元格头部右上角展示（展示文字），当textIcon存在时，右上角展示图标，text内容在鼠标hover时出现
3.color表示右上角展示底色
```

### 参数说明：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| type | 选择器类型 | one / range / multiple |  | one |
| rangeSelectedDate | type 为 range 时默认选中时间区间 | string[] |  |  |
| multipleSelectedDate | type 为 multiple 时默认选中时间区间 | string[] |  |  |
| mode | 日期加载模式 | 'month' \|'week'\|'doubleWeek' |  | month |
| weekMode | 初始mode为month时，决定切换模式时切换到周/双周 | 'week'\|'doubleWeek' |  | month |
| rowSize | 行大小 | 'normal' , 'xl' |  | normal |
| isShowWeekBar | 左侧第几周显示栏 | boolean |  | false |
| isShowWeekStartBar | 上方周几导航栏 | boolean |  | true |
| disabledChangeMode | 禁止切换周月模式 | boolean |  | false |
| dateExtra | 日期额外数据 | any |  |  |
| extraTitle | 日历额外扩展标题 | any |  |  |
| weekStart | 每周起始天 | number |  | 1 |
| hideLunar | 是否隐藏农历 | Boolean |  | false |
| date | 根据该 date 受控当前面板 | Date |  |  |
| defaultDate | 面板初始化 date | Date |  |  |
| maxDate | 最大日期 | Date |  |  |
| minDate | 最小日期 | Date |  |  |
| onCellClick | 日期点击回调 | (date: Date, rangeDate?: string[]) => void |  |  |
| onMonthChange（后续废弃，采用onPanelChange） | 当日历面板改变时的回调 | (month: string[], range: string[], title: string, mode: string, selectRange?: any[]) => any |  |  |
| onPanelChange | 当日历面板改变时的回调 | (data: AnyObj) => any |  |  |
| renderTitle | 自定义 title | (title: Date) => React.ReactNode; |  |  |
| onLayout | 获取日历高度 | (clientHight: number) => void |  |  |
| renderFooter | 底部自定义渲染 | (mode: string) => React.ReactNode |  |  |
| hideHeader | 隐藏头部 | boolean |  | false |
| renderHeader | 头部自定义渲染 | (date: Date) => React.ReactNode |  |  |
| renderCellItem | 日期自定义渲染 | (data?: any) => React.ReactNode |  |  |
| customColumn | 自定义列 | number(取值在1-6之间) |  |  |
| monthChangeAutoSelectFirstDate | 翻页是否自动选中第一天 | boolean | true |  |
| solarFestival | 阳历节日 | string[] |  |  |
| lunarFestival | 阴历节日 | string[] |  |  |
| showSolarTerm | 是否展示节气 | boolean |  |  |
| pageChangeAnimation | 月份切换是否开启动画 | boolean | boolean | true |
| useAttendanceHoliday | 是否接入考勤组接口数据 | boolean |  |  |
| useAttendanceSameViewHoliday | 是否使用面板内同视图的节假日数据 | boolean |  |  |
