feat(channel-monitor): gate UI by feature switch + polish form UX

- AppSidebar 三处菜单项(管理端渠道监控、用户端/个人页渠道状态)按
  channel_monitor_enabled 条件展开,关闭时隐藏
- ChannelStatusView setInterval 随开关启停:关闭 clearInterval,
  开启/未知态自动启动,避免禁用功能后仍在轮询
- MonitorFormDialog provider Select 改为 3 色单选按钮
  (openai=emerald / anthropic=orange / gemini=sky),i18n 文案
  供应商 → 平台 / Provider → Platform
- MonitorKeyPickerDialog 按钮列表改为 name/key/group 三列表格 +
  搜索框,按 key.group.platform === provider 过滤,避免跨平台误选
- form.provider 变化时清空 api_key,修复切换平台仍保留旧 key 的
  错配 bug
- providerPickerClass 抽取到 useChannelMonitorFormat composable,
  统一 emerald/orange/sky 颜色语义,消除硬编码 Tailwind class 重复
- maskApiKey 工具函数统一(utils/maskApiKey.ts),KeysView 与
  MonitorKeyPickerDialog 共用 slice(0,6)...slice(-4) 策略
- bump version to 0.1.114.27
This commit is contained in:
erio
2026-04-21 01:42:58 +08:00
parent 0d01bd908e
commit ba98243cc2
9 changed files with 165 additions and 35 deletions

View File

@@ -160,14 +160,34 @@ watch(items, () => {
void ensureDetailsForWindow()
})
function startTimer() {
if (countdownTimer !== undefined) return
countdownTimer = setInterval(tick, 1000) as unknown as number
}
function stopTimer() {
if (countdownTimer !== undefined) {
clearInterval(countdownTimer)
countdownTimer = undefined
}
}
watch(
() => appStore.cachedPublicSettings?.channel_monitor_enabled,
(enabled) => {
if (enabled === false) stopTimer()
else startTimer()
},
)
// ── Lifecycle ──
onMounted(() => {
void reload(false)
countdownTimer = setInterval(tick, 1000) as unknown as number
if (appStore.cachedPublicSettings?.channel_monitor_enabled !== false) startTimer()
})
onBeforeUnmount(() => {
if (countdownTimer !== undefined) clearInterval(countdownTimer)
stopTimer()
if (abortController) abortController.abort()
})
</script>

View File

@@ -61,7 +61,7 @@
<template #cell-key="{ value, row }">
<div class="flex items-center gap-2">
<code class="code text-xs">
{{ maskKey(value) }}
{{ maskApiKey(value) }}
</code>
<button
@click="copyToClipboard(value, row.id)"
@@ -1072,6 +1072,7 @@ import TablePageLayout from '@/components/layout/TablePageLayout.vue'
import type { Column } from '@/components/common/types'
import type { BatchApiKeyUsageStats } from '@/api/usage'
import { formatDateTime } from '@/utils/format'
import { maskApiKey } from '@/utils/maskApiKey'
// Helper to format date for datetime-local input
const formatDateTimeLocal = (isoDate: string): string => {
@@ -1260,11 +1261,6 @@ const filteredGroupOptions = computed(() => {
})
})
const maskKey = (key: string): string => {
if (key.length <= 12) return key
return `${key.slice(0, 8)}...${key.slice(-4)}`
}
const copyToClipboard = async (text: string, keyId: number) => {
const success = await clipboardCopy(text, t('keys.copied'))
if (success) {