From d2d91ff9a85adff73694e2ef08c246053d1c375c Mon Sep 17 00:00:00 2001 From: IanShaw027 Date: Fri, 7 Aug 2026 11:01:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(channel-monitor-v2):=20=E8=A1=A5=E9=BD=90?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E7=AB=AF=E9=85=8D=E7=BD=AE=E3=80=81=E9=9A=90?= =?UTF-8?q?=E8=97=8F=E5=90=9E=E5=90=90=E5=BC=80=E5=85=B3=E4=B8=8E=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 管理端 V2 配置面板与系统设置中的模式/隐藏 RPM·TPM 开关,纳入关键 vitest 与 Makefile 前端关键路径,覆盖门控与展示行为。 --- Makefile | 7 +- frontend/src/api/admin/settings.ts | 4 + .../src/i18n/locales/en/admin/settings.ts | 15 ++- .../src/i18n/locales/zh/admin/settings.ts | 15 ++- frontend/src/types/index.ts | 4 + frontend/src/utils/featureFlags.ts | 36 ++++++- .../src/views/admin/ChannelMonitorView.vue | 71 +++++++++++++- frontend/src/views/admin/SettingsView.vue | 97 ++++++++++++++++--- .../ChannelMonitorView.duplicate.spec.ts | 11 +++ .../__tests__/ChannelMonitorView.grok.spec.ts | 11 +++ 10 files changed, 244 insertions(+), 27 deletions(-) diff --git a/Makefile b/Makefile index a2a49abb2..b0bc1b99f 100644 --- a/Makefile +++ b/Makefile @@ -3,12 +3,17 @@ FRONTEND_CRITICAL_VITEST := \ src/api/__tests__/client.spec.ts \ src/api/__tests__/tokenRefresh.spec.ts \ + src/api/__tests__/channelMonitorV2.spec.ts \ src/views/auth/__tests__/LinuxDoCallbackView.spec.ts \ src/views/auth/__tests__/WechatCallbackView.spec.ts \ src/views/user/__tests__/PaymentView.spec.ts \ src/views/user/__tests__/PaymentResultView.spec.ts \ + src/views/user/__tests__/ChannelStatusView.mode.spec.ts \ src/components/user/profile/__tests__/ProfileInfoCard.spec.ts \ - src/views/admin/__tests__/SettingsView.spec.ts + src/views/admin/__tests__/SettingsView.spec.ts \ + src/features/channel-monitor-v2/__tests__/designSystem.structure.spec.ts \ + src/features/channel-monitor-v2/__tests__/monitorFormat.spec.ts \ + src/features/channel-monitor-v2/__tests__/monitorZoom.spec.ts # 一键编译前后端 build: build-backend build-frontend diff --git a/frontend/src/api/admin/settings.ts b/frontend/src/api/admin/settings.ts index c32e0a5d6..1b5d34766 100644 --- a/frontend/src/api/admin/settings.ts +++ b/frontend/src/api/admin/settings.ts @@ -670,7 +670,9 @@ export interface SystemSettings { // Channel Monitor feature switch channel_monitor_enabled: boolean; + channel_monitor_mode?: 'v1' | 'v2'; channel_monitor_default_interval_seconds: number; + channel_monitor_hide_throughput?: boolean; // Available Channels feature switch available_channels_enabled: boolean; @@ -961,7 +963,9 @@ export interface UpdateSettingsRequest { // Channel Monitor feature switch channel_monitor_enabled?: boolean; + channel_monitor_mode?: 'v1' | 'v2'; channel_monitor_default_interval_seconds?: number; + channel_monitor_hide_throughput?: boolean; // Available Channels feature switch available_channels_enabled?: boolean; diff --git a/frontend/src/i18n/locales/en/admin/settings.ts b/frontend/src/i18n/locales/en/admin/settings.ts index 60630aaf3..c19b798a8 100644 --- a/frontend/src/i18n/locales/en/admin/settings.ts +++ b/frontend/src/i18n/locales/en/admin/settings.ts @@ -16,12 +16,21 @@ export default { features: { channelMonitor: { title: 'Channel Monitor', - description: 'Periodically probe configured channels and surface availability / latency to users. Turning it off stops the scheduler and returns an empty list on the user page.', + description: 'Choose either V1 active probes or V2 passive usage monitoring. When disabled, both background jobs stop and the user entry is hidden.', configureLink: 'Configure monitors in Channel Management > Channel Monitor', enabled: 'Enable Channel Monitor', - enabledHint: 'Disabling stops background checks; existing history is preserved.', + enabledHint: 'Disabling stops both the V1 scheduler and V2 aggregation; existing config and history are kept.', + mode: 'Monitor mode', + modeHint: 'Only one implementation can be active: V2 never sends upstream probes; V1 probes configured monitors on a schedule.', + modeV2: 'V2 passive monitoring', + modeV1: 'V1 active probes', + modeV2Hint: 'Aggregates health metrics from real gateway traffic without upstream probe traffic.', + modeV1Hint: 'Runs scheduled upstream health checks for configured channel monitors (probe traffic).', defaultInterval: 'Default check interval (seconds)', - defaultIntervalHint: 'Pre-fills the interval when creating a new monitor; each monitor can override it. Range 15 – 3600.', + defaultIntervalHint: 'V1 only: default interval for new monitors (overridable per monitor). Range 15 – 3600 seconds.', + hideThroughput: 'Hide throughput rates from users (RPM / TPM)', + hideThroughputHint: + 'When on, the user Channel Monitor page and user APIs omit RPM and TPM so fleet volume cannot be reverse-estimated from rates × window. Admins still see full metrics. Error rates, latency, and cache rates remain visible.', }, availableChannels: { title: 'Available Channels', diff --git a/frontend/src/i18n/locales/zh/admin/settings.ts b/frontend/src/i18n/locales/zh/admin/settings.ts index 952c7b605..67ddaf921 100644 --- a/frontend/src/i18n/locales/zh/admin/settings.ts +++ b/frontend/src/i18n/locales/zh/admin/settings.ts @@ -16,12 +16,21 @@ export default { features: { channelMonitor: { title: '渠道监控', - description: '定期对配置的渠道发起健康检查,向用户展示可用性与延迟。关闭后调度器停止扫描,用户端列表为空。', + description: '启用后在 V1 主动探测与 V2 被动用量监控中二选一。关闭后两种模式的后台任务均停止,用户端入口隐藏。', configureLink: '前往 渠道管理 > 渠道监控 配置监控项', enabled: '启用渠道监控', - enabledHint: '关闭后后台不再执行定时检测,已有数据保留。', + enabledHint: '关闭后 V1 调度器与 V2 聚合均停止;已有配置与历史保留。', + mode: '监控模式', + modeHint: '同一时间只能启用一种实现:V2 不产生上游探测流量;V1 会按配置的监控项主动探活。', + modeV2: 'V2 被动监控', + modeV1: 'V1 主动探测', + modeV2Hint: '基于真实网关流量聚合健康指标,不向上游发送探活请求。', + modeV1Hint: '按配置的渠道监控项定时发起上游健康检查(产生探测流量)。', defaultInterval: '默认检测间隔(秒)', - defaultIntervalHint: '新建渠道监控时表单的默认值,可被单个渠道覆盖。范围 15 – 3600 秒。', + defaultIntervalHint: '仅 V1 模式使用:新建渠道监控时表单的默认值,可被单个渠道覆盖。范围 15 – 3600 秒。', + hideThroughput: '对用户隐藏吞吐速率(RPM / TPM)', + hideThroughputHint: + '开启后,用户端渠道监控页面与用户 API 不返回 RPM/TPM,避免用「速率 × 时间窗」反推集群规模。管理员仍可见完整指标;错误率、延迟、缓存率照常展示。', }, availableChannels: { title: '可用渠道', diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 80cd0d315..08ffc4f17 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -262,7 +262,11 @@ export interface PublicSettings { account_quota_notify_enabled: boolean balance_low_notify_threshold: number channel_monitor_enabled: boolean + /** Exclusive mode: v1 active probes or v2 passive aggregation. Default v2. */ + channel_monitor_mode?: 'v1' | 'v2' channel_monitor_default_interval_seconds: number + /** When true, user monitor hides RPM/TPM so scale cannot be reverse-estimated. */ + channel_monitor_hide_throughput?: boolean available_channels_enabled: boolean model_plaza_enabled: boolean model_plaza_require_auth: boolean diff --git a/frontend/src/utils/featureFlags.ts b/frontend/src/utils/featureFlags.ts index 5004c068b..9fcbb7f19 100644 --- a/frontend/src/utils/featureFlags.ts +++ b/frontend/src/utils/featureFlags.ts @@ -68,9 +68,9 @@ * `makeSidebarFlag(flag)` returns a `() => boolean | undefined` compatible with * `AppSidebar.NavItem.featureFlag`, where `false` hides the menu entry. */ - import { useAppStore } from '@/stores/app' import type { PublicSettings } from '@/types' +import { DEFAULT_INTERVAL_SECONDS } from '@/constants/channelMonitor' export type FeatureFlagMode = 'opt-in' | 'opt-out' @@ -152,3 +152,37 @@ export function isFeatureFlagEnabled(flag: FeatureFlagDefinition): boolean { export function makeSidebarFlag(flag: FeatureFlagDefinition): () => boolean { return () => isFeatureFlagEnabled(flag) } + +/** True when channel monitor feature flag is enabled. */ +export function isChannelMonitorRouteEnabled(): boolean { + return isFeatureFlagEnabled(FeatureFlags.channelMonitor) +} + +export type ChannelMonitorMode = 'v1' | 'v2' + +/** Exclusive channel-monitor implementation. Invalid/missing → v2. */ +export function getChannelMonitorMode(): ChannelMonitorMode { + const appStore = useAppStore() + const mode = appStore.cachedPublicSettings?.channel_monitor_mode + return mode === 'v1' ? 'v1' : 'v2' +} + +export function isChannelMonitorV1Mode(): boolean { + return isChannelMonitorRouteEnabled() && getChannelMonitorMode() === 'v1' +} + +export function isChannelMonitorV2Mode(): boolean { + return isChannelMonitorRouteEnabled() && getChannelMonitorMode() === 'v2' +} + +export function getChannelMonitorRefreshIntervalSeconds(): number { + const appStore = useAppStore() + const configured = appStore.cachedPublicSettings?.channel_monitor_default_interval_seconds + return configured && configured > 0 ? configured : DEFAULT_INTERVAL_SECONDS +} + +/** Hide RPM/TPM on user-facing monitor (scale privacy). Admin always shows full metrics. */ +export function isChannelMonitorThroughputHidden(): boolean { + const appStore = useAppStore() + return Boolean(appStore.cachedPublicSettings?.channel_monitor_hide_throughput) +} diff --git a/frontend/src/views/admin/ChannelMonitorView.vue b/frontend/src/views/admin/ChannelMonitorView.vue index d58a842d7..d1bb148e8 100644 --- a/frontend/src/views/admin/ChannelMonitorView.vue +++ b/frontend/src/views/admin/ChannelMonitorView.vue @@ -1,6 +1,55 @@