当前位置: 首页>编程语言>正文

字节byte-week-picker(修改-反选bug解决)

<template>
    <div class="weektime" id="timecontainer">
        <div v-if="selectBoxDashed" class="select-box-dashed" ref="selectBoxDashed" @mousemove="handleMousemove"></div>
        <div class="weektime-main">
            <div class="weektime-hd">
                <div class="weektime-hd-title font-bold">星期 / 时间</div>
                <div class="weektime-hd-con">
                    <div class="weektime-hd-con-top">
                        <div class="weektime-date-range font-bold">00:00 - 12:00</div>
                        <div class="weektime-date-range font-bold">12:00 - 24:00</div>
                    </div>
                    <div class="weektime-hd-con-bottom">
                        <span class="weektime-date-cell" v-for="hour in 24" :key="hour">{{hour-1}}</span>
                    </div>
                </div>
            </div>
            <div class="weektime-bd" >
                <div class="week-body">
                    <div v-for="week in weekDays" :key="week" class="week-item">{{week}}</div>
                </div>
                <div class="time-body" @mousedown="handleMousedown" @mouseup="handleMouseup" @mousemove="handleMousemove">
                    <el-tooltip
                            v-for="(i,key) in weekTimes"
                            :key="key"
                            :data-index="key"
                            :content="tiptxt(key)"
                            :open-delay="800"
                            placement="top"
                            effect="light"
                    >
                        <div class="time-cell" :class="{'active':list[key]==='1'}"></div>
                    </el-tooltip>
                </div>
            </div>
        </div>
        <div class="weektime-help">
            <div class="weektime-help-tx">
                <div class="weektime-help-bd">
                    可移动鼠标选择时间段
                </div>
                <div class="weektime-help-ft" @click="initList()">清空</div>
            </div>
            <div class="weektime-help-select">
                <p v-for="(week,key) in weekDays" :key="key" v-show="showTimeText[key]">
                    <span class="weektime-help-week-tx">{{week+":"}}</span>
                    <span>{{showTimeText[key]}}</span>
                </p>
            </div>
        </div>
    </div>
</template>

<script>
import Tooltip from 'element-ui/lib/tooltip.js'
import 'element-ui/lib/theme-chalk/tooltip.css';
import 'element-ui/packages/theme-chalk/src/common/transition.scss';

const DayTimes = 24 * 2;

export default {
    name: "byte-weektime-picker",
    components: {
        "el-tooltip": Tooltip
    },
    props: {
        value: String
    },
    watch: {
        value(n) {
          if (n.split('') === this.list.join('')) return;
            this.initList(n);
        }
    },
    data() {
        return {
            isMove: false,
            list: [],
            weekTimes: 7 * DayTimes,
            weekDays: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],
            timeTextList: [], //显示的时间数组 ["00:00","00:30","01:00",...]
            startIndex: 0,
            axis: {},
            preViewIndex: [],
            showTimeText: [],
            selectBoxDashed: false,
            startX: null,
            startY: null,
            initx: null,
            scrollX:null,
            scrollY:null,
            inity: null
        }
    },
    methods: {
        /**
         * 鼠标停留时提示当前时间段
         */
        tiptxt(index) {
            let timeIndex = index % DayTimes;
            let weekIndex = ~~(index / DayTimes);
            return `${this.weekDays[weekIndex]} ${this.timeTextList[timeIndex]}~${this.timeTextList[timeIndex + 1]}`
        },
        /**
         * 初始化显示的时间数组
         * @return {Array} ["00:00","00:30","01:00",...]
         */
        initTimeText() {
            let timeTextList = [], hours = [], minutes = ['00', '30'];
            for (let i = 0; i <= 24; i++) {
                i < 10 hours.push('0' + i) : hours.push(i.toString())
            }
            for (const hour of hours) {
                for (const minute of minutes) {
                    timeTextList.push(`${hour}:${minute}`)
                }
            }
            return timeTextList
        },
        handleMousedown(event) {
            this.isMove = true;
            this.startIndex = event.target.getAttribute('data-index');
            this.axis.startx = this.startIndex % DayTimes;
            this.axis.starty = ~~(this.startIndex / DayTimes);

            this.selectBoxDashed = true
            //  设置选框的初始位置
            this.startX = event.x + this.scrollX || event.clientX + this.scrollX
            this.startY = event.y + this.scrollY || event.clientY + this.scrollY
        },
        handleMouseup(event) {
            this.handleMousemove(event);
            this.resetMousemove()
            this.selectBoxDashed = false
        },
        handleMousemove(event) {
            if (this.selectBoxDashed) {
                //  根据鼠标移动,设置选框的位置、宽高
                this.initx = event.x + this.scrollX || event.clientX + this.scrollX
                this.inity = event.y + this.scrollY || event.clientY + this.scrollY

                //  暂存选框的位置及宽高,用于将 select-item 选中
                this.left = Math.min(this.initx, this.startX)
                this.top = Math.min(this.inity, this.startY)
                this.width = Math.abs(this.initx - this.startX)
                this.height = Math.abs(this.inity - this.startY)

                this.$refs.selectBoxDashed.style.left = `${this.left}px`
                this.$refs.selectBoxDashed.style.top = `${this.top}px`
                this.$refs.selectBoxDashed.style.width = `${this.width}px`
                this.$refs.selectBoxDashed.style.height = `${this.height}px`
            }



            if (!this.isMove) return;
            let index = event.target.getAttribute('data-index');
            if (index !== null) {
              this.axis.endx = index % DayTimes;
              this.axis.endy = ~~(index / DayTimes);
              this.preViewIndex = this.getSelectIndex()
            }
        },
        resetMousemove() {
            if (!this.isMove) return;
            this.setSelectIndex(this.preViewIndex);
            this.isMove = false;
            this.axis = {};
            this.preViewIndex = [];
            this.selectBoxDashed = false
        },
        /**
         * 获取拖动鼠标选择的index数组
         */
        getSelectIndex() {
            let indexList = [],
                newAxis = {
                    startx: Math.min(this.axis.startx, this.axis.endx),
                    starty: Math.min(this.axis.starty, this.axis.endy),
                    endx: Math.max(this.axis.startx, this.axis.endx),
                    endy: Math.max(this.axis.starty, this.axis.endy)
                }
            for (let y = newAxis.starty; y <= newAxis.endy; y++) {
                for (let x = newAxis.startx; x <= newAxis.endx; x++) {
                    indexList.push(x + y * DayTimes)
                }
            }
            return indexList
        },
        /**
         * 设置选择的时间段并赋给绑定的值
         * @param {Array} indexList 选择的index数组
         */
        setSelectIndex(indexList) {
            if (!Array.isArray(indexList)) return;
            let listLength = indexList.length;
            let newData = this.list[this.startIndex] === '1' '0' : '1';
            for (let i = 0; i < listLength; i++) {
                this.list.splice(indexList[i], 1, newData);
            }

            this.$emit('input', this.list.join(''));
            this.showSelectTime(this.list);
        },
        /**
         * 展示选择的时间段
         * @param {Array} list 已选择的list数组
         */
        showSelectTime(list) {
            if (!Array.isArray(list)) return;
            let weeksSelect = [], listlength = list.length;
            this.showTimeText = [];
            if (listlength === 0) return;
            // 把 336长度的 list 分成 7 组,每组 48 个
            for (var i = 0; i < listlength; i += DayTimes) {
                weeksSelect.push(list.slice(i, i + DayTimes));
            }
            weeksSelect.forEach(item => {
                this.showTimeText.push(this.getTimeText(item))
            });
        },
        getTimeText(arrIndex) {
            if (!Array.isArray(arrIndex)) return "";

            /*方法一 matchAll 正则匹配 (速度较慢) */
            // let strIndex = arrIndex.join('');
            // let arrMatches = Array.from(strIndex.matchAll(/1+/g));
            // let timeText = "";
            // arrMatches.forEach(value => {
            //   timeText += this.timeTextList[value.index];
            //   timeText += '~' + this.timeTextList[value.index + value[0].length] + '、';
            // })
            /*方法一 end */

            /**方法二 循环 (速度是方法一的十倍+)*/
            let timeLength = arrIndex.length,
                isSelect = false,
                timeText = "";
            arrIndex.forEach((value, index) => {
                if (value === '1') {
                    if (!isSelect) {
                        timeText += this.timeTextList[index]
                        isSelect = true;
                    }
                    if (index === timeLength - 1) timeText += '~' + this.timeTextList[index + 1] + '、';
                } else {
                    if (isSelect) {
                        timeText += '~' + this.timeTextList[index] + '、'
                        isSelect = false;
                    }
                }
            })
            /*方法二 end */

            return timeText.slice(0, -1)
        },
        initList(value) {
            let reg = new RegExp("^[01]{" + this.weekTimes + "}$");
            if (value && reg.test(value)) {
                this.list = value.split('');
                this.showSelectTime(this.list);
                return
            }
            this.list = new Array(this.weekTimes).fill('0');
            this.$emit('input', this.list.join(''));
            this.showSelectTime(this.list);
        },
    },
    destroyed() {
        document.removeEventListener('mouseup', this.resetMousemove)
    },
    created() {
        this.timeTextList = this.initTimeText();
        document.addEventListener('mouseup', this.resetMousemove);
        this.initList(this.value);
    }
}
</script>

<style scoped>
    div,
    span,
    p {
        margin: 0;
        padding: 0;
        border: 0;
        font-weight: normal;
        vertical-align: baseline;
        -webkit-tap-highlight-color: transparent;
        -ms-tap-highlight-color: transparent;
        -moz-box-sizing: border-box;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
    }
    .weektime {
        width: 658px;
        font-size: 14px;
        line-height: 32px;
        color: #515a6e;
        user-select: none;
        margin: 100px auto;
        background: white;
        border-radius: 5px;
    }
    .weektime .weektime-main {
        border: 1px solid #dcdee2;
        position: relative;
        border-radius: 5px 5px 0 0;
        overflow: hidden;
    }
    .weektime .weektime-hd {
        display: flex;
        background: white;
    }
    .weektime .weektime-hd-title {
        display: flex;
        align-items: center;
        padding: 0 6px;
        width: 80px;
        height: 65px;
    }
    .font-bold {
        font-weight: bold;
        font-size: 12px;
        color: black;
    }
    .weektime .weektime-hd-con {
        flex: 1;
        display: flex;
        -webkit-box-orient: vertical;
        flex-direction: column;
    }
    .weektime .weektime-hd-con-top {
        display: flex;
        border-bottom: 1px solid #dcdee2;
    }
    .weektime .weektime-date-range {
        width: 288px;
        height: 42px;
        line-height: 42px;
        text-align: center;
        border-left: 1px solid #dcdee2;
    }
    .weektime .weektime-hd-con-bottom {
        display: flex;
    }
    .weektime .weektime-date-cell {
        width: 24px;
        height: 32px;
        line-height: 32px;
        text-align: center;
        border-left: 1px solid #dcdee2;
    }
    .weektime .weektime-bd {
        display: flex;
    }
    .weektime .week-body {
        width: 80px;
        flex-shrink: 0;
        background: white;
    }
    .weektime .week-item {
        border-top: 1px solid #dcdee2;
        text-align: center;
        height: 30px;
        line-height: 30px;
    }
    .weektime .time-body {
        width: 576px;
        height: 210px;
        display: flex;
        flex-wrap: wrap;
        align-items: flex-start;
        position: relative;
    }
    .weektime .time-cell {
        position: relative;
        width: 12px;
        height: 30px;
        border-left: 1px solid #efefef;
        border-top: 1px solid #efefef;
        overflow: hidden;
        transition: background 0.3s ease;
        outline-width: 0;
    }
    .time-cell:hover {
        background: #ebebeb;
    }
    .weektime .time-cell.active {
        background: #2d8cf0;
    }
    .weektime .time-cell::after {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: transparent;
        opacity: 0.5;
        transition: background 888ms ease;
        z-index: 9000;
    }
    .weektime .pre-active::after {
        background: #113860;
    }
    .time-area {
        width: 576px;
        height: 210px;
        position: absolute;
        top: 0;
        left: 0;
        z-index: 100;
        background: transparent;
    }
    .weektime .weektime-help {
        width: 658px;
        border: 1px solid #dcdee2;
        border-top: none;
        padding: 5px 15px;
        border-radius: 0 0 5px 5px;
    }
    .weektime .weektime-help-tx {
        display: flex;
        align-items: center;
        justify-content: space-between;
    }

    .weektime .weektime-help-week-tx {
        color: #999;
    }

    .weektime .weektime-help-bd {
        display: flex;
        align-items: center;
        -webkit-box-pack: start;
        -ms-flex-pack: start;
        justify-content: flex-start;
        padding: 4px 0;
    }
    .weektime .weektime-help .color-box {
        width: 14px;
        height: 20px;
        background: #fff;
        border: 1px solid #dddddd;
        display: block;
        margin-right: 6px;
    }
    .weektime .weektime-help-bd .color-box.color-active {
        background: #2d8cf0;
    }
    .weektime .weektime-help .text-box {
        margin-right: 15px;
    }
    .weektime .weektime-help .weektime-help-ft {
        color: #2d8cf0;
        cursor: pointer;
    }
    .select-box-dashed{
        position: absolute;
        width: 0;
        height: 0;
        padding: 0px;
        margin: 0px;
        border: 1px dashed #0099ff;
        background-color: #c3d5ed;
        opacity: 0.5;
        filter: alpha(opacity=50);
        font-size: 0px;
        z-index: 99999;
    }
</style>

https://www.xamrdz.com/lan/5ue1995591.html

相关文章: