微信小程序-日历

import { Block, View, Picker, Text, Image } from ‘@tarojs/components‘;
import Taro from ‘@tarojs/taro‘;
import withWeapp from ‘@tarojs/with-weapp‘;
import { calendarType } from ‘../../utils/broker.js‘;
import ‘./index.scss‘;

@withWeapp(‘Component‘)
class _C extends Taro.Component {

  state = {
    // 当前显示的年
    currentYear: new Date().getFullYear(),
    // 当前显示的月
    currentMonth: new Date().getMonth() + 1,
    allArr: [],
    // 当天日期
    nowData: {},
    // 选中日期的数据
    chooseData: {},
  }

  componentWillMount = () => {
    this.getDates();
  }

  getDates = () => {
    // 调用函数时,传入new Date()参数,返回值是日期和时间
    const time = this.formatTime(new Date());
    const next = this.getNextWeekDay(7);
    const nextMonday = `${next.year}${this.formatNumber(next.month)}${this.formatNumber(next.days)}`;
    const nextS = this.getNextWeekDay(13);
    const nextSunday = `${nextS.year}${this.formatNumber(nextS.month)}${this.formatNumber(nextS.days)}`;
    this.setData({
      nowData: `${time.year}${this.formatNumber(time.month)}${this.formatNumber(time.day)}`,
      chooseData: {
        date: nextMonday,
      },
      nextMonday,
      nextSunday,
    }, () => {
      this.getAllArr();
    });
  }

  // 获取下周一(num=7)或者下周日(num=13)的日期
  getNextWeekDay(num) {
    const time = this.formatTime(new Date());
    let days = time.day + num - this.getFirstDateWeek(time.year, time.month, time.day);
    const timeDistance = this.getDateLen(time.year, time.month);
    let month = new Date().getMonth() + 1;
    let year = new Date().getFullYear();
    // 下周一跨月
    if (days > timeDistance) {
      days -= timeDistance;
      month += 1;
      // 下周一跨年
      if (month > 12) {
        year += 1;
        month -= 12;
      }
    }
    return { year, month, days };
  }

  getDataList = () => {
    // 获取数据
  }

  // 设置默认选中
  setDefaultChoice(List) {
    // 默认选中当天
    const setDate = this.state.nowData;
    for (const item of List) {
      if (setDate === item.date) {
        this.getNowData(item);
        break;
      }
    }
  }

  // 初始化今天的日期
  formatTime = date => {
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const day = date.getDate();

    return { year, month, day };
  }


  // 获取某年某月总共多少天
  getDateLen(year, month) {
    let actualMonth = month - 1;
    let timeDistance = +new Date(year, month) - +new Date(year, actualMonth);
    return timeDistance / (1000 * 60 * 60 * 24);
  }

  // 获取某月几号是周几
  getFirstDateWeek(year, month, days = 0) {
    const day = new Date(year, month - 1, days || 1).getDay() - 1;
    if (day < 0) {
      return 6;
    }
    return day;
  }

  // 上月 年、月
  preMonth(year, month) {
    if (month == 1) {
      return {
        year: --year,
        month: 12,
      };
    } else {
      return {
        year: year,
        month: --month,
      };
    }
  }

  // 下月 年、月
  nextMonth(year, month) {
    if (month == 12) {
      return {
        year: ++year,
        month: 1,
      };
    } else {
      return {
        year: year,
        month: ++month,
      };
    }
  }

  // 整合当月所有数据
  getAllArr() {
    const { currentYear, currentMonth } = this.state;
    // 获取当月中,上月多余数据
    const preMonthDateLen = this.getFirstDateWeek(currentYear, currentMonth); // 当月1号是周几 == 上月残余天数)
    const preMonthDateArr = []; // 定义空数组
    if (preMonthDateLen > 0) {
      const { year, month } = this.preMonth(currentYear, currentMonth); // 获取上月 年、月
      let day = this.getDateLen(year, month); // 获取上月天数
      for (let i = 0; i < preMonthDateLen; i++) {
        preMonthDateArr.unshift({ // 尾部追加
          monthType: false, // 只是为了增加标识,区分当、上月
          month,
          year,
          day: day,
          date: `${year}${this.formatNumber(month)}${this.formatNumber(day)}`,
          items: [],
        });
        day--;
      }
    }
    // 获取当月数据
    const currentMonthDateLen = this.getDateLen(currentYear, currentMonth); // 获取当月天数
    const currentMonthDateArr = []; // 定义空数组
    if (currentMonthDateLen > 0) {
      for (let i = 1; i <= currentMonthDateLen; i++) {
        const date = `${currentYear}${this.formatNumber(currentMonth)}${this.formatNumber(i)}`;
        currentMonthDateArr.push({
          monthType: true, // 只是为了增加标识,区分上下月
          month: currentMonth,
          year: currentYear,
          day: i,
          date: date,
          items: [],
        });
      }
    }
    // 获取当月中,下月多余数据,
    let nextMonthDateLen = 7 - (preMonthDateLen + currentMonthDateLen) % 7; // 下月多余天数
    if (nextMonthDateLen === 7) {
      nextMonthDateLen = 0;
    }
    // 月末的时候能看到下周
    nextMonthDateLen += 7;
    const nextMonthDateArr = []; // 定义空数组
    if (nextMonthDateLen > 0) {
      const { year, month } = this.nextMonth(this.state.currentYear, this.state.currentMonth);
      for (let i = 1; i <= nextMonthDateLen; i++) {
        const date = `${year}${this.formatNumber(month)}${this.formatNumber(i)}`;
        nextMonthDateArr.push({
          monthType: false,// 只是为了增加标识,区分当、下月
          month,
          year,
          day: i,
          date,
          items: [],
        });
      }
    }
    const allArr = [...preMonthDateArr, ...currentMonthDateArr, ...nextMonthDateArr];

    this.getDataList(allArr);
  }

  // 点击具体日期
  getNowData(data) {
    this.setState({
      chooseData: data,
    });
  }

  // 更换月份
  handleTimeChange = e => {
    const dataList = e.detail.value.toString().split(‘-‘);
    const newYear = parseInt(dataList[0], 10);
    const newMonth = parseInt(dataList[1], 10);
    const { currentYear, currentMonth } = this.state;
    if (newYear === currentYear && currentMonth === newMonth) {
      return;
    }
    this.setState({
      currentYear: newYear,
      currentMonth: newMonth,
      chooseData: {},
    }, () => {
      this.getAllArr();
    });
  };

  // 格式化时间
  formatNumber = n => {
    n = n.toString();
    return n[1] ? n : ‘0‘ + n;
  }

  handleGetClasname = (item, chooseData) => {
    // 选中的日期
    if (item.date === chooseData.date) {
      return ‘chooseDay‘;
    }

    if (!item.monthType) {
      return ‘ontInMonth‘;
    }
  }


  render() {
    const { allArr, currentYear, currentMonth, nowData, chooseData } = this.state;
    return (
      <Block>
        <View className="calendar">
          <View className=‘tit‘>
            <Picker
              mode="date"
              fields=‘month‘
              className=‘picker‘
              onChange={this.handleTimeChange}
            >
              <Text className=‘current‘>{currentYear}年{currentMonth}月</Text>
              <Image
                src={require(‘../../statics/images/bluedown.png‘)}
                className="xiala"
              />
            </Picker>
          </View>
          <View className=‘content‘>
            <View className=‘showData‘>
              <View>一</View>
              <View>二</View>
              <View>三</View>
              <View>四</View>
              <View>五</View>
              <View style=‘color: #999999‘>六</View>
              <View style=‘color: #999999‘>日</View>
            </View>
            {
              allArr.map(item => (
                <View
                  key={item.date}
                  className=‘itemData‘
                  onClick={() => this.getNowData(item)}
                >
                  <View className={this.handleGetClasname(item, chooseData)} style={item.items.length ? ‘color:rgba(69,69,83,1);‘ : ‘color:rgba(153,153,153,1);‘}>
                    <Text>{item.day}</Text>
                    {
                      item.date === nowData &&
                      <View className=‘toDay‘>今</View>
                    }
                  </View>
                </View>
              ))
            }
          </View>
        </View>
      </Block >
    );
  }
}

export default _C;
 
 
$morning: rgba(255, 86, 88, 1);
$afterNoon: rgba(3, 186, 185, 1);

.calendar {
  width: 100%;
  background: #fff;
  padding: 0 32px 100px 32px;

  .tit {
    display: flex;
    height: 99px;
    line-height: 99px;

    .picker {
      width: 100%;
      .current {
        font-size: 28px;
        font-weight: bold;
        color: rgba(69, 69, 83, 1);
      }

      .xiala {
        width: 16px;
        height: 8px;
        float: right;
        margin-top: 50px;
      }
    }
  }

  .content {
    display: flex;
    flex-wrap: wrap;
    box-sizing: border-box;
    background: rgba(247, 247, 247, 0.8);
    margin-bottom: 30px;
    color: #999999;
    padding: 30px;
  }

  .itemData {
    width: 14%;
    height: 70px;
    line-height: 70px;
    flex-shrink: 0;
    font-size: 30px;
    color: #2a2a2a;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;

    .chooseDay {
      background: rgba(0, 100, 255, 1) !important;
      color: #ffffff !important;
      width: 100%;
    }

    .ontInMonth {
      background: rgba(229, 229, 229, 0.8);
      width: 100%;
    }

    .toDay {
      position: absolute;
      color: rgba(50, 150, 250, 1);
      font-size: 20px;
      font-weight: bold;
      font-family: PingFangSC-Regular, PingFang SC;
      left: 10px;
      bottom: -9px;
    }
  }

  .opinion {
    border-top: 2px solid #f2f2f2;
    font-size: 28px;
    font-weight: 500;
    color: rgba(255, 2, 0, 1);
    position: relative;
    height: 86px;
    line-height: 86px;

    .leftArrow {
      right: 24px;
      bottom: 35px;
    }
  }

  .showData {
    display: flex;
    justify-content: center;
    align-items: center;
    box-sizing: border-box;
    width: 100%;
    background: rgba(247, 247, 247, 0.8);

    view {
      width: 14%;
      height: 70px;
      line-height: 70px;
      text-align: center;
      font-size: 28px;
      font-weight: bold;
      color: rgba(69, 69, 83, 1);
    }
  }
}

.btnBox {
  display: flex;
  height: 98px;
  line-height: 98px;
  font-size: 30px;
  font-weight: 400;
  position: fixed;
  bottom: 0px;
  width: 100%;
  text-align: center;

  .reject {
    flex: 1;
    color: rgba(40, 40, 40, 1);
    background: rgba(251, 251, 251, 1);
  }

  .adopt {
    flex: 1;
    color: rgba(255, 255, 255, 1);
    background: rgba(0, 100, 255, 1);
  }
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;

  .modal-mask {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.8);
    z-index: -1;

    .modal-tips {
      width: 562px;
      margin: 0 auto;
      background-color: #fff;
      border-radius: 11px;
      overflow: hidden;
    }

    .modal-tips-item {
      font-size: 24px;
      color: #9a9aa4;
      letter-spacing: 1px;
      line-height: 33px;
      margin-bottom: 33px;
      padding: 0 60px;
    }

    .modal-tips-btn {
      background: #0064ff;
      border-radius: 100px;
      height: 87px;
      margin: 78px 60px 60px;
      font-size: 30px;
      color: #ffffff;
      letter-spacing: 2.54px;
      text-align: center;
      line-height: 87px;
    }
  }
}

.datas {
  margin-top: 16px;
  display: flex;
  font-size: 32px;

  .text {
    margin: auto;
    text-align: center;
    font-weight: bold;
    width: 124px;
  }

  .dataBox {
    min-height: 152px;
    flex: 1;
    background: rgba(247, 247, 247, 1);
    position: relative;

    .noData {
      padding: 32px;
      text-align: center;
      color: rgba(153, 153, 153, 1);
      width: 100%;
      line-height: 88px;
    }

    .timeContent {
      padding: 32px 32px 0 32px;
      position: relative;
      .halfDay {
        font-size: 24px;
        position: absolute;
        right: 32px;
        top: 32px;

        .completed {
          color: rgba(0, 100, 255, 1);
        }

        .unexecuted {
          color: rgba(143, 143, 152, 1);
        }

        .notSub {
          color: rgba(255, 86, 88, 1);
        }
      }
    }

    .detail {
      padding-bottom: 32px;
      position: relative;

      .flexBox {
        display: flex;
        width: 100%;
      }

      .flexContent {
        flex: 1;
      }
      .statusImg {
        width: 30px;
        height: 30px;
        margin-top: 10px;
        margin-right: 16px;
      }

      .detailStatus {
        font-size: 28px;
        font-weight: 500;
        color: #454553;

        .outside {
          font-size: 24px;
          font-weight: bold;
          margin-left: 16px;
          color: rgba(241, 158, 160, 1);
        }

        .undoTitle {
          font-size: 24px;
          font-weight: bold;
          margin-left: 16px;
          color: rgba(251, 71, 41, 1);
        }
      }

      .detailTitle {
        font-size: 28px;
        font-weight: 400;
        color: rgba(102, 102, 102, 1);

        .detailContent {
          color: rgba(69, 69, 83, 1);
          font-weight: 500;
          word-break: break-all;
        }
      }
    }

    .leftArrow {
      right: 32px;
      bottom: 45px;
    }
  }
}

.leftArrow {
  position: absolute;
  width: 8px;
  height: 16px;
}

.morning {
  .text {
    color: $morning;
  }

  .dataBox {
    border-left: 2px solid $morning;
  }

  .timeContent {
    background-color: #fbeded;
  }
}

.afterNoon {
  margin-bottom: 30px;
  .text {
    color: $afterNoon;
  }

  .dataBox {
    border-left: 2px solid $afterNoon;
  }

  .timeContent {
    background-color: #edfbf7;
  }
}

.plessGo {
  font-size: 32px;
  font-weight: 400;
  color: rgba(153, 153, 153, 1);
  line-height: 45px;
  text-align: center;
}

微信小程序-日历

上一篇:vue 开发系列 企业微信整合


下一篇:序列化框架的选型和比对