yylib-quick-mobile
Version:
yylib-quick-mobile
425 lines (390 loc) • 15.4 kB
JavaScript
/**
* 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;