feat(platform): add vehicle detail aggregate api

This commit is contained in:
lingniu
2026-07-03 21:34:50 +08:00
parent 0438d054f6
commit d4bd70fdf4
7 changed files with 147 additions and 51 deletions

View File

@@ -3,6 +3,8 @@ package platform
import (
"context"
"net/url"
"sort"
"strings"
)
type Store interface {
@@ -44,6 +46,60 @@ func (s *Service) Vehicles(ctx context.Context, query url.Values) (Page[VehicleR
return s.store.Vehicles(ctx, query)
}
func (s *Service) VehicleDetail(ctx context.Context, vin string, protocol string) (VehicleDetail, error) {
vin = strings.TrimSpace(vin)
protocol = strings.TrimSpace(protocol)
vehicleQuery := url.Values{"keyword": {vin}, "limit": {"10"}}
realtimeQuery := url.Values{"vin": {vin}, "limit": {"20"}}
historyQuery := url.Values{"vin": {vin}, "limit": {"20"}}
rawQuery := RawFrameQuery{VIN: vin, IncludeFields: true, Limit: 10}
mileageQuery := url.Values{"vin": {vin}, "limit": {"20"}}
if protocol != "" {
realtimeQuery.Set("protocol", protocol)
historyQuery.Set("protocol", protocol)
rawQuery.Protocol = protocol
}
vehicles, err := s.store.Vehicles(ctx, vehicleQuery)
if err != nil {
return VehicleDetail{}, err
}
realtime, err := s.store.RealtimeLocations(ctx, realtimeQuery)
if err != nil {
return VehicleDetail{}, err
}
history, err := s.store.HistoryLocationsFromTDengine(ctx, historyQuery)
if err != nil {
return VehicleDetail{}, err
}
raw, err := s.RawFrames(ctx, rawQuery)
if err != nil {
return VehicleDetail{}, err
}
mileage, err := s.store.DailyMileage(ctx, mileageQuery)
if err != nil {
return VehicleDetail{}, err
}
var identity *VehicleRow
for index := range vehicles.Items {
if strings.EqualFold(vehicles.Items[index].VIN, vin) {
identity = &vehicles.Items[index]
break
}
}
if identity == nil && len(vehicles.Items) > 0 {
identity = &vehicles.Items[0]
}
return VehicleDetail{
VIN: vin,
Identity: identity,
Sources: vehicleSources(vehicles.Items, realtime.Items, raw.Items, mileage.Items),
Realtime: realtime.Items,
History: history,
Raw: raw,
Mileage: mileage,
}, nil
}
func (s *Service) RealtimeLocations(ctx context.Context, query url.Values) (Page[RealtimeLocationRow], error) {
return s.store.RealtimeLocations(ctx, query)
}
@@ -70,3 +126,32 @@ func (s *Service) QualityIssues(ctx context.Context, query url.Values) (Page[Qua
func (s *Service) OpsHealth(ctx context.Context) (OpsHealth, error) {
return s.store.OpsHealth(ctx)
}
func vehicleSources(vehicles []VehicleRow, realtime []RealtimeLocationRow, raw []RawFrameRow, mileage []DailyMileageRow) []string {
seen := map[string]struct{}{}
add := func(value string) {
value = strings.TrimSpace(value)
if value == "" {
return
}
seen[value] = struct{}{}
}
for _, row := range vehicles {
add(row.Protocol)
}
for _, row := range realtime {
add(row.Protocol)
}
for _, row := range raw {
add(row.Protocol)
}
for _, row := range mileage {
add(row.Source)
}
out := make([]string, 0, len(seen))
for source := range seen {
out = append(out, source)
}
sort.Strings(out)
return out
}