From 398aad011f12bbd82783b4b09e73988933a464fc Mon Sep 17 00:00:00 2001 From: Orion Date: Fri, 10 Jul 2026 10:48:20 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=B1=20=E4=BC=98=E5=8C=96=E4=BB=AA?= =?UTF-8?q?=E8=A1=A8=E7=9B=98=E5=81=A5=E5=BA=B7=E5=8D=A1=E4=B8=8E=E8=B6=8B?= =?UTF-8?q?=E5=8A=BF=E5=9B=BE=E8=A7=A6=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/SmoothTrendCanvas.vue | 44 ++++++++++++++++++--- src/views/manage/DashboardView.vue | 39 +++++++++--------- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/src/components/common/SmoothTrendCanvas.vue b/src/components/common/SmoothTrendCanvas.vue index 7433ade..9fb7cde 100644 --- a/src/components/common/SmoothTrendCanvas.vue +++ b/src/components/common/SmoothTrendCanvas.vue @@ -2,7 +2,7 @@
() type DragState = { + startX: number lastX: number time: number + pointerType: string + moved: boolean } type TooltipState = { @@ -381,36 +384,67 @@ const handleWheel = (event: WheelEvent) => { zoom(event.deltaY > 0 ? 1.16 : 0.86, rect ? (event.clientX - rect.left) / rect.width : 0.5) } +const setHoverFromClientX = (clientX: number) => { + const rect = canvasRef.value?.getBoundingClientRect() + if (!rect) return + hoverX.value = clamp(clientX - rect.left, 0, rect.width) + scheduleDraw() +} + const handlePointerDown = (event: PointerEvent) => { canvasRef.value?.setPointerCapture(event.pointerId) cancelInertia() velocity.value = 0 - drag.value = { lastX: event.clientX, time: event.timeStamp || performance.now() } + setHoverFromClientX(event.clientX) + drag.value = { + startX: event.clientX, + lastX: event.clientX, + time: event.timeStamp || performance.now(), + pointerType: event.pointerType, + moved: false + } } const handlePointerMove = (event: PointerEvent) => { const rect = canvasRef.value?.getBoundingClientRect() - const pointerEvents = event.getCoalescedEvents?.() || [event] + const coalescedEvents = event.getCoalescedEvents?.() || [] + const pointerEvents = coalescedEvents.length ? coalescedEvents : [event] const latestEvent = pointerEvents[pointerEvents.length - 1] || event if (rect) hoverX.value = latestEvent.clientX - rect.left if (!drag.value) { scheduleDraw() return } + + if (drag.value.pointerType === 'touch') { + scheduleDraw() + return + } + + const totalDistance = Math.abs(latestEvent.clientX - drag.value.startX) + const threshold = 3 + if (!drag.value.moved && totalDistance < threshold) { + scheduleDraw() + return + } + drag.value.moved = true + pointerEvents.forEach((pointerEvent) => { const now = pointerEvent.timeStamp || performance.now() const deltaX = pointerEvent.clientX - drag.value!.lastX const deltaTime = Math.max(1, now - drag.value!.time) velocity.value = deltaX / deltaTime pan(deltaX) - drag.value = { lastX: pointerEvent.clientX, time: now } + drag.value = { ...drag.value!, lastX: pointerEvent.clientX, time: now, moved: true } }) } const handlePointerUp = () => { + const shouldInertia = Boolean(drag.value?.moved) drag.value = null cancelInertia() - inertiaRafId.value = window.requestAnimationFrame(applyInertia) + if (shouldInertia) inertiaRafId.value = window.requestAnimationFrame(applyInertia) + else scheduleDraw() } const handlePointerCancel = () => { diff --git a/src/views/manage/DashboardView.vue b/src/views/manage/DashboardView.vue index e15b16f..bc68f8a 100644 --- a/src/views/manage/DashboardView.vue +++ b/src/views/manage/DashboardView.vue @@ -80,10 +80,10 @@
-
+

{{ t('admin.dashboard.fileHealth') }} @@ -98,7 +98,7 @@ />

-
+
-
+
-
+

@@ -163,7 +163,7 @@

@@ -182,7 +182,7 @@

@@ -230,7 +230,7 @@
@@ -239,6 +239,7 @@

{{ analyticsSummaryText }}

+

轻触或滑动查看数据,使用下方按钮调整范围

@@ -309,7 +310,7 @@
@@ -631,12 +632,12 @@ const MetricProgress = defineComponent({ 'div', { class: - 'theme-2026-card-hover rounded-[30px] border border-[#d4e0e3] bg-[#f6faf9] p-4 shadow-md transition-all duration-200 hover:-translate-y-0.5 hover:border-[#8fb2bf] hover:shadow-lg hover:shadow-[#a9bdc2]/60 dark:border-[#40545c] dark:bg-[#17252c]/50 dark:hover:border-[#7199a8] dark:hover:bg-[#263941] dark:hover:shadow-black/25' + 'theme-2026-card-hover rounded-[18px] border border-[#d4e0e3] bg-[#f6faf9] p-2.5 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:border-[#8fb2bf] hover:shadow-md sm:rounded-[30px] sm:p-4 sm:shadow-md dark:border-[#40545c] dark:bg-[#17252c]/50 dark:hover:border-[#7199a8] dark:hover:bg-[#263941] dark:hover:shadow-black/25' }, [ - h('div', { class: 'mb-2 flex items-center justify-between text-sm' }, [ - h('span', { class: 'text-gray-500 dark:text-gray-400' }, props.label), - h('span', { class: 'font-medium text-gray-900 dark:text-white' }, `${props.value}%`) + h('div', { class: 'mb-2 flex flex-col gap-0.5 text-xs sm:flex-row sm:items-center sm:justify-between sm:text-sm' }, [ + h('span', { class: 'line-clamp-1 text-gray-500 dark:text-gray-400' }, props.label), + h('span', { class: 'font-medium tabular-nums text-gray-900 dark:text-white' }, `${props.value}%`) ]), h('div', { class: 'h-2 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-700' }, [ h('div', { @@ -644,7 +645,7 @@ const MetricProgress = defineComponent({ style: { width: `${props.value}%` } }) ]), - h('p', { class: 'mt-2 text-sm text-gray-500 dark:text-gray-400' }, props.detail) + h('p', { class: 'mt-2 hidden text-sm text-gray-500 sm:block dark:text-gray-400' }, props.detail) ] ) }