diff --git a/vehicle-data-platform/apps/web/src/v2/pages/StatisticsPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/StatisticsPage.tsx index 4ce2baa3..4affa28f 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/StatisticsPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/StatisticsPage.tsx @@ -209,7 +209,12 @@ function SummaryRail({ data, criteria, fleetTotal, loading }: { data?: MileageSt ['区间总里程', `${formatKm(data?.periodMileageKm)} km`, `${data?.recordCount ?? 0} 条车辆日记录`], ['日均里程', `${formatKm(data?.averageDailyMileageKm)} km`, '按有效车辆日平均'] ]; - return
{items.map(([label, value, note], index) =>
{label}{value}{note}
)}
; + const primary = items[2]; + const secondary = [items[0], items[1], items[3]]; + return
+
{primary[0]}{primary[1]}{primary[2]}
+
{secondary.map(([label, value, note]) =>
{label}{value}{note}
)}
+
; } type VehicleMileageMatrix = VehicleOption & { days: Map; sources: Map; totalMileageKm: number }; @@ -244,7 +249,7 @@ function dateLabel(date: string) { function MileageTable({ rows, dates }: { rows: VehicleMileageMatrix[]; dates: string[] }) { const mobile = useMobileMileageLayout(); - if (mobile) return
{rows.map((row) =>
{row.plate || '未绑定'}{row.vin}
{formatKm(row.totalMileageKm)} km区间总里程
{dates.map((date) =>
{row.days.has(date) ? `${formatKm(row.days.get(date))} km` : '—'}
)}
)}
; + if (mobile) return
{rows.map((row) =>
{row.plate || '未绑定'}{row.vin}
{formatKm(row.totalMileageKm)} km区间总里程
每日里程左右滑动查看 {dates.length} 天
{dates.map((date) => { const source = row.sources.get(date); return
{row.days.has(date) ? `${formatKm(row.days.get(date))} km` : '—'}{source ? {source === 'YUTONG_MQTT' ? 'YUTONG' : source} : null}
; })}
)}
; let maxDailyMileage = 1; for (const row of rows) { for (const mileage of row.days.values()) maxDailyMileage = Math.max(maxDailyMileage, mileage); @@ -419,7 +424,6 @@ export default function StatisticsPage() { }; return
-

里程查询

未选择车牌时分页展示全部已绑定主车辆;选择车牌后查询指定车辆。

@@ -428,14 +432,14 @@ export default function StatisticsPage() { setDraft((current) => ({ ...current, sources }))} /> -
快捷范围
+
快捷范围
{validationError || criteriaError ?

{validationError || criteriaError}

: null}
{statistics.isError || mileage.isError || fleetVehicles.isError ? { statistics.refetch(); mileage.refetch(); if (!hasVehicles) fleetVehicles.refetch(); }} /> : null}
-
车辆每日里程{criteria.dateFrom} 至 {criteria.dateTo}
{hasVehicles ? `${totalVehicles} 辆车` : `当前 ${displayVehicles.length} 辆 / 共 ${totalVehicles} 辆`} · {dates.length} 个自然日
+
车辆每日里程{criteria.dateFrom} 至 {criteria.dateTo}
{hasVehicles ? `${totalVehicles} 辆车` : `当前 ${displayVehicles.length} 辆 / 共 ${totalVehicles} 辆`} · {dates.length} 个自然日
{exportProgress ?
{exportProgress.label}{exportPercent == null ? '处理中' : `${exportPercent}%`} diff --git a/vehicle-data-platform/apps/web/src/v2/styles/v2.css b/vehicle-data-platform/apps/web/src/v2/styles/v2.css index a2c62d04..62b29ec0 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/v2.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/v2.css @@ -990,14 +990,14 @@ button, a { -webkit-tap-highlight-color: transparent; } .v2-ops-kpis { grid-template-columns: repeat(3,1fr); }.v2-ops-grid { grid-template-columns: 1fr; }.v2-ops-sources > div { grid-template-columns: 1fr; }.v2-ops-sources article + article { border-top: 1px solid var(--v2-border); border-left: 0; } } -.v2-mileage-page { display: flex; min-height: 100%; flex-direction: column; gap: 14px; padding: 22px 24px 20px; } +.v2-mileage-page { display: flex; min-height: 100%; flex-direction: column; gap: 12px; padding: 18px 20px 20px; } .v2-mileage-heading { display: flex; align-items: center; justify-content: space-between; gap: 18px; } .v2-mileage-heading h2 { margin: 0; color: #172033; font-size: 24px; font-weight: 720; letter-spacing: -.04em; } .v2-mileage-heading p { margin: 6px 0 0; color: #748196; font-size: 12px; line-height: 1.5; } .v2-mileage-heading > button { display: flex; height: 36px; align-items: center; gap: 7px; border: 1px solid #d8e0eb; border-radius: 8px; background: #fff; padding: 0 13px; color: #56657a; cursor: pointer; font-size: 12px; font-weight: 600; transition: border-color .16s ease, color .16s ease, background .16s ease; } .v2-mileage-heading > button:hover { border-color: #aebed3; background: #f8fafc; color: #1f4e8c; } -.v2-mileage-query-panel { overflow: visible; border: 1px solid #dce3ec; border-radius: 11px; background: #fff; box-shadow: 0 1px 2px rgba(15,23,42,.025); } -.v2-mileage-filter { display: grid; grid-template-columns: minmax(320px,1.5fr) minmax(132px,.55fr) minmax(132px,.55fr) auto auto auto; align-items: start; gap: 12px; padding: 18px 20px 16px; } +.v2-mileage-query-panel { overflow: visible; border: 1px solid #d9e2ed; border-radius: 12px; background: #fff; box-shadow: 0 6px 22px rgba(24,39,62,.055); } +.v2-mileage-filter { display: grid; grid-template-columns: minmax(320px,1.5fr) minmax(132px,.55fr) minmax(132px,.55fr) auto auto auto; align-items: start; gap: 12px; padding: 16px 18px 15px; } .v2-mileage-filter > label { display: flex; min-width: 0; flex-direction: column; gap: 7px; color: #4f5f75; font-size: 11px; font-weight: 650; } .v2-mileage-filter > label > input { width: 100%; height: 40px; border: 1px solid #d7e0ea; border-radius: 7px; background: #fff; padding: 0 11px; color: #253248; outline: 0; font-family: inherit; font-size: 13px; transition: border-color .16s ease, box-shadow .16s ease; } .v2-mileage-filter > label > input:focus, .v2-mileage-multiselect:focus-within { border-color: #6d9ff1; box-shadow: 0 0 0 3px rgba(37,99,235,.08); } @@ -1053,25 +1053,31 @@ button, a { -webkit-tap-highlight-color: transparent; } .v2-mileage-source-list article > p button:disabled { opacity: .32; cursor: default; } .v2-mileage-source-popover > footer { display: flex; min-height: 49px; align-items: center; justify-content: space-between; gap: 10px; padding: 0 13px 0 16px; } .v2-mileage-source-popover > footer button { height: 30px; border: 0; border-radius: 6px; background: var(--v2-blue); padding: 0 13px; color: #fff; cursor: pointer; font-size: 10px; font-weight: 650; } -.v2-mileage-ranges { display: flex; align-items: center; align-self: end; gap: 2px; margin-bottom: 1px; } +.v2-mileage-ranges { display: flex; align-items: center; align-self: end; gap: 3px; margin-bottom: 1px; border-radius: 8px; background: #f3f6fa; padding: 2px; } .v2-mileage-ranges > span { display: none; } -.v2-mileage-ranges button { height: 38px; border: 0; border-radius: 6px; background: transparent; padding: 0 9px; color: #64748b; cursor: pointer; font-size: 11px; font-weight: 550; white-space: nowrap; transition: color .16s ease, background .16s ease; } +.v2-mileage-ranges button { height: 34px; border: 0; border-radius: 6px; background: transparent; padding: 0 9px; color: #64748b; cursor: pointer; font-size: 11px; font-weight: 600; white-space: nowrap; transition: color .16s ease, background .16s ease, box-shadow .16s ease; } .v2-mileage-ranges button:hover { background: #f1f5fb; color: var(--v2-blue); } -.v2-mileage-summary { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); border-top: 1px solid #e5eaf1; background: #fbfcfe; } -.v2-mileage-summary article { position: relative; min-width: 0; padding: 15px 22px 16px; } -.v2-mileage-summary article + article::before { position: absolute; inset: 15px auto 15px 0; width: 1px; background: #dfe6ef; content: ""; } +.v2-mileage-ranges button.is-active { background: #fff; color: var(--v2-blue); box-shadow: 0 1px 4px rgba(20,44,78,.12); } +.v2-mileage-summary { display: grid; grid-template-columns: minmax(330px,.9fr) minmax(0,1.55fr); border-top: 1px solid #e3e9f1; background: #f7f9fc; } +.v2-mileage-summary article { min-width: 0; } .v2-mileage-summary small, .v2-mileage-summary span { display: block; overflow: hidden; color: #7c899b; font-size: 10px; text-overflow: ellipsis; white-space: nowrap; } -.v2-mileage-summary strong { display: block; margin: 6px 0 3px; overflow: hidden; color: #172033; font-size: clamp(18px,1.45vw,24px); font-variant-numeric: tabular-nums; letter-spacing: -.035em; text-overflow: ellipsis; white-space: nowrap; } -.v2-mileage-summary .is-primary strong { color: var(--v2-blue); } -.v2-mileage-results { display: flex; min-height: 430px; flex: 1; flex-direction: column; overflow: hidden; border: 1px solid #dce3ec; border-radius: 11px; background: #fff; box-shadow: 0 1px 2px rgba(15,23,42,.025); } -.v2-mileage-results > header, .v2-mileage-results > footer { display: flex; min-height: 50px; flex: 0 0 auto; align-items: center; justify-content: space-between; gap: 12px; padding: 0 18px; } +.v2-mileage-summary strong { display: block; margin: 7px 0 4px; overflow: hidden; color: #172033; font-size: clamp(20px,1.6vw,26px); font-variant-numeric: tabular-nums; letter-spacing: -.04em; text-overflow: ellipsis; white-space: nowrap; } +.v2-mileage-summary > .is-primary { position: relative; overflow: hidden; background: #1268f3; padding: 18px 24px 20px; color: #fff; } +.v2-mileage-summary > .is-primary small, .v2-mileage-summary > .is-primary span { position: relative; z-index: 1; color: rgba(255,255,255,.76); } +.v2-mileage-summary > .is-primary strong { position: relative; z-index: 1; color: #fff; font-size: clamp(27px,2.15vw,36px); } +.v2-mileage-summary-secondary { display: grid; min-width: 0; grid-template-columns: repeat(3,minmax(0,1fr)); background: #fff; } +.v2-mileage-summary-secondary article { position: relative; display: flex; min-width: 0; justify-content: center; flex-direction: column; padding: 17px 20px 18px; } +.v2-mileage-summary-secondary article + article::before { position: absolute; inset: 17px auto 17px 0; width: 1px; background: #e0e6ee; content: ""; } +.v2-mileage-results { display: flex; min-height: 430px; flex: 1; flex-direction: column; overflow: hidden; border: 1px solid #d9e2ed; border-radius: 12px; background: #fff; box-shadow: 0 6px 22px rgba(24,39,62,.05); } +.v2-mileage-results > header, .v2-mileage-results > footer { display: flex; min-height: 54px; flex: 0 0 auto; align-items: center; justify-content: space-between; gap: 12px; padding: 0 18px; } .v2-mileage-results > header { border-bottom: 1px solid #e4e9f0; } .v2-mileage-results > header div { display: flex; align-items: baseline; gap: 10px; } -.v2-mileage-results > header strong { color: #1f2a3d; font-size: 13px; } +.v2-mileage-results > header strong { color: #17253a; font-size: 15px; } .v2-mileage-results > header span, .v2-mileage-results > header em, .v2-mileage-results > footer { color: #7c899b; font-size: 10px; font-style: normal; } .v2-mileage-results > header .v2-mileage-result-actions { align-items: center; gap: 12px; } .v2-mileage-result-actions > button { display: inline-flex; height: 32px; align-items: center; gap: 6px; border: 1px solid #cbd8e8; border-radius: 7px; background: #fff; padding: 0 11px; color: #315f9f; cursor: pointer; font-size: 10px; font-weight: 650; box-shadow: 0 1px 2px rgba(15,23,42,.04); transition: border-color .16s ease, background .16s ease, box-shadow .16s ease; } .v2-mileage-result-actions > button:hover { border-color: #99b6dd; background: #f5f9ff; box-shadow: 0 2px 7px rgba(37,99,235,.08); } +.v2-mileage-result-actions > button.is-refresh { border-color: transparent; background: #f2f5f9; color: #5f6f84; box-shadow: none; } .v2-mileage-result-actions > button:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; } .v2-mileage-export-progress { display: flex; flex: 0 0 auto; align-items: center; gap: 12px; border-bottom: 1px solid #e4e9f0; background: #f7faff; padding: 9px 18px; } .v2-mileage-export-progress > span { display: flex; min-width: 190px; align-items: center; justify-content: space-between; gap: 12px; color: #315f9f; font-size: 10px; } @@ -1082,8 +1088,8 @@ button, a { -webkit-tap-highlight-color: transparent; } @keyframes v2-export-progress { 0% { transform: translateX(-110%); } 100% { transform: translateX(290%); } } .v2-mileage-table-wrap { min-height: 0; flex: 1; overflow: auto; } .v2-mileage-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12px; } -.v2-mileage-table th { position: sticky; z-index: 2; top: 0; height: 42px; border-bottom: 1px solid #dfe6ef; background: #f8fafc; padding: 0 14px; color: #59677b; font-size: 11px; font-weight: 650; text-align: left; white-space: nowrap; } -.v2-mileage-table td { height: 52px; border-bottom: 1px solid #e8edf3; padding: 0 14px; color: #46556a; white-space: nowrap; } +.v2-mileage-table th { position: sticky; z-index: 2; top: 0; height: 46px; border-bottom: 1px solid #dfe6ef; background: #f5f8fc; padding: 0 14px; color: #526279; font-size: 11px; font-weight: 700; text-align: left; white-space: nowrap; } +.v2-mileage-table td { height: 56px; border-bottom: 1px solid #e8edf3; padding: 0 14px; color: #46556a; white-space: nowrap; } .v2-mileage-table tbody tr:hover { background: #f8fbff; } .v2-mileage-table td strong { color: #263448; } .v2-mileage-table code { color: #69778b; font-family: ui-monospace,SFMono-Regular,Menlo,monospace; font-size: 10px; } @@ -1097,7 +1103,7 @@ button, a { -webkit-tap-highlight-color: transparent; } .v2-mileage-table th.is-total { z-index: 5; background: #f1f6fe; color: #315f9f; } .v2-mileage-table .is-daily { color: #28496f; font-size: 11px; font-weight: 650; } .v2-mileage-table .is-empty { color: #b2bcc9; text-align: center; } -.v2-mileage-table .is-period { color: #263448; font-weight: 700; } +.v2-mileage-table .is-period { color: #135fcb; font-size: 12px; font-weight: 800; } .v2-mileage-source { display: inline-flex; height: 22px; align-items: center; border: 1px solid #dbe4ef; border-radius: 4px; background: #f8fafc; padding: 0 7px; color: #66758a; font-size: 8px; } .v2-mileage-results > footer { border-top: 1px solid var(--v2-border); background: #fbfcfe; } .v2-mileage-results > footer div { display: flex; gap: 6px; } @@ -1850,6 +1856,16 @@ button, a { -webkit-tap-highlight-color: transparent; } .v2-access-inspector-summary span, .v2-access-protocol-cell span { font-size: 11px; } +/* Mileage query: one dominant conclusion, compact controls, data-first results. */ +.v2-mileage-page { gap: 12px; padding: 18px 20px 20px; } +.v2-mileage-summary > .is-primary small, +.v2-mileage-summary > .is-primary span { font-size: 11px; } +.v2-mileage-summary-secondary small, +.v2-mileage-summary-secondary span { font-size: 11px; } +.v2-mileage-table th { height: 46px; } +.v2-mileage-table td { height: 56px; } +.v2-mileage-mobile-day-heading { display: none; } + @media (max-width: 1280px) { .v2-alert-workspace { grid-template-columns: minmax(650px, 1fr) 330px; } .v2-track-page { grid-template-columns: 310px minmax(0, 1fr); } @@ -1897,4 +1913,35 @@ button, a { -webkit-tap-highlight-color: transparent; } .v2-history-mobile-list { display: flex; } :is(.v2-alert-filter,.v2-access-filter-v3,.v2-history-toolbar,.v2-mileage-filter).is-mobile-collapsed { display: none !important; } .v2-track-page.is-rail-collapsed { display: grid; grid-template-columns: minmax(0,1fr); } + + .v2-mileage-page { gap: 10px; padding: 8px 8px 18px; } + .v2-mileage-query-panel { padding: 8px; border-radius: 12px; } + .v2-mileage-query-panel > .v2-mobile-filter-toggle { margin: 0 0 8px; } + .v2-mileage-summary { display: grid; grid-template-columns: 1fr; gap: 8px; border: 0; background: transparent; } + .v2-mileage-summary > .is-primary { min-height: 112px; border-radius: 10px; padding: 16px 17px 17px; } + .v2-mileage-summary > .is-primary strong { margin: 8px 0 5px; font-size: 27px; } + .v2-mileage-summary-secondary { grid-template-columns: repeat(3,minmax(0,1fr)); overflow: hidden; border: 1px solid #e1e7ef; border-radius: 10px; } + .v2-mileage-summary-secondary article { min-height: 94px; justify-content: flex-start; border-bottom: 0 !important; padding: 13px 11px 12px; } + .v2-mileage-summary-secondary article + article::before { inset: 13px auto 13px 0; } + .v2-mileage-summary-secondary strong { margin: 7px 0 4px; font-size: 17px; } + .v2-mileage-summary-secondary span { overflow: hidden; font-size: 9px; line-height: 1.4; text-overflow: ellipsis; white-space: nowrap; } + .v2-mileage-results { min-height: 430px; border-radius: 12px; } + .v2-mileage-results > header { gap: 8px; padding: 12px; } + .v2-mileage-results > header strong { font-size: 15px; } + .v2-mileage-results > header .v2-mileage-result-actions { gap: 6px; } + .v2-mileage-results > header .v2-mileage-result-actions em { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + .v2-mileage-result-actions > button { height: 36px; padding: 0 10px; font-size: 10px; } + .v2-mileage-mobile-list { gap: 9px; background: #f4f7fb; padding: 9px; } + .v2-mileage-mobile-list article { overflow: hidden; border: 1px solid #dfe6ef; border-radius: 10px; background: #fff; padding: 14px 13px 13px; box-shadow: 0 2px 8px rgba(23,39,62,.035); } + .v2-mileage-mobile-list article > header strong { font-size: 15px; } + .v2-mileage-mobile-list article > header b { color: #135fcb; font-size: 19px; letter-spacing: -.025em; } + .v2-mileage-mobile-list article > header b small { margin-top: 4px; font-size: 9px; } + .v2-mileage-mobile-day-heading { display: flex; align-items: center; justify-content: space-between; margin-top: 13px; border-top: 1px solid #edf1f5; padding-top: 11px; } + .v2-mileage-mobile-day-heading span { color: #526176; font-size: 11px; font-weight: 700; } + .v2-mileage-mobile-day-heading em { color: #8b97a8; font-size: 9px; font-style: normal; } + .v2-mileage-mobile-days { grid-auto-columns: 88px; gap: 6px; margin-top: 8px; padding-bottom: 2px; scroll-snap-type: x proximity; } + .v2-mileage-mobile-days > div { min-height: 66px; border-color: #e3e9f1; border-radius: 8px; background: #f8fafc; padding: 8px 9px; scroll-snap-align: start; } + .v2-mileage-mobile-days time { font-size: 9px; } + .v2-mileage-mobile-days strong { margin-top: 6px; color: #26364b; font-size: 11px; } + .v2-mileage-mobile-days small { display: block; margin-top: 4px; overflow: hidden; color: #7d8ba0; font-size: 8px; text-overflow: ellipsis; white-space: nowrap; } }