feat(platform): add vehicle coverage view

This commit is contained in:
lingniu
2026-07-03 21:54:09 +08:00
parent 6352289c25
commit 110041a9db
13 changed files with 223 additions and 5 deletions

View File

@@ -40,6 +40,40 @@ func buildVehicleListSQL(query url.Values) SQLQuery {
}
}
func buildVehicleCoverageSQL(query url.Values) SQLQuery {
limit := parsePositive(query.Get("limit"), 20)
offset := parsePositive(query.Get("offset"), 0)
args := []any{}
where := []string{"s.vin IS NOT NULL", "s.vin <> ''"}
if keyword := strings.TrimSpace(query.Get("keyword")); keyword != "" {
where = append(where, "(s.vin LIKE ? OR s.plate LIKE ? OR b.vin LIKE ? OR b.plate LIKE ? OR b.phone LIKE ? OR b.oem LIKE ?)")
like := "%" + keyword + "%"
args = append(args, like, like, like, like, like, like)
}
if protocol := strings.TrimSpace(query.Get("protocol")); protocol != "" {
where = append(where, "s.protocol = ?")
args = append(args, protocol)
}
args = append(args, limit, offset)
return SQLQuery{
Text: `SELECT s.vin, ` +
`COALESCE(NULLIF(MAX(NULLIF(s.plate, '')), ''), b.plate, '') AS plate, ` +
`COALESCE(b.phone, '') AS phone, COALESCE(b.oem, '') AS oem, ` +
`COALESCE(GROUP_CONCAT(DISTINCT s.protocol ORDER BY s.protocol SEPARATOR ','), '') AS protocols, ` +
`COUNT(DISTINCT s.protocol) AS source_count, ` +
`SUM(CASE WHEN s.updated_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) THEN 1 ELSE 0 END) AS online_source_count, ` +
`CASE WHEN SUM(CASE WHEN s.updated_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) THEN 1 ELSE 0 END) > 0 THEN 1 ELSE 0 END AS online, ` +
`COALESCE(DATE_FORMAT(MAX(s.updated_at), '%Y-%m-%d %H:%i:%s'), '') AS last_seen, ` +
`CASE WHEN b.vin IS NOT NULL AND b.vin <> '' THEN 'bound' ELSE 'unbound' END AS binding_status ` +
`FROM vehicle_realtime_snapshot s ` +
`LEFT JOIN vehicle_identity_binding b ON b.vin = s.vin ` +
`WHERE ` + strings.Join(where, " AND ") + ` ` +
`GROUP BY s.vin, b.plate, b.phone, b.oem, b.vin ` +
`ORDER BY MAX(s.updated_at) DESC LIMIT ? OFFSET ?`,
Args: args,
}
}
func buildDailyMileageSQL(query url.Values) SQLQuery {
limit := parsePositive(query.Get("limit"), 20)
offset := parsePositive(query.Get("offset"), 0)