diff --git a/business/api/order.go b/business/api/order.go index 7e59c79..885c7bf 100644 --- a/business/api/order.go +++ b/business/api/order.go @@ -15,7 +15,6 @@ import ( "pet-house.com/core/server/web/web_iris" "pet-house.com/core/server/zap_server" "strconv" - "strings" "sync" "time" ) @@ -560,10 +559,7 @@ func GetOrderDetail(orderId string) OrderDetail { } func checkOrderServiceTime(serviceTime string, projectionServiceTime int) bool { - type orderMainTmp struct { - ServiceTime string - ProjectionServiceTime int - } + serviceTimeD, _ := time.Parse("2006-01-02 15:04", serviceTime) hour := serviceTimeD.Hour() if hour == 20 && projectionServiceTime > 2*60 { @@ -573,14 +569,9 @@ func checkOrderServiceTime(serviceTime string, projectionServiceTime int) bool { return true } - var orderMainTmpList []orderMainTmp - //服务时间>=预约时间 and 服务时间<=预计结束时间 时间范围内无订单才可预约 - database.Instance().Model(&models.OrderMain{}).Where("service_time >= ? and service_time < DATE_FORMAT(DATE_ADD('"+serviceTime+"', INTERVAL "+strconv.Itoa(projectionServiceTime)+" MINUTE), '%Y-%m-%d %H:%i') and order_status != 3 and order_status != 4 and status = 1", serviceTime).Find(&orderMainTmpList) - //时间点订单数量<服务车辆*车辆单次服务数量 才可接受预约 - if len(orderMainTmpList) > 0 { - return len(orderMainTmpList) >= len(CarMap)*CarServiceNum - } - return false + var orderTempList []utils.OrderTemp + database.Instance().Model(&models.OrderMain{}).Where("service_time >= DATE_SUB(NOW(), INTERVAL 7 DAY) and order_status != 3 and order_status != 4 and status = 1").Find(&orderTempList) + return utils.CheckAvailability(orderTempList, len(CarMap), serviceTime, projectionServiceTime) } type OrderListRequest struct { @@ -795,10 +786,6 @@ type OrderServiceTimeRequest struct { ServiceAddrId int64 } -type OrderServiceTimeResponse struct { - Times map[string][]TimeObject `json:"times"` -} - // 获取订单可预约时间 func (p DefParty) orderServiceTime() web_iris.Party { return web_iris.Party{Prefix: p.Prefix, PartyFunc: func(index iris.Party) { @@ -811,81 +798,9 @@ func (p DefParty) orderServiceTime() web_iris.Party { ParamError.Fail(ctx, orderServiceTimeRequest) return } - type orderMainTmp struct { - ServiceTime string - ProjectionServiceTime int - } - var orderMainTmpList []orderMainTmp - database.Instance().Model(&models.OrderMain{}).Where("service_time >= DATE_SUB(NOW(), INTERVAL 7 DAY) and order_status != 3 and order_status != 4 and status = 1").Find(&orderMainTmpList) - // 执行查询 - var orderMainTmp1 []struct { - ServiceTime string - Count int - ProjectionServiceTime int - } - err := database.Instance().Raw(` - SELECT service_time, COUNT(1) AS count, projection_service_time - FROM order_mains - WHERE service_time >= DATE_SUB(NOW(), INTERVAL 7 DAY) - AND order_status != 3 - AND order_status != 4 - AND status = 1 - GROUP BY service_time - HAVING count > 0 - `).Scan(&orderMainTmp1).Error - if err != nil { - ServerError.Fail(ctx, err) - return - } - - var orderTimeMap = make(map[string]string) - var orderTimeNum = make(map[string]int) - var orderTimeCount = make(map[string]int) - var orderProjectionTime = make(map[string]int) - for _, val := range orderMainTmp1 { - orderTimeCount[val.ServiceTime] = val.Count - orderProjectionTime[val.ServiceTime] = val.ProjectionServiceTime - } - - for _, value := range orderMainTmpList { - orderTimeMap[value.ServiceTime] = value.ServiceTime - orderTimeNum[value.ServiceTime] = orderTimeNum[value.ServiceTime] + 1 - if value.ProjectionServiceTime > 0 { - //计算出服务时间点之后累计延长时间 - date, _ := time.Parse("2006-01-02 15:04", value.ServiceTime) - lastDate := date.Add(time.Minute * time.Duration(value.ProjectionServiceTime)) - for t := date; t.Before(lastDate); t = t.Add(time.Hour) { - timeStr := t.Format("2006-01-02 15:04") - if timeStr != value.ServiceTime { - orderTimeMap[timeStr] = timeStr - orderTimeNum[timeStr] = orderTimeNum[timeStr] + 1 - orderTimeCount[timeStr] = orderTimeCount[timeStr] + 1 - } - } - } - } - serviceTime := AddrServiceMap[orderServiceTimeRequest.ServiceAddrId] - times := strings.Split(serviceTime.Times, ",") - carNum := len(CarMap) - daysMap := utils.GetStrDays(7, 60, ReserveMap, orderTimeMap, carNum, orderTimeNum, CarServiceNum, times, orderTimeCount, orderProjectionTime) - var dayHoursMap = make(map[string][]TimeObject) - for day, values := range daysMap { - key := day - for _, value := range values { - if _, ok := dayHoursMap[key]; ok { - dayHoursMap[key] = append(dayHoursMap[key], TimeObject{ - Time: value.Time, - Y: value.Y, - }) - } else { - dayHoursMap[key] = []TimeObject{{ - Time: value.Time, - Y: value.Y, - }} - } - } - } - Success(ctx, headerBaseInfo, OrderServiceTimeResponse{dayHoursMap}) + var orderTempList []utils.OrderTemp + database.Instance().Model(&models.OrderMain{}).Where("service_time >= DATE_SUB(NOW(), INTERVAL 7 DAY) and order_status != 3 and order_status != 4 and status = 1").Find(&orderTempList) + Success(ctx, headerBaseInfo, utils.ProcessOrders(orderTempList, len(CarMap), 7)) }) }} } diff --git a/business/go.mod b/business/go.mod index 47f0f98..9839067 100644 --- a/business/go.mod +++ b/business/go.mod @@ -6,9 +6,10 @@ require ( github.com/bwmarrin/snowflake v0.3.0 github.com/dgb8901/go-wechat-miniapp-sdk v1.0.1-release github.com/kataras/iris/v12 v12.2.10 - github.com/kellydunn/golang-geo v0.7.0 github.com/spf13/viper v1.18.2 + github.com/wechatpay-apiv3/wechatpay-go v0.2.20 go.uber.org/zap v1.27.0 + golang.org/x/net v0.21.0 gorm.io/gorm v1.25.8 pet-house.com/core v0.0.0 ) @@ -24,7 +25,6 @@ require ( github.com/aymerick/douceur v0.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/flosch/pongo2/v4 v4.0.2 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -51,11 +51,9 @@ require ( github.com/kataras/sitemap v0.0.6 // indirect github.com/kataras/tunnel v0.0.4 // indirect github.com/klauspost/compress v1.17.4 // indirect - github.com/kylelemons/go-gypsy v1.0.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect github.com/lestrrat-go/strftime v1.0.6 // indirect - github.com/lib/pq v1.3.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailgun/raymond/v2 v2.0.48 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -82,13 +80,10 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - github.com/wechatpay-apiv3/wechatpay-go v0.2.20 // indirect github.com/yosssi/ace v0.0.5 // indirect - github.com/ziutek/mymysql v1.5.4 // indirect go.uber.org/multierr v1.10.0 // indirect golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect - golang.org/x/net v0.21.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect diff --git a/business/go.sum b/business/go.sum index 65aaf35..412b56b 100644 --- a/business/go.sum +++ b/business/go.sum @@ -12,6 +12,7 @@ github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8L github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM= github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw= github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= @@ -48,8 +49,6 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= -github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= -github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= @@ -126,8 +125,6 @@ github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= -github.com/kellydunn/golang-geo v0.7.0 h1:A5j0/BvNgGwY6Yb6inXQxzYwlPHc6WVZR+MrarZYNNg= -github.com/kellydunn/golang-geo v0.7.0/go.mod h1:YYlQPJ+DPEzrHx8kT3oPHC/NjyvCCXE+IuKGKdrjrcU= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -136,8 +133,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/go-gypsy v1.0.0 h1:7/wQ7A3UL1bnqRMnZ6T8cwCOArfZCxFmb1iTxaOOo1s= -github.com/kylelemons/go-gypsy v1.0.0/go.mod h1:chkXM0zjdpXOiqkCW1XcCHDfjfk14PH2KKkQWxfJUcU= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= @@ -147,8 +142,6 @@ github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECae github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= @@ -257,8 +250,6 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= -github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= diff --git a/business/utils/Test1.go b/business/utils/Test1.go new file mode 100644 index 0000000..4a4dc25 --- /dev/null +++ b/business/utils/Test1.go @@ -0,0 +1,125 @@ +package utils + +/*import ( + "encoding/json" + "fmt" + "time" +) + +type TimeObject1 struct { + Time string `json:"time"` // 时间格式 "HH:MM" + Y bool `json:"y"` // Y=true: 可预约 (空闲),Y=false: 不可预约 (已占用) +} + +type OrderServiceTimeResponse struct { + Times map[string][]TimeObject1 `json:"times"` // 按日期分组 +} + +func generateTimeSlots(startTime time.Time, maxDays int) []string { + var timeSlots []string + // 生成当前时间起未来 maxDays 天,9点到22点每小时整点的时间段 + for d := 0; d < maxDays; d++ { + // 计算当前天的9点到22点时间段 + day := startTime.Add(time.Duration(d) * 24 * time.Hour) // 当前日期 + for h := 9; h <= 22; h++ { + timeSlots = append(timeSlots, fmt.Sprintf("%04d-%02d-%02d %02d:00:00", day.Year(), day.Month(), day.Day(), h)) + } + } + return timeSlots +} + +func processOrders(orders []Order, maxCars int, maxDays int) OrderServiceTimeResponse { + // 存储每个时间段的车辆占用情况 + response := OrderServiceTimeResponse{ + Times: make(map[string][]TimeObject1), + } + + // 用来记录每个时间段的车占用情况 + occupiedSlots := make(map[string]int) // key: 时间段, value: 占用的车数 + + // 遍历每个订单 + for _, order := range orders { + startTime, err := time.Parse("2006-01-02 15:04", order.ServiceTime) + if err != nil { + fmt.Println("Error parsing time:", err) + continue + } + + // 计算每个时间段的结束时间 + endTime := startTime.Add(time.Duration(order.ProjectionServiceTime) * time.Minute) + + // 处理服务时间占用 + for t := startTime; t.Before(endTime); t = t.Add(time.Hour) { + // 格式化每个小时的整点 + timeSlot := fmt.Sprintf("%04d-%02d-%02d %02d:00:00", t.Year(), t.Month(), t.Day(), t.Hour()) + + // 如果这个时间段已经被占用了,则增加占用车数 + occupiedSlots[timeSlot]++ + } + } + + // 计算时间段的范围,生成当前时间到未来7天内的每小时时间段 + startTime := time.Now() + allTimeSlots := generateTimeSlots(startTime, maxDays) + + // 填充每个时间段的占用情况 + for _, slot := range allTimeSlots { + isOccupied := false + // 格式化时间为 "HH:MM" + timeOnly := slot[11:16] + + // 当前时间段的占用车数 + occupiedCars := occupiedSlots[slot] + + // 如果当前时间段的车占用数大于或等于最大车数,则标记为占用 + if occupiedCars >= maxCars { + isOccupied = true + } + + // 提取日期作为 key + date := slot[:10] + + // 根据占用情况设置 Y 的值,true 表示可预约,false 表示不可预约 + response.Times[date] = append(response.Times[date], TimeObject1{ + Time: timeOnly, + Y: !isOccupied, // true 是可预约,false 是不可预约 + }) + } + + return response +} + +// 模拟的订单结构 +type Order struct { + OrderID string + UID int64 + ServiceTime string // 格式: "2025-02-11 09:00" + ProjectionServiceTime int64 // 服务时长,单位:分钟 +} + +func main() { + // 假设我们从数据库获取的订单数据 + orders := []Order{ + {"1886746333474197504", 10012, "2025-02-11 10:00", 600}, + {"1887103577298571264", 11089, "2025-02-12 19:00", 125}, + {"1887680412080148480", 10575, "2025-02-11 18:00", 120}, + {"1888482012872839168", 10273, "2025-02-14 19:00", 65}, + {"1888834477728206848", 10012, "2025-02-13 17:00", 180}, + {"1888932349274492928", 10012, "2025-02-15 10:00", 60}, + {"1889211058120298496", 10462, "2025-02-12 10:00", 120}, + {"1889211312915877888", 10462, "2025-02-12 11:00", 120}, + {"1889211441857171456", 10462, "2025-02-12 12:00", 120}, + {"1889211684388605952", 10462, "2025-02-12 13:00", 120}, + {"1889214115952463872", 10012, "2025-02-12 14:00", 120}, + } + + response := processOrders(orders, 2, 7) // 假设有2台车,查询近7天的预约情况 + + jsonData, err := json.MarshalIndent(response, "", " ") + if err != nil { + fmt.Println("Error marshaling to JSON:", err) + return + } + fmt.Println(string(jsonData)) +} +*/ diff --git a/business/utils/commonUtil.go b/business/utils/commonUtil.go index 8d357e5..1c66392 100644 --- a/business/utils/commonUtil.go +++ b/business/utils/commonUtil.go @@ -2,6 +2,7 @@ package utils import ( "encoding/json" + "fmt" "github.com/kataras/iris/v12/context" "io" "math" @@ -134,3 +135,156 @@ func GetStrDays(day int, minute int, reserveMap map[string]models.ReserveTimeFil func RoundToOneDecimalPlace(value float64) float64 { return math.Round(value*10) / 10 } + +func generateTimeSlots(startTime time.Time, maxDays int) []string { + var timeSlots []string + // 生成当前时间起未来 maxDays 天,9点到22点每小时整点的时间段 + for d := 0; d < maxDays; d++ { + // 计算当前天的9点到22点时间段 + day := startTime.Add(time.Duration(d) * 24 * time.Hour) // 当前日期 + for h := 10; h <= 19; h++ { + timeSlots = append(timeSlots, fmt.Sprintf("%04d-%02d-%02d %02d:00:00", day.Year(), day.Month(), day.Day(), h)) + } + } + return timeSlots +} + +type OrderServiceTimeResponse struct { + Times map[string][]TimeObject `json:"times"` +} + +type OrderTemp struct { + OrderId string + Uid int64 + ServiceTime string // 格式: "2025-02-11 09:00" + ProjectionServiceTime int64 // 服务时长,单位:分钟 +} + +func ProcessOrders(orders []OrderTemp, maxCars int, maxDays int) OrderServiceTimeResponse { + // 存储每个时间段的车辆占用情况 + response := OrderServiceTimeResponse{ + Times: make(map[string][]TimeObject), + } + + // 用来记录每个用户的占用时间 + userOccupiedTime := make(map[int64]map[string]bool) + + // 遍历每个订单 + for _, order := range orders { + startTime, err := time.Parse("2006-01-02 15:04", order.ServiceTime) + if err != nil { + fmt.Println("Error parsing time:", err) + continue + } + + // 计算每个时间段的结束时间 + endTime := startTime.Add(time.Duration(order.ProjectionServiceTime) * time.Minute) + + // 记录用户的占用时间 + if userOccupiedTime[order.Uid] == nil { + userOccupiedTime[order.Uid] = make(map[string]bool) + } + + // 处理服务时间占用 + for t := startTime; t.Before(endTime); t = t.Add(time.Hour) { + // 格式化每个小时的整点 + timeSlot := fmt.Sprintf("%04d-%02d-%02d %02d:00:00", t.Year(), t.Month(), t.Day(), t.Hour()) + // 用户在该时间段占用时间,标记为已占用 + userOccupiedTime[order.Uid][timeSlot] = true + } + } + + // 计算时间段的范围,生成当前时间到未来 maxDays 天内的每小时时间段 + startTime := time.Now() + allTimeSlots := generateTimeSlots(startTime, maxDays) + + // 填充每个时间段的占用情况 + for _, slot := range allTimeSlots { + isOccupied := false + // 格式化时间为 "HH:MM" + timeOnly := slot[11:16] + + // 计算该时间段的总占用情况 + occupiedCars := 0 + for _, userTimes := range userOccupiedTime { + if userTimes[slot] { + occupiedCars++ + } + } + + // 如果当前时间段的车占用数大于或等于最大车数,则标记为占用 + if occupiedCars >= maxCars { + isOccupied = true + } + + // 提取日期作为 key + date := slot[:10] + + // 根据占用情况设置 Y 的值,true 表示可预约,false 表示不可预约 + response.Times[date] = append(response.Times[date], TimeObject{ + Time: timeOnly, + Y: !isOccupied, // true 是可预约,false 是不可预约 + }) + } + return response +} +func CheckAvailability(orders []OrderTemp, maxCars int, checkTime string, durationMinutes int) bool { + // 解析传入的时间字符串 + startTime, err := time.Parse("2006-01-02 15:04", checkTime) + if err != nil { + fmt.Println("Error parsing check time:", err) + return true // 出现解析错误时直接返回不可预约 + } + + // 计算结束时间 + endTime := startTime.Add(time.Duration(durationMinutes) * time.Minute) + + // 用来记录每个用户的占用时间 + userOccupiedTime := make(map[int64]map[string]bool) + + // 遍历每个订单 + for _, order := range orders { + orderStartTime, err := time.Parse("2006-01-02 15:04", order.ServiceTime) + if err != nil { + fmt.Println("Error parsing order time:", err) + continue + } + + // 计算每个订单的结束时间 + orderEndTime := orderStartTime.Add(time.Duration(order.ProjectionServiceTime) * time.Minute) + + // 记录用户的占用时间 + if userOccupiedTime[order.Uid] == nil { + userOccupiedTime[order.Uid] = make(map[string]bool) + } + + // 处理服务时间占用 + for t := orderStartTime; t.Before(orderEndTime); t = t.Add(time.Hour) { + // 格式化每个小时的整点 + timeSlot := fmt.Sprintf("%04d-%02d-%02d %02d:00:00", t.Year(), t.Month(), t.Day(), t.Hour()) + // 用户在该时间段占用时间,标记为已占用 + userOccupiedTime[order.Uid][timeSlot] = true + } + } + + // 检查指定时间段是否有足够的空闲时间 + for t := startTime; t.Before(endTime); t = t.Add(time.Hour) { + timeSlot := fmt.Sprintf("%04d-%02d-%02d %02d:00:00", t.Year(), t.Month(), t.Day(), t.Hour()) + + // 计算该时间段的总占用情况 + occupiedCars := 0 + for _, userTimes := range userOccupiedTime { + if userTimes[timeSlot] { + occupiedCars++ + } + } + + // 如果当前时间段的车占用数大于或等于最大车数,则表示不可预约 + if occupiedCars >= maxCars { + return true // 如果不可预约,返回true + } + } + + // 如果没有占用冲突,则可以预约 + return false // 如果可以预约,返回false +}