Files
go-yu/handlers/timeslot.go
lingxiao865 13d1175057 13
2026-02-10 09:30:37 +08:00

219 lines
6.2 KiB
Go

package handlers
import (
"strconv"
"time"
"yuyue/database"
"yuyue/middleware"
"yuyue/models"
"yuyue/utils"
"github.com/gofiber/fiber/v2"
)
type TimeSlotRequest struct {
Date string `json:"date" validate:"required"`
StartTime string `json:"start_time" validate:"required"`
EndTime string `json:"end_time" validate:"required"`
MaxPeople int `json:"max_people" validate:"required,min=1"`
IsActive bool `json:"is_active"`
}
func CreateTimeSlot(c *fiber.Ctx) error {
// 检查是否为管理员
if middleware.GetUserRole(c) != models.RoleAdmin {
return utils.Unauthorized(c, "需要管理员权限")
}
var req TimeSlotRequest
if err := c.BodyParser(&req); err != nil {
return utils.BadRequest(c, "请求数据格式错误")
}
// 解析日期时间
date, err := time.Parse("2006-01-02", req.Date)
if err != nil {
return utils.BadRequest(c, "日期格式错误,应为 YYYY-MM-DD")
}
startTime, err := time.Parse("15:04", req.StartTime)
if err != nil {
return utils.BadRequest(c, "开始时间格式错误,应为 HH:MM")
}
endTime, err := time.Parse("15:04", req.EndTime)
if err != nil {
return utils.BadRequest(c, "结束时间格式错误,应为 HH:MM")
}
// 组合完整的时间
fullStartTime := time.Date(date.Year(), date.Month(), date.Day(),
startTime.Hour(), startTime.Minute(), 0, 0, date.Location())
fullEndTime := time.Date(date.Year(), date.Month(), date.Day(),
endTime.Hour(), endTime.Minute(), 0, 0, date.Location())
// 检查时间合理性
if fullStartTime.After(fullEndTime) || fullStartTime.Equal(fullEndTime) {
return utils.BadRequest(c, "开始时间必须早于结束时间")
}
timeSlot := models.TimeSlot{
Date: date,
StartTime: fullStartTime,
EndTime: fullEndTime,
MaxPeople: req.MaxPeople,
CurrentPeople: 0,
IsActive: req.IsActive,
}
if err := database.GetDB().Create(&timeSlot).Error; err != nil {
return utils.InternalServerError(c, "时间槽创建失败")
}
return utils.Success(c, timeSlot)
}
func GetTimeSlots(c *fiber.Ctx) error {
var timeSlots []models.TimeSlot
query := database.GetDB().Model(&models.TimeSlot{})
// 可选的查询参数
date := c.Query("date")
if date != "" {
query = query.Where("date = ? ", date)
} else {
// 2. 如果没传日期,才默认显示“今天及以后”的数据
today := time.Now()
sevenDaysLater := today.AddDate(0, 0, 14)
query = query.Where("date >= ? and date <= ?", today.Format("2006-01-02"), sevenDaysLater.Format("2006-01-02"))
}
//isActive := c.Query("is_active")
//if isActive != "" {
// active, err := strconv.ParseBool(isActive)
// if err == nil {
// query = query.Where("is_active = ?", active)
// }
//}
////
//// 只显示未来的时段
now := time.Now().Format("2006-01-02")
query = query.Where("date >= ? and is_active = true", now)
// 按日期和时间排序
query = query.Order("date ASC, start_time ASC")
if err := query.Find(&timeSlots).Error; err != nil {
return utils.InternalServerError(c, "获取时间槽列表失败")
}
return utils.Success(c, timeSlots)
}
func GetTimeSlot(c *fiber.Ctx) error {
id, err := strconv.ParseUint(c.Params("id"), 10, 32)
if err != nil {
return utils.BadRequest(c, "无效的时间槽ID")
}
var timeSlot models.TimeSlot
if err := database.GetDB().First(&timeSlot, uint(id)).Error; err != nil {
return utils.NotFound(c, "时间槽不存在")
}
return utils.Success(c, timeSlot)
}
func UpdateTimeSlot(c *fiber.Ctx) error {
// 检查是否为管理员
if middleware.GetUserRole(c) != models.RoleAdmin {
return utils.Unauthorized(c, "需要管理员权限")
}
id, err := strconv.ParseUint(c.Params("id"), 10, 32)
if err != nil {
return utils.BadRequest(c, "无效的时间槽ID")
}
var req TimeSlotRequest
if err := c.BodyParser(&req); err != nil {
return utils.BadRequest(c, "请求数据格式错误")
}
var timeSlot models.TimeSlot
if err := database.GetDB().First(&timeSlot, uint(id)).Error; err != nil {
return utils.NotFound(c, "时间槽不存在")
}
// 解析日期时间
date, err := time.Parse("2006-01-02", req.Date)
if err != nil {
return utils.BadRequest(c, "日期格式错误,应为 YYYY-MM-DD")
}
startTime, err := time.Parse("15:04", req.StartTime)
if err != nil {
return utils.BadRequest(c, "开始时间格式错误,应为 HH:MM")
}
endTime, err := time.Parse("15:04", req.EndTime)
if err != nil {
return utils.BadRequest(c, "结束时间格式错误,应为 HH:MM")
}
// 组合完整的时间
fullStartTime := time.Date(date.Year(), date.Month(), date.Day(),
startTime.Hour(), startTime.Minute(), 0, 0, date.Location())
fullEndTime := time.Date(date.Year(), date.Month(), date.Day(),
endTime.Hour(), endTime.Minute(), 0, 0, date.Location())
// 检查时间合理性
if fullStartTime.After(fullEndTime) || fullStartTime.Equal(fullEndTime) {
return utils.BadRequest(c, "开始时间必须早于结束时间")
}
// 检查是否会影响现有预约
if req.MaxPeople < timeSlot.CurrentPeople {
return utils.BadRequest(c, "最大人数不能小于当前已预约人数")
}
timeSlot.Date = date
timeSlot.StartTime = fullStartTime
timeSlot.EndTime = fullEndTime
timeSlot.MaxPeople = req.MaxPeople
timeSlot.IsActive = req.IsActive
if err := database.GetDB().Save(&timeSlot).Error; err != nil {
return utils.InternalServerError(c, "更新时间槽失败")
}
return utils.Success(c, timeSlot)
}
func DeleteTimeSlot(c *fiber.Ctx) error {
// 检查是否为管理员
if middleware.GetUserRole(c) != models.RoleAdmin {
return utils.Unauthorized(c, "需要管理员权限")
}
id, err := strconv.ParseUint(c.Params("id"), 10, 32)
if err != nil {
return utils.BadRequest(c, "无效的时间槽ID")
}
// 检查是否有关联的预约
var appointmentCount int64
database.GetDB().Model(&models.Appointment{}).Where("time_slot_id = ?", uint(id)).Count(&appointmentCount)
if appointmentCount > 0 {
return utils.BadRequest(c, "该时间槽已有预约,无法删除")
}
if err := database.GetDB().Delete(&models.TimeSlot{}, uint(id)).Error; err != nil {
return utils.InternalServerError(c, "删除时间槽失败")
}
return utils.Success(c, fiber.Map{"message": "时间槽删除成功"})
}