From cb7a4a6147f0fa18a5960ab73ab5f0d5bc26f36d Mon Sep 17 00:00:00 2001 From: lion <120344285@qq.com> Date: Tue, 9 Jun 2026 14:46:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Dashboard.vue | 262 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 250 insertions(+), 12 deletions(-) diff --git a/src/views/Dashboard.vue b/src/views/Dashboard.vue index 6a5f1c4..b887314 100644 --- a/src/views/Dashboard.vue +++ b/src/views/Dashboard.vue @@ -199,6 +199,40 @@ function parseVenuePcRowsFromResponse(p: HikPeopleCountingResponse | null): Dash const dashboardVenuePcRows = computed((): DashboardVenuePcRow[] => parseVenuePcRowsFromResponse(pcData.value)) +type VenuePcViewMode = 'chart' | 'table' +const venuePcViewMode = ref('chart') + +const dashboardVenuePcEnterTotal = computed(() => + dashboardVenuePcRows.value.reduce((sum, row) => sum + (Number(row.enter) || 0), 0), +) + +const venuePcRangeLabel = computed(() => { + const picked = pickVenuePcRangeFromPicker() + if (!picked) return '' + return picked.start === picked.end ? picked.start : `${picked.start} 至 ${picked.end}` +}) + +const venuePcMaxEnter = computed(() => { + const rows = dashboardVenuePcRows.value + if (!rows.length) return 1 + return Math.max(1, ...rows.map((r) => Number(r.enter) || 0)) +}) + +function venuePcBarHeightPct(enter: number): string { + const max = venuePcMaxEnter.value + const v = Number(enter) || 0 + if (v <= 0) return '0%' + return `${Math.max(6, (v / max) * 100)}%` +} + +function onVenuePcChartWheel(e: WheelEvent) { + const el = e.currentTarget as HTMLElement | null + if (!el || el.scrollWidth <= el.clientWidth + 1) return + if (Math.abs(e.deltaX) >= Math.abs(e.deltaY)) return + e.preventDefault() + el.scrollLeft += e.deltaY +} + function dashboardVenuePcSummary(ctx: { data: DashboardVenuePcRow[] }) { const rows = Array.isArray(ctx.data) ? ctx.data : [] let enter = 0 @@ -1075,18 +1109,75 @@ onMounted(async () => { {{ pcError }} -
- +
+
+
+ {{ venuePcRangeLabel }} + 合计入馆人数 + {{ dashboardVenuePcEnterTotal }} +
+ + + 图表 + + + 数据 + + +
+ +
+ + +
+ +
@@ -1334,6 +1425,8 @@ onMounted(async () => { border: 1px solid #e8eaed; border-radius: 12px; box-shadow: 0 1px 4px rgba(15, 23, 42, 0.04); + min-width: 0; + max-width: 100%; } .dash-bundle .dash-overview-dual, @@ -2031,6 +2124,7 @@ onMounted(async () => { .dash-metric-card--venue-pc { width: 100%; + min-width: 0; } .dash-metric-card__icon--venue-pc { @@ -2040,12 +2134,156 @@ onMounted(async () => { .dash-metric-card__body--venue-pc { min-height: 0; + min-width: 0; +} + +.dash-metric-card__body--venue-pc :deep(.arco-spin), +.dash-metric-card__body--venue-pc :deep(.arco-spin-children) { + display: block; + width: 100%; + max-width: 100%; + min-width: 0; } .dash-venue-pc-table-wrap { width: 100%; } +.dash-venue-pc-content { + width: 100%; + max-width: 100%; + min-width: 0; + overflow: hidden; +} + +.dash-venue-pc-viewbar { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 10px 16px; + margin-bottom: 12px; +} + +.dash-venue-pc-total { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 6px 10px; + font-size: 13px; + color: #4e5969; +} + +.dash-venue-pc-total__range { + color: #86909c; + font-size: 12px; +} + +.dash-venue-pc-total__value { + color: #165dff; + font-size: 20px; + font-weight: 700; + font-variant-numeric: tabular-nums; + line-height: 1.2; +} + +.dash-venue-pc-chart { + width: 100%; + max-width: 100%; + min-width: 0; + padding: 4px 0 0; +} + +.dash-venue-pc-chart__scroll { + width: 100%; + max-width: 100%; + min-width: 0; + overflow-x: scroll; + overflow-y: hidden; + overscroll-behavior-x: contain; + -webkit-overflow-scrolling: touch; + touch-action: pan-x; + padding-bottom: 6px; + border-radius: 8px; + background: #fafbfd; + border: 1px solid #f0f1f5; +} + +.dash-venue-pc-chart__scroll::-webkit-scrollbar { + height: 8px; +} + +.dash-venue-pc-chart__scroll::-webkit-scrollbar-thumb { + background: #c9cdd4; + border-radius: 4px; +} + +.dash-venue-pc-chart__scroll::-webkit-scrollbar-track { + background: #f2f3f5; + border-radius: 4px; +} + +.dash-venue-pc-chart__plot { + display: inline-flex; + flex-wrap: nowrap; + align-items: flex-end; + gap: 6px; + min-height: 280px; + padding: 8px 8px 4px; + box-sizing: border-box; + vertical-align: top; +} + +.dash-venue-pc-chart__col { + flex: 0 0 38px; + width: 38px; + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; +} + +.dash-venue-pc-chart__col-value { + font-size: 11px; + font-weight: 600; + color: #1d2129; + font-variant-numeric: tabular-nums; + line-height: 1.2; + white-space: nowrap; +} + +.dash-venue-pc-chart__col-track { + width: 28px; + height: 220px; + display: flex; + align-items: flex-end; + justify-content: center; + border-radius: 4px 4px 0 0; + background: linear-gradient(180deg, #f7f8fa 0%, #fafbfd 100%); +} + +.dash-venue-pc-chart__col-bar { + width: 20px; + min-height: 0; + border-radius: 4px 4px 0 0; + background: linear-gradient(180deg, #4080ff 0%, #165dff 100%); + transition: height 0.25s ease; +} + +.dash-venue-pc-chart__col-label { + width: 38px; + font-size: 10px; + line-height: 1.3; + color: #4e5969; + text-align: center; + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + line-clamp: 2; + word-break: break-all; +} + .dash-venue-pc-bundle :deep(.dash-venue-pc-table.arco-table), .dash-venue-pc-table-wrap :deep(.dash-venue-pc-table.arco-table) { width: 100%;