效果图

源码
结构

popupBox_Contentt_time_radio.vue
<template>
<picker-view
indicator-style="height: 50px;"
mask-style="padding:10px 0"
@change="Change"
:value="positioning"
>
<picker-view-column>
<view class="item" v-for="(item, index) in hours" :key="index">{{
item
}}</view>
</picker-view-column>
<picker-view-column>
<view class="item" v-for="(item, index) in minutes" :key="index">{{
item
}}</view>
</picker-view-column>
</picker-view>
</template>
<script setup>
import { onLoad } from "@dcloudio/uni-app";
import { ref, computed, defineProps } from "vue";
const hours = ref([
"00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23",
]);
const minutes = ref([
"00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
]);
const seconds = ref([
"00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
]);
const hour = ref("00");
const minute = ref("00");
const second = ref("00");
function Change(e) {
const val = e.detail.value;
hour.value = hours.value[val[0]];
minute.value = minutes.value[val[1]];
second.value = seconds.value[val[2]];
}
const time = computed(() => {
return hour.value + ":" + minute.value;
});
const positioning = computed(() => {
return [Number(hour.value),Number(minute.value),Number(second.value)]
});
defineExpose({
time,
hour,
minute,
second
});
</script>
<style scoped lang="scss">
picker-view {
width: 100%;
height: 500rpx;
.item {
line-height: 100rpx;
text-align: center;
}
}
</style>
popupBox_time_MultipleChoice.vue,使用弹窗容器包裹,完成最后的组件
<template>
<popupBox
ref="SubmitSureRef"
@sure="SubmitSureRef.close()"
:onConfirmDisable="onConfirmDisable"
>
<template #title
><view class="top">
<view class="left">
<text class="title">{{ props.title }}</text>
<text class="remark"
>已选:{{ `${startTime_Ref?.time} - ${endTime_Ref?.time}` }} </text
><br />
<text class="remark2" v-if="onConfirmDisable"
>请注意:结束时间 必须大于 开始时间
</text>
</view>
</view></template
>
<template #content>
<view
style="display: flex; align-items: center"
class="popupBox_Contentt_time_radio"
>
<popupBox_Contentt_time_radio
ref="startTime_Ref"
></popupBox_Contentt_time_radio>
<view style="padding: 0 20rpx">至</view>
<popupBox_Contentt_time_radio
ref="endTime_Ref"
></popupBox_Contentt_time_radio>
</view>
</template>
</popupBox>
</template>
<script setup>
import { ref, onMounted, computed, watch } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import popupBox_Contentt_time_radio from "./popupBox_Contentt_time_radio.vue";
import popupBox from "../popupBox.vue";
const props = defineProps({
title: {
type: String,
default: "时段选择",
},
});
const SubmitSureRef = ref(null);
const startTime_Ref = ref(null);
const endTime_Ref = ref(null);
const onConfirmDisable = computed(() => {
if (
Number(startTime_Ref.value?.time.split(":").join("")) >=
Number(endTime_Ref.value?.time.split(":").join(""))
) {
return true;
}
return false;
});
const time = computed(() => {
return [startTime_Ref.value?.time, endTime_Ref.value?.time];
});
function open(params) {
SubmitSureRef.value.open({
cancelText: "取消",
confirmText: "确定",
onOpen: function () {
if (params.time) {
let startTime = params.time[0] || "00:00";
let endTime = params.time[1] || "00:00";
startTime_Ref.value.hour = startTime.split(":")[0];
startTime_Ref.value.minute = startTime.split(":")[1];
endTime_Ref.value.hour = endTime.split(":")[0];
endTime_Ref.value.minute = endTime.split(":")[1];
}
},
onConfirm: function () {
if (params.onConfirm) {
params.onConfirm(time.value);
}
SubmitSureRef.value.close();
},
onClose: function () {
if (params.onClose) {
params.onClose();
}
},
});
}
onLoad(() => {});
defineExpose({
open,
});
</script>
<style scoped lang="scss">
.top {
// display: flex;
// justify-content: space-between;
width: 100%;
.left {
.title {
font-size: 34.35rpx;
font-weight: 600;
}
.remark {
margin-left: 30rpx;
color: rgba(122, 122, 122, 1);
font-size: 26.71rpx;
}
.remark2 {
color: red;
font-size: 26.71rpx;
}
}
.right {
}
}
</style>
使用
<template>
{{ timedata }}<br />
<view @click="open">打开时间段弹窗</view>
<popupBox_time_MultipleChoice ref="popupBox_time_MultipleChoice_Ref">
</popupBox_time_MultipleChoice>
</template>
<script setup>
import { ref, onMounted, computed, watch, defineProps } from "vue";
import popupBox_time_MultipleChoice from "./components/popupBox_time_MultipleChoice/popupBox_time_MultipleChoice.vue";
const popupBox_time_MultipleChoice_Ref = ref(null);
const timedata = ref("");
function open() {
popupBox_time_MultipleChoice_Ref.value.open({
time: timedata.value.split("-"),
onConfirm: (time) => {
timedata.value = time.join("-");
},
onClose: () => {},
});
}
</script>
<style scoped></style>