| | |
| | | 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 { Select, Radio, Row, Col, Popover, Badge, Spin } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | // import Utils from '@/utils/utils.js' |
| | | import './index.scss' |
| | | |
| | | const { Option } = Select |
| | |
| | | class Calendar extends Component { |
| | | static propTpyes = { |
| | | data: PropTypes.any, // 事件数据 |
| | | levels: PropTypes.any |
| | | calendar: PropTypes.any, |
| | | changeDate: PropTypes.func, |
| | | triggerDate: PropTypes.func, |
| | | loading: false |
| | | } |
| | | |
| | | state = { |
| | |
| | | selectYear: moment().format('YYYY'), |
| | | selectMonth: moment().format('MM'), |
| | | datelist: null, |
| | | monthlist: null, |
| | | monthlist: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { levels } = this.props |
| | | const { calendar, data } = this.props |
| | | |
| | | let yearlist = [] |
| | | let _selectYear = +this.state.selectYear |
| | |
| | | } |
| | | |
| | | let datelist = this.getDateList(this.state.selectYear) |
| | | let _levels = null |
| | | |
| | | if (!levels) { |
| | | _levels = ['day', 'month', 'year'] |
| | | } else { |
| | | _levels = levels |
| | | if (data && data.length > 0) { |
| | | datelist = this.mountdata(datelist, data) |
| | | } |
| | | |
| | | |
| | | let _levels = calendar.levels |
| | | let level = _levels[0] |
| | | let monthlist = null |
| | | level = 'month' |
| | | |
| | | if (_levels.includes('month')) { |
| | | if (_levels.includes('month') || _levels.includes('year')) { |
| | | monthlist = datelist.filter(item => item.month === moment().format('MM'))[0] |
| | | } |
| | | |
| | |
| | | |
| | | UNSAFE_componentWillReceiveProps(nextProps) { |
| | | if (!is(fromJS(this.props.data), fromJS(nextProps.data))) { |
| | | let datelist = this.getDateList(this.state.selectYear) |
| | | let monthlist = null |
| | | |
| | | datelist = this.mountdata(datelist, nextProps.data) |
| | | |
| | | if (this.state.levels.includes('month') || this.state.levels.includes('year')) { |
| | | monthlist = datelist.filter(item => item.month === this.state.selectMonth)[0] |
| | | } |
| | | |
| | | this.setState({ |
| | | datelist: datelist, |
| | | monthlist |
| | | }) |
| | | } else if (!is(fromJS(this.props.calendar), fromJS(nextProps.calendar))) { |
| | | this.setState({ |
| | | levels: nextProps.calendar.levels |
| | | }) |
| | | } |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | return !is(fromJS(this.props.loading), fromJS(nextProps.loading)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | mountdata = (datelist, data) => { |
| | | const { calendar } = this.props |
| | | |
| | | let datalist = [] |
| | | let colors = { |
| | | transparent: 'rgba(0, 0, 0, 0)', |
| | | red: 'rgba(208, 2, 27, 1)', |
| | | orange: 'rgba(245, 166, 35, 1)', |
| | | yellow: 'rgba(248, 231, 28, 1)', |
| | | green: 'rgba(126, 211, 33, 1)', |
| | | cyan: 'rgba(80, 227, 194, 1)', |
| | | blue: 'rgba(24, 144, 255, 1)', |
| | | purple: 'rgba(189, 16, 224, 1)', |
| | | gray: 'rgba(155, 155, 155, 1)' |
| | | } |
| | | |
| | | data && data.forEach(item => { |
| | | let startTime = item[calendar.startfield] |
| | | let endTime = item[calendar.endfield] |
| | | let color = item[calendar.colorfield] |
| | | |
| | | if (!startTime || !/^(1|2)\d{3}(-|\/)\d{2}(-|\/)\d{2}/.test(startTime)) return |
| | | if (!endTime || !/^(1|2)\d{3}(-|\/)\d{2}(-|\/)\d{2}/.test(endTime)) return |
| | | if (!item[calendar.remarkfield]) return |
| | | |
| | | let equal = endTime.substr(0, 4) === startTime.substr(0, 4) |
| | | |
| | | datalist.push({ |
| | | color: colors[color] || color, |
| | | remark: item[calendar.remarkfield], |
| | | startMonth: startTime.substr(0, 4) + startTime.substr(5, 2), |
| | | endMonth: endTime.substr(0, 4) + endTime.substr(5, 2), |
| | | start: startTime.substr(0, 4) + startTime.substr(5, 2) + startTime.substr(8, 2), |
| | | startTime: equal ? `${startTime.substr(5, 2)}-${startTime.substr(8, 2)}` : `${startTime.substr(0, 4)}-${startTime.substr(5, 2)}-${startTime.substr(8, 2)}`, |
| | | end: endTime.substr(0, 4) + endTime.substr(5, 2) + endTime.substr(8, 2), |
| | | endTime: equal ? `${endTime.substr(5, 2)}-${endTime.substr(8, 2)}` : `${endTime.substr(0, 4)}-${endTime.substr(5, 2)}-${endTime.substr(8, 2)}` |
| | | }) |
| | | }) |
| | | |
| | | return datelist.map(month => { |
| | | month.subData = [] |
| | | datalist.forEach(item => { |
| | | if (item.startMonth <= month.time && item.endMonth >= month.time) { |
| | | month.subData.push(item) |
| | | } |
| | | }) |
| | | month.style = this.getStyle(month.subData[0]) |
| | | month.sublist = month.sublist.map(week => { |
| | | week.sublist = week.sublist.map(day => { |
| | | if (!day) return null |
| | | |
| | | day.subData = [] |
| | | datalist.forEach(item => { |
| | | if (item.start <= day.time && item.end >= day.time) { |
| | | day.subData.push(item) |
| | | } |
| | | }) |
| | | day.style = this.getStyle(day.subData[0]) |
| | | return day |
| | | }) |
| | | return week |
| | | }) |
| | | return month |
| | | }) |
| | | } |
| | | |
| | | 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) => { |
| | |
| | | } |
| | | |
| | | for (let i = 1; i <= end; i++) { |
| | | let _day = i < 10 ? `0${i}` : `${i}` |
| | | |
| | | if (_weeklist[_weeklist.length - 1].sublist.length < 7) { |
| | | _weeklist[_weeklist.length - 1].sublist.push({day: i < 10 ? `0${i}` : `${i}`, label: i}) |
| | | _weeklist[_weeklist.length - 1].sublist.push({day: _day, time: selectYear + month + _day, label: i, subData: []}) |
| | | } else { |
| | | let _week = {week: _weeklist.length + 1, sublist: [{day: i < 10 ? `0${i}` : `${i}`, label: i}]} |
| | | let _week = {week: _weeklist.length + 1, sublist: [{day: _day, time: selectYear + month + _day, label: i, subData: []}]} |
| | | _weeklist.push(_week) |
| | | } |
| | | } |
| | | |
| | | let re = 7 - _weeklist[_weeklist.length - 1].sublist.length |
| | | 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 |
| | | sublist: _weeklist, |
| | | subData: [] |
| | | }) |
| | | }) |
| | | |
| | |
| | | } |
| | | |
| | | yearChange = (value) => { |
| | | const { calendar, data } = this.props |
| | | const { levels, selectMonth } = this.state |
| | | let datelist = this.getDateList(value) |
| | | let monthlist = null |
| | | |
| | | if (levels.includes('month')) { |
| | | if (levels.includes('month') || levels.includes('year')) { |
| | | monthlist = datelist.filter(item => item.month === selectMonth)[0] |
| | | } |
| | | |
| | | if (calendar.refresh !== 'true') { |
| | | datelist = this.mountdata(datelist, data) |
| | | |
| | | this.setState({ selectYear: value, datelist, monthlist }) |
| | | this.setState({ selectYear: value, datelist, monthlist }) |
| | | } else { |
| | | this.setState({ selectYear: value, datelist, monthlist }, () => { |
| | | this.props.changeDate(value) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | monthChange = (value) => { |
| | | const { datelist } = this.state |
| | | const { datelist, levels, selectYear } = this.state |
| | | |
| | | if (!levels.includes('month')) { |
| | | if (this.props.triggerDate) { |
| | | this.props.triggerDate({ |
| | | time: `${selectYear}${value}01` |
| | | }) |
| | | } |
| | | return |
| | | } |
| | | |
| | | this.setState({ |
| | | level: 'month', |
| | | selectMonth: value, |
| | | monthlist: datelist.filter(item => item.month === value)[0] |
| | | }) |
| | | } |
| | | |
| | | triggerDay = (item) => { |
| | | |
| | | if (this.props.triggerDate) { |
| | | this.props.triggerDate(item) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { loading } = this.props |
| | | const { level, selectMonth, selectYear, yearlist, levels, datelist, monthlist } = this.state |
| | | const _levelName = {day: '日', month: '月', year: '年'} |
| | | const listData = [ |
| | | { type: 'orange', content: 'This is error event 2.' }, |
| | | { type: 'cyan', content: 'This is error event 3.' }, |
| | | { type: 'green', content: 'This is error event 4.' }, |
| | | ] |
| | | |
| | | |
| | | return ( |
| | | <div className="mk-calendar"> |
| | | {loading ? <div className="loading-data"><Spin /></div> : null} |
| | | <div className="mk-calendar-control"> |
| | | <Select value={selectYear} onChange={this.yearChange}> |
| | | {yearlist.map(item => (<Option key={item} value={item}>{item}年</Option>))} |
| | |
| | | <tr key={cell.week}> |
| | | {cell.sublist.map((d, i) => ( |
| | | <td key={i}> |
| | | {d ? <div className={'day-wrap ' + d.class} onClick={() => this.triggerDay(d)}> |
| | | {d.label ? <Popover mouseEnterDelay={0.3} overlayClassName="calendar-day-pop" content={ |
| | | {d ? <div className="day-wrap" style={d.style || null} onClick={() => this.triggerDay(d)}> |
| | | {d.subData.length > 0 ? <Popover mouseEnterDelay={0.3} overlayClassName="calendar-day-pop" content={ |
| | | <div> |
| | | {listData.map((data, index) => ( |
| | | {d.subData.map((data, index) => ( |
| | | <div key={index} className="message"> |
| | | <Badge color={data.type} text={data.content} /> |
| | | <Badge color={data.color} text={ |
| | | <span> |
| | | {data.remark} |
| | | <span style={{color: 'rgba(0,0,0,.45)'}}>({data.startTime + ' ~ ' + data.endTime})</span> |
| | | </span>} |
| | | /> |
| | | </div> |
| | | ))} |
| | | </div> |
| | |
| | | <tr key={cell.week}> |
| | | {cell.sublist.map((d, i) => ( |
| | | <td key={i}> |
| | | {d ? <div className="month-wrap" onClick={() => this.triggerDay(d)}> |
| | | {d ? <div className="month-wrap" style={d.style || null} onClick={() => this.triggerDay(d)}> |
| | | <div className="header"> |
| | | {d.label} |
| | | </div> |
| | | <ul className="content"> |
| | | {[1,3,7,18,22].includes(d.label) && listData.map((data, index) => ( |
| | | <li key={index} className="message" title={data.content}> |
| | | <Badge color={data.type} text={data.content} /> |
| | | {d.subData.map((data, index) => ( |
| | | <li key={index} className="message"> |
| | | <Badge color={d.style ? (data.color === d.style.background ? '#ffffff' : data.color) : data.color} text={data.remark} /> |
| | | </li> |
| | | ))} |
| | | </ul> |
| | |
| | | {level === 'year' && monthlist ? <Row className="year-calendar"> |
| | | {datelist.map(item => ( |
| | | <Col span={8} key={item.month}> |
| | | <div className="year-wrap"> |
| | | <div className="header"> |
| | | <div className="year-wrap" style={item.style || null} onClick={() => this.monthChange(item.month)}> |
| | | <div className="header" style={item.style ? null : {color: '#1890ff'}}> |
| | | {item.label} |
| | | </div> |
| | | <ul className="content"> |
| | | {['01', '05', '10'].includes(item.month) && listData.map((data, index) => ( |
| | | <li key={index} className="message" title={data.content}> |
| | | <Badge color={data.type} text={data.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> |