feat(platform): consolidate production vehicle data workflows

This commit is contained in:
lingniu
2026-07-15 23:26:29 +08:00
parent 6cddc0a43d
commit 3fabcf181a
59 changed files with 6849 additions and 3532 deletions

View File

@@ -364,10 +364,11 @@ func (s *Service) DashboardSummary(ctx context.Context) (DashboardSummary, error
}
const (
monitorVehicleLimit = 10000
monitorPointLimit = 2000
monitorPointZoom = 11
monitorClusterGridPixels = 64
monitorVehicleLimit = 10000
monitorPointLimit = 2000
monitorPointZoom = 11
monitorClusterGridPixels = 64
vehicleSearchKeywordLimit = 100
)
type monitorBounds struct {
@@ -428,7 +429,7 @@ func normalizeMonitorQuery(query url.Values) url.Values {
}
next.Set("limit", strconv.Itoa(monitorVehicleLimit))
next.Set("offset", "0")
if next.Get("vin") == "" && strings.TrimSpace(next.Get("keyword")) != "" {
if next.Get("vin") == "" && strings.TrimSpace(next.Get("keywords")) == "" && strings.TrimSpace(next.Get("keyword")) != "" {
next.Set("vin", strings.TrimSpace(next.Get("keyword")))
}
switch strings.TrimSpace(next.Get("status")) {
@@ -440,6 +441,41 @@ func normalizeMonitorQuery(query url.Values) url.Values {
return next
}
func vehicleSearchKeywords(query url.Values) []string {
rawValues := query["keywords"]
if len(rawValues) == 0 {
rawValues = []string{firstNonEmpty(query.Get("vin"), query.Get("keyword"))}
}
result := make([]string, 0, len(rawValues))
seen := map[string]struct{}{}
for _, raw := range rawValues {
parts := strings.FieldsFunc(raw, func(char rune) bool {
switch char {
case ',', '', '、', ';', '', '\n', '\r', '\t', ' ':
return true
default:
return false
}
})
for _, part := range parts {
part = strings.TrimSpace(part)
if part == "" {
continue
}
key := strings.ToLower(part)
if _, exists := seen[key]; exists {
continue
}
seen[key] = struct{}{}
result = append(result, part)
if len(result) == vehicleSearchKeywordLimit {
return result
}
}
}
return result
}
func matchesMonitorStatus(row VehicleRealtimeRow, requested string) bool {
requested = strings.TrimSpace(requested)
return requested == "" || monitorVehicleStatus(row) == requested || requested == "online" && row.Online
@@ -3103,6 +3139,10 @@ func (s *Service) DailyMileage(ctx context.Context, query url.Values) (Page[Dail
if err != nil {
return Page[DailyMileageRow]{}, err
}
resolvedQuery, err = normalizeMileageVINSelection(resolvedQuery)
if err != nil {
return Page[DailyMileageRow]{}, err
}
return s.store.DailyMileage(ctx, resolvedQuery)
}
@@ -3111,6 +3151,10 @@ func (s *Service) MileageStatistics(ctx context.Context, query url.Values) (Mile
if err != nil {
return MileageStatistics{}, err
}
resolvedQuery, err = normalizeMileageVINSelection(resolvedQuery)
if err != nil {
return MileageStatistics{}, err
}
resolvedQuery, err = normalizeMileageStatisticsWindow(resolvedQuery, time.Now())
if err != nil {
return MileageStatistics{}, err
@@ -3118,6 +3162,29 @@ func (s *Service) MileageStatistics(ctx context.Context, query url.Values) (Mile
return s.store.MileageStatistics(ctx, resolvedQuery)
}
func normalizeMileageVINSelection(query url.Values) (url.Values, error) {
next := cloneValues(query)
seen := map[string]bool{}
vins := make([]string, 0)
for _, item := range strings.Split(next.Get("vins"), ",") {
vin := strings.TrimSpace(item)
if vin == "" || seen[vin] {
continue
}
seen[vin] = true
vins = append(vins, vin)
}
if len(vins) > 20 {
return nil, clientError{Code: "TOO_MANY_VEHICLES", Message: "里程查询一次最多选择 20 辆车"}
}
if len(vins) == 0 {
next.Del("vins")
} else {
next.Set("vins", strings.Join(vins, ","))
}
return next, nil
}
func normalizeMileageStatisticsWindow(query url.Values, now time.Time) (url.Values, error) {
next := cloneValues(query)
dateTo := strings.TrimSpace(next.Get("dateTo"))
@@ -3502,6 +3569,9 @@ func cloneStringMap(values map[string]string) map[string]string {
func (s *Service) resolveVehicleQuery(ctx context.Context, query url.Values) (url.Values, error) {
resolved := cloneValues(query)
if strings.TrimSpace(resolved.Get("keywords")) != "" {
return resolved, nil
}
vin := firstNonEmpty(resolved.Get("vin"), resolved.Get("keyword"))
if vin == "" {
return resolved, nil