UNPKG

yylib-quick-mobile

Version:

yylib-quick-mobile

425 lines (390 loc) 15.4 kB
/** * Created by Ryn on 2016/8/7. * 日历组件 */ import React from 'react'; import H from './Help'; import './YYCalendarRange.less' class Calendar extends React.Component{ constructor(props){ super(props); this.state={ select_year :H.getFullYear(props.beginDate),//通过给定的日期确定年 select_month : H.getMonth(props.beginDate),//通过给定的日期确定月 select_day : 1,//通过给定的日期确定天 click_day:null, date_num_array : [], current_year:H.getFullYear(),//获取当前月 current_month:H.getMonth(),//获取当前月 current_day:H.getDay(), weekDay:null//起始日期所在的是周几 } } componentDidMount() { if(this.props.endDate){ //如果有结束日期 则不需要时间间隔 this.setState({endDate:this.props.endDate,beginDate:this.props.beginDate?this.props.beginDate:new Date()}) } else if(this.props.dayCount){ var beginSetDate=this.props.beginDate?this.props.beginDate:new Date();//设置的时间 var beginDate=this.getWorkDay(beginSetDate);//获取开始日期 //如果传入时间间隔 且没有结束日期 则用时间间隔计算 注意 计算时 需要将工作日计算在内 this.setEndDate(beginDate);//计算结束日期 } } setEndDate(beginDate){ var {dayCount,onlyWorkDay}=this.props; var endDate= Date.parse(H.pattern(beginDate,"yyyy-MM-dd")); if(!isNaN(parseInt(dayCount))){ /****计算终止日期****/ dayCount=parseInt(dayCount); var count=0; //先循环整个工作日数字 for(var index=0;index<dayCount;index++){ endDate=this.addOneDay(endDate); if(onlyWorkDay){ if(!this.isWeek(endDate)){ //如果当前天不是工作日 则认为有效工作日 count++; } }else{ count++; } } if(count<dayCount){ //一旦发现工作日数量够设定天数 则继续循环 设定一个较大值 如果满足之后就跳出 for(var index=0;index<100;index++){ endDate=this.addOneDay(endDate); if(onlyWorkDay){ if(!this.isWeek(endDate)){ //如果当前天不是工作日 则认为有效工作日 count++; } }else{ count++; } if(count==dayCount){ //发现已经满足了设定工作日天数 则跳出 break; } } } this.setState({beginDate:beginDate,endDate:endDate}); } } getWorkDay(date){ if(this.props.onlyWorkDay&&this.isWeek(date)){ //如果是工作日 则往后追加 直到不是非工作日为止 date=this.addOneDay(date); if(this.isWeek(date)){ date=this.getWorkDay(date) } } return date; } //加一天 addOneDay(date){ if(!(date instanceof Date)){ date=new Date(date); } date.setDate(date.getDate()+1);//设置天数 +1 天 return date; } /** * 给月份数组附上每月天数 * @param year 年份 * @private */ _initMonthDayNumber(year) { let _date_array = []; for (var i = 0; i < 12; i++) { switch (i + 1) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: _date_array.push(31); break; case 4: case 6: case 9: case 11: _date_array.push(30); break; case 2: if (H.isLeapYear(year)) { _date_array.push(29); } else { _date_array.push(28); } break; default: break; } } return _date_array; } /** * 组件将要挂载 * 设置月份数组以及计算出每月的第一天星期几 */ componentWillMount() { let date_num_array = this._initMonthDayNumber(this.state.select_year); let weekDay = H.weekOfMonth(this.getFullDate(this.state.select_year,this.state.select_month+1,1)); this.setState({date_num_array : date_num_array,weekDay:weekDay}); } /** * 日期选择 * @param s_day */ selectDate(s_day) { let { select_year, select_month} = this.state; var clickDate=this.getFullDate(select_year, select_month + 1, s_day); this.setState({ click_day : clickDate }, () => { this.props.onSelectDate&&this.props.onSelectDate(clickDate); }); } /** * 前一个单元 可能是前两周 也可能是前一周 */ previousMonth() { let {select_year, select_month, select_day, date_num_array, weekDay} = this.state; //说明到了上个月 if (select_month === 0) { select_year = select_year - 1; select_month = 11; date_num_array = this._initMonthDayNumber(select_year); } else { select_month = select_month - 1; } weekDay = H.weekOfMonth(new Date(select_year, select_month,select_day)); this.setState({ select_year : select_year, select_month : select_month, select_day : select_day, date_num_array : date_num_array, weekDay : weekDay }, () => { this.props.onPreviousMonth&&this.props.onPreviousMonth(select_year, select_month + 1); }) } /** * 之后一个月 */ nextMonth() { let { select_year, select_month, select_day, date_num_array, weekDay} = this.state; //到了下个月 if(select_month === 11) { select_year = +select_year + 1; select_month = 0; date_num_array = this._initMonthDayNumber(select_year); } else { select_month = +select_month + 1; } weekDay = H.weekOfMonth(new Date(select_year, select_month,select_day)); this.setState({ select_year : select_year, select_month : select_month, select_day : select_day, date_num_array : date_num_array, weekDay : weekDay }, () => { this.props.onNextMonth&&this.props.onNextMonth(select_year, select_month + 1); }) } getFullDate(year,month,day){ if(month==1){ month="12"; } if((month+"").length<2){ month="0"+month; } if((day+"").length<2){ day="0"+day; } return year+"-"+month+"-"+day } /**** *比较两个日期的大小 * **/ compartDate(date1,date2){ if(date1&&date2){ if(!(date1 instanceof Date)){ date1=new Date(date1); } if(!(date2 instanceof Date)){ date2=new Date(date2); } var year1=H.getFullYear(date1); var year2=H.getFullYear(date2); var month1=H.getMonth(date1); var month2=H.getMonth(date2); var day1=H.getDay(date1); var day2=H.getDay(date2); var fullDate1=this.getFullDate(year1,month1,day1); var fullDate2=this.getFullDate(year2,month2,day2); return fullDate1>=fullDate2; } } //是否是休息日 isWeek(date){ return (H.weekOfMonth(date)==0||H.weekOfMonth(date)==6) } getPage(){ let {endDate,beginDate,select_year, select_month, select_day,date_num_array, weekDay,click_day}=this.state; let normal=beginDate&&endDate;//只有当开始日期和结束日期都有的时候 才要进行 日期的截断 console.log("开始日期:"+H.pattern(beginDate,"yyyy-MM-dd")) console.log("结束日期:"+H.pattern(endDate,"yyyy-MM-dd")) let { weekCount, col_number, tags,onlyWorkDay } = this.props; let month_day = date_num_array[select_month];//当前月有多少天 let all_day=weekCount * col_number;//总共的天数 let n_day = all_day - weekDay - month_day; let previous_month_days; let next_month_days; let previous_month; let next_month; let current_days=[];//当前月对象 let previous_days=[];//上个月对象 let next_days=[];//下个月对象 let total_days=[]; //整体对象 let startDay=1;//当前时间的起始日 if(weekCount==5){ select_day=1;//当显示五周时 默认从1号开始 } // 算法从起始那天算日期 即从周日算起 如果当天有前面的周 也一并算入 if (select_month === 0) { previous_month = 11; next_month=1;//第二年的第一个月份是1月 } else { previous_month = select_month - 1; next_month=select_month + 1;//否则等于加1 } if(select_month===11){ next_month=0; } previous_month_days = date_num_array[previous_month];//取上一个月的天数 next_month_days = date_num_array[next_month];//取下一个月的天数 let lastDayCount=0;//本周中的上月天数 let currentDayCount=0;//本月的天数 let nextDayCount=0;//下个月的天数 let tempDay=weekDay==0?7:weekDay; lastDayCount=(tempDay-select_day)>0?(tempDay-select_day):0;//计算上个月的天数 currentDayCount=all_day-lastDayCount;//下个月的天数 nextDayCount=(all_day-lastDayCount-(month_day-select_day))>0?(all_day-lastDayCount-(month_day-select_day)):0;//计算下个月的天数 if(lastDayCount==0){ //说明没有上个月的日期 startDay=(select_day-weekDay)+1;//如果本周没有上月的日期 则本周一从给定时间的周一开始 } /****计算上月的日期*****/ for (let i = 0; i < lastDayCount; i++) { previous_days.unshift((<li className="item-gray" key={'previous'+i}> <a href="javascript:void(0)">{previous_month_days - i}</a> </li>)); } /*******计算本月的日期****/ for (let i = 0; i < currentDayCount; i++) { if((startDay+i)>month_day) break;//当循环超出一定本月的天数的的时候 var currentDate=this.getFullDate(select_year,(select_month+1),(startDay+i));//获取当前渲染的日期 let currentText = ''; let currentClassName = ''; // 今天样式 currentText = startDay+i; if(click_day&&H.equalDate(currentDate,click_day)){ currentClassName = 'item-active';//点击时触发 } if (H.equalDate(currentDate,new Date())) { currentClassName = 'item-current'; } if(onlyWorkDay&&this.isWeek(currentDate)){ //如果是周末 currentClassName="item-gray" } if(normal){ //是否需要截断日期 正常情况下步需要截断 if(!this.compartDate(currentDate,beginDate)||this.compartDate(currentDate,endDate)){ currentClassName="item-gray";//如果当前事件小于开始时间 } } //比对当前日期和渲染的比对 根据标记日期 标记渲染的日期 tags&&tags.length&&tags.map((tagDate)=>{ if (H.equalDate(currentDate,tagDate)) { //判断当前天是否和标记的相等 currentClassName += ' item-tag'; } }) current_days.push((<li className={currentClassName} key={'current'+i}> <a href="javascript:;" onClick={this.selectDate.bind(this, i + 1)}> {currentText} </a> </li>)); } /****计算下月的日期****/ for (let i = 0; i < nextDayCount; i++) { if((i+1)>next_month_days)break; next_days.push((<li className="item-gray" key={'next'+i}> <a href="javascript:;">{i + 1}</a> </li>)); } total_days =[...previous_days,...current_days,...next_days]; let ul_list = []; if (total_days.length > 0) { for (let i = 0; i < weekCount; i++) { let li_list = [], start_index = i * col_number, end_index = (i + 1) * col_number; for (let j = start_index; j < end_index; j++) { li_list.push(total_days[j]); } ul_list.push(li_list); } } var currentPage=( <div style={{"display":this.props.visible?"block":"none"}} className="calendar" key={select_year+"-"+select_month+"-"+select_day}> <div className="calendar-header"> <i className="icon-left" onClick={this.previousMonth.bind(this)}></i> <span className="calendar-date">{select_year} 年 {select_month + 1} 月</span> <i className="icon-right" onClick={this.nextMonth.bind(this)}></i> </div> <div className="calendar-body"> <ul className="c-body-head"> <li>一</li> <li>二</li> <li>三</li> <li>四</li> <li>五</li> <li>六</li> <li>日</li> </ul> <div className="c-body-content"> { ul_list.map((u, index) => { return (<ul key={'ul'+index} className="content-row">{u}</ul>); }) } </div> </div> </div>); return currentPage; } /** * 渲染页面 * @returns {XML} */ render() { return (this.getPage(this.state)); } } Calendar.defaultProps={ weekCount : 5,//显示几周 col_number : 7, tags:[],//标记日期 beginDate:null,//开始日期 endDate:null,//结束日期 onlyWorkDay:false, //只是工作日之内 排除双休日 dayCount:0 , //开始时间往后推几天 可以点击 visible:true } export default Calendar;