511 lines
12 KiB
Vue
511 lines
12 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="time-popup">
|
|||
|
|
<view class="popup-header">
|
|||
|
|
<text class="popup-title">选择服务</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="time-picker-content">
|
|||
|
|
<!-- 日期选择 -->
|
|||
|
|
<view class="time-picker-content__datas">
|
|||
|
|
<view class="time-picker-content__datas__date__item" v-for="(date, index) in dateList" :key="index"
|
|||
|
|
@click="selectDate(index)">
|
|||
|
|
<text class="time-picker-content__datas__date__item__text"
|
|||
|
|
:class="{ active: selectedDateIndex === index }">{{ date }}</text>
|
|||
|
|
<image v-if="selectedDateIndex === index" src="/static/images/dataBox.png"
|
|||
|
|
class="time-picker-content__datas__date__item__box" mode="aspectFit"></image>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<!-- 时间选择 -->
|
|||
|
|
<scroll-view class="time-picker-content__time__list" scroll-y>
|
|||
|
|
<view class="time-picker-content__time__list__item"
|
|||
|
|
v-for="(time, index) in timeOptions[selectedDateIndex]" :key="index" :class="[
|
|||
|
|
getItemClass(time.state),
|
|||
|
|
{
|
|||
|
|
isActive:
|
|||
|
|
activeList.includes(index) &&
|
|||
|
|
sureTimeDataIndex == selectedDateIndex,
|
|||
|
|
},
|
|||
|
|
]" @click="selectTime(time, index)">
|
|||
|
|
<view class="time-picker-content__time__list__item__text">{{
|
|||
|
|
time.show_time
|
|||
|
|
}}</view>
|
|||
|
|
<view class="time-picker-content__time__list__item__state">{{
|
|||
|
|
time.stateName
|
|||
|
|
}}</view>
|
|||
|
|
</view>
|
|||
|
|
</scroll-view>
|
|||
|
|
<!-- <view class="time-picker-content__time__sure">
|
|||
|
|
<view class="time-picker-content__time__sure__box" @click="sureTime"
|
|||
|
|
>确认</view
|
|||
|
|
>
|
|||
|
|
</view> -->
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
/**
|
|||
|
|
* sureTime 确认时间触发事件
|
|||
|
|
* openTime 打开时间选择弹框
|
|||
|
|
* closeTime 关闭时间选择弹框
|
|||
|
|
* selectDate 选择日期
|
|||
|
|
* selectTime 选择时间
|
|||
|
|
* getItemClass 获取列表项的class
|
|||
|
|
* handelGetTimeArr 获取时间段,
|
|||
|
|
*/
|
|||
|
|
import request from "@/utils/request";
|
|||
|
|
export default {
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
isFirstOPen: true,
|
|||
|
|
sureTimeObj: {}, // 确认时间对象
|
|||
|
|
dateList: ["今天", "明天", "后天"],
|
|||
|
|
startTimeIndex: null, // 开始时间索引
|
|||
|
|
endTimeIndex: null, //结束时间
|
|||
|
|
activeList: [],
|
|||
|
|
sureTimeDataIndex: 0, // 确认的时间索引
|
|||
|
|
selectedDateIndex: 0, // 选中的日期索引
|
|||
|
|
// 状态映射配置
|
|||
|
|
stateConfig: {
|
|||
|
|
1: {
|
|||
|
|
class: "state-available",
|
|||
|
|
text: "可约",
|
|||
|
|
},
|
|||
|
|
2: {
|
|||
|
|
class: "state-full",
|
|||
|
|
text: "约满",
|
|||
|
|
},
|
|||
|
|
3: {
|
|||
|
|
class: "state-rest",
|
|||
|
|
text: "休息",
|
|||
|
|
},
|
|||
|
|
4: {
|
|||
|
|
class: "state-locked",
|
|||
|
|
text: "锁定",
|
|||
|
|
},
|
|||
|
|
5: {
|
|||
|
|
class: "state-unavailable",
|
|||
|
|
text: "不可用",
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
props: {
|
|||
|
|
// 时间选项数组
|
|||
|
|
timeOptions: {
|
|||
|
|
type: Array,
|
|||
|
|
default: () => [],
|
|||
|
|
},
|
|||
|
|
// 服务信息
|
|||
|
|
service: {
|
|||
|
|
type: Object,
|
|||
|
|
default: () => ({}),
|
|||
|
|
},
|
|||
|
|
url: {
|
|||
|
|
type: String,
|
|||
|
|
default: "",
|
|||
|
|
},
|
|||
|
|
identity: {
|
|||
|
|
type: Number,
|
|||
|
|
default: 0, //0为商家,1为手艺人
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
created() {
|
|||
|
|
console.log("选择时间", this.service);
|
|||
|
|
},
|
|||
|
|
mounted() {},
|
|||
|
|
methods: {
|
|||
|
|
// 列表项的class获取方法
|
|||
|
|
getItemClass(state) {
|
|||
|
|
return this.stateConfig[state]?.class || "state-unknown";
|
|||
|
|
},
|
|||
|
|
// 选择日期
|
|||
|
|
selectDate(index) {
|
|||
|
|
this.selectedDateIndex = index;
|
|||
|
|
},
|
|||
|
|
// 生成两个数字之间的数组(包含边界值)
|
|||
|
|
createRangeArray(start, end) {
|
|||
|
|
// 确定步长,正数表示递增,负数表示递减
|
|||
|
|
let step = start <= end ? 1 : -1;
|
|||
|
|
let length = Math.abs(end - start) + 1;
|
|||
|
|
|
|||
|
|
// 创建数组并填充值
|
|||
|
|
return Array.from({
|
|||
|
|
length
|
|||
|
|
}, (_, i) => start + i * step);
|
|||
|
|
},
|
|||
|
|
selectTime(time, index) {
|
|||
|
|
let that = this;
|
|||
|
|
//如果和记录日期不同重新记录
|
|||
|
|
if (this.sureTimeDataIndex != this.selectedDateIndex) {
|
|||
|
|
that.startTimeIndex = null;
|
|||
|
|
that.endTimeIndex = null;
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
let startTimeIndex = this.startTimeIndex;
|
|||
|
|
let endTimeIndex = this.endTimeIndex;
|
|||
|
|
if (time.state === 1) {
|
|||
|
|
// 可约状态
|
|||
|
|
if(startTimeIndex == endTimeIndex && endTimeIndex == index){
|
|||
|
|
this.startTimeIndex = null;
|
|||
|
|
this.endTimeIndex = null;
|
|||
|
|
this.storageStatus();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (startTimeIndex == null || startTimeIndex != endTimeIndex) {
|
|||
|
|
this.startTimeIndex = index;
|
|||
|
|
this.endTimeIndex = index;
|
|||
|
|
this.storageStatus();
|
|||
|
|
that.handelGetTimeArr();
|
|||
|
|
uni.showToast({
|
|||
|
|
title: `您已选择${this.timeOptions[this.selectedDateIndex][this.startTimeIndex].show_time},烦请再选一个时间,完成「开始 / 结束」的时间段设置`,
|
|||
|
|
icon: "none",
|
|||
|
|
duration: 1000,
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
} else {
|
|||
|
|
// if (endTimeIndex == index) {
|
|||
|
|
// this.endTimeIndex = startTimeIndex;
|
|||
|
|
// this.storageStatus();
|
|||
|
|
// that.handelGetTimeArr();
|
|||
|
|
// return;
|
|||
|
|
// } else if (startTimeIndex == index) {
|
|||
|
|
// this.startTimeIndex = endTimeIndex;
|
|||
|
|
// this.storageStatus();
|
|||
|
|
// that.handelGetTimeArr();
|
|||
|
|
// return;
|
|||
|
|
// } else if (startTimeIndex > index) {
|
|||
|
|
// startTimeIndex = index;
|
|||
|
|
// } else if (endTimeIndex < index) {
|
|||
|
|
// endTimeIndex = index;
|
|||
|
|
// } else {
|
|||
|
|
// let leftNum = index - startTimeIndex;
|
|||
|
|
// let rightNum = endTimeIndex - index;
|
|||
|
|
// //如果靠近开始时间
|
|||
|
|
// if (leftNum < rightNum) {
|
|||
|
|
// startTimeIndex = index;
|
|||
|
|
// } else {
|
|||
|
|
// endTimeIndex = index;
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
if (startTimeIndex > index) {
|
|||
|
|
startTimeIndex = index;
|
|||
|
|
} else{
|
|||
|
|
endTimeIndex = index;
|
|||
|
|
}
|
|||
|
|
// let len = this.timeOptions[this.sureTimeDataIndex].length
|
|||
|
|
if (endTimeIndex - startTimeIndex < 3) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: "预约时间最少需要30分钟,请调整您的结束时间选择~",
|
|||
|
|
icon: "none",
|
|||
|
|
duration: 1000,
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
let found = this.timeOptions[this.selectedDateIndex].slice(startTimeIndex,endTimeIndex).findIndex(item=>item.state !=1)
|
|||
|
|
console.log(22222,found,this.timeOptions[this.selectedDateIndex].slice(startTimeIndex,endTimeIndex))
|
|||
|
|
if(found!=-1){
|
|||
|
|
uni.showToast({
|
|||
|
|
title: "您选择的时间段内部分时间不可用,请调整后重新选择~",
|
|||
|
|
icon: "none",
|
|||
|
|
duration: 1000,
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let parms;
|
|||
|
|
if (this.identity == 0) {
|
|||
|
|
parms = {
|
|||
|
|
user_syr_id: this.service.user_syr.id,
|
|||
|
|
reserve_time: this.timeOptions[this.selectedDateIndex][startTimeIndex]
|
|||
|
|
.time,
|
|||
|
|
end_time: this.timeOptions[this.selectedDateIndex][endTimeIndex].time,
|
|||
|
|
};
|
|||
|
|
} else if (this.identity == 1) {
|
|||
|
|
parms = {
|
|||
|
|
work_seat_id: this.service.work_seat.id,
|
|||
|
|
user_sj_id: this.service.user_sj.id,
|
|||
|
|
reserve_time: this.timeOptions[this.selectedDateIndex][startTimeIndex]
|
|||
|
|
.time,
|
|||
|
|
end_time: this.timeOptions[this.selectedDateIndex][endTimeIndex].time,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (this.url) {
|
|||
|
|
request
|
|||
|
|
.post(this.url, parms)
|
|||
|
|
.then(async (res) => {
|
|||
|
|
if (res.code == 200) {
|
|||
|
|
that.startTimeIndex = startTimeIndex;
|
|||
|
|
that.endTimeIndex = endTimeIndex;
|
|||
|
|
this.storageStatus();
|
|||
|
|
that.handelGetTimeArr();
|
|||
|
|
} else {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: res.msg,
|
|||
|
|
icon: "none",
|
|||
|
|
duration: 1000,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.catch((err) => {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '网络繁忙,稍后再试',
|
|||
|
|
icon: "none",
|
|||
|
|
duration: 1000,
|
|||
|
|
});
|
|||
|
|
console.log("报错", err);
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
that.startTimeIndex = startTimeIndex;
|
|||
|
|
that.endTimeIndex = endTimeIndex;
|
|||
|
|
this.storageStatus();
|
|||
|
|
that.handelGetTimeArr();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
//存储状态
|
|||
|
|
storageStatus() {
|
|||
|
|
this.sureTimeDataIndex = this.selectedDateIndex;
|
|||
|
|
if(this.startTimeIndex==null){
|
|||
|
|
this.activeList = []
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
this.activeList = this.createRangeArray(
|
|||
|
|
this.startTimeIndex,
|
|||
|
|
this.endTimeIndex
|
|||
|
|
);
|
|||
|
|
},
|
|||
|
|
handelGetTimeArr() {
|
|||
|
|
//获取时间段
|
|||
|
|
let startTime =
|
|||
|
|
this.timeOptions[this.selectedDateIndex][
|
|||
|
|
this.startTimeIndex
|
|||
|
|
].time.split(" ");
|
|||
|
|
let data = {
|
|||
|
|
reserve_start_time: this.timeOptions[this.selectedDateIndex][this.startTimeIndex].time,
|
|||
|
|
reserve_end_time: this.timeOptions[this.selectedDateIndex][this.endTimeIndex].time,
|
|||
|
|
startTime: this.timeOptions[this.selectedDateIndex][this.startTimeIndex]
|
|||
|
|
.show_time,
|
|||
|
|
endTime: this.timeOptions[this.selectedDateIndex][this.endTimeIndex].show_time,
|
|||
|
|
date: startTime[0],
|
|||
|
|
num: this.activeList.length - 1,
|
|||
|
|
};
|
|||
|
|
this.$emit("changeTime", data);
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped lang="less">
|
|||
|
|
/* 时间选择弹框 */
|
|||
|
|
.time-popup {
|
|||
|
|
background-color: #ffffff;
|
|||
|
|
border-radius: 24rpx 24rpx 0 0;
|
|||
|
|
overflow: hidden;
|
|||
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|||
|
|
transform: translateY(0);
|
|||
|
|
transition: transform 0.3s;
|
|||
|
|
z-index: 999;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.popup-header {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
padding: 30rpx 30rpx 36rpx 30rpx;
|
|||
|
|
|
|||
|
|
.popup-close {
|
|||
|
|
font-family: PingFangSC, PingFang SC;
|
|||
|
|
font-weight: 400;
|
|||
|
|
font-size: 26rpx;
|
|||
|
|
color: #999999;
|
|||
|
|
line-height: 37rpx;
|
|||
|
|
text-align: left;
|
|||
|
|
font-style: normal;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.popup-title {
|
|||
|
|
font-family: PingFangSC, PingFang SC;
|
|||
|
|
font-weight: 500;
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
line-height: 42rpx;
|
|||
|
|
text-align: left;
|
|||
|
|
font-style: normal;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-picker-content {
|
|||
|
|
padding: 0rpx 30rpx 30rpx 30rpx;
|
|||
|
|
|
|||
|
|
&__datas {
|
|||
|
|
display: flex;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
|
|||
|
|
&__date__item {
|
|||
|
|
width: 214rpx;
|
|||
|
|
height: 67rpx;
|
|||
|
|
background: #f7f8fa;
|
|||
|
|
border-radius: 10rpx;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
|
|||
|
|
&__text {
|
|||
|
|
font-family: PingFangSC, PingFang SC;
|
|||
|
|
font-weight: 400;
|
|||
|
|
font-size: 26rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
line-height: 37rpx;
|
|||
|
|
text-align: left;
|
|||
|
|
font-style: normal;
|
|||
|
|
position: relative;
|
|||
|
|
position: relative;
|
|||
|
|
z-index: 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__text.active {
|
|||
|
|
color: #ffffff;
|
|||
|
|
background: transparent;
|
|||
|
|
background-position: bottom;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__box {
|
|||
|
|
width: 214rpx;
|
|||
|
|
height: 74rpx;
|
|||
|
|
position: absolute;
|
|||
|
|
z-index: 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__time__list {
|
|||
|
|
flex: 1;
|
|||
|
|
height: 400rpx;
|
|||
|
|
margin-top: 30rpx;
|
|||
|
|
|
|||
|
|
::-webkit-scrollbar {
|
|||
|
|
display: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
uni-scroll-view .uni-scroll-view::-webkit-scrollbar {
|
|||
|
|
display: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
::v-deep .uni-scroll-view-content {
|
|||
|
|
display: flex;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
justify-content: flex-start;
|
|||
|
|
-webkit-column-gap: 21rpx;
|
|||
|
|
column-gap: 21rpx;
|
|||
|
|
row-gap: 30rpx;
|
|||
|
|
max-height: 100%;
|
|||
|
|
height: auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__item {
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
width: 156rpx;
|
|||
|
|
height: 90rpx;
|
|||
|
|
background: #f7f8fa;
|
|||
|
|
border-radius: 10rpx;
|
|||
|
|
font-family: PingFangSC, PingFang SC;
|
|||
|
|
font-weight: 400;
|
|||
|
|
font-size: 26rpx;
|
|||
|
|
color: #3c3638;
|
|||
|
|
line-height: 37rpx;
|
|||
|
|
text-align: left;
|
|||
|
|
font-style: normal;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
|
|||
|
|
.__text {}
|
|||
|
|
|
|||
|
|
.__state {}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.state-available {
|
|||
|
|
color: #3c3638;
|
|||
|
|
background: #f7f8fa;
|
|||
|
|
/* 可约 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.state-full {
|
|||
|
|
color: #3c3638;
|
|||
|
|
background: #e4e9f0;
|
|||
|
|
/* 约满 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.state-rest {
|
|||
|
|
color: #cdcdcd;
|
|||
|
|
background: #f7f8f9;
|
|||
|
|
/* 休息 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.state-locked {
|
|||
|
|
color: #3c3638;
|
|||
|
|
background: #e4e9f0;
|
|||
|
|
/* 锁定 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.state-unavailable {
|
|||
|
|
color: #ffffff;
|
|||
|
|
background: #e4e9f0;
|
|||
|
|
/* 不可用 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.state-unknown {
|
|||
|
|
/* 未知状态 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.isActive {
|
|||
|
|
background: rgba(252, 67, 124, 0.08);
|
|||
|
|
border-radius: 10rpx;
|
|||
|
|
border: 1rpx solid #E8101E;
|
|||
|
|
color: #E8101E;
|
|||
|
|
/* 选中状态 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__item.active {
|
|||
|
|
background-color: #fff0f0;
|
|||
|
|
color: #ff3e3e;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__item.noselected {
|
|||
|
|
/* background-color: #FFF0F0; */
|
|||
|
|
color: #999999;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__time__sure {
|
|||
|
|
padding: 39rpx 0;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
|
|||
|
|
&__box {
|
|||
|
|
width: 648rpx;
|
|||
|
|
height: 94rpx;
|
|||
|
|
background: linear-gradient(140deg, #fa4e9a 0%, #E8101E 100%);
|
|||
|
|
border-radius: 48rpx;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
font-family: PingFangSC, PingFang SC;
|
|||
|
|
font-weight: 400;
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #ffffff;
|
|||
|
|
line-height: 42rpx;
|
|||
|
|
text-align: left;
|
|||
|
|
font-style: normal;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|