feat(platform): consolidate production vehicle data workflows
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user