import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Select, Radio, Row, Col, Badge } from 'antd'
|
import moment from 'moment'
|
|
import './index.scss'
|
|
const { Option } = Select
|
|
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 <= 50; 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 = null
|
|
if (_levels.includes('month')) {
|
monthlist = datelist.filter(item => item.month === moment().format('MM'))[0]
|
}
|
|
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
|
})
|
}
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
getNongLi = (nyear, nmonth, nday) => {
|
let jq = this.getjq(nyear, nmonth, nday)
|
|
if (jq) return jq
|
|
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
|
}
|
|
if (lday === '初一') {
|
return lmonth + '月'
|
}
|
|
return lday
|
}
|
|
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
|
}
|
|
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']
|
let monthName = {
|
'01': '一月', '02': '二月', '03': '三月', '04': '四月', '05': '五月', '06': '六月',
|
'07': '七月', '08': '八月', '09': '九月', '10': '十月', '11': '十一月', '12': '十二月'
|
}
|
|
months.forEach(month => {
|
let _weeklist = [{week: 1, sublist: []}]
|
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)
|
}
|
|
for (let i = 1; i <= end; i++) {
|
let _day = i < 10 ? `0${i}` : `${i}`
|
|
let item = {
|
day: _day,
|
time: selectYear + month + _day,
|
nltime: this.getNongLi(+selectYear, +month, +_day),
|
label: i,
|
subData: []
|
}
|
|
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)
|
}
|
}
|
|
let re = 7 - _weeklist.slice(-1)[0].sublist.length
|
for (let i = 0; i < re; i++) {
|
_weeklist[_weeklist.length - 1].sublist.push(null)
|
}
|
|
datelist.push({
|
month: month,
|
time: selectYear + month,
|
label: monthName[month],
|
sublist: _weeklist,
|
subData: []
|
})
|
})
|
|
return datelist
|
}
|
|
levelChange = (e) => {
|
this.setState({ level: e.target.value })
|
}
|
|
yearChange = (value) => {
|
const { levels, selectMonth } = this.state
|
let datelist = this.getDateList(value)
|
let monthlist = null
|
|
if (levels.includes('month')) {
|
monthlist = datelist.filter(item => item.month === selectMonth)[0]
|
}
|
|
this.setState({ selectYear: value, datelist, monthlist })
|
}
|
|
render() {
|
const { level, selectYear, yearlist, levels, datelist, monthlist } = this.state
|
const _levelName = {day: '日', month: '月'}
|
|
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>
|
{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.sublist.map(cell => (
|
<tr key={cell.week}>
|
{cell.sublist.map((d, i) => (
|
<td key={i}>
|
{d ? <div className="day-wrap" style={d.style || null}>
|
{d.label}
|
</div> : null }
|
</td>
|
))}
|
</tr>
|
))}
|
</tbody>
|
</table>
|
</Col>
|
))}
|
</Row> : null}
|
{level === 'month' && monthlist ? <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'}}>
|
{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>
|
</div>
|
</Col>
|
))}
|
</Row>: null}
|
</div>
|
</div>
|
)
|
}
|
}
|
|
export default CalendarBoard
|