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

基于jQuery/Bootstrap的无复选框预约调度数据保存方案咨询

Hey Wesley! Let's tackle this appointment scheduling feature step by step. Your current approach with multiple hidden inputs is getting unwieldy—let's simplify it with a single JSON-backed hidden field, cleaner click logic, and a straightforward database setup.

1. Frontend Refactor: Simplify Selection & State Management

Instead of having separate hidden inputs for each possible slot, we'll use a single hidden field to store the entire schedule as JSON. This makes it easier to track selections, handle cancellations, and avoid messy input naming.

Updated HTML Structure

We'll add data-* attributes to each slot to make identifying days and slot types easier, and use a single hidden input for the schedule:

<form action="save-schedule.php" method="post">
  <!-- Single hidden field to store schedule state as JSON -->
  <input type="hidden" name="schedule" id="schedule" value='{}'>

  <div class="row" id="days">
    <div class="col-lg-1"></div>
    <div class="col-lg-2 day-column" data-day="monday">
      <h3>MONDAY</h3>
      <div id="finaldates"></div>
      <!-- Default slots with data attributes -->
      <p class="slot default-slot" data-slot="05:00a - 8:00a">05:00a - 8:00a</p>
      <p class="slot default-slot" data-slot="05:30a - 8:30a">05:30a - 8:30a</p>
      <p class="slot default-slot" data-slot="06:00a - 9:00a">06:00a - 9:00a</p>
      <p class="slot default-slot" data-slot="07:00a - 10:00a">07:00a - 10:00a</p>
      <p class="slot default-slot" data-slot="10:00a - 1:00p">10:00a - 1:00p</p>
      <p class="slot default-slot" data-slot="10:00a - 2:00p">10:00a - 2:00p</p>
      
      <div class="buffer"></div>
      <img src="pics/PM-icon.png" alt="PM Slots">
      
      <p class="slot default-slot" data-slot="03:00p - 6:00p">03:00p - 6:00p</p>
      <p class="slot default-slot" data-slot="03:30p - 6:30p">03:30p - 6:30p</p>
      <p class="slot default-slot" data-slot="04:00p - 7:00p">04:00p - 7:00p</p>
      
      <!-- Special options -->
      <p class="slot custom-option" data-type="custom">Choose Your Own</p>
      <p class="slot no-appt-option" data-type="no-appt">NO MONDAYS</p>
    </div>

    <!-- Repeat similar structure for Tuesday-Friday -->
  </div>
  <button type="submit">Save Schedule</button>
</form>

<!-- Add some CSS for selected state -->
<style>
  .slot {
    cursor: pointer;
    padding: 5px;
    margin: 3px 0;
    border-radius: 4px;
  }
  .slot.selected {
    background-color: #007bff;
    color: white;
  }
  .day-column .no-appt-option.selected ~ .slot {
    opacity: 0.5; /* Dim other slots if "no appointments" is selected */
  }
</style>

jQuery Logic for Selection & Cancellation

This code will handle clicking slots, tracking the schedule state, updating the hidden field, and managing the selected UI state:

$(document).ready(function() {
  // Initialize schedule from hidden field (or empty object)
  let schedule = JSON.parse($('#schedule').val() || '{}');

  // Helper to update the hidden field and UI
  function updateSchedule() {
    $('#schedule').val(JSON.stringify(schedule));
    // Refresh UI state
    $('.slot').removeClass('selected');
    Object.keys(schedule).forEach(day => {
      const dayData = schedule[day];
      if (dayData.noAppointment) {
        $(`.day-column[data-day="${day}"] .no-appt-option`).addClass('selected');
      } else if (dayData.slots) {
        dayData.slots.forEach(slot => {
          $(`.day-column[data-day="${day}"] .slot[data-slot="${slot}"]`).addClass('selected');
        });
        if (dayData.customSlot) {
          // Display custom slot in the finaldates container
          $(`.day-column[data-day="${day}"] #finaldates`).text(`Custom: ${dayData.customSlot}`);
        } else {
          $(`.day-column[data-day="${day}"] #finaldates`).empty();
        }
      }
    });
  }

  // Load initial state
  updateSchedule();

  // Handle slot clicks
  $('.slot').click(function() {
    const $slot = $(this);
    const day = $slot.closest('.day-column').data('day');
    const slotType = $slot.data('type');
    const slotValue = $slot.data('slot');

    // Initialize day entry if it doesn't exist
    if (!schedule[day]) {
      schedule[day] = { slots: [], customSlot: null, noAppointment: false };
    }
    const daySchedule = schedule[day];

    // Case 1: "NO MONDAYS" (no appointments) selected
    if (slotType === 'no-appt') {
      daySchedule.noAppointment = !daySchedule.noAppointment;
      // Reset other options if enabling no appointments
      if (daySchedule.noAppointment) {
        daySchedule.slots = [];
        daySchedule.customSlot = null;
      }
    }
    // Case 2: Custom slot selection
    else if (slotType === 'custom') {
      const customSlot = prompt("Enter your custom time slot (e.g., 09:00a - 12:00p):");
      if (customSlot) {
        daySchedule.customSlot = customSlot;
        daySchedule.noAppointment = false;
        // Ensure we don't exceed 2 slots total (custom + 1 default)
        if (daySchedule.slots.length > 1) {
          daySchedule.slots.pop();
        }
      }
    }
    // Case 3: Default slot selection
    else {
      daySchedule.noAppointment = false;
      daySchedule.customSlot = null; // Clear custom if selecting default
      const slotIndex = daySchedule.slots.indexOf(slotValue);
      if (slotIndex !== -1) {
        // Remove slot if already selected (cancellation)
        daySchedule.slots.splice(slotIndex, 1);
      } else {
        // Add slot if under 2 selections
        if (daySchedule.slots.length < 2) {
          daySchedule.slots.push(slotValue);
        } else {
          alert(`You can only select 2 slots per day for ${day.charAt(0).toUpperCase() + day.slice(1)}!`);
          return;
        }
      }
    }

    // Update the schedule state
    updateSchedule();
  });
});

2. Backend: PHP Handling & Database Storage

First, let's define a clean database table structure to store the schedule. We'll use a row per day/slot combination for flexibility:

Database Table Schema

CREATE TABLE appointment_schedules (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT NOT NULL, -- Link to your users table
  day_of_week ENUM('monday', 'tuesday', 'wednesday', 'thursday', 'friday') NOT NULL,
  slot VARCHAR(50) DEFAULT NULL, -- For default slots
  custom_slot VARCHAR(50) DEFAULT NULL, -- For custom slots
  is_no_appointment BOOLEAN DEFAULT FALSE, -- For "no appointments" option
  start_date DATE NOT NULL, -- For 3-month coverage (adjust to your date range)
  end_date DATE NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id) -- Adjust to your users table name
);

PHP Code to Save the Schedule

Create a save-schedule.php file to handle form submission:

<?php
// Assume you have a database connection established (PDO or mysqli)
// Example PDO connection:
$pdo = new PDO('mysql:host=localhost;dbname=your_database', 'username', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Get the logged-in user ID (adjust this to your auth system)
$userId = 1; // Replace with actual user ID

// Define 3-month date range (adjust start/end as needed)
$startDate = date('Y-m-d');
$endDate = date('Y-m-d', strtotime('+3 months'));

// Get the schedule JSON from the form
$scheduleJson = $_POST['schedule'] ?? '{}';
$schedule = json_decode($scheduleJson, true);

// First, delete existing schedule for the user in this date range
$stmt = $pdo->prepare("DELETE FROM appointment_schedules WHERE user_id = ? AND start_date = ? AND end_date = ?");
$stmt->execute([$userId, $startDate, $endDate]);

// Insert new schedule entries
foreach ($schedule as $day => $dayData) {
  if ($dayData['noAppointment']) {
    // Insert "no appointments" entry
    $stmt = $pdo->prepare("INSERT INTO appointment_schedules (user_id, day_of_week, is_no_appointment, start_date, end_date) VALUES (?, ?, ?, ?, ?)");
    $stmt->execute([$userId, $day, true, $startDate, $endDate]);
  } else {
    // Insert default slots
    foreach ($dayData['slots'] as $slot) {
      $stmt = $pdo->prepare("INSERT INTO appointment_schedules (user_id, day_of_week, slot, start_date, end_date) VALUES (?, ?, ?, ?, ?)");
      $stmt->execute([$userId, $day, $slot, $startDate, $endDate]);
    }
    // Insert custom slot if exists
    if (!empty($dayData['customSlot'])) {
      $stmt = $pdo->prepare("INSERT INTO appointment_schedules (user_id, day_of_week, custom_slot, start_date, end_date) VALUES (?, ?, ?, ?, ?)");
      $stmt->execute([$userId, $day, $dayData['customSlot'], $startDate, $endDate]);
    }
  }
}

// Redirect back or show success message
header("Location: your-schedule-page.php?success=1");
exit;
?>

Key Improvements Over Your Current Setup

  • Simpler State Management: Using JSON to store the entire schedule eliminates the need for dozens of hidden inputs.
  • Built-in Cancellation: Clicking an already selected slot removes it from the schedule.
  • Clear Slot Limits: Enforces the 2-slot per day rule with a user-friendly alert.
  • Flexible Database Storage: The table structure supports default slots, custom slots, and "no appointment" options, plus the 3-month coverage you mentioned.
  • Maintainable Code: Separating concerns (frontend state, backend storage) makes it easier to extend later (like adding date range pickers for the 3-month window).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:24:56