import React, {useState, useEffect} from 'react'; import moment from 'moment' import {Button} from 'antd' import {LeftCircleFilled, RightCircleFilled, CaretLeftFilled, CaretRightFilled } from '@ant-design/icons' import classname from 'classnames' import style from './index.less' /* 判断 平年闰年 */ const isLeapYear = (year) => { return (year % 400 === 0) || (year % 100 !== 0 && year % 4 === 0); }; /* 获得某年某月的 1号 是星期几,这里要注意的是 JS 的 API-getDay() 是从 [日-六](0-6),返回 number */ const getWeek= (year, month, day) => { const date = new Date(year, month, day); return date.getDay(); }; const getWeekday = (year, month, day) => { const date = new Date(year, month, day); const week = date.getDay(); return ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][week] }; /* 获得每个月的日期有多少 */ const getMonthCount = (year, month) => { const arr = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; const count = arr[month] || (isLeapYear(year) ? 29 : 28); return Array.from(new Array(count), (item, value) =>{ return { week: getWeekday(year, month, value + 1), day: value + 1, weekDay: getWeek(year, month, value + 1) } }); }; const isLargeScreen = document.body.clientWidth >= 1920; const Index = (props) => { const {onChange} = props const [date, setDate] = useState([]); const monthData = getMonthCount(date[0], date[1]); const [moveLength, setMoveLength] = useState(0) /** * @日历方法 */ /* 获得上个月的天数 */ const getPreMonthCount = () => { const year = date[0]; const month = date[1]; const day = date[2]; let preYear; let preMonth; if (month === 0) { preYear = year - 1; preMonth = 11; } else { preYear = year; preMonth = month - 1; } setDate([preYear, preMonth, day]); if (onChange) onChange([preYear, preMonth, day]) return getMonthCount(preYear, preMonth); }; /* 获得下个月的天数 */ const getNextMonthCount = () => { const year = date[0]; const month = date[1]; const day = date[2]; let nextYear; let nextMonth; if (month === 11) { nextYear = year + 1; nextMonth = 0; } else { nextYear = year; nextMonth = month + 1; } setDate([nextYear, nextMonth, day]) if (onChange) onChange([nextYear, nextMonth, day]) return getMonthCount(nextYear, nextMonth); }; /* 选择日历 天 */ const dateChange = (day) => { const newDate = [...date]; newDate[2] = day; setDate(newDate) if (onChange) onChange(newDate) } /* 日历右移 */ const ulMoveRight = () => { const target = document.getElementById('JS_calendar'); const width = target.clientWidth; const maxWidth = target.scrollWidth - width; if (maxWidth > 0) { const newMove = moveLength < maxWidth ? moveLength + 54 : maxWidth; target.scrollLeft = newMove setMoveLength(newMove) } } /* 日历左移 */ const ulMoveLeft = () => { const target = document.getElementById('JS_calendar'); const width = target.clientWidth; const maxWidth = target.scrollWidth - width if (maxWidth > 0) { const newMove = moveLength >= 52 ? moveLength - 52 : 0; target.scrollLeft = newMove setMoveLength(newMove) } } const backToday = () => { const target = [moment().year(), moment().month(), moment().date()] setDate(target) if (onChange) onChange(target) } useEffect(() => { setDate([moment().year(), moment().month(), moment().date()]) }, []) return ( <div className="pos_column" style={{...props.style}}> <div className={classname("pos_center", style.calendar_title)}> <LeftCircleFilled onClick={getPreMonthCount} className={style.calendar_title_icon}/> {`${date[0]}年${date[1] + 1}月`} <RightCircleFilled onClick={getNextMonthCount} className={style.calendar_title_icon}/> <div className={style.calendar_title_extra}> <Button onClick={backToday}>回到今天</Button> {props.extra} </div> </div> <div className="pos_center" > {!isLargeScreen && ( <div className={classname('pos_center', style.calendar_move)}> <CaretLeftFilled onClick={ulMoveLeft}/> </div> )} <ul id="JS_calendar" className={style.calendar_ul}> {monthData.map((item) => ( <li key={item.day} className={classname( style.calendar_li, item.weekDay > 0 && item.weekDay < 6 ? style.bg_gray : style.bg_white, item.day === date[2] ? style.calendar_current : style.calendar_normal, props.children && item.day === date[2] && style.calendar_current_children )} onClick={() => dateChange(item.day)}> <div> <p style={{fontSize: 16}}>{item.day}</p> <p style={{fontSize: 12}}>{item.week}</p> </div> </li> ))} </ul> {!isLargeScreen && ( <div className={classname('pos_center', style.calendar_move)}> <CaretRightFilled onClick={ulMoveRight}/> </div> )} </div> {props.children && ( <div className={style.calendar_child_box} style={{flex: 1}}> {props.children} </div> )} </div> ); }; export default Index;