自定义日历,可选择显示预订信息

Posted zhuangcui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义日历,可选择显示预订信息相关的知识,希望对你有一定的参考价值。

日历组件:

可点击选择日期,可显示已选日期、预订内容

技术图片

 

 

 

style:

.reserve-calendar {
  #dateInput {
    background: #33CCCC;
    color: white;
    font-weight: bold;
    max-width: 450px;
    margin: 0 auto;
    padding: 1em;
  }

  .calendar {
      max-width: 450px;
      margin: 0 auto;
      padding: 1em;
      border: 1px solid #ddd;
      border-radius: 3px;
  }

  .calendarHeader {
    text-align: center;
    padding: 6px 30px;
    border-bottom: 1px solid #eee;
  }

  .back {
    color: #aaa;
    width: 30px;
    display: inline-block;
    font-size: 15px;
    cursor: pointer;
  }

  .forward {
    color: #aaa;
    width: 30px;
    font-size: 15px;
    display: inline-block;
    cursor: pointer;
  }

  .cur {
      position: relative;
      font-size: 14px;
      position: relative;
      display: inline-block;
      width: 70%;
      font-weight: 700;
  }

  table {
      max-width: 450px;
      margin: 0 auto;
      padding: 1em;

  }

  th,td {
      width: 50px;
      padding: 10px;
      text-align: center;
  }
  td {
    cursor: pointer;
    padding: 0px;
    background-color: #fff;
  }
  td .item {
    border: 1px solid #fff;
    padding: 10px;
    height: 40px;
    box-sizing: border-box;
  }
  td.disabled {
    background-color: #eee;
    color: #bbb;
  }

  td.abled:hover .valid {
      border:1px solid #108ee9;
      color: #108ee9;
  }
  .checked {
    background-color: #FFCC00;
  }
  .checked-view {
    background-color: #FFCC00;
    position: relative;
  }
  .selected {
    background-color: #63b7f3af;
  }

  .tip {
    position: absolute;
    left: 5px;
    bottom: -3px;
    font-size: 10px;
  }
}

 

html

<div class="reserve-calendar">
  <div class="calendar">
      <div class="calendarHeader">
          <div>
              <div class="back" (click)="backMonth()">
                  <i class="anticon anticon-left"></i>
              </div>
              <div class="cur">{{title}}</div>
              <div class="forward" (click)="forwardMoth()">
                  <i class="anticon anticon-right"></i>
              </div>

          </div>
      </div>
      <div id="calendarTable">
          <table>
              <thead>
                  <tr>
                      <th>日</th>
                      <th>一</th>
                      <th>二</th>
                      <th>三</th>
                      <th>四</th>
                      <th>五</th>
                      <th>六</th>
                  </tr>
              </thead>
              <tbody>
                <tr *ngFor="let tr of calendar;let trI = index">
                  <!-- 1.时间小于今天都,不可选
                    2.已预订:不可选,橙色、鼠标移上显示预定内容,
                    3.未预定:可选,鼠标移上有蓝框效果, -->
                  <td
                  [ngClass]="{‘abled‘: !td.disabled,‘disabled‘: td.disabled}"
                  *ngFor="let td of tr;let tdI = index"
                  >
                  <div *ngIf="type === ‘order‘">

                      <div class="item" *ngIf="td.status !== ‘checked‘ && td.status !== ‘valid‘" [title]="td.date ? td.date : ‘‘">{{td.txt}}</div>

                      <nz-tooltip
                      *ngIf="td.status === ‘checked‘"
                      [nzTitle]="td.memo"
                      [nzPlacement]="‘bottom‘">
                        <div nz-tooltip class="item checked checked-view">
                            <p>{{td.txt}}</p>
                            <span class="tip">已预订</span>
                        </div>
                      </nz-tooltip>

                      <div
                        *ngIf="td.status === ‘valid‘"
                        class="item valid"
                        [ngClass]="{‘selected‘: td.isSelected}"
                        (click)="ItemClick(td)"
                        [title]="td.date">{{td.txt}}</div>
                  </div>
                  <div *ngIf="type === ‘view‘">
                      <div class="item" *ngIf="td.status !== ‘checked‘" [title]="td.date ? td.date : ‘‘">{{td.txt}}</div>

                      <div class="item checked-view" *ngIf="td.status === ‘checked‘" [title]="td.date">
                        <p>{{td.txt}}</p>
                        <span class="tip">已预订</span>
                      </div>
                  </div>
                  <div *ngIf="type === ‘‘">
                    <div class="item" [title]="td.date">{{td.txt}}</div>
                  </div>
                </td>
                </tr>
              </tbody>
          </table>
      </div>
  </div>
</div>

js:

import {
  Component,
  OnInit,
  Input,
  Output,
  EventEmitter,
  ElementRef
} from ‘@angular/core‘;
import * as moment from ‘moment‘;

@Component({
  selector: ‘reserve-calendar‘,
  templateUrl: ‘./reserve-calendar.component.html‘,
  styleUrls: [‘./reserve-calendar.component.less‘]
})

export class ReserveCalendarComponent implements OnInit {
  @Output() getDate: EventEmitter<any> = new EventEmitter();
  @Output() clickOne: EventEmitter<any> = new EventEmitter();

  @Input() calendar = [];
  @Input() type = ‘‘;

  constructor() {}

  public y;
  public m;
  public title = ‘‘;
  public calendarData = [];
  public startTime = ‘‘;
  public endTime = ‘‘;
  public orderTimes = [];

  ngOnInit(): void {
    this.initiate();
  }

  // 设置日历的标题
  private setCalendarTitle(obj) {
      const year = obj.getFullYear();
      const month = obj.getMonth() + 1;
      this.title = ‘‘  + month + ‘月 ‘ + year + ‘年‘;
      this.y = year;
      this.m = month;
      const now = new Date(year, month - 1, 1);
      this.startTime = moment(now).format(‘YYYY-MM-DD‘);
      this.calculateDay(now);
  }

  // 计算当前月份有几天,第一天是星期几
  private is_leap(year) {
     return (year % 100 === 0 ? (year % 400 === 0 ? 1 : 0) : ( year % 4 === 0 ? 1 : 0 ));
  }

  private day(year) {
      const mDays = new Array(31, 28 + this.is_leap(year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
      return mDays;
  }

  private calculateDay(obj) {
      const dayArr = this.day(obj.getFullYear());
      const dayNum = dayArr[obj.getMonth()];
      this.endTime = moment(this.y + ‘-‘ + this.m + ‘-‘ + dayNum).format(‘YYYY-MM-DD‘);
      const dayFirst = obj.getDay(); // 0是星期天, 6是星期六
      const firstRow = 7 - dayFirst; // 第一行有日期的单元格个数,从右边数
      const firstRowBlank = 7 - firstRow;   // 第一行空的个数
      let lastRow = (dayNum - firstRow) % 7;   // 最后一个有日期的单元格个数
      lastRow = lastRow === 0 ? 7 : lastRow;
      const lastRowBlank = 7 - lastRow;
      const RowNum = (dayNum - firstRow - lastRow) / 7 + 2;
      this.renderCalendar(RowNum, firstRow, firstRowBlank, lastRow, lastRowBlank);
      this.changeDate();
  }

  private renderCalendar(RowNum, firstRow, firstRowBlank, lastRow, lastRowBlank) {

    this.calendarData = [];
     let i = 1;
     let j = 1;
     for (; i <= RowNum; i++) {
             if (i === 1) {
                const tr = [];
                 while (firstRowBlank > 0) {
                    tr.push({
                      disabled: true
                    });
                    firstRowBlank--;
                 }
                 while (firstRow > 0) {
                    this.handleTime(tr, j);
                     j++;
                     firstRow--;
                 }
                this.calendarData.push(tr);
             } else if (i === RowNum && lastRow > 0) {
                const tr = [];
                 while (lastRow > 0) {
                    this.handleTime(tr, j);
                     j++;
                     lastRow--;
                 }
                 while (lastRowBlank > 0) {
                    tr.push({
                      disabled: true
                    });
                     lastRowBlank--;
                 }
                this.calendarData.push(tr);
             } else {
                 let  day = 7;
                const tr = [];
                 while (day > 0) {
                    this.handleTime(tr, j);
                     j++;
                     day--;
                 }
                 this.calendarData.push(tr);
             }
     }

  }

  private handleTime(tr, j) {
    const td = {
      txt: j,
      date: this.timeFormat(this.y + ‘-‘ + this.m + ‘-‘ + j),
      disabled: false
    };
    if (new Date() > new Date(td.date + ‘ 23:59:59‘)) {
      td.disabled = true;
    }
    tr.push(td);
  }

  private timeFormat(date) {
    const newDate = new Date(date);
    const a = moment(newDate).format(‘YYYY-MM-DD‘);
    return a;
  }

  // 读取系统当前时间,设置
  private initiate() {
      const now = new Date();
      this.setCalendarTitle(now);
  }

  public forwardMoth() {
          const year = this.y;
          const month = this.m;
          if ((month + 1) <= 12) {
              const newDate1 = new Date(year, month, 1);
              this.setCalendarTitle(newDate1);
          } else {
              const newDate1 = new Date(year + 1, 0, 1);
              this.setCalendarTitle(newDate1);
          }
  }

  public backMonth() {
          const year = this.y;
          const month = this.m;
          if ((month - 1) >= 1) {
              const newDate1 = new Date(year, month - 2, 1);
              this.setCalendarTitle(newDate1);
              this.m = month - 1;
          } else {
              const newDate1 = new Date(year - 1, 11, 1);
              this.setCalendarTitle(newDate1);
              this.m = 12;
          }
  }

  public ItemHover(td) {

  }
  public ItemClick(td) {
    const date = td.date;
    this.clickOne.emit(date);
  }

  public changeDate() {
    const a = {
      startTime: this.startTime,
      endTime: this.endTime,
      calendarData: this.calendarData
    };
    this.getDate.emit(a);
  }

  // addEvent(initiate());
  // addEvent(checkCalendar());
  // addEvent(forwardMoth());
  // addEvent(backMonth());
}

 

使用:

<div class="reserve-pad-cal">
          <reserve-calendar
          [type]="‘order‘"
          [calendar]="calendarData"
          (getDate)="getCalendarData($event)"
          (clickOne)="getChangeOne($event)"
          *ngIf="reserveCalendar"></reserve-calendar>
public getChangeOne(date) {
      const index = this.orderTimes.indexOf(date);
      if (index === -1) {
        this.orderTimes.push(date);
        this.calendarData.forEach(item => {
          item.forEach(e => {
              if (e.date === date) {
                e.isSelected = true;
              }
          });
        });
      } else {
        this.orderTimes.splice(index, 1);
        this.calendarData.forEach(item => {
          item.forEach(e => {
              if (e.date === date) {
                e.isSelected = false;
              }
          });
        });
      }
    }

public getCalendarData(data) {
      const param = `接口地址?resourceId=${this.resourceId}&startDate=${data.startTime}&endDate=${data.endTime}`;
      const list = data.calendarData;
      this.handleGetCalendar(param, list);
    }

    public getCalendarViewData(data) {
      const param = `接口地址?resourceId=${this.orderId}&orderId=${this.viewOrderId}&startDate=${data.startTime}&endDate=${data.endTime}`;
      const list = data.calendarData;
      this.handleGetCalendar(param, list);
    }

    private handleGetCalendar(param, list) {
     接口地址(res => {
        if (res && res.code === ‘0‘) {
          const dateData = res.data;
          list.forEach(item => {
            item.forEach(e => {
              const index = this.orderTimes.indexOf(e.date);

              if (index > -1) {
                e.isSelected = true;
              }
              dateData.forEach(a => {
                if (e.date === a.date) {
                  e.status = a.status;
                  if (a.memo) {
                    e.memo = a.memo;
                  }
                }
              });
            });
          });
          this.calendarData = list;
        } else {
          if (res.message) {
            this._message.create(‘error‘, res.message);
          } else {
            this._message.create(‘error‘, ‘获取预约时间失败‘);
          }
          this.calendarData = list;
        }

      },
      error => {
        console.log(error);
      });
    }

 

传入数据:[{date:‘2020-01-01‘,status:‘valid‘}]

以上是关于自定义日历,可选择显示预订信息的主要内容,如果未能解决你的问题,请参考以下文章

自定义日历-区间选择控件

如何设计WinForm中DataGridView控件的自定义按钮列

酒店预订价格显示日历

VSCode自定义代码片段——CSS选择器

VSCode自定义代码片段6——CSS选择器

自定义水平滚动日历