feat(platform): expose quality issue identity
This commit is contained in:
@@ -114,7 +114,7 @@ func TestHandlerHistoryMileageQualityOps(t *testing.T) {
|
|||||||
{"/api/mileage/summary?limit=10", "totalMileageKm"},
|
{"/api/mileage/summary?limit=10", "totalMileageKm"},
|
||||||
{"/api/mileage/daily?limit=10", "dailyMileageKm"},
|
{"/api/mileage/daily?limit=10", "dailyMileageKm"},
|
||||||
{"/api/quality/summary?limit=10", "issueVehicleCount"},
|
{"/api/quality/summary?limit=10", "issueVehicleCount"},
|
||||||
{"/api/quality/issues?limit=10", "issueType"},
|
{"/api/quality/issues?limit=10", "sourceEndpoint"},
|
||||||
{"/api/ops/health", "linkHealth"},
|
{"/api/ops/health", "linkHealth"},
|
||||||
}
|
}
|
||||||
handler := NewHandler(NewService(NewMockStore()))
|
handler := NewHandler(NewService(NewMockStore()))
|
||||||
|
|||||||
@@ -309,8 +309,8 @@ func (m *MockStore) QualitySummary(_ context.Context, query url.Values) (Quality
|
|||||||
|
|
||||||
func mockQualityRows() []QualityIssueRow {
|
func mockQualityRows() []QualityIssueRow {
|
||||||
return []QualityIssueRow{
|
return []QualityIssueRow{
|
||||||
{VIN: "unknown", Plate: "", Protocol: "JT808", IssueType: "VIN_MISSING", Severity: "warning", LastSeen: "2026-07-03 19:58:00", Detail: "phone 13300000001 未命中 binding 表"},
|
{VIN: "unknown", Plate: "", Phone: "13300000001", SourceEndpoint: "127.0.0.1:808", Protocol: "JT808", IssueType: "VIN_MISSING", Severity: "warning", LastSeen: "2026-07-03 19:58:00", Detail: "phone 13300000001 未命中 binding 表"},
|
||||||
{VIN: "LNXNEGRR7SR318212", Plate: "川AHTWO1", Protocol: "GB32960", IssueType: "LINK_GAP", Severity: "error", LastSeen: "2026-07-03 18:20:00", Detail: "Hyundai 平台近 60 分钟无转发"},
|
{VIN: "LNXNEGRR7SR318212", Plate: "川AHTWO1", Phone: "", SourceEndpoint: "Hyundai", Protocol: "GB32960", IssueType: "LINK_GAP", Severity: "error", LastSeen: "2026-07-03 18:20:00", Detail: "Hyundai 平台近 60 分钟无转发"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,13 +151,15 @@ type MileageSummary struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type QualityIssueRow struct {
|
type QualityIssueRow struct {
|
||||||
VIN string `json:"vin"`
|
VIN string `json:"vin"`
|
||||||
Plate string `json:"plate"`
|
Plate string `json:"plate"`
|
||||||
Protocol string `json:"protocol"`
|
Phone string `json:"phone"`
|
||||||
IssueType string `json:"issueType"`
|
SourceEndpoint string `json:"sourceEndpoint"`
|
||||||
Severity string `json:"severity"`
|
Protocol string `json:"protocol"`
|
||||||
LastSeen string `json:"lastSeen"`
|
IssueType string `json:"issueType"`
|
||||||
Detail string `json:"detail"`
|
Severity string `json:"severity"`
|
||||||
|
LastSeen string `json:"lastSeen"`
|
||||||
|
Detail string `json:"detail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type QualitySummary struct {
|
type QualitySummary struct {
|
||||||
|
|||||||
@@ -513,13 +513,15 @@ func (s *ProductionStore) QualityIssues(ctx context.Context, query url.Values) (
|
|||||||
return Page[QualityIssueRow]{}, err
|
return Page[QualityIssueRow]{}, err
|
||||||
}
|
}
|
||||||
items = append(items, QualityIssueRow{
|
items = append(items, QualityIssueRow{
|
||||||
VIN: vin,
|
VIN: vin,
|
||||||
Plate: plate,
|
Plate: plate,
|
||||||
Protocol: "JT808",
|
Phone: phone,
|
||||||
IssueType: "VIN_MISSING",
|
SourceEndpoint: source,
|
||||||
Severity: "warning",
|
Protocol: "JT808",
|
||||||
LastSeen: lastSeen,
|
IssueType: "VIN_MISSING",
|
||||||
Detail: fmt.Sprintf("phone %s 未命中 binding 表,来源 %s", phone, source),
|
Severity: "warning",
|
||||||
|
LastSeen: lastSeen,
|
||||||
|
Detail: fmt.Sprintf("phone %s 未命中 binding 表,来源 %s", phone, source),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return Page[QualityIssueRow]{Items: items, Total: total, Limit: limit, Offset: offset}, rows.Err()
|
return Page[QualityIssueRow]{Items: items, Total: total, Limit: limit, Offset: offset}, rows.Err()
|
||||||
|
|||||||
@@ -143,6 +143,8 @@ export interface MileageSummary {
|
|||||||
export interface QualityIssueRow {
|
export interface QualityIssueRow {
|
||||||
vin: string;
|
vin: string;
|
||||||
plate: string;
|
plate: string;
|
||||||
|
phone: string;
|
||||||
|
sourceEndpoint: string;
|
||||||
protocol: string;
|
protocol: string;
|
||||||
issueType: string;
|
issueType: string;
|
||||||
severity: string;
|
severity: string;
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export function Quality({ onHealthLoaded }: { onHealthLoaded?: (health: OpsHealt
|
|||||||
loadSummary(nextFilters);
|
loadSummary(nextFilters);
|
||||||
loadIssues(nextFilters, 1, pagination.pageSize);
|
loadIssues(nextFilters, 1, pagination.pageSize);
|
||||||
}} style={{ marginBottom: 12 }}>
|
}} style={{ marginBottom: 12 }}>
|
||||||
<Form.Input field="keyword" label="关键词" placeholder="手机号 / 来源地址 / 车牌" style={{ width: 240 }} />
|
<Form.Input field="keyword" label="关键词" placeholder="手机号 / 来源地址 / 车牌" style={{ width: 260 }} />
|
||||||
<Form.Select field="protocol" label="协议" placeholder="全部协议" style={{ width: 160 }}>
|
<Form.Select field="protocol" label="协议" placeholder="全部协议" style={{ width: 160 }}>
|
||||||
<Select.Option value="JT808">JT808</Select.Option>
|
<Select.Option value="JT808">JT808</Select.Option>
|
||||||
</Form.Select>
|
</Form.Select>
|
||||||
@@ -146,6 +146,8 @@ export function Quality({ onHealthLoaded }: { onHealthLoaded?: (health: OpsHealt
|
|||||||
columns={[
|
columns={[
|
||||||
{ title: 'VIN', dataIndex: 'vin' },
|
{ title: 'VIN', dataIndex: 'vin' },
|
||||||
{ title: '车牌', dataIndex: 'plate' },
|
{ title: '车牌', dataIndex: 'plate' },
|
||||||
|
{ title: '手机号', dataIndex: 'phone' },
|
||||||
|
{ title: '来源地址', dataIndex: 'sourceEndpoint' },
|
||||||
{ title: '协议', dataIndex: 'protocol' },
|
{ title: '协议', dataIndex: 'protocol' },
|
||||||
{ title: '问题', dataIndex: 'issueType' },
|
{ title: '问题', dataIndex: 'issueType' },
|
||||||
{ title: '级别', render: (_: unknown, row: QualityIssueRow) => <Tag color={row.severity === 'error' ? 'red' : 'orange'}>{row.severity}</Tag> },
|
{ title: '级别', render: (_: unknown, row: QualityIssueRow) => <Tag color={row.severity === 'error' ? 'red' : 'orange'}>{row.severity}</Tag> },
|
||||||
|
|||||||
Reference in New Issue
Block a user