From 2f3f2975effe417ebcd16a855592fe187b58a27b Mon Sep 17 00:00:00 2001 From: Zyy Date: Sat, 17 Oct 2026 20:03:36 +0800 Subject: [PATCH] feat(ui): upgrade UI to v0.5.0 and simplify health popovers Use shared hover and dismissal handling for health timeline popovers, remove host workarounds and redundant footer copy, and pin the UI dependency and submodule to v0.5.0. Co-authored-by: Codex --- frontend/package.json | 2 +- frontend/pnpm-lock.yaml | 18 +- .../usage/HealthTimelinePointPopover.vue | 4 - .../usage/RequestHealthTimelineCard.vue | 155 ++++++++---------- modules/ui | 2 +- 5 files changed, 80 insertions(+), 101 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index d53ee33f4..76da95d45 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,7 +17,7 @@ }, "dependencies": { "@boxicons/vue": "1.0.1", - "@codex-proxy/ui": "github:zyycn/codex-proxy-ui#v0.4.1", + "@codex-proxy/ui": "github:zyycn/codex-proxy-ui#v0.5.0", "@fontsource-variable/inter": "^5.3.0", "@fontsource-variable/jetbrains-mono": "^5.3.0", "@lucide/vue": "^1.47.0", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 87fa1dbe3..8c52bae0f 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -195,8 +195,8 @@ importers: specifier: 1.0.1 version: 1.0.1(vue@3.5.43(typescript@6.0.3)) '@codex-proxy/ui': - specifier: github:zyycn/codex-proxy-ui#v0.4.1 - version: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/1496e21637e7e80e87c7f75387e27ced5029187a(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(vite@8.3.0(@types/node@26.6.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.43(typescript@6.0.3)) + specifier: github:zyycn/codex-proxy-ui#v0.5.0 + version: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/5eac879635ab4c15cfeea71d3d65fbf467780bbc(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(vite@8.3.0(@types/node@26.6.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.43(typescript@6.0.3)) '@fontsource-variable/inter': specifier: ^5.3.0 version: 5.3.0 @@ -418,9 +418,9 @@ packages: resolution: {integrity: sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==} engines: {node: '>= 20.12.0'} - '@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/1496e21637e7e80e87c7f75387e27ced5029187a': - resolution: {gitHosted: true, integrity: sha512-/buYpi7vGPyKu0dwO4/P+dCYruUEjGDDlKGiVsW79BAtTmtVTDYo2DhdBFN5+haqTg+QjqEvTcym+2Fu9hOgSg==, tarball: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/1496e21637e7e80e87c7f75387e27ced5029187a} - version: 0.4.1 + '@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/5eac879635ab4c15cfeea71d3d65fbf467780bbc': + resolution: {gitHosted: true, integrity: sha512-/n01jJCEKGxCzwkHkpBFUOP3Z+MeV5ufA/14qnrHJ3k9pm9cdb083Nhvd4KaIP9PftHXbCOISUzY9D9EzTZWBA==, tarball: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/5eac879635ab4c15cfeea71d3d65fbf467780bbc} + version: 0.5.0 engines: {node: '>=24'} peerDependencies: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1326,6 +1326,9 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + dayjs@1.11.23: + resolution: {integrity: sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -2825,13 +2828,14 @@ snapshots: fast-wrap-ansi: 0.2.2 sisteransi: 1.0.5 - '@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/1496e21637e7e80e87c7f75387e27ced5029187a(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(vite@8.3.0(@types/node@26.6.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.43(typescript@6.0.3))': + '@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/5eac879635ab4c15cfeea71d3d65fbf467780bbc(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(vite@8.3.0(@types/node@26.6.2)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.43(typescript@6.0.3))': dependencies: '@ant-design/colors': 8.0.1 '@ant-design/fast-color': 3.0.1 '@lucide/vue': 1.54.0(vue@3.5.43(typescript@6.0.3)) '@vueuse/core': 15.0.0(vue@3.5.43(typescript@6.0.3)) '@vueuse/integrations': 15.0.0(axios@1.20.0(debug@4.4.3))(change-case@5.4.4)(sortablejs@1.15.7)(vue@3.5.43(typescript@6.0.3)) + dayjs: 1.11.23 dompurify: 3.4.16 es-toolkit: 1.52.0 gsap: 3.15.0 @@ -3611,6 +3615,8 @@ snapshots: csstype@3.2.3: {} + dayjs@1.11.23: {} + debug@4.4.3: dependencies: ms: 2.1.3 diff --git a/frontend/src/components/usage/HealthTimelinePointPopover.vue b/frontend/src/components/usage/HealthTimelinePointPopover.vue index 33e33fadb..5f693ef7d 100644 --- a/frontend/src/components/usage/HealthTimelinePointPopover.vue +++ b/frontend/src/components/usage/HealthTimelinePointPopover.vue @@ -122,10 +122,6 @@ const metricItems = outcomeMeta - -

- 取消与调用方错误不计入可用性 -

diff --git a/frontend/src/components/usage/RequestHealthTimelineCard.vue b/frontend/src/components/usage/RequestHealthTimelineCard.vue index ee3e1f02e..3d2a672eb 100644 --- a/frontend/src/components/usage/RequestHealthTimelineCard.vue +++ b/frontend/src/components/usage/RequestHealthTimelineCard.vue @@ -2,9 +2,9 @@ import type { DashboardHealthTimeline, DashboardHealthTimelinePoint } from '@/api' import { ZButton, ZCard, ZPopover } from '@codex-proxy/ui' -import { useEventListener, usePreferredReducedMotion, useResizeObserver } from '@vueuse/core' +import { usePreferredReducedMotion, useResizeObserver } from '@vueuse/core' import { gsap } from 'gsap' -import { computed, nextTick, onBeforeUnmount, shallowRef, useTemplateRef, watch } from 'vue' +import { computed, onBeforeUnmount, shallowRef, useTemplateRef, watch } from 'vue' import HealthTimelinePointPopover from '@/components/usage/HealthTimelinePointPopover.vue' import { formatHealthCount, healthEligibleRequestCount, healthLegend, healthObservedRequestCount, healthStatusMeta } from '@/components/usage/shared/health' @@ -24,9 +24,7 @@ const preferredMotion = usePreferredReducedMotion() const points = computed(() => props.timeline.points) const activePoint = shallowRef() -const activeAnchor = shallowRef(null) const popoverOpen = shallowRef(false) -const highlightedPointBucket = shallowRef() let wavedCellIndexes = new Set() let anchorXTo: ReturnType | undefined let anchorYTo: ReturnType | undefined @@ -36,34 +34,23 @@ function isInteractivePoint(point: DashboardHealthTimelinePoint) { } function isActivePoint(point: DashboardHealthTimelinePoint) { - return popoverOpen.value && highlightedPointBucket.value === point.bucketStart + return popoverOpen.value && activePoint.value?.bucketStart === point.bucketStart } -async function activatePoint(point: DashboardHealthTimelinePoint, pointIndex: number, event: Event) { +function activatePoint(point: DashboardHealthTimelinePoint, pointIndex: number, event: Event) { if (!(event.currentTarget instanceof HTMLElement)) return - // 浮层卸载会恢复原焦点,不能把关闭期间的焦点恢复当作再次打开 - if (event instanceof FocusEvent && !activePoint.value && activeAnchor.value && !event.relatedTarget) - return if (!isInteractivePoint(point)) { closePointPopover() return } const anchor = event.currentTarget - const opening = !activePoint.value || !popoverOpen.value + const opening = !popoverOpen.value activePoint.value = point - highlightedPointBucket.value = point.bucketStart animatePointWave(pointIndex) - // 首次挂载后再打开,让浮层先建立定位监听,后续逐格切换直接更新 - if (opening) { - await nextTick() - if (activePoint.value !== point) - return - } positionPointAnchor(anchor, opening) - activeAnchor.value = popoverAnchor.value popoverOpen.value = true } @@ -105,20 +92,7 @@ function stopPointAnchor() { } function closePointPopover() { - void resetPointInteraction() -} - -async function resetPointInteraction() { - highlightedPointBucket.value = undefined - activePoint.value = undefined - releasePointWave() - stopPointAnchor() - // 锚点保留到浮层卸载完成,避免焦点恢复重新打开气泡或关闭时位置跳变 - await nextTick() - if (!activePoint.value) { - popoverOpen.value = false - activeAnchor.value = null - } + pointPopover.value?.close() } function timelineButtons() { @@ -223,12 +197,12 @@ function pointAccessibilityLabel(point: DashboardHealthTimelinePoint) { } watch(popoverOpen, (open) => { - if (!open && activePoint.value) - closePointPopover() + if (!open) { + releasePointWave() + stopPointAnchor() + } }) -useEventListener(timelineGrid, 'mouseleave', closePointPopover) - useResizeObserver(timelineGrid, () => { if (!popoverOpen.value || !activePoint.value) return @@ -275,60 +249,63 @@ onBeforeUnmount(() => { diff --git a/modules/ui b/modules/ui index 1496e2163..5eac87963 160000 --- a/modules/ui +++ b/modules/ui @@ -1 +1 @@ -Subproject commit 1496e21637e7e80e87c7f75387e27ced5029187a +Subproject commit 5eac879635ab4c15cfeea71d3d65fbf467780bbc