import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Select, Radio, Row, Col, Popover, Badge } from 'antd'
|
import moment from 'moment'
|
import 'moment/locale/zh-cn'
|
|
import MKEmitter from '@/utils/events.js'
|
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) {
|
const { datelist } = this.state
|
if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
|
this.setState({
|
datelist: this.mountdata(datelist, nextProps.data)
|
})
|
}
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
mountdata = (datelist, data) => {
|
return fromJS(datelist).toJS().map(month => {
|
month.subData = []
|
data.forEach(item => {
|
if (item.$startM <= month.time && item.$endM >= month.time) {
|
month.subData.push(item)
|
}
|
})
|
|
month.children = month.children.map(week => {
|
week.children = week.children.map(day => {
|
if (day.$disable) return day
|
|
day.subData = []
|
day.style = null
|
day.$level = 100
|
data.forEach(item => {
|
if (item.$start <= day.time && item.$end >= day.time) {
|
day.subData.push(item)
|
|
if (!day.style) {
|
day.style = item.$style
|
day.$level = item.$level
|
} else if (item.$level < day.$level) {
|
day.style = item.$style
|
day.$level = item.$level
|
}
|
}
|
})
|
return day
|
})
|
return week
|
})
|
return month
|
})
|
}
|
|
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 { data } = this.props
|
const { selectMonth } = this.state
|
let datelist = this.getDateList(value)
|
|
if (data.length > 0) {
|
datelist = this.mountdata(datelist, data)
|
}
|
|
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 })
|
|
this.props.yearChange(value)
|
}
|
|
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)
|
})
|
}
|
|
triggerDay = (d) => {
|
const { config } = this.props
|
|
if (!config.setting.linkbtn) return
|
|
let id = d.time + ''
|
id = id.substr(0, 4) + '-' + id.substr(4, 2) + '-' + id.substr(6)
|
|
MKEmitter.emit('triggerBtnId', config.setting.linkbtn, [{$$uuid: id}])
|
}
|
|
openView = (data, e) => {
|
const { config } = this.props
|
|
if (!config.wrap.click) return
|
|
e && e.stopPropagation()
|
|
if (config.wrap.click === 'menus') {
|
let menu = null
|
|
if (config.wrap.menus && config.wrap.menus.length > 0) {
|
let s = data[config.wrap.menuType] + ''
|
config.wrap.menus.forEach(m => {
|
if (s !== m.sign) return
|
menu = m
|
})
|
}
|
if (!menu) return
|
|
let newtab = {
|
MenuID: menu.MenuID,
|
MenuName: menu.MenuName,
|
MenuNo: menu.MenuNo || '',
|
type: menu.tabType,
|
param: {$BID: data.$$uuid || ''}
|
}
|
|
Object.keys(data).forEach(key => {
|
if (/^\$/.test(key)) return
|
newtab.param[key] = data[key]
|
})
|
|
MKEmitter.emit('modifyTabs', newtab, true)
|
} else if (config.wrap.click === 'menu') {
|
let menuId = config.wrap.menu.slice(-1)[0]
|
let menu = null
|
|
if (window.GLOB.mkThdMenus.has(menuId)) {
|
menu = {...window.GLOB.mkThdMenus.get(menuId)}
|
} else if (config.wrap.MenuID) {
|
menu = {
|
MenuID: config.wrap.MenuID,
|
MenuName: config.wrap.MenuName,
|
type: config.wrap.tabType
|
}
|
}
|
|
if (!menu) return
|
|
menu.param = {$BID: data.$$uuid || ''}
|
|
Object.keys(data).forEach(key => {
|
if (/^\$/.test(key)) return
|
menu.param[key] = data[key]
|
})
|
|
MKEmitter.emit('modifyTabs', menu, true)
|
}
|
}
|
|
render() {
|
const { config } = this.props
|
const { level, selectYear, selectMonth, yearlist, levels, datelist, monthlist } = this.state
|
const _levelName = {day: '日', month: '月', year: '年'}
|
|
return (
|
<div className={'mk-calendar' + (config.setting.linkbtn ? ' open-pop' : '') + (config.wrap.click ? ' open-menu' : '')}>
|
<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 style={d.style} className={'day-wrap' + (d.$disable ? ' disabled' : '')} onClick={() => !d.$disable && this.triggerDay(d)}>
|
{d.subData.length > 0 ? <Popover mouseEnterDelay={0.3} overlayClassName={'calendar-day-pop' + (config.wrap.click ? ' open-menu' : '')} content={
|
<div onClick={(e) => e.stopPropagation()}>
|
{d.subData.map((data, index) => (
|
<div key={index} className="message" onClick={() => this.openView(data)}>
|
<Badge color={data.$color} text={
|
<span>
|
{data.$message}
|
<span style={{color: 'rgba(0,0,0,.45)'}}>({data.$startTime + ' ~ ' + data.$endTime})</span>
|
</span>}
|
/>
|
</div>
|
))}
|
</div>
|
} trigger="hover">
|
{d.label}
|
</Popover> : 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' : '')} onClick={() => !d.$disable && this.triggerDay(d)}>
|
<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">
|
{d.subData.map((data, index) => (
|
<li key={index} className="message" onClick={(e) => this.openView(data, e)}>
|
<Badge color={data.$color} text={data.$message} />
|
</li>
|
))}
|
</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">
|
{item.subData.map((data, index) => (
|
<li key={index} className="message" onClick={() => this.openView(data)}>
|
<Badge color={data.$color} text={`${data.$message} (${data.$startTime} ~ ${data.$endTime})`}/>
|
</li>
|
))}
|
</ul>
|
</div>
|
</Col>
|
))}
|
</Row>: null}
|
</div>
|
</div>
|
)
|
}
|
}
|
|
export default CalendarBoard
|