- 后端:新增 /api/vehicles/subjects 端点返回公司列表+台数预览;所有聚合端点接受 ?subject= 参数按 tab_truck.org_id 对应的主体公司过滤 - 前端:标题下方新增 Scope Chip 单选下拉,支持搜索+台数预览,选中后全页 KPI/汇总/库存统计按公司联动刷新 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,12 +11,29 @@ import { fetchJson } from '../../auth/api-client';
|
||||
|
||||
const BASE = '/api/vehicles';
|
||||
|
||||
export async function fetchSummary(): Promise<SummaryData> {
|
||||
return fetchJson<SummaryData>(`${BASE}/summary`);
|
||||
export interface SubjectOption {
|
||||
name: string;
|
||||
total: number;
|
||||
inventory: number;
|
||||
operating: number;
|
||||
}
|
||||
|
||||
export async function fetchByType(): Promise<TypeSummary[]> {
|
||||
return fetchJson<TypeSummary[]>(`${BASE}/by-type`);
|
||||
function withSubject(path: string, subject?: string | null): string {
|
||||
if (!subject) return path;
|
||||
const sep = path.includes('?') ? '&' : '?';
|
||||
return `${path}${sep}subject=${encodeURIComponent(subject)}`;
|
||||
}
|
||||
|
||||
export async function fetchSubjects(): Promise<SubjectOption[]> {
|
||||
return fetchJson<SubjectOption[]>(`${BASE}/subjects`);
|
||||
}
|
||||
|
||||
export async function fetchSummary(subject?: string | null): Promise<SummaryData> {
|
||||
return fetchJson<SummaryData>(withSubject(`${BASE}/summary`, subject));
|
||||
}
|
||||
|
||||
export async function fetchByType(subject?: string | null): Promise<TypeSummary[]> {
|
||||
return fetchJson<TypeSummary[]>(withSubject(`${BASE}/by-type`, subject));
|
||||
}
|
||||
|
||||
export async function fetchVehicleList(params: {
|
||||
@@ -32,6 +49,7 @@ export async function fetchVehicleList(params: {
|
||||
isTrailer?: string;
|
||||
department?: string;
|
||||
attendance?: string;
|
||||
subject?: string | null;
|
||||
}): Promise<VehicleListItem[]> {
|
||||
const query = new URLSearchParams();
|
||||
if (params.batch) query.set('batch', params.batch);
|
||||
@@ -46,6 +64,7 @@ export async function fetchVehicleList(params: {
|
||||
if (params.isTrailer) query.set('isTrailer', params.isTrailer);
|
||||
if (params.department) query.set('department', params.department);
|
||||
if (params.attendance) query.set('attendance', params.attendance);
|
||||
if (params.subject) query.set('subject', params.subject);
|
||||
return fetchJson<VehicleListItem[]>(`${BASE}/list?${query.toString()}`);
|
||||
}
|
||||
|
||||
@@ -57,29 +76,40 @@ export interface WeeklyDetailItem {
|
||||
customer_name: string | null;
|
||||
}
|
||||
|
||||
export async function fetchDeptStats(): Promise<DeptGroup[]> {
|
||||
return fetchJson<DeptGroup[]>(`${BASE}/dept-stats`);
|
||||
export async function fetchDeptStats(subject?: string | null): Promise<DeptGroup[]> {
|
||||
return fetchJson<DeptGroup[]>(withSubject(`${BASE}/dept-stats`, subject));
|
||||
}
|
||||
|
||||
export async function fetchRegionStats(params?: { customer?: string; city?: string; region?: string }): Promise<RegionGroup[]> {
|
||||
export async function fetchRegionStats(
|
||||
params?: { customer?: string; city?: string; region?: string },
|
||||
subject?: string | null,
|
||||
): Promise<RegionGroup[]> {
|
||||
const query = new URLSearchParams();
|
||||
if (params?.customer) query.set('customer', params.customer);
|
||||
if (params?.city) query.set('city', params.city);
|
||||
if (params?.region) query.set('region', params.region);
|
||||
if (subject) query.set('subject', subject);
|
||||
const qs = query.toString();
|
||||
return fetchJson<RegionGroup[]>(`${BASE}/region-stats${qs ? `?${qs}` : ''}`);
|
||||
}
|
||||
|
||||
export async function fetchCustomerStats(): Promise<CustomerStats[]> {
|
||||
return fetchJson<CustomerStats[]>(`${BASE}/customer-stats`);
|
||||
export async function fetchCustomerStats(subject?: string | null): Promise<CustomerStats[]> {
|
||||
return fetchJson<CustomerStats[]>(withSubject(`${BASE}/customer-stats`, subject));
|
||||
}
|
||||
|
||||
export async function fetchInventoryStats(): Promise<RegionalInventoryStats[]> {
|
||||
return fetchJson<RegionalInventoryStats[]>(`${BASE}/inventory-stats`);
|
||||
export async function fetchInventoryStats(subject?: string | null): Promise<RegionalInventoryStats[]> {
|
||||
return fetchJson<RegionalInventoryStats[]>(withSubject(`${BASE}/inventory-stats`, subject));
|
||||
}
|
||||
|
||||
export async function fetchRegionChart(groupBy: string, top = 8, source = 'realtime'): Promise<{ name: string; value: number }[]> {
|
||||
return fetchJson<{ name: string; value: number }[]>(`${BASE}/region-chart?groupBy=${groupBy}&top=${top}&source=${source}`);
|
||||
export async function fetchRegionChart(
|
||||
groupBy: string,
|
||||
top = 8,
|
||||
source = 'realtime',
|
||||
subject?: string | null,
|
||||
): Promise<{ name: string; value: number }[]> {
|
||||
return fetchJson<{ name: string; value: number }[]>(
|
||||
withSubject(`${BASE}/region-chart?groupBy=${groupBy}&top=${top}&source=${source}`, subject),
|
||||
);
|
||||
}
|
||||
|
||||
export async function fetchWeeklyDetail(type: string): Promise<WeeklyDetailItem[]> {
|
||||
|
||||
Reference in New Issue
Block a user