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

汽车预订系统基于用户输入生成可用时段的后端逻辑咨询

汽车预订系统后端(Node.js+MongoDB)实现方案

一、MongoDB数据模型设计

先定义核心的预订记录集合,用来存储已完成的预订信息,后续生成可用时段时会依赖它排除冲突:

const mongoose = require('mongoose');

const bookingSchema = new mongoose.Schema({
  start: { type: Date, required: true }, // 预订开始时间
  end: { type: Date, required: true },   // 预订结束时间
  duration: { type: Number, required: true } // 用车时长(单位:分钟)
});

const Booking = mongoose.model('Booking', bookingSchema);

二、核心逻辑:生成可用时段

1. 基础规则

  • 以用户选择日期的0点为起始,按「用车时长+10分钟洗车间隔」循环生成时段,直到当天24点
  • 若存在已预订时段,需排除重叠时段,并调整后续时段的起始时间(以上一个已预订时段的结束时间+10分钟为起点)

2. 完整实现函数

使用date-fns处理日期(和前端保持一致,减少跨端差异),函数会自动过滤冲突时段:

const { addMinutes, isSameDay, isWithinInterval, startOfDay, endOfDay } = require('date-fns');
const Booking = require('./models/Booking');

async function generateAvailableSlots(selectedDate, duration) {
  const timeToWash = 10;
  const dayStart = startOfDay(new Date(selectedDate));
  const dayEnd = endOfDay(new Date(selectedDate));
  
  // 获取当天所有已预订记录,按开始时间排序
  const bookings = await Booking.find({
    start: { $gte: dayStart, $lt: dayEnd }
  }).sort({ start: 1 });

  // 先生成无冲突的基础时段列表
  const baseSlots = [];
  let currentStart = dayStart;
  while (addMinutes(currentStart, duration) <= dayEnd) {
    const currentEnd = addMinutes(currentStart, duration);
    baseSlots.push({ start: currentStart, end: currentEnd });
    currentStart = addMinutes(currentEnd, timeToWash);
  }

  // 过滤冲突并调整时段
  const availableSlots = [];
  let lastAvailableEnd = dayStart;

  for (const slot of baseSlots) {
    // 检查当前时段是否与已预订记录重叠
    const hasConflict = bookings.some(booking => {
      return isWithinInterval(slot.start, { start: booking.start, end: booking.end }) ||
             isWithinInterval(slot.end, { start: booking.start, end: booking.end }) ||
             isWithinInterval(booking.start, { start: slot.start, end: slot.end });
    });

    if (!hasConflict) {
      // 确保当前时段起始时间不早于上一个可用/已预订时段结束+洗车时间
      const adjustedStart = addMinutes(lastAvailableEnd, timeToWash) > slot.start 
        ? addMinutes(lastAvailableEnd, timeToWash) 
        : slot.start;
      const adjustedEnd = addMinutes(adjustedStart, duration);
      
      if (adjustedEnd <= dayEnd) {
        availableSlots.push({
          start: adjustedStart.toISOString(),
          end: adjustedEnd.toISOString()
        });
        lastAvailableEnd = adjustedEnd;
      }
    } else {
      // 找到冲突的预订记录,更新lastAvailableEnd为该预订的结束时间
      const conflictBooking = bookings.find(booking => {
        return isWithinInterval(slot.start, { start: booking.start, end: booking.end }) ||
               isWithinInterval(slot.end, { start: booking.start, end: booking.end }) ||
               isWithinInterval(booking.start, { start: slot.start, end: slot.end });
      });
      lastAvailableEnd = conflictBooking.end;
    }
  }

  return availableSlots;
}

三、Express接口示例

1. 安装依赖

npm install mongoose date-fns express

2. 接口实现

const express = require('express');
const app = express();
const mongoose = require('mongoose');

// 连接MongoDB
mongoose.connect('mongodb://localhost:27017/car-booking')
  .then(() => console.log('MongoDB连接成功'))
  .catch(err => console.error('MongoDB连接失败:', err));

app.use(express.json());

// 获取可用时段接口
app.post('/api/available-slots', async (req, res) => {
  try {
    const { selectedDate, duration } = req.body;
    if (!selectedDate || duration <= 0) {
      return res.status(400).json({ error: '参数无效,请检查日期和时长' });
    }
    const slots = await generateAvailableSlots(selectedDate, duration);
    res.json(slots);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// 创建预订接口
app.post('/api/bookings', async (req, res) => {
  try {
    const { start, end, duration } = req.body;
    const booking = new Booking({ start, end, duration });
    await booking.save();
    res.status(201).json(booking);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

app.listen(3000, () => console.log('服务运行在端口3000'));

四、关键注意事项

  • 时区处理:始终用ISO字符串或MongoDB的Date类型存储时间,避免前后端时区不一致导致的错误
  • 性能优化:给预订集合的start字段创建索引,提升当天预订记录的查询速度
  • 边界处理:函数中通过adjustedEnd <= dayEnd过滤掉超过当天24点的无效时段
  • 冲突判断:覆盖了所有重叠场景(当前时段包含预订时段、预订时段包含当前时段、部分重叠)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:21:58