Hospital Appointment Reservation System Using WeChat Mini-Program with SSM and Vue.js

System Architecture Overview

The hospital appointment reservation system employs a three-tier architecture consisting of the presentation layer, business logic layer, and data access layer. The WeChat mini-program serves as the client-side interface, while the backend uses Spring MVC for request handling, MyBatis for database operations, and Vue.js for the management console. This architecture ensures clear separation of concerns and maintainable code structure.

Backend Implementation with Spring Boot

Spring Boot provides auto-configuration capabilities that significantly reduce boilerplate code. The framework integrates embedded servers and offers simplified dependency management through starter packages.

The application entry point and a basic controller implementation:

package com.hospital.appointment;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;

@SpringBootApplication
@RestController
@RequestMapping("/api")
public class AppointmentApplication {

    public static void main(String[] args) {
        SpringApplication.run(AppointmentApplication.class, args);
    }

    @GetMapping("/health")
    public ResponseEntity<String> healthCheck() {
        return ResponseEntity.ok("System running");
    }

    @PostMapping("/appointments")
    public ResponseEntity<AppointmentResponse> createAppointment(
            @RequestBody AppointmentRequest request) {
        AppointmentResponse response = appointmentService.bookAppointment(request);
        return ResponseEntity.ok(response);
    }
}

The controller handles HTTP requests and delegates business logic to the service layer. Spring Boot's auto-configuration eliminates the need for manual dispatcher-servlet and view resolver setup.

Data Access Layer with MyBatis

MyBatis separates SQL statements from application code through XML mapping files or annotations. This approach provides developers with full control over SQL execution while maintaining clean Java interfaces.

Entity class structure:

package com.hospital.appointment.entity;

public class Doctor {
    private Long doctorId;
    private String doctorName;
    private String department;
    private String specialty;
    private Integer availableSlots;
    private String workSchedule;
    
    // getters and setters omitted for brevity
}

The mapper interface defines database operations:

package com.hospital.appointment.mapper;

import com.hospital.appointment.entity.Doctor;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface DoctorMapper {
    
    @Select("SELECT * FROM doctor WHERE department = #{department}")
    List<Doctor> findByDepartment(@Param("department") String department);
    
    @Insert("INSERT INTO doctor(name, department, specialty) VALUES(#{name}, #{department}, #{specialty})")
    @Options(useGeneratedKeys = true, keyProperty = "doctorId")
    int insert(Doctor doctor);
    
    @Update("UPDATE doctor SET available_slots = #{availableSlots} WHERE doctor_id = #{doctorId}")
    int updateAvailability(Doctor doctor);
    
    @Delete("DELETE FROM doctor WHERE doctor_id = #{doctorId}")
    int deleteById(@Param("doctorId") Long doctorId);
}

Frontend Implementation with Vue.js

Vue.js implements a reactive data binding system that automatically synchronizes the view with underlying data changes. The framework uses a virtual DOM for efficient rendering updates.

Basic Vue component structure:

<template>
  <div class="appointment-container">
    <h2>Doctor Appointment</h2>
    <select v-model="selectedDepartment" @change="loadDoctors">
      <option v-for="dept in departments" :key="dept.id" :value="dept.id">
        {{ dept.name }}
      </option>
    </select>
    
    <div class="doctor-list">
      <div v-for="doctor in doctors" :key="doctor.id" class="doctor-card">
        <h3>{{ doctor.name }}</h3>
        <p>Specialty: {{ doctor.specialty }}</p>
        <p>Available: {{ doctor.availableSlots }} slots</p>
        <button @click="showSchedule(doctor)">View Schedule</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'AppointmentBooking',
  data() {
    return {
      selectedDepartment: null,
      departments: [],
      doctors: []
    }
  },
  methods: {
    loadDepartments() {
      this.$http.get('/api/departments').then(response => {
        this.departments = response.data;
      });
    },
    loadDoctors() {
      this.$http.get(`/api/doctors/department/${this.selectedDepartment}`)
        .then(response => {
          this.doctors = response.data;
        });
    },
    showSchedule(doctor) {
      this.$router.push(`/schedule/${doctor.id}`);
    }
  },
  mounted() {
    this.loadDepartments();
  }
}
</script>

<style scoped>
.appointment-container {
  padding: 20px;
}
.doctor-card {
  border: 1px solid #ddd;
  padding: 15px;
  margin: 10px 0;
  border-radius: 8px;
}
</style>

Database Schema Design

The appointment system requires tables for departments, doctors, patients, appointments, and time slots.

CREATE TABLE department (
  dept_id BIGINT PRIMARY KEY AUTO_INCREMENT,
  dept_name VARCHAR(100) NOT NULL,
  dept_description VARCHAR(500),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE doctor (
  doctor_id BIGINT PRIMARY KEY AUTO_INCREMENT,
  doctor_name VARCHAR(50) NOT NULL,
  dept_id BIGINT NOT NULL,
  specialty VARCHAR(100),
  title VARCHAR(50),
  phone VARCHAR(20),
  available_count INT DEFAULT 0,
  FOREIGN KEY (dept_id) REFERENCES department(dept_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE patient (
  patient_id BIGINT PRIMARY KEY AUTO_INCREMENT,
  patient_name VARCHAR(50) NOT NULL,
  id_card VARCHAR(18) NOT NULL UNIQUE,
  phone VARCHAR(20),
  medical_history TEXT,
  register_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE appointment (
  appointment_id BIGINT PRIMARY KEY AUTO_INCREMENT,
  patient_id BIGINT NOT NULL,
  doctor_id BIGINT NOT NULL,
  appointment_date DATE NOT NULL,
  time_slot VARCHAR(20) NOT NULL,
  status VARCHAR(20) DEFAULT 'pending',
  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (patient_id) REFERENCES patient(patient_id),
  FOREIGN KEY (doctor_id) REFERENCES doctor(doctor_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE INDEX idx_appointment_date ON appointment(appointment_date);
CREATE INDEX idx_doctor_date ON appointment(doctor_id, appointment_date);

Authentication and Authorization

The system implements token-based authentication for secure access. The interceptor validates tokens on each request and maintains user sessions.

@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
    
    public static final String AUTH_HEADER = "Authorization";
    
    @Autowired
    private TokenManager tokenManager;
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler) throws Exception {
        
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
        
        if (RequestMethod.OPTIONS.name().equals(request.getMethod())) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }
        
        Method method = ((HandlerMethod) handler).getMethod();
        if (method.isAnnotationPresent(PublicAccess.class)) {
            return true;
        }
        
        String token = request.getHeader(AUTH_HEADER);
        if (StringUtils.isEmpty(token)) {
            sendUnauthorizedResponse(response, "Missing authentication token");
            return false;
        }
        
        UserSession session = tokenManager.validateToken(token);
        if (session == null) {
            sendUnauthorizedResponse(response, "Invalid or expired token");
            return false;
        }
        
        request.setAttribute("currentUser", session);
        return true;
    }
    
    private void sendUnauthorizedResponse(HttpServletResponse response, String message) 
            throws IOException {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("{\"error\":\"" + message + "\"}");
    }
}

Testing Strategy

System testing validates that all functional modules operate according to specifications. Test cases cover normal workflows, boundary conditions, and error handling scenarios.

Sample login test cases:

Test Case Input Expected Actual Status
Valid login username: admin, password: admin123, code: valid Success, redirect to dashboard Success, redirect to dashboard Pass
Invalid password username: admin, password: wrong456, code: valid Error message displayed Error message displayed Pass
Empty username username: "", password: admin123, code: valid Validation error Validation error Pass
Expired session session timeout Redirect to login Redirect to login Pass

Appointment booking test scenarios:

Scenario Input Expected Actual Status
Available slot Select available time slot Booking confirmation Booking confirmation Pass
Double booking Same slot already taken Error: slot unavailable Error: slot unavailable Pass
Past date Select yesterday's date Error: invalid date Error: invalid date Pass
Cancel booking Valid booking ID Cancellation confirmed Cancellation confirmed Pass

System Configuration

Application configuration in application.yml:

server:
  port: 8080
  servlet:
    context-path: /hospital-system

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/hospital_db?useSSL=false&serverTimezone=UTC
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
  
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.hospital.appointment.entity

logging:
  level:
    com.hospital.appointment: DEBUG
    org.springframework: INFO

API Endpoints

The system provides RESTful endpoints for client integration:

Method Endpoint Description
GET /api/departments List all departments
GET /api/doctors/{deptId} Get doctors by department
GET /api/schedule/{doctorId} Get doctor's available schedule
POST /api/appointments Create new appointment
GET /api/appointments/{patientId} Get patient's appointments
PUT /api/appointments/{id}/cancel Cancel appointment
POST /api/auth/login User authentication
GET /api/doctors/{id}/detail Get doctor information

Tags: WeChat Mini-Program Spring Boot MyBatis Vue.js Hospital Information System

Posted on Wed, 22 Jul 2026 16:21:17 +0000 by ultrasound0000