package vehicle import ( "errors" "fmt" "server/dao" "server/global" "server/model/vehicle/request" "time" ) type VehicleService struct{} // CreateVehicle 创建车辆信息 func (s *VehicleService) CreateVehicle(req request.VehicleCreate) error { // 检查车牌号是否已存在 var existingVehicle dao.Vehicle result := global.GVA_DB.Where("plate_number = ? OR rfid_tag = ?", req.PlateNumber, req.RFIDTag).First(&existingVehicle) if result.RowsAffected > 0 { return errors.New("车牌号已存在") } // 检查车辆类型是否存在 var vehicleType dao.VehicleType result = global.GVA_DB.First(&vehicleType, req.VehicleTypeID) if result.RowsAffected == 0 { return errors.New("车辆类型不存在") } // 处理临时车辆的情况 var ownerId *uint if req.OwnerId > 0 { ownerId = &req.OwnerId } vehicle := dao.Vehicle{ PlateNumber: req.PlateNumber, VehicleTypeID: req.VehicleTypeID, VehicleBrand: req.VehicleBrand, VehicleColor: req.VehicleColor, OwnerId: ownerId, } return global.GVA_DB.Create(&vehicle).Error } // UpdateVehicle 更新车辆信息 func (s *VehicleService) UpdateVehicle(req request.VehicleUpdate) error { var vehicle dao.Vehicle result := global.GVA_DB.First(&vehicle, req.ID) if result.RowsAffected == 0 { return errors.New("车辆不存在") } // 检查车牌号是否被其他车辆使用 var existingVehicle dao.Vehicle result = global.GVA_DB.Where("(plate_number = ? OR rfid_tag = ?) AND id != ?", req.PlateNumber, req.RFIDTag, req.ID).First(&existingVehicle) fmt.Println("result", result.RowsAffected) if result.RowsAffected > 0 { return errors.New("车牌号已被其他车辆使用") } // 检查车辆类型是否存在 var vehicleType dao.VehicleType result = global.GVA_DB.First(&vehicleType, req.VehicleTypeID) if result.RowsAffected == 0 { return errors.New("车辆类型不存在") } // 处理临时车辆的情况 var ownerId *uint if req.OwnerId > 0 { ownerId = &req.OwnerId } else { ownerId = nil } err := global.GVA_DB.Model(&vehicle).Updates(map[string]interface{}{ "plate_number": req.PlateNumber, "rfid_tag": req.RFIDTag, "vehicle_type_id": req.VehicleTypeID, "vehicle_brand": req.VehicleBrand, "vehicle_color": req.VehicleColor, "owner_id": ownerId, }).Error return err } // GetVehicleByID 根据ID获取车辆信息 func (s *VehicleService) GetVehicleByID(id uint) (dao.Vehicle, error) { var vehicle dao.Vehicle result := global.GVA_DB.First(&vehicle, id) if result.RowsAffected == 0 { return dao.Vehicle{}, errors.New("车辆不存在") } return vehicle, nil } // GetVehicleByPlateNumber 根据车牌号获取车辆信息 func (s *VehicleService) GetVehicleByPlateNumber(plateNumber, RFIDTag string) (dao.Vehicle, error) { var vehicle dao.Vehicle result := global.GVA_DB.Where("plate_number = ? or rfid_tag = ?", plateNumber, RFIDTag).Preload("VehicleType").First(&vehicle) if result.RowsAffected == 0 { return dao.Vehicle{}, errors.New("车辆不存在") } return vehicle, nil } func (s *VehicleService) QueryAllVehicles() ([]dao.Vehicle, error) { var vehicles []dao.Vehicle err := global.GVA_DB.Find(&vehicles).Error if err != nil { return vehicles, err } return vehicles, nil } // ListVehicles 获取车辆列表 func (s *VehicleService) ListVehicles(req request.VehicleQuery) (int64, []dao.Vehicle, error) { var vehicles []dao.Vehicle var total int64 query := global.GVA_DB.Model(&dao.Vehicle{}) if req.PlateNumber != "" { query = query.Where("plate_number LIKE ?", "%"+req.PlateNumber+"%") } if req.VehicleTypeID > 0 { query = query.Where("vehicle_type_id = ?", req.VehicleTypeID) } if req.OwnerId > 0 { query = query.Where("owner_id = ?", req.OwnerId) } // 计算总数 query.Count(&total) // 分页查询 offset := (req.Page - 1) * req.PageSize result := query.Offset(offset).Limit(req.PageSize).Preload("Owner").Preload("VehicleType").Find(&vehicles) if result.Error != nil { return 0, nil, result.Error } return total, vehicles, nil } // DeleteVehicle 删除车辆 func (s *VehicleService) DeleteVehicle(id uint) error { result := global.GVA_DB.Delete(&dao.Vehicle{}, id) if result.RowsAffected == 0 { return errors.New("车辆不存在") } return result.Error } // VehicleEntry 车辆入场 func (s *VehicleService) VehicleEntry(req request.VehicleEntry) (request.VehicleEntryResponse, error) { // 检查车辆是否存在 vehicle, err := s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag) if err != nil { // 如果车辆不存在,创建新车辆,默认使用ID为1的车辆类型(临时车) createReq := request.VehicleCreate{ PlateNumber: req.PlateNumber, VehicleTypeID: 1, // 默认类型ID为1(临时车) OwnerId: 0, // 默认无车主 } err = s.CreateVehicle(createReq) if err != nil { return request.VehicleEntryResponse{}, err } vehicle, _ = s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag) } // 检查是否有未出场的记录 var existingRecord dao.VehicleRecord result := global.GVA_DB.Where("(plate_number = ? OR rfid_tag = ?) AND exit_time IS NULL", req.PlateNumber, req.RFIDTag).First(&existingRecord) if result.RowsAffected > 0 { return request.VehicleEntryResponse{}, errors.New("车辆已入场,未出场") } // 创建入场记录 entryTime := time.Now() record := dao.VehicleRecord{ PlateNumber: req.PlateNumber, RFIDTag: req.RFIDTag, EntryTime: entryTime, ParkingLotID: req.ParkingLotID, ParkingSpaceID: req.ParkingSpaceID, EntryImage: req.EntryImage, PaymentStatus: "unpaid", } err = global.GVA_DB.Create(&record).Error if err != nil { return request.VehicleEntryResponse{}, err } // 更新车辆最近入场时间 vehicle.LastEntryTime = &entryTime global.GVA_DB.Save(&vehicle) response := request.VehicleEntryResponse{ Success: true, Message: "车辆入场成功", } response.Data.PlateNumber = req.PlateNumber response.Data.EntryTime = entryTime.Unix() response.Data.ParkingLotID = req.ParkingLotID response.Data.ParkingSpaceID = req.ParkingSpaceID return response, nil } // VehicleExit 车辆出场 func (s *VehicleService) VehicleExit(req request.VehicleExit) (request.VehicleExitResponse, error) { // 1. 查询未出场记录 var record dao.VehicleRecord if err := global.GVA_DB.Where("(plate_number = ? OR rfid_tag = ?) AND exit_time IS NULL", req.PlateNumber, req.RFIDTag).First(&record).Error; err != nil { return request.VehicleExitResponse{}, errors.New("车辆未入场或已出场") } // 2. 获取车辆信息 vehicle, err := s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag) if err != nil { return request.VehicleExitResponse{}, err } // 3. 计算停留时长 & 费用 exitTime := time.Now() stayTime := int64(exitTime.Sub(record.EntryTime).Minutes()) if stayTime < 0 { stayTime = 0 } fee := s.calculateFee(&vehicle, stayTime) // 4. 更新出场记录 record.ExitTime = &exitTime record.StayTime = stayTime record.Fee = fee record.ExitImage = req.ExitImage record.PaymentStatus = "paid" if err := global.GVA_DB.Save(&record).Error; err != nil { return request.VehicleExitResponse{}, err } // 5. 更新车辆统计信息 vehicle.LastExitTime = &exitTime vehicle.TotalStayTime += stayTime vehicle.TotalFee += fee global.GVA_DB.Save(&vehicle) // 6. 完全匹配你的匿名结构体返回(正确写法) var response request.VehicleExitResponse response.Success = true response.Message = "车辆出场成功" response.Data.PlateNumber = record.PlateNumber response.Data.EntryTime = record.EntryTime.Unix() response.Data.ExitTime = exitTime.Unix() response.Data.StayTime = stayTime response.Data.Fee = fee response.Data.PaymentStatus = record.PaymentStatus return response, nil } // calculateFee 计算停车费用 func (s *VehicleService) calculateFee(vehicle *dao.Vehicle, stayTime int64) float64 { // 1. 根据车辆类型ID获取收费配置(唯一) var feeConfig dao.FeeConfig if err := global.GVA_DB.Where("vehicle_type_id = ?", vehicle.VehicleTypeID).First(&feeConfig).Error; err != nil { // 无配置 → 默认计费 return float64(stayTime) * 0.1 } // 2. 判断VIP有效性 isVIP := false if vehicle.OwnerId != nil { var owner dao.Owner if err := global.GVA_DB.First(&owner, *vehicle.OwnerId).Error; err == nil { isVIP = owner.IsVip && time.Now().Before(owner.VipExpireTime) } } // 3. VIP 免费 if isVIP && feeConfig.IsVIPFree { return 0 } // 4. 基础费用计算 fee := feeConfig.StartFee if stayTime > int64(feeConfig.StartTime) { extraTime := stayTime - int64(feeConfig.StartTime) extraUnits := extraTime / int64(feeConfig.UnitTime) if extraTime%int64(feeConfig.UnitTime) > 0 { extraUnits++ } fee += float64(extraUnits) * feeConfig.UnitFee } // 5. 每日封顶 if feeConfig.DailyMaxFee > 0 && fee > feeConfig.DailyMaxFee { fee = feeConfig.DailyMaxFee } // 6. VIP 折扣 if isVIP { fee *= feeConfig.VIPDiscount } return fee }