|
@@ -0,0 +1,895 @@
|
|
|
|
+<style lang="less">
|
|
|
|
+.componet-period-time-slider {
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 182rpx;
|
|
|
|
+ position: relative;
|
|
|
|
+ z-index: 2;
|
|
|
|
+ overflow-x: hidden;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .peroid-content-wrapper {
|
|
|
|
+ width: 658rpx;
|
|
|
|
+ position: absolute;
|
|
|
|
+ // left: 48rpx;
|
|
|
|
+ // right: 48rpx;
|
|
|
|
+ height: 182rpx;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .period-time-scroller {
|
|
|
|
+ position: absolute;
|
|
|
|
+ left: 32rpx;
|
|
|
|
+ right: 32rpx;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .sliders-scroller-wrapper {
|
|
|
|
+ display: inline-block;
|
|
|
|
+ position: relative;
|
|
|
|
+ // border-right: 1px solid #c4c4c4;
|
|
|
|
+ height: 100%;
|
|
|
|
+}
|
|
|
|
+.componet-period-time-slider .sliders-list {
|
|
|
|
+ height: 100%;
|
|
|
|
+ width: 100%;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .sliders-wrapper {
|
|
|
|
+ width: 40px;
|
|
|
|
+ height: 100%;
|
|
|
|
+ display: inline-block;
|
|
|
|
+ vertical-align: bottom;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ position: relative;
|
|
|
|
+ z-index: 10;
|
|
|
|
+ &:last-child {
|
|
|
|
+ height: 154rpx;
|
|
|
|
+ border-right: 1px solid #c4c4c4;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .disabled-block {
|
|
|
|
+ position: absolute;
|
|
|
|
+ height: 120rpx;
|
|
|
|
+ // line-height: 120rpx;
|
|
|
|
+ left: 0;
|
|
|
|
+ right: 0;
|
|
|
|
+ background-repeat: repeat;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .sliders {
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: column;
|
|
|
|
+ justify-content: flex-end;
|
|
|
|
+ position: relative;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .sliders .label {
|
|
|
|
+ width: 100%;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ height: 62rpx;
|
|
|
|
+ position: relative;
|
|
|
|
+ .split {
|
|
|
|
+ position: absolute;
|
|
|
|
+ height: 34rpx;
|
|
|
|
+ width: 1px;
|
|
|
|
+ left: 0;
|
|
|
|
+ bottom: 0;
|
|
|
|
+ background: #c4c4c4;
|
|
|
|
+ }
|
|
|
|
+ .text {
|
|
|
|
+ position: absolute;
|
|
|
|
+ left: 14rpx;
|
|
|
|
+ top: 0;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
+ line-height: 32rpx;
|
|
|
|
+ color: #656872;
|
|
|
|
+ font-family: Montserrat;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .sliders .slider-block {
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 120rpx;
|
|
|
|
+
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ background-repeat: repeat;
|
|
|
|
+ &.hasBorder {
|
|
|
|
+ border-left: 1px solid #ccc;
|
|
|
|
+ }
|
|
|
|
+ &.is-booked-selected-slider {
|
|
|
|
+ background-color: rgba(229, 87, 79, 0.6);
|
|
|
|
+ }
|
|
|
|
+ &.is-can-selected-slider {
|
|
|
|
+ background-color: rgba(0, 220, 35, 0.2);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area {
|
|
|
|
+ height: 120rpx;
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 0;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: row;
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+ z-index: 12;
|
|
|
|
+ &.showBg {
|
|
|
|
+ background: rgba(0, 220, 35, 0.2);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area.disabled {
|
|
|
|
+ // background-color: rgba(255, 77, 94, 0.26);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .booked-area {
|
|
|
|
+ height: 100%;
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 0;
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
+ line-height: 112rpx;
|
|
|
|
+ text-align: center;
|
|
|
|
+ color: rgba(6, 6, 61, 0.3);
|
|
|
|
+ z-index: 11;
|
|
|
|
+ .bg {
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 0;
|
|
|
|
+ height: 120rpx;
|
|
|
|
+ width: 100%;
|
|
|
|
+ background-repeat: repeat;
|
|
|
|
+ }
|
|
|
|
+ &.selected {
|
|
|
|
+ z-index: 12;
|
|
|
|
+ .bg {
|
|
|
|
+ background-color: rgba(255, 232, 35, 0.2);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .booked-user-info {
|
|
|
|
+ padding: 18rpx;
|
|
|
|
+ background: #ffffff;
|
|
|
|
+ box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.08);
|
|
|
|
+ border-radius: 54rpx;
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 66rpx;
|
|
|
|
+ left: 50%;
|
|
|
|
+ transform: translateX(-50%);
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: row;
|
|
|
|
+ align-items: center;
|
|
|
|
+ z-index: 13;
|
|
|
|
+ text-align: left;
|
|
|
|
+ .avatar {
|
|
|
|
+ width: 72rpx;
|
|
|
|
+ height: 72rpx;
|
|
|
|
+ display: block;
|
|
|
|
+ border-radius: 50%;
|
|
|
|
+ }
|
|
|
|
+ .info {
|
|
|
|
+ width: 156rpx;
|
|
|
|
+ margin-left: 22rpx;
|
|
|
|
+ .name {
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
+ line-height: 40rpx;
|
|
|
|
+ color: #000000;
|
|
|
|
+ margin-top: 2rpx;
|
|
|
|
+ white-space: nowrap;
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ }
|
|
|
|
+ .time {
|
|
|
|
+ color: #656872;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ font-size: 20rpx;
|
|
|
|
+ line-height: 24rpx;
|
|
|
|
+ font-family: Montserrat;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area .start,
|
|
|
|
+.componet-period-time-slider .selected-area .end {
|
|
|
|
+ position: absolute;
|
|
|
|
+ height: 100%;
|
|
|
|
+ width: 50rpx;
|
|
|
|
+ background: transparent;
|
|
|
|
+ /* display: flex;
|
|
|
|
+ flex-direction: row;
|
|
|
|
+ justify-content: center; */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area .start {
|
|
|
|
+ left: 0;
|
|
|
|
+ transform: translateX(-50%);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area .end {
|
|
|
|
+ right: 0;
|
|
|
|
+ transform: translateX(50%);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area .start-axis {
|
|
|
|
+ /* right:-20%; */
|
|
|
|
+ // margin-left: 20rpx;
|
|
|
|
+ left: 50%;
|
|
|
|
+ transform: translateX(-50%);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area .end-axis {
|
|
|
|
+ // margin-left: 30rpx;
|
|
|
|
+ right: 50%;
|
|
|
|
+ transform: translateX(50%);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area .axis {
|
|
|
|
+ height: 100%;
|
|
|
|
+ width: 3px;
|
|
|
|
+ background-color: #00dc23;
|
|
|
|
+ position: absolute;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area .axis.disabled {
|
|
|
|
+ background-color: #e5574f;
|
|
|
|
+ &::before {
|
|
|
|
+ border-color: #e5574f;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.componet-period-time-slider .selected-area .end-axis:before {
|
|
|
|
+ content: ' ';
|
|
|
|
+ position: absolute;
|
|
|
|
+ height: 24rpx;
|
|
|
|
+ width: 24rpx;
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ border: 3px solid #00dc23;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ top: 50%;
|
|
|
|
+ left: 50%;
|
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
|
+ z-index: 13;
|
|
|
|
+ border-radius: 50%;
|
|
|
|
+}
|
|
|
|
+</style>
|
|
|
|
+
|
|
|
|
+<template>
|
|
|
|
+ <div
|
|
|
|
+ class="componet-period-time-slider"
|
|
|
|
+ v-on:touchend.stop="stopPragation"
|
|
|
|
+ >
|
|
|
|
+ <div class="peroid-content-wrapper">
|
|
|
|
+ <scroller-x
|
|
|
|
+ @componet-scroller-x-scroll="scroll"
|
|
|
|
+ containerId="peroid-content-wrapper"
|
|
|
|
+ canMove="{{!isSelectPeriodIng}}"
|
|
|
|
+ scrollLeft="{{scrollLeft}}"
|
|
|
|
+ >
|
|
|
|
+ <div class="sliders-scroller-wrapper">
|
|
|
|
+ <div class="sliders-list">
|
|
|
|
+ <div
|
|
|
|
+ class="sliders-wrapper"
|
|
|
|
+ v-for="(item,index) in sliders"
|
|
|
|
+ data-index="{{index}}"
|
|
|
|
+ >
|
|
|
|
+ <div class="sliders">
|
|
|
|
+ <div
|
|
|
|
+ class="label"
|
|
|
|
+ v-if="index%2==0"
|
|
|
|
+ >
|
|
|
|
+ <div class="split"></div>
|
|
|
|
+ <div class="text">{{item.label}}</div>
|
|
|
|
+ </div>
|
|
|
|
+ <!-- slider-block class判断逻辑:如果选中了, 则需判断该块的状态来增加对应的背景色 -->
|
|
|
|
+ <!-- slider-block style判断逻辑:
|
|
|
|
+ 一: 如果是过去的状态下: 1-需要展示过去状态需要红斜线(该块不是预定状态下(因为预定的斜线在booked-area里合并展示) 2- 是在选择区域,选择区域在过去状态需要红斜线)展示红斜线
|
|
|
|
+ 二: 如果展示未运营时间范围内且disabledUnopened 则需要展示 红斜线-->
|
|
|
|
+ <div
|
|
|
|
+ class="{{'slider-block' + (item.isInSelectArea ? (item.isBooked || item.status=='unOpened' || item.status=='past')?' is-booked-selected-slider':' is-can-selected-slider' :'') + (index%2==0? ' hasBorder':'')}}"
|
|
|
|
+ v-on:click="selectPeriod"
|
|
|
|
+ data-index="{{index}}"
|
|
|
|
+ style="{{((item.status=='past'&& (showPastDisabled || item.isInSelectArea)) || (disabledUnopened && item.status=='unOpened'))? 'background-color:'+'#e3e3e3' : ''+';'+(item.isBooked?'background-image:url('+h5StaticPath+'/page-meeting-room/bg_disabled_red_v2.svg)':'')}}"
|
|
|
|
+ ></div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div
|
|
|
|
+ @click="deleteSelectedBookArea"
|
|
|
|
+ class="{{'selected-area'+(canBookSelectArea?'': 'disabled') + (isSelectPeriodIng? ' showBg': '')}}"
|
|
|
|
+ v-if="startIndex!==null"
|
|
|
|
+ style="{{'left:' +selectArealeft + 'px;right:'+ selectAreaRight+ 'px;' }}"
|
|
|
|
+ >
|
|
|
|
+ <div
|
|
|
|
+ class="start"
|
|
|
|
+ data-from="start"
|
|
|
|
+ >
|
|
|
|
+ <div class="{{'start-axis axis'+ (!firstSelectSliderCanBook?' disabled': '')}}"></div>
|
|
|
|
+ </div>
|
|
|
|
+ <div
|
|
|
|
+ class="end"
|
|
|
|
+ v-on:touchmove.stop="changeEndTimeMove"
|
|
|
|
+ v-on:touchstart.stop="changeEndTimeStart"
|
|
|
|
+ v-on:touchend.stop="changeEndTimeEnd"
|
|
|
|
+ >
|
|
|
|
+ <div
|
|
|
|
+ class="{{'end-axis axis'+ (!endSelectSliderCanBook ? 'disabled': '')}}"
|
|
|
|
+ data-from="end"
|
|
|
|
+ ></div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- <div
|
|
|
|
+ class="{{'booked-area' + (index === selectedBookAreaIndex? ' selected': '')}}"
|
|
|
|
+ v-for="(item,index) in formattedBookList"
|
|
|
|
+ :key="index"
|
|
|
|
+ style="{{'left:' +item.left + 'px;right:'+ (item.right)+ 'px;'}}"
|
|
|
|
+ bindlongtap="{{deleteSelectedBookArea(index)}}"
|
|
|
|
+ >
|
|
|
|
+ <div
|
|
|
|
+ class="bg"
|
|
|
|
+ style="{{'background-image:url('+h5StaticPath+'/page-meeting-room/bg_disabled_red_v2.svg)'}}"
|
|
|
|
+ ></div>
|
|
|
|
+ </div> -->
|
|
|
|
+ </div>
|
|
|
|
+ </scroller-x>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+import {
|
|
|
|
+ generateTimeValuesByArea,
|
|
|
|
+ SliderUnit
|
|
|
|
+} from '@/service/meetingTimes';
|
|
|
|
+import { generateTimeSliders,TimeStart,TimeEnd } from '@/packagesEnv/pages/common.js'
|
|
|
|
+let SliderWidth = 40; // ('单位为px');
|
|
|
|
+let startX = 0;
|
|
|
|
+let scrollerMarginLeft = 16; // ('单位为px');
|
|
|
|
+let axiosWidth = 56; // ('单位为px');
|
|
|
|
+let componentWrapInfo = {};
|
|
|
|
+let maxScrollLeft = 0;
|
|
|
|
+let addTimer = null;
|
|
|
|
+let reduceTimer = null;
|
|
|
|
+let overRightMoveX = 0;
|
|
|
|
+let reduceLeftMoveX = 0;
|
|
|
|
+let SlidersWrapperTotaLength = ((TimeEnd - TimeStart) / SliderUnit) * SliderWidth;
|
|
|
|
+let ShowAreaLength = 0;
|
|
|
|
+import wepy from '@wepy/core';
|
|
|
|
+import config from '@/config';
|
|
|
|
+wepy.component({
|
|
|
|
+ data: {
|
|
|
|
+ sliders: [],
|
|
|
|
+ bookedTimeValues: [], //这个用来判断当前slider是否是占用的
|
|
|
|
+ formattedBookList: [], //这个用来展示占用人名字居中的
|
|
|
|
+ startIndex: null,
|
|
|
|
+ duration: 0,
|
|
|
|
+ selectArealeft: 0,
|
|
|
|
+ selectAreaRight: '100%',
|
|
|
|
+ sliderFrom: '', //end,触发结束轴,start触发增加轴,
|
|
|
|
+ scrollLeft: 0,
|
|
|
|
+ isSelectPeriodIng: false, //用来标记是否在滑动选时间中
|
|
|
|
+ componentWrapWidth: 375,
|
|
|
|
+ h5StaticPath: config.h5StaticPath,
|
|
|
|
+ scrollLeftByTouch: 0, //用来记录自身滚动值,与设置的值区分开,防止多次设置组件内部滚动值会出现抖动
|
|
|
|
+ featuresVersion: config.featuresVersion,
|
|
|
|
+ selectedBookAreaIndex: null
|
|
|
|
+ },
|
|
|
|
+ props: {
|
|
|
|
+ selectValue: Object,
|
|
|
|
+ disabledPast: {
|
|
|
|
+ type: Boolean,
|
|
|
|
+ default: false
|
|
|
|
+ },
|
|
|
|
+ defaultSelectedPeriod: Object,
|
|
|
|
+ bookedList: Array,
|
|
|
|
+ hiddenBookedUserName: {
|
|
|
|
+ type: Boolean,
|
|
|
|
+ default: false
|
|
|
|
+ },
|
|
|
|
+ openStartTime: {
|
|
|
|
+ type: Number
|
|
|
|
+ },
|
|
|
|
+ openEndTime: {
|
|
|
|
+ type: Number
|
|
|
|
+ },
|
|
|
|
+ disabledUnopened: {
|
|
|
|
+ type: Boolean,
|
|
|
|
+ default: false
|
|
|
|
+ },
|
|
|
|
+ showPastDisabled: {
|
|
|
|
+ type: Boolean,
|
|
|
|
+ default: false
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ ready() {
|
|
|
|
+ this.getComponentWrapInfo().then(({ area }) => {
|
|
|
|
+ ShowAreaLength = area;
|
|
|
|
+ maxScrollLeft = ShowAreaLength - SlidersWrapperTotaLength;
|
|
|
|
+ const { selectValue } = this;
|
|
|
|
+ if (selectValue && selectValue.start && selectValue.end) {
|
|
|
|
+ // 防止此时选择时间列表还未全部渲染完毕
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ this.setValeByStartAndValue(selectValue.start, selectValue.end);
|
|
|
|
+ }, 500);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+ computed: {
|
|
|
|
+ sliders() {
|
|
|
|
+ let sliders = generateTimeSliders(
|
|
|
|
+ this.openStartTime,
|
|
|
|
+ this.openEndTime,
|
|
|
|
+ this.disabledPast
|
|
|
|
+ );
|
|
|
|
+ // 找出已经booked, 并标记isBooked
|
|
|
|
+ if (this.formattedBookList && this.formattedBookList.length !== 0) {
|
|
|
|
+ sliders = sliders.map(slider => {
|
|
|
|
+ let item = { ...slider };
|
|
|
|
+ let sliderHasBooked = this.bookedTimeValues.find(
|
|
|
|
+ time => slider.value == time
|
|
|
|
+ );
|
|
|
|
+ if (typeof sliderHasBooked === 'number') {
|
|
|
|
+ item.isBooked = true;
|
|
|
|
+ }
|
|
|
|
+ return { ...item };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 找出在selectesArea里面的, 并标记isInSelectArea
|
|
|
|
+ if (this.startIndex !== null && this.duration) {
|
|
|
|
+ let start = sliders[this.startIndex].value;
|
|
|
|
+ let end = start + this.duration * SliderUnit;
|
|
|
|
+ sliders = sliders.map((slider, index) => {
|
|
|
|
+ let isInSelectArea = false;
|
|
|
|
+ if (slider.value >= start && slider.value < end) {
|
|
|
|
+ isInSelectArea = true;
|
|
|
|
+ }
|
|
|
|
+ return { ...slider, isInSelectArea };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ return sliders;
|
|
|
|
+ },
|
|
|
|
+ formattedBookList() {
|
|
|
|
+ let { formattedBookList } = this.formattedPeriodBookList(this.bookedList);
|
|
|
|
+ return formattedBookList;
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+ bookedTimeValues() {
|
|
|
|
+ let {
|
|
|
|
+ formattedBookList,
|
|
|
|
+ bookedTimeValues
|
|
|
|
+ } = this.formattedPeriodBookList(this.bookedList);
|
|
|
|
+ return bookedTimeValues;
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+ canBookSelectArea() {
|
|
|
|
+ let { canBooked } = this.selectAareaCanBook();
|
|
|
|
+ return canBooked;
|
|
|
|
+ },
|
|
|
|
+ firstSelectSliderCanBook() {
|
|
|
|
+ let { firstCanBook } = this.selectAareaCanBook();
|
|
|
|
+ return firstCanBook;
|
|
|
|
+ },
|
|
|
|
+ endSelectSliderCanBook() {
|
|
|
|
+ let { endCanBook } = this.selectAareaCanBook();
|
|
|
|
+ return endCanBook;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ watch: {
|
|
|
|
+ selectValue: function (newSelectValue, oldSelectValue) {
|
|
|
|
+ if (JSON.stringify(oldSelectValue) !== JSON.stringify(newSelectValue)) {
|
|
|
|
+ if (newSelectValue.from !== 'outer') {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (newSelectValue && newSelectValue.start && newSelectValue.end) {
|
|
|
|
+ this.setValeByStartAndValue(newSelectValue.start, newSelectValue.end);
|
|
|
|
+ } else {
|
|
|
|
+ this.reset();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ bookedList: function (newBookedList, oldBooledList) {
|
|
|
|
+ if (JSON.stringify(oldBooledList) !== JSON.stringify(newBookedList)) {
|
|
|
|
+ // this.changedSlidersWithBookList();
|
|
|
|
+ const { selectValue } = this;
|
|
|
|
+ if (selectValue && selectValue.start && selectValue.end) {
|
|
|
|
+ this.setValeByStartAndValue(selectValue.start, selectValue.end);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ disabledPast: function (newDisabledPast, oldDisabledPast) {
|
|
|
|
+ const { selectValue } = this;
|
|
|
|
+ if (selectValue && selectValue.start && selectValue.end) {
|
|
|
|
+ this.setValeByStartAndValue(selectValue.start, selectValue.end);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ formattedPeriodBookList(bookedList) {
|
|
|
|
+ let formattedBookList = [],
|
|
|
|
+ bookedTimeValues = [];
|
|
|
|
+ if (!bookedList || (bookedList && bookedList.length == 0)) {
|
|
|
|
+ return { formattedBookList, bookedTimeValues };
|
|
|
|
+ }
|
|
|
|
+ formattedBookList = bookedList.map(booked => {
|
|
|
|
+ //todo
|
|
|
|
+ let { start, end } = booked;
|
|
|
|
+ let duration = (end - start) / SliderUnit;
|
|
|
|
+ let list = generateTimeValuesByArea(start, end);
|
|
|
|
+ bookedTimeValues = bookedTimeValues.concat(list);
|
|
|
|
+ let left = ((start - TimeStart) / SliderUnit) * SliderWidth;
|
|
|
|
+
|
|
|
|
+ let right = SlidersWrapperTotaLength - left - duration * SliderWidth;
|
|
|
|
+ return { ...booked, duration, left, right };
|
|
|
|
+ });
|
|
|
|
+ return { formattedBookList, bookedTimeValues };
|
|
|
|
+ },
|
|
|
|
+ reset() {
|
|
|
|
+ this.startIndex = null;
|
|
|
|
+ this.duration = 0;
|
|
|
|
+ this.scrollLeft = 0;
|
|
|
|
+ this.selectArealeft = 0;
|
|
|
|
+ this.selectAreaRight = 0;
|
|
|
|
+ },
|
|
|
|
+ setValeByStartAndValue(start, end) {
|
|
|
|
+ let duration = (end - start) / SliderUnit;
|
|
|
|
+ let startIndex = this.sliders.findIndex(item => item.value == start);
|
|
|
|
+ let scrollLeft = -(startIndex * SliderWidth) + 50;
|
|
|
|
+ if (scrollLeft > 0) {
|
|
|
|
+ scrollLeft = 0;
|
|
|
|
+ } else if (scrollLeft < maxScrollLeft) {
|
|
|
|
+ scrollLeft = maxScrollLeft;
|
|
|
|
+ }
|
|
|
|
+ this.startIndex = startIndex;
|
|
|
|
+ this.duration = duration;
|
|
|
|
+ this.scrollLeftByTouch = scrollLeft; //同时也要记录;
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ this.scrollLeft = scrollLeft;
|
|
|
|
+ }, 100); // 防止初始是,时间轴列表还未渲染完,此时设置滚动不生效
|
|
|
|
+ const { canBookSelectArea } = this;
|
|
|
|
+ this.$emit(
|
|
|
|
+ 'component-period-time-slider-judgecanselectedend',
|
|
|
|
+ canBookSelectArea
|
|
|
|
+ );
|
|
|
|
+ this.setSelectArea(startIndex, duration);
|
|
|
|
+ },
|
|
|
|
+ selectAareaCanBook() {
|
|
|
|
+ const { startIndex, duration, sliders, disabledPast } = this;
|
|
|
|
+
|
|
|
|
+ let canBooked = true;
|
|
|
|
+ let firstCanBook = true;
|
|
|
|
+ let endCanBook = true;
|
|
|
|
+ // 只有当有值才去判断
|
|
|
|
+ if (sliders && sliders.length && duration && !isNaN(startIndex)) {
|
|
|
|
+ let start = sliders[startIndex].value;
|
|
|
|
+ let selectedSliders = [];
|
|
|
|
+ for (let i = 0; i < duration; i++) {
|
|
|
|
+ selectedSliders.push(start + i * SliderUnit);
|
|
|
|
+ }
|
|
|
|
+ selectedSliders.forEach((selectedItem, index) => {
|
|
|
|
+ let selectSlider = sliders.find(item => item.value == selectedItem);
|
|
|
|
+ if (
|
|
|
|
+ (selectSlider && disabledPast && selectSlider.status == 'past') ||
|
|
|
|
+ (selectSlider && selectSlider.status === 'unOpened')
|
|
|
|
+ ) {
|
|
|
|
+ canBooked = false;
|
|
|
|
+ // 在不能预约的块里面是否有第一个,
|
|
|
|
+ if (index == 0) {
|
|
|
|
+ firstCanBook = false;
|
|
|
|
+ }
|
|
|
|
+ //再不能最后一个
|
|
|
|
+ if (index == selectedSliders.length - 1) {
|
|
|
|
+ endCanBook = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return { canBooked, firstCanBook, endCanBook };
|
|
|
|
+ },
|
|
|
|
+ scroll(scrollLeft) {
|
|
|
|
+ this.scrollLeftByTouch = scrollLeft;
|
|
|
|
+ },
|
|
|
|
+ selectPeriod(e) {
|
|
|
|
+ let index = e.$wx.target.dataset.index;
|
|
|
|
+ // if (this.index === index) {
|
|
|
|
+ // this.cancelSelect();
|
|
|
|
+ // } else {
|
|
|
|
+ // this.selectSlider(index)
|
|
|
|
+ // }
|
|
|
|
+ this.resetCanBook();
|
|
|
|
+ this.selectSlider(index);
|
|
|
|
+ this.onEndSelectFun();
|
|
|
|
+ },
|
|
|
|
+ resetCanBook() {
|
|
|
|
+ this.canBookSelectArea = true;
|
|
|
|
+ },
|
|
|
|
+ cancelSelect() {
|
|
|
|
+ this.startIndex = null;
|
|
|
|
+ this.duration = 0;
|
|
|
|
+ this.selectArealeft = 0;
|
|
|
|
+ this.selectAreaRight = 0; //默认保留一个宽度;
|
|
|
|
+ },
|
|
|
|
+ selectSlider(index) {
|
|
|
|
+ this.startIndex = index;
|
|
|
|
+ this.duration = 1;
|
|
|
|
+ this.setSelectArea(index, 1);
|
|
|
|
+ this.selectedBookAreaIndex = null;
|
|
|
|
+ },
|
|
|
|
+ setSelectArea(startIndex, duration) {
|
|
|
|
+ // console.log('设置偏移值',left, right);
|
|
|
|
+ let left = SliderWidth * startIndex;
|
|
|
|
+ let right = SlidersWrapperTotaLength - left - duration * SliderWidth;
|
|
|
|
+ this.selectArealeft = parseInt(left);
|
|
|
|
+ this.selectAreaRight = parseInt(right);
|
|
|
|
+ },
|
|
|
|
+ changeEndTimeStart(e) {
|
|
|
|
+ startX = Number(e.touches[0].pageX);
|
|
|
|
+ this.isSelectPeriodIng = true;
|
|
|
|
+ },
|
|
|
|
+ changeEndTimeMove(e) {
|
|
|
|
+ let {
|
|
|
|
+ scrollLeftByTouch,
|
|
|
|
+ startIndex,
|
|
|
|
+ duration,
|
|
|
|
+ selectArealeft,
|
|
|
|
+ selectAreaRight
|
|
|
|
+ } = this;
|
|
|
|
+ let touch = e.touches[0],
|
|
|
|
+ x = Number(touch.pageX);
|
|
|
|
+ let from = e.target.dataset.from;
|
|
|
|
+ if (x === startX) {
|
|
|
|
+ // 没有实质性的移动,不做处理,提高性能
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ let touchLength = parseInt(x - startX);
|
|
|
|
+ startX = x;
|
|
|
|
+ //左边最起始x位置
|
|
|
|
+ let leftLimit = scrollerMarginLeft;
|
|
|
|
+ //因为要保证最少有一格,故滑动start轴最右边是当前结束位置向前移一格
|
|
|
|
+ let startLimit =
|
|
|
|
+ scrollerMarginLeft +
|
|
|
|
+ SliderWidth * (startIndex + duration - 1) +
|
|
|
|
+ scrollLeftByTouch;
|
|
|
|
+ //右边最大结束x位置
|
|
|
|
+ let rightLimit = scrollerMarginLeft + componentWrapInfo.width;
|
|
|
|
+ //因为要保证最少有一格,故滑动end轴结束位置为当前开始位置加一格
|
|
|
|
+ let endLimit =
|
|
|
|
+ scrollerMarginLeft + SliderWidth * (startIndex + 1) + scrollLeftByTouch;
|
|
|
|
+ //end 轴往前滑
|
|
|
|
+
|
|
|
|
+ if (touchLength >= 0 && x >= ShowAreaLength) {
|
|
|
|
+ this.clerReduceTimer();
|
|
|
|
+ // console.log('超出右边界,增加右边');
|
|
|
|
+ this.scrollToRightEdgBySelectArea(touchLength);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // if (touchLength <= 0 && (selectArealeft + scrollLeftByTouch) < 0) {
|
|
|
|
+ // this.clearAddTimer();
|
|
|
|
+ // console.log('左边看不见,可以减少左边');
|
|
|
|
+ // this.reduceSelectAreaRight();
|
|
|
|
+ // return
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ if (
|
|
|
|
+ touchLength <= 0 &&
|
|
|
|
+ SlidersWrapperTotaLength -
|
|
|
|
+ (selectAreaRight - touchLength) -
|
|
|
|
+ selectArealeft <=
|
|
|
|
+ SliderWidth
|
|
|
|
+ ) {
|
|
|
|
+ //保证一格,不让滑了
|
|
|
|
+ this.selectAreaRight =
|
|
|
|
+ SlidersWrapperTotaLength - selectArealeft - SliderWidth;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.clearAddTimer();
|
|
|
|
+ this.clerReduceTimer();
|
|
|
|
+ // console.log('正常滑动增加或减少');
|
|
|
|
+ this.selectAreaRight = selectAreaRight - touchLength;
|
|
|
|
+ },
|
|
|
|
+ scrollToRightEdgBySelectArea() {
|
|
|
|
+ let { scrollLeftByTouch, selectAreaRight } = this;
|
|
|
|
+ if (addTimer) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ addTimer = setInterval(() => {
|
|
|
|
+ // console.log('进入增加定时器');
|
|
|
|
+ overRightMoveX = overRightMoveX + 1;
|
|
|
|
+ let translateX = scrollLeftByTouch - overRightMoveX;
|
|
|
|
+ let newSelectAreaRight = selectAreaRight - overRightMoveX; //同时selectAreaRight也要变小
|
|
|
|
+ if (translateX <= maxScrollLeft) {
|
|
|
|
+ //如果超出边界值,就不在滑动了
|
|
|
|
+ this.clearAddTimer();
|
|
|
|
+ this.scrollLeftByTouch = maxScrollLeft; //同时也要记录;
|
|
|
|
+ this.scrollLeft = maxScrollLeft;
|
|
|
|
+ this.selectAreaRight = 0;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ this.scrollLeftByTouch = translateX; //同时也要记录;
|
|
|
|
+ this.scrollLeft = translateX;
|
|
|
|
+ this.selectAreaRight = newSelectAreaRight;
|
|
|
|
+ }, 10);
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ reduceSelectAreaRight() {
|
|
|
|
+ let { scrollLeftByTouch, selectArealeft, selectAreaRight } = this;
|
|
|
|
+ if (addTimer) {
|
|
|
|
+ this.clearAddTimer();
|
|
|
|
+ }
|
|
|
|
+ if (reduceTimer) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ reduceTimer = setInterval(() => {
|
|
|
|
+ // console.log('进入减少定时器');
|
|
|
|
+ let toMinScrollLeft = false;
|
|
|
|
+ reduceLeftMoveX = reduceLeftMoveX + 1;
|
|
|
|
+ let translateX = scrollLeftByTouch + reduceLeftMoveX; //scroll增加,滚动减小
|
|
|
|
+ let right = selectAreaRight + reduceLeftMoveX; //right增加,选择区域减小
|
|
|
|
+
|
|
|
|
+ let minScrollLeft = -selectArealeft;
|
|
|
|
+ if (translateX >= minScrollLeft) {
|
|
|
|
+ //当滚动到当前选项结束开始位置位于屏幕左测开始位置
|
|
|
|
+ toMinScrollLeft = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.scrollLeftByTouch = toMinScrollLeft ? minScrollLeft : translateX; //同时记录
|
|
|
|
+ this.scrollLeft = toMinScrollLeft ? minScrollLeft : translateX;
|
|
|
|
+ this.selectAreaRight = right;
|
|
|
|
+
|
|
|
|
+ if (SlidersWrapperTotaLength - right - selectArealeft <= SliderWidth) {
|
|
|
|
+ //如果right 减小到与left 只剩一格,则不再减少,并且设置为1格的间距
|
|
|
|
+ this.clerReduceTimer(); //就不再滑动了
|
|
|
|
+ // console.log('保证一格了,不再减少了');
|
|
|
|
+ this.scrollLeftByTouch = toMinScrollLeft ? minScrollLeft : translateX; //同时记录
|
|
|
|
+ this.scrollLeft = toMinScrollLeft ? minScrollLeft : translateX;
|
|
|
|
+ this.selectAreaRight =
|
|
|
|
+ SlidersWrapperTotaLength - selectArealeft - SliderWidth;
|
|
|
|
+ }
|
|
|
|
+ }, 10);
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ clearAddTimer() {
|
|
|
|
+ if (addTimer) {
|
|
|
|
+ // console.log('清楚增加定时器');
|
|
|
|
+ overRightMoveX = 0;
|
|
|
|
+ addTimer = clearInterval(addTimer);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ clerReduceTimer() {
|
|
|
|
+ if (reduceTimer) {
|
|
|
|
+ // console.log('清楚减少定时器');
|
|
|
|
+ reduceLeftMoveX = 0;
|
|
|
|
+ reduceTimer = clearInterval(reduceTimer);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ moveLeftToScreenLeft() {
|
|
|
|
+ const { scrollLeftByTouch, selectArealeft } = this;
|
|
|
|
+ let distance = selectArealeft + scrollLeftByTouch;
|
|
|
|
+ if (distance <= 0) {
|
|
|
|
+ this.scrollLeft = scrollLeftByTouch - distance;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ moveRihtToScreenRight() {
|
|
|
|
+ const { scrollLeftByTouch, selectAreaRight } = this;
|
|
|
|
+ let distance =
|
|
|
|
+ SlidersWrapperTotaLength -
|
|
|
|
+ selectAreaRight +
|
|
|
|
+ scrollLeftByTouch -
|
|
|
|
+ ShowAreaLength;
|
|
|
|
+ if (distance > 0) {
|
|
|
|
+ this.scrollLeft = scrollLeftByTouch - distance;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ changeEndTimeEnd() {
|
|
|
|
+ this.clerReduceTimer();
|
|
|
|
+ this.clearAddTimer();
|
|
|
|
+ this.isSelectPeriodIng = false;
|
|
|
|
+ let { selectAreaRight, selectArealeft, startIndex } = this;
|
|
|
|
+ let numbers;
|
|
|
|
+ let remainder;
|
|
|
|
+ let selectAreaX =
|
|
|
|
+ SlidersWrapperTotaLength - selectAreaRight - selectArealeft;
|
|
|
|
+ // console.log('touchEnd', selectAreaX)
|
|
|
|
+ let moveNumbers = (Math.abs(selectAreaX) / SliderWidth)
|
|
|
|
+ .toString()
|
|
|
|
+ .split('.');
|
|
|
|
+ numbers = parseInt(moveNumbers[0]);
|
|
|
|
+ remainder = parseFloat('0.' + moveNumbers[1]);
|
|
|
|
+ if (Math.abs(remainder) >= 0.5) {
|
|
|
|
+ ++numbers;
|
|
|
|
+ //如果进一的时候,屏幕看不到了,则多滚一点
|
|
|
|
+ this.moveRihtToScreenRight();
|
|
|
|
+ }
|
|
|
|
+ // console.log('滑动结束', startIndex, duration);
|
|
|
|
+ this.duration = numbers;
|
|
|
|
+ this.startIndex = startIndex;
|
|
|
|
+ this.setSelectArea(startIndex, numbers);
|
|
|
|
+ startX = 0;
|
|
|
|
+ this.onEndSelectFun();
|
|
|
|
+ // 钉钉短震动(仅在 iPhone 7 / 7 Plus 以上及 Android 机型生效)
|
|
|
|
+ if (wx.canIUse('vibrateShort')) {
|
|
|
|
+ wx.vibrateShort();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ getComponentWrapInfo() {
|
|
|
|
+
|
|
|
|
+ if (SlidersWrapperTotaLength && ShowAreaLength) {
|
|
|
|
+ return Promise.resolve({
|
|
|
|
+ total: SlidersWrapperTotaLength,
|
|
|
|
+ area: ShowAreaLength
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ this.$wx
|
|
|
|
+ .createSelectorQuery()
|
|
|
|
+ .select('.peroid-content-wrapper')
|
|
|
|
+ .boundingClientRect()
|
|
|
|
+ .exec(ret => {
|
|
|
|
+ if (!ret[0].width) {
|
|
|
|
+ reject();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ return resolve({
|
|
|
|
+ area: ret[0].width
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }, 300);
|
|
|
|
+
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ onEndSelectFun() {
|
|
|
|
+ const { startIndex, duration, sliders } = this;
|
|
|
|
+ let start = sliders[startIndex].value;
|
|
|
|
+ let end = start + duration * SliderUnit;
|
|
|
|
+ let hasUuBooked = this.hasUuBooked();
|
|
|
|
+ // console.log(start,'start!!!!!');
|
|
|
|
+ // console.log(end,'end!!!!!');
|
|
|
|
+ this.$emit('component-period-time-slider-select', { start, end,hasUuBooked });
|
|
|
|
+
|
|
|
|
+ this.$emit(
|
|
|
|
+ 'component-period-time-slider-judgecanselectedend',
|
|
|
|
+ this.canBookSelectArea
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ stopPragation() { },
|
|
|
|
+ hasUuBooked(){ // 选区有新的增加
|
|
|
|
+ let hasUuBooked = false;
|
|
|
|
+ this.sliders.forEach((item,idx) => {
|
|
|
|
+ if (item.isInSelectArea && !item.isBooked) {
|
|
|
|
+ hasUuBooked = true;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return hasUuBooked
|
|
|
|
+ },
|
|
|
|
+ deleteSelectedBookArea() { // 点击 删除
|
|
|
|
+ // console.log('1111');
|
|
|
|
+ let hasUuBooked = this.hasUuBooked();
|
|
|
|
+ if (hasUuBooked)return
|
|
|
|
+ // console.log('222');
|
|
|
|
+ this.$emit('component-bookList-delete')
|
|
|
|
+ // this.selectedBookAreaIndex = idx;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+});
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<config>
|
|
|
|
+{
|
|
|
|
+ "usingComponents":{
|
|
|
|
+ "scroller-x": "~@/components/common/scroller-x"
|
|
|
|
+ },
|
|
|
|
+ componentPlaceholder: {
|
|
|
|
+ 'scroller-x': 'view'
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</config
|