mrr.sj.front/components/select-time-page/select-time-page2.vue

511 lines
12 KiB
Vue
Raw Normal View History

2026-03-24 11:45:13 +08:00
<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;
2026-06-02 11:39:23 +08:00
border: 1rpx solid #FF4767;
color: #FF4767;
2026-03-24 11:45:13 +08:00
/* 选中状态 */
}
&__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;
2026-06-02 11:39:23 +08:00
background: linear-gradient(140deg, #fa4e9a 0%, #FF4767 100%);
2026-03-24 11:45:13 +08:00
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>