新增 admin「渠道监控」模块(参考 BingZi-233/check-cx),独立于现有 Channel 体系。
admin 配置 + 后台定时调用上游 LLM chat completions 健康检查 + 所有登录用户只读可见。
后端:
- ent: channel_monitor + channel_monitor_history(AES-256-GCM 加密 api_key)
- service 按职责拆分:service/aggregator/validate/checker/runner/ssrf
- provider strategy map 替代 switch(openai/anthropic/gemini)
- repository batch 聚合(ListLatestForMonitorIDs + ComputeAvailabilityForMonitors)消除 N+1
- runner: ticker(5s) + pond worker pool(5) + inFlight 防并发 + TrySubmit 防雪崩
+ 凌晨 3 点 cron 清理 30 天历史
- SSRF 防护:强制 https + 私网/loopback/云元数据 IP 拒绝(127/8、10/8、172.16/12、
192.168/16、169.254/16、100.64/10、::1、fc00::/7、fe80::/10)+ DialContext
在 socket 层防 DNS rebinding
- API key sanitize:擦除 url.Error 与上游响应 body 中的 sk-/sk-ant-/AIza/JWT 模式
- APIKeyDecryptFailed 标志位 + 单 monitor 路径检测,避免空 key 调用上游
handler:
- admin: CRUD + 手动触发 + 历史接口(api_key 脱敏)
- user: 只读列表 + 状态详情(去除 api_key/endpoint)
- ParseChannelMonitorID 共用 + dto.ChannelMonitorExtraModelStatus 共用
前端:
- 路由 /admin/channels/{pricing,monitor} + /monitor(用户只读)
- AppSidebar 父项 expandOnly 支持
- ChannelMonitorView 拆为 8 个子组件 + ChannelStatusView 拆出 detail dialog
- composables/useChannelMonitorFormat + constants/channelMonitor 共享
- i18n monitorCommon namespace 消除 admin/user 两 view 重复
合规:所有文件符合 CLAUDE.md(Go ≤ 500 行 / Vue ≤ 300 行 / 函数 ≤ 30 行)
CI: go build / gofmt / golangci-lint(0 issues) / make test-unit / pnpm build 全绿
Layout Components
Vue 3 layout components for the Sub2API frontend, built with Composition API, TypeScript, and TailwindCSS.
Components
1. AppLayout.vue
Main application layout with sidebar and header.
Usage:
<template>
<AppLayout>
<!-- Your page content here -->
<h1>Dashboard</h1>
<p>Welcome to your dashboard!</p>
</AppLayout>
</template>
<script setup lang="ts">
import { AppLayout } from '@/components/layout'
</script>
Features:
- Responsive sidebar (collapsible)
- Fixed header at top
- Main content area with slot
- Automatically adjusts margin based on sidebar state
2. AppSidebar.vue
Navigation sidebar with user and admin sections.
Features:
- Logo/brand at top
- User navigation links:
- Dashboard
- API Keys
- Usage
- Redeem
- Profile
- Admin navigation links (shown only if user is admin):
- Admin Dashboard
- Users
- Groups
- Accounts
- Proxies
- Redeem Codes
- Collapsible sidebar with toggle button
- Active route highlighting
- Icons using HTML entities
- Responsive (mobile-friendly)
Used automatically by AppLayout - no need to import separately.
3. AppHeader.vue
Top header with user info and actions.
Features:
- Mobile menu toggle button
- Page title (from route meta or slot)
- User balance display (desktop only)
- User dropdown menu with:
- Profile link
- Logout button
- User avatar with initials
- Click-outside handling for dropdown
- Responsive design
Usage with custom title:
<template>
<AppLayout>
<template #title> Custom Page Title </template>
<!-- Your content -->
</AppLayout>
</template>
Used automatically by AppLayout - no need to import separately.
4. AuthLayout.vue
Simple centered layout for authentication pages (login/register).
Usage:
<template>
<AuthLayout>
<!-- Login/Register form content -->
<h2 class="mb-6 text-2xl font-bold">Login</h2>
<form @submit.prevent="handleLogin">
<!-- Form fields -->
</form>
<!-- Optional footer slot -->
<template #footer>
<p>
Don't have an account?
<router-link to="/register" class="text-indigo-600 hover:underline"> Sign up </router-link>
</p>
</template>
</AuthLayout>
</template>
<script setup lang="ts">
import { AuthLayout } from '@/components/layout'
function handleLogin() {
// Login logic
}
</script>
Features:
- Centered card container
- Gradient background
- Logo/brand at top
- Main content slot
- Optional footer slot for links
- Fully responsive
Route Configuration
To set page titles in the header, add meta to your routes:
// router/index.ts
const routes = [
{
path: '/dashboard',
component: DashboardView,
meta: { title: 'Dashboard' }
},
{
path: '/api-keys',
component: ApiKeysView,
meta: { title: 'API Keys' }
}
// ...
]
Store Dependencies
These components use the following Pinia stores:
- useAuthStore: For user authentication state, role checking, and logout
- useAppStore: For sidebar state management and toast notifications
Make sure these stores are properly initialized in your app.
Styling
All components use TailwindCSS utility classes. Make sure your tailwind.config.js includes the component paths:
module.exports = {
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}']
// ...
}
Icons
Components use HTML entity icons for simplicity:
- 📈 Chart (Dashboard)
- 🔑 Key (API Keys)
- 📊 Bar Chart (Usage)
- 🎁 Gift (Redeem)
- 👤 User (Profile)
- 🔌 Admin
- 👥 Users
- 📁 Folder (Groups)
- 🌐 Globe (Accounts)
- 🔄 Network (Proxies)
- 🏷 Ticket (Redeem Codes)
You can replace these with your preferred icon library (e.g., Heroicons, Font Awesome) if needed.
Mobile Responsiveness
All components are fully responsive:
- AppSidebar: Fixed positioning on desktop, hidden by default on mobile
- AppHeader: Shows mobile menu toggle on small screens, hides balance display
- AuthLayout: Adapts padding and card size for mobile devices
The sidebar uses Tailwind's responsive breakpoints (md:) to adjust behavior.