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> |