美文网首页
vue 日期选择 类似飞猪

vue 日期选择 类似飞猪

作者: fordG | 来源:发表于2019-04-18 15:17 被阅读0次

    实现功能

    基本照抄ixc-page-calendar日历, 没有配置头部, 单一动画可自己扩展
    注意返回的iconFont可以自己的

    GkA9rgFNsS.gif
    • vue文件
    <template>
        <div class="wrapper" :class="showPage ? 'show' : 'hide'">
            <div class="header">
                <div style="height: 100%; width: 80upx;" @click="back">
                    <text class="icon-font" style="color: white">&#xe654;</text>
                </div>
                <div class="middle">
                    <text class="title">选择日期</text>
                </div>
            </div>
            <view>
                <div class="calendar-weekday">
                    <text class="flex-item weekday-text"
                        :key="k"
                        :aria-label="`周${week}`"
                        v-for="(week,k) in ['日','一','二','三','四','五','六']">{{week}}</text>
                </div>
                <scroll-view class="calendar-list" scroll-y="true" :scroll-into-view="scrollIntoId">
                  <view v-for="(month,index) in monthsArray"
                        :key="index"
                        :id="sub+month.title"
                        :class="[!month.title && 'calendar-row']">
                    <text class="month-text"
                          v-if="month.title">{{month.title}}</text>
                    <view v-else
                         v-for="(cell,rowIndex) in month"
                         :key="`${index}-${rowIndex}`"
                         :ref="cell.ref"
                         :class="['row-item', cell.cellClass]"
                         :style="cell.isSelected ? selectedCellStyle:{}"
                         :accessible="true"
                         :aria-label="`${cell.text?cell.text:''},${cell.note?cell.note:''},${cell.ext?cell.ext:''}`"
                         @click="onClickDate(cell)">
                      <text :class="['calendar-note', cell.cls]"
                            :style="cell.isSelected ? selectedTextStyle:{}">{{cell.note}}</text>
                      <text :class="['calendar-day', cell.cls]"
                            :style="cell.isSelected ? selectedTextStyle:{}">{{cell.text}}</text>
                      <text :class="['calendar-ext', cell.cls]"
                            :style="cell.isSelected ? selectedTextStyle:{}">{{cell.ext}}</text>
                    </view>
                  </view>
                </scroll-view>
            </view>
        </div>
    </template>
    
    <script>
    import Format from './format.js'
    export default {
        components: {},
        props: {
            selectedDate: Array,
            dateRange: {
              type: Array,
              required: true,
              default: () => ([])
            },
            selectedNote: {
              type: Array,
              default: () => (['开始', '到达', '往返'])
            },
            isRange: {
              type: Boolean,
              default: false
            },
            needDestroy: {
              type: Boolean,
              default: false
            },
            descList: {
              type: Array,
              default: () => ([])
            },
            selectedCellStyle: {
              type: Object,
              default: () => ({})
            },
            selectedTextStyle: {
              type: Object,
              default: () => ({})
            },
        },
    
        computed: {
        
            today(){
                return Format.getToDay()
            },
            
            monthsArray () {
              const { dateRange: range, today, departDate, arriveDate, selectedNote, descList } = this;
              const param = { range, today, departDate, arriveDate, selectedNote, descList }
              return Format.generateDateCell(param);
            }
        },
    
        data: () => ({
            Format: Format,
            showPage: false,
            reSelect: true,
            scrollIntoId: '',
            departDate: '',
            arriveDate: '',
            sub: 'sub',
        }),
    
        created() {
            
        },
        
        mounted() {
        },
    
        methods: {
            
            show(){
                this.reSelect = true;
                this.showPage = true;
                this.detectShow();
            },
            
            back(){
                this.reSelect = false;
                this.showPage = false;
            },
            
            onClickDate (datConfig) {
              const self = this;
              if (datConfig.disabled || datConfig.isEmpty) return;
            
              if (self.reSelect) {
                self.departDate = '';
                self.arriveDate = '';
                self.reSelect = false;
              }
            
              if (self.isRange) {
                if (self.departDate && Date.parse(self.departDate) <= Date.parse(datConfig.date)) {
                  self.arriveDate = datConfig.date;
                } else {
                  self.departDate = datConfig.date;
                }
                if (self.departDate && self.arriveDate) {
                  self.dispatchDateChange([self.departDate, self.arriveDate]);
                }
              } else {
                self.departDate = datConfig.date;
                self.dispatchDateChange([self.departDate]);
              }
            },
            
            dispatchDateChange (dateArr) {
              const duration = 400;
              setTimeout(() => {
                this.back();
              }, duration);
              this.$emit('wxcPageCalendarDateSelected', {
                date: dateArr
              });
            },
            
            detectShow () {
              if (this.isRange && this.selectedDate.length >= 2) {
                this.departDate = this.selectedDate[0];
                this.arriveDate = this.selectedDate[1];
              } else if (this.selectedDate.length >= 1) {
                this.departDate = this.selectedDate[0];
                this.arriveDate = '';
              }
              for(var i = 0; i < this.monthsArray.length; i++){
                  var title =  this.monthsArray[i].title
                  if(title){
                      var subtitle = this.sub+title
                      console.log('测试数据',title, this.departDate)
                      if(title == this.subId(this.departDate)){
                            this.scrollIntoId = this.sub + title
                            console.log('测试数据scrollIntoId',title, this.scrollIntoId)
                      }
                  }
              }
              
            },
            
            subId(title){
                return title.substring(0, 7)
            },
        }
    };
    </script>
    
    <style >
    @font-face {
        font-family: 'iconfont';
        src: url('~@/static/iconfont/iconfont.ttf');
    }
    
    .wrapper {
        position: fixed;
        z-index: 999999;
        background: #ffffff;
        height: 100%;
        width: 100%;
        top: 0px;
        left: 0px;
    }
    
    .content {
        height: 100%;
        width: 100%;
        background-color: #ffffff;
    }
    
    .show {
        left: 0;
        width: 100%;
        transition: left .3s ease;
    }
    
    .hide {
        left: 100%;
        width: 100%;
        transition: left .3s ease;
    }
    
    .header{
        height: 83upx;
        background-color: #00aafb;
        display: flex;
        flex-direction: row;
        padding-top: 15upx;
        padding-left: 15upx;
    }
    
    .icon-font{
        font-family: 'iconfont';
        font-size: 30upx;
    }
    
    .middle{
        width: 100%;
        display: flex;
        padding-right: 95upx;
        justify-content: center
    }
        
    .title{
        font-size: 30upx;
        color: white;
    }
    
    .calendar-weekday {
        height: 60upx;
        background-color: #ffffff;
        border-bottom-width: 1upx;
        border-top-width: 1upx;
        border-color: #e2e2e2;
        flex-direction: row;
        display: flex;
        border-bottom-style: solid;
        justify-content: space-around;
        align-items: center;
      }
    
    .flex-item {
        flex: 1;
        width: 20%;
        text-align: center;
    }
    
    .weekday-text {
        color: #000000;
        flex: 1;
        font-size: 24upx;
        text-align: center;
    }
    
    .calendar-list {
        position: absolute;
        top: 143upx;
        bottom: 0upx;
        width: 100%;
    }
    
    .month-text {
        font-size: 32upx;
        height: 60upx;
        line-height: 60upx;
        width: 750upx;
        display: flex;
        text-align: center;
        flex-direction: column;
        align-items: center;
        background-color: #f2f3f4;
      }
    
      .calendar-row {
        height: 140upx;
        display: flex;
        flex-direction: row;
        background-color: #ffffff;
        border-bottom-width: 1px;
        border-color: #f2f3f4;
        border-bottom-style: solid;
        align-items: center;
        justify-content: space-between;
      }
    
    .row-item {
        flex: 1;
        height: 140upx;
        padding-top: 10upx;
        padding-bottom: 10upx;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }
    
    .calendar-note {
        height: 36upx;
        line-height: 36upx;
        font-size: 24upx;
        color: #000000;
        text-align: center;
      }
    
      .calendar-day {
        height: 48upx;
        line-height: 48upx;
        font-size: 36upx;
        color: #000000;
        text-align: center;
      }
    
      .calendar-ext {
        height: 36upx;
        line-height: 36upx;
        color: #999999;
        text-align: center;
        font-size: 24upx;
        text-overflow: ellipsis;
      }
    
      .calendar-holiday {
        color: #FF5000;
      }
    
      .calendar-rest {
        color: #FF5000;
      }
    
      .item-row-selected {
        color: #ffffff;
        background-color: #FFC900;
        text-align: center;
      }
    
      .item-text-selected {
        color: #3d3d3d;
        text-align: center;
      }
    
      .calendar-disabled {
        color: #CCCCCC;
      }
    
      .cell-disabled {
        background-color: #FBFBFB;
      }
    
      .calendar-day-include {
        background-color: #FFF7D6;
      }
    
    </style>
    
    • Format.js文件
    /**
     * CopyRight (C) 2017-2022 Alibaba Group Holding Limited.
     * Created by Tw93 on 2017/07/29.
     */
    
    const Format = {
    
            // 国际节日
            GLOBAL_HOLIDAY: {
                '01-01': '元旦',
                '02-14': '情人',
                '05-01': '劳动',
                '06-01': '儿童',
                '10-01': '国庆',
                '12-25': '圣诞'
            },
    
            // 传统节日
            TRADITIONAL_HOLIDAY: {
                '除夕': ['2015-02-18', '2016-02-07', '2017-01-27', '2018-02-15', '2019-02-04', '2020-01-24'],
                '春节': ['2015-02-19', '2016-02-08', '2017-01-28', '2018-02-16', '2019-02-05', '2020-01-25'],
                '元宵': ['2015-03-05', '2016-02-22', '2017-02-11', '2018-03-02', '2019-02-19', '2020-02-08'],
                '清明': ['2015-04-05', '2016-04-04', '2017-04-04', '2018-04-05', '2019-04-05', '2020-04-04'],
                '端午': ['2015-06-20', '2016-06-09', '2017-05-30', '2018-06-18', '2019-06-07', '2020-06-25'],
                '中秋': ['2015-09-27', '2016-09-15', '2017-10-04', '2018-09-24', '2019-09-13', '2020-10-01'],
                '重阳': ['2015-10-21', '2016-10-09', '2017-10-28', '2018-10-17', '2019-10-07', '2020-10-25']
            },
    
            // 放假日
            REST_DAYS: ['2017-10-01', '2017-10-02', '2017-10-03', '2017-10-04', '2017-10-05', '2017-10-06', '2017-10-07',
                '2017-10-08'
            ],
    
            // 工作日
            WORK_DAYS: ['2017-09-30'],
    
            _getTraditionalHoliday() {
                const HOLIDAY_TEMP = {};
    
                const keys = Object.keys(Format.TRADITIONAL_HOLIDAY);
                keys.forEach((k) => {
                    const arr = Format.TRADITIONAL_HOLIDAY[k];
                    arr.forEach((i) => {
                        HOLIDAY_TEMP[i] = k;
                    })
                });
                return HOLIDAY_TEMP;
            },
    
            _isDate(obj) {
                const type = obj === null ? String(obj) : {}.toString.call(obj) || 'object';
                return type === '[object date]';
            },
    
            /**
             * 检测Hash
             *
             * @method _checkHash
             * @private
             */
            _checkHash(url, hash) {
                return url && url.match(/#/) && url.replace(/^.*#/, '') === hash;
            },
    
            /**
             * 获取当前日期的毫秒数
             * @method getTime
             * @param {String} date
             * @return {Number}
             */
            getTime(date) {
                if (Format._isDate(date)) {
                    return new Date(date).getTime();
                } else {
                    try {
                        return new Date(date.replace(/-/g, '/')).getTime();
                    } catch (e) {
                        return 0;
                    }
                }
            },
    
            _isInRange(range, date) {
                const start = Format.getTime(range[0]);
                const end = Format.getTime(range[1]);
                const d = Format.getTime(date);
                return (start <= d && end >= d);
            },
    
            _isInSelectRange(range, date) {
                const start = Format.getTime(range[0]);
                const end = Format.getTime(range[1]);
                const d = Format.getTime(date);
                return (start < d && end > d);
            },
    
            _fixNum(num) {
                return (num < 10 ? '0' : '') + num;
            },
    
            /**
             * 是否是周末
             * @method isWeekend
             * @param {String} date
             * @return {Boolean}
             */
            _isWeekend(date) {
                const day = new Date(date.replace(/-/g, '/')).getDay();
                return day === 0 || day === 6;
            },
    
            /**
             * 是否是今天
             * @method isToday
             * @param {String} date
             * @return {Boolean}
             */
            _isToday(today, date) {
                return Format.getTime(today) === Format.getTime(date);
            },
    
            /**
             * 检查是否是闰年
             * @method _checkLeapYear
             * @param {Number} y 年份
             * @param {Date} t today
             * @protected
             */
            _getMonthDays(y, t) {
                const MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
                const year = y || t.getFullYear();
                let isLeapYear = false;
    
                if (year % 100) {
                    isLeapYear = !(year % 4);
                } else {
                    isLeapYear = !(year % 400);
                }
    
                if (isLeapYear) {
                    MONTH_DAYS[1] = 29;
                } else {
                    MONTH_DAYS[1] = 28;
                }
                return MONTH_DAYS;
            },
    
            /**
             * 当月1号前面有多少空格
             * @method _getPadding
             * @protected
             */
            _getPadding(year, month) {
                const date = new Date(year + '/' + month + '/1');
                return date.getDay();
            },
    
            _unique(array) {
                return Array.prototype.filter.call(array, function(item, index) {
                    return array.indexOf(item) === index;
                });
            },
    
            getToDay() {
                return new Date().getFullYear() + '-' + Format._fixNum(new Date().getMonth() + 1) + '-' + Format._fixNum(new Date().getDate());
            },
    
            getWeekRows(y, m, today, dateRange, departDate, arriveDate, selectedNote, descList) {
                const monthDays = Format._getMonthDays(y, today);
                const padding = Format._getPadding(y, m, 7);
                const num = monthDays[m - 1] + padding;
                const rows = Math.ceil(num / 7);
                const remain = num % 7;
                const rowsData = [];
    
                for (let i = 1; i <= rows; i++) {
                    const cells = [];
    
                    for (let j = 1; j <= 7; j++) {
                        let cell = {};
                        // 前后空格
                        if (i === 1 && j <= padding || remain && i === rows && j > remain) {
                            cell.isEmpty = true;
                        } else {
                            const d = (i - 1) * 7 + j - padding;
                            const date = y + '-' + Format._fixNum(m) + '-' + Format._fixNum(d);
                            let cls = [];
                            let ref = '';
                            const cellClass = [];
                            const isInRange = Format._isInRange(dateRange, date);
                            let disabled = false;
                            const global = Format._fixNum(m) + '-' + Format._fixNum(d);
                            let note = '';
                            let ext = '';
                            let isSelected = false;
    
                            if (descList && descList.length > 0) {
                                const nowDesc = descList.filter(item => item.date === date);
                                if (nowDesc && nowDesc.length > 0) {
                                    ext = nowDesc[0].value;
                                    if (nowDesc[0].emphasize) {
                                        cls.push('calendar-holiday');
                                    }
                                }
                            }
    
                            // 国际节日
                            if (Format.GLOBAL_HOLIDAY[global]) {
                                note = Format.GLOBAL_HOLIDAY[global];
                                cls.push('calendar-holiday');
                            }
    
                            const tHoliday = Format._getTraditionalHoliday()[date];
    
                            // 传统节日
                            if (tHoliday) {
                                note = tHoliday;
                                cls.push('calendar-holiday');
                            }
                            // 放假日
                            if (Format.REST_DAYS.indexOf(date) > -1) {
                                cls.push('calendar-holiday');
                            }
    
                            // 工作日
                            if (Format.WORK_DAYS.indexOf(date) > -1) {
                                cls.push('calendar-work');
                            }
    
                            // 周末
                            if (Format._isWeekend(date)) {
                                cls.push('calendar-holiday');
                            }
    
                            // 今天
                            if (Format._isToday(today, date)) {
                                cls.push('calendar-today');
                                note = '今天';
                            }
    
                            // 不在日期范围内
                            if (!isInRange) {
                                disabled = true;
                            }
    
                            if (disabled) {
                                cls = [];
                                cls.push('calendar-disabled');
                                cellClass.push('cell-disabled');
                            }
    
                            if (!ext && disabled && isInRange) {
                                ext = '不可选';
                            }
    
                            if (departDate === date || arriveDate === date) {
                                note = departDate === date ? selectedNote[0] : selectedNote[1];
                                ref = departDate === date ? 'departDate' : 'arriveDate';
                                if (departDate === arriveDate && selectedNote.length >= 3) {
                                    note = selectedNote[2];
                                }
                                isSelected = true;
                                cls.push('item-text-selected');
                                cellClass.push('item-row-selected');
                            }
    
                            if (departDate && arriveDate && Format._isInSelectRange([departDate, arriveDate], date)) {
                                cellClass.push('calendar-day-include');
                            }
    
                            cell = {
                                isSelected,
                                isEmpty: false,
                                ref,
                                cls: Format._unique(cls).join(' '),
                                cellClass: Format._unique(cellClass).join(' '),
                                note: note,
                                date: date,
                                ext: ext,
                                disabled: disabled,
                                text: d
                            };
                        }
                        cells.push(cell);
                    }
    
                    rowsData.push(cells);
                }
    
                return rowsData;
            },
    
            generateDateCell({
                range,
                today,
                departDate,
                arriveDate,
                selectedNote,
                descList
            }) {
                const start = new Date(range[0].replace(/-/g, '/'));
                const end = new Date(range[1].replace(/-/g, '/'));
                const startYear = start.getFullYear();
                const startMonth = start.getMonth() + 1;
                const endYear = end.getFullYear();
                const endMonth = end.getMonth() + 1;
    
                const l = (endYear - startYear) * 12 + endMonth - startMonth + 1;
                let y = startYear;
                let n = startMonth;
                const months = [];
    
                for (let i = 0; i < l; i++) {
                    if (n > 12) {
                        n = 1;
                        y++;
                    }
                    months.push({
                            title: `${y}-${Format._fixNum(n)}`
                        },
                        ...Format.getWeekRows(y, n, today, range, departDate, arriveDate, selectedNote, descList)
                    );
                    n++;
                }
                return months
            },
        }
    
        export default Format
    

    相关文章

      网友评论

          本文标题:vue 日期选择 类似飞猪

          本文链接:https://www.haomeiwen.com/subject/hplwbqtx.html