You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3组合式API日期时间输入限制及已选时间禁用问题

Vue3 预约表单:时间输入限制与已选时间禁用方案

针对你的两个需求,以下是具体实现方案:


一、动态设置时间输入的 max/min 限制

原生 input[type="time"] 支持通过 :min 和 :max 属性限制可选时间范围,结合选中的日期动态调整规则:

  • 若选择当日,时间最小值设为当前时间(防止选择过去的时段),最大值设为营业结束时间
  • 若选择未来日期,时间范围直接限制在营业时间内
<script setup>
import { ref, watch } from 'vue'

const selectedDate = ref(new Date().toISOString().split('T')[0])
const selectedTime = ref('')
// 自定义营业时间
const businessStart = '09:00'
const businessEnd = '18:00'
const timeMin = ref(businessStart)
const timeMax = ref(businessEnd)

// 监听日期变化,动态更新时间限制
watch(selectedDate, (newDate) => {
  const today = new Date().toISOString().split('T')[0]
  if (newDate === today) {
    // 格式化当前时间为 HH:mm
    const now = new Date()
    const currentHour = String(now.getHours()).padStart(2, '0')
    const currentMinute = String(now.getMinutes()).padStart(2, '0')
    timeMin.value = `${currentHour}:${currentMinute}`
  } else {
    timeMin.value = businessStart
  }
  timeMax.value = businessEnd
})
</script>

<template>
  <input 
    type="date" 
    v-model="selectedDate" 
    :min="new Date().toISOString().split('T')[0]"
  >
  <input 
    type="time" 
    v-model="selectedTime" 
    :min="timeMin" 
    :max="timeMax"
  >
</template>

二、禁用已被选择的时间

原生时间输入框无法直接禁用特定时段,建议通过生成可选时间列表的方式实现,过滤掉已预约的时段:

  1. 维护一个已预约时间的数组(可从后端接口获取)
  2. 根据选中日期和营业时间,生成所有可选时段,标记已预约的时段为禁用状态
  3. 使用下拉选择框或自定义选择器展示可选时间
<script setup>
import { ref, computed } from 'vue'

const selectedDate = ref(new Date().toISOString().split('T')[0])
const selectedTime = ref('')
const businessStart = '09:00'
const businessEnd = '18:00'
// 模拟已预约的时间数据
const bookedTimes = ref([
  { date: '2024-05-20', time: '10:00' },
  { date: '2024-05-20', time: '14:30' }
])

// 计算生成可选时间列表(按30分钟间隔)
const availableTimes = computed(() => {
  const times = []
  const startMs = new Date(`2000-01-01 ${businessStart}`).getTime()
  const endMs = new Date(`2000-01-01 ${businessEnd}`).getTime()
  const interval = 30 * 60 * 1000 // 30分钟间隔

  // 当日从当前时间之后开始(向上取整到最近的间隔)
  const today = new Date().toISOString().split('T')[0]
  let currentMs = startMs
  if (selectedDate.value === today) {
    const nowMs = new Date().getTime()
    const todayStartMs = new Date(`${today} ${businessStart}`).getTime()
    // 若当前时间早于营业开始,从营业开始时间算
    currentMs = nowMs < todayStartMs ? todayStartMs : nowMs
    // 向上取整到间隔时间
    const remainder = currentMs % interval
    currentMs = remainder ? currentMs + (interval - remainder) : currentMs
  }

  // 生成所有可选时段
  while (currentMs <= endMs) {
    const timeStr = new Date(currentMs).toTimeString().slice(0, 5)
    // 检查该时段是否已被预约
    const isBooked = bookedTimes.value.some(item => 
      item.date === selectedDate.value && item.time === timeStr
    )
    times.push({
      time: timeStr,
      disabled: isBooked || currentMs < startMs
    })
    currentMs += interval
  }
  return times
})

// 提交预约,添加到已预约列表
const submitBooking = () => {
  if (selectedTime.value) {
    bookedTimes.value.push({
      date: selectedDate.value,
      time: selectedTime.value
    })
    selectedTime.value = ''
  }
}
</script>

<template>
  <input 
    type="date" 
    v-model="selectedDate" 
    :min="new Date().toISOString().split('T')[0]"
  >
  <select v-model="selectedTime">
    <option value="">请选择时段</option>
    <option 
      v-for="item in availableTimes" 
      :key="item.time" 
      :value="item.time"
      :disabled="item.disabled"
    >
      {{ item.time }} {{ item.disabled ? '(已预约)' : '' }}
    </option>
  </select>
  <button @click="submitBooking" :disabled="!selectedTime">提交预约</button>
</template>

内容的提问来源于stack exchange,提问作者coochie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:20:07