<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: [], //顯示的時間數(shù)組 ["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]}`
},
/**
* 初始化顯示的時間數(shù)組
* @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
// 設(shè)置選框的初始位置
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) {
// 根據(jù)鼠標移動于樟,設(shè)置選框的位置、寬高
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數(shù)組
*/
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
},
/**
* 設(shè)置選擇的時間段并賦給綁定的值
* @param {Array} indexList 選擇的index數(shù)組
*/
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數(shù)組
*/
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 */
/**方法二 循環(huán) (速度是方法一的十倍+)*/
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>
字節(jié)byte-week-picker(修改-反選bug解決)
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窒舟,“玉大人系忙,你說我怎么就攤上這事』莶颍” “怎么了银还?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長洁墙。 經(jīng)常有香客問我蛹疯,道長,這世上最難降的妖魔是什么热监? 我笑而不...
- 正文 為了忘掉前任弧械,我火速辦了婚禮剧蹂,結(jié)果婚禮上划咐,老公的妹妹穿的比我還像新娘舞肆。我一直安慰自己或衡,他們只是感情好速兔,可當我...
- 文/花漫 我一把揭開白布雁竞。 她就那樣靜靜地躺著秒咐,像睡著了一般歉铝。 火紅的嫁衣襯著肌膚如雪盈简。 梳的紋絲不亂的頭發(fā)上,一...
- 文/蒼蘭香墨 我猛地睜開眼宴霸,長吁一口氣:“原來是場噩夢啊……” “哼囱晴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瓢谢,我...
- 正文 年R本政府宣布,位于F島的核電站皂林,受9級特大地震影響朗鸠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜础倍,卻給世界環(huán)境...
- 文/蒙蒙 一烛占、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沟启,春花似錦忆家、人聲如沸。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至胳搞,卻和暖如春卸例,著一層夾襖步出監(jiān)牢的瞬間称杨,已是汗流浹背。 一陣腳步聲響...
推薦閱讀更多精彩內(nèi)容
- 基本用法 (vue2): 需要添加別的屬性: 基本用法 (vue3): Vue3中將 $listener 刪除了呻袭,...
- read()方法我知道是讀一個字節(jié),如果用while循環(huán)讀取的話篓足,為什么他第二次循環(huán)的時候就自動read后面的字節(jié)...
- Java代碼 /** *通信格式轉(zhuǎn)換 * *Java和一些windows編程語言如c段誊、c++、delphi所寫的網(wǎng)...