mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
feat: OAuth 账户管理、维护调度、端点健康检查增强及前端优化
- 新增 OAuth 账户管理对话框和提供商详情抽屉中的 OAuth 信息展示 - 新增维护调度器(maintenance_scheduler)支持定时清理和健康检查 - 增强端点健康检查器,支持更多检测策略 - 重构 codex 服务为 metadata_collectors 模块 - 优化 OpenAI CLI normalizer 代码结构 - 前端: 改进使用量表格、统计图表、指南页面和异步任务管理 - 扩展多个数据库字符串列为 TEXT 类型 - 新增倒计时 composable 和 provider OAuth API 端点
This commit is contained in:
@@ -1,21 +1,46 @@
|
||||
<template>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<Select v-model:open="presetSelectOpen" v-model="selectedPreset">
|
||||
<Select
|
||||
v-model:open="presetSelectOpen"
|
||||
v-model="selectedPreset"
|
||||
>
|
||||
<SelectTrigger class="h-8 w-32 text-xs border-border/60">
|
||||
<SelectValue placeholder="选择时间段" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="today">今天</SelectItem>
|
||||
<SelectItem value="yesterday">昨天</SelectItem>
|
||||
<SelectItem value="last7days">最近7天</SelectItem>
|
||||
<SelectItem value="last30days">最近30天</SelectItem>
|
||||
<SelectItem value="last90days">最近90天</SelectItem>
|
||||
<SelectItem value="this_week">本周</SelectItem>
|
||||
<SelectItem value="last_week">上周</SelectItem>
|
||||
<SelectItem value="this_month">本月</SelectItem>
|
||||
<SelectItem value="last_month">上月</SelectItem>
|
||||
<SelectItem value="this_year">今年</SelectItem>
|
||||
<SelectItem value="custom">自定义</SelectItem>
|
||||
<SelectItem value="today">
|
||||
今天
|
||||
</SelectItem>
|
||||
<SelectItem value="yesterday">
|
||||
昨天
|
||||
</SelectItem>
|
||||
<SelectItem value="last7days">
|
||||
最近7天
|
||||
</SelectItem>
|
||||
<SelectItem value="last30days">
|
||||
最近30天
|
||||
</SelectItem>
|
||||
<SelectItem value="last90days">
|
||||
最近90天
|
||||
</SelectItem>
|
||||
<SelectItem value="this_week">
|
||||
本周
|
||||
</SelectItem>
|
||||
<SelectItem value="last_week">
|
||||
上周
|
||||
</SelectItem>
|
||||
<SelectItem value="this_month">
|
||||
本月
|
||||
</SelectItem>
|
||||
<SelectItem value="last_month">
|
||||
上月
|
||||
</SelectItem>
|
||||
<SelectItem value="this_year">
|
||||
今年
|
||||
</SelectItem>
|
||||
<SelectItem value="custom">
|
||||
自定义
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
@@ -36,15 +61,30 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Select v-if="showGranularity" v-model:open="granularitySelectOpen" v-model="selectedGranularity">
|
||||
<Select
|
||||
v-if="showGranularity"
|
||||
v-model:open="granularitySelectOpen"
|
||||
v-model="selectedGranularity"
|
||||
>
|
||||
<SelectTrigger class="h-8 w-24 text-xs border-border/60">
|
||||
<SelectValue placeholder="粒度" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-if="allowHourly && canUseHourly" value="hour">小时</SelectItem>
|
||||
<SelectItem value="day">天</SelectItem>
|
||||
<SelectItem value="week">周</SelectItem>
|
||||
<SelectItem value="month">月</SelectItem>
|
||||
<SelectItem
|
||||
v-if="allowHourly && canUseHourly"
|
||||
value="hour"
|
||||
>
|
||||
小时
|
||||
</SelectItem>
|
||||
<SelectItem value="day">
|
||||
天
|
||||
</SelectItem>
|
||||
<SelectItem value="week">
|
||||
周
|
||||
</SelectItem>
|
||||
<SelectItem value="month">
|
||||
月
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
<template>
|
||||
<Card class="p-4 space-y-2">
|
||||
<div class="text-xs text-muted-foreground">{{ label }}</div>
|
||||
<div class="text-lg font-semibold">{{ value }}</div>
|
||||
<div class="text-xs" :class="changeClass">
|
||||
<div class="text-xs text-muted-foreground">
|
||||
{{ label }}
|
||||
</div>
|
||||
<div class="text-lg font-semibold">
|
||||
{{ value }}
|
||||
</div>
|
||||
<div
|
||||
class="text-xs"
|
||||
:class="changeClass"
|
||||
>
|
||||
<span v-if="changePercent !== null">{{ changePercent }}%</span>
|
||||
<span v-else>--</span>
|
||||
<span class="ml-1 text-muted-foreground">vs 对比期</span>
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
<template>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-sm font-semibold">{{ title }}</h3>
|
||||
<span class="text-xs text-muted-foreground" v-if="subtitle">{{ subtitle }}</span>
|
||||
<h3 class="text-sm font-semibold">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<span
|
||||
v-if="subtitle"
|
||||
class="text-xs text-muted-foreground"
|
||||
>{{ subtitle }}</span>
|
||||
</div>
|
||||
<div v-if="loading" class="p-6">
|
||||
<div
|
||||
v-if="loading"
|
||||
class="p-6"
|
||||
>
|
||||
<LoadingState />
|
||||
</div>
|
||||
<div v-else class="h-[280px]">
|
||||
<LineChart :data="chartData" :options="chartOptions" />
|
||||
<div
|
||||
v-else
|
||||
class="h-[280px]"
|
||||
>
|
||||
<LineChart
|
||||
:data="chartData"
|
||||
:options="chartOptions"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
<template>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-sm font-semibold">{{ title }}</h3>
|
||||
<span class="text-xs text-muted-foreground" v-if="subtitle">{{ subtitle }}</span>
|
||||
<h3 class="text-sm font-semibold">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<span
|
||||
v-if="subtitle"
|
||||
class="text-xs text-muted-foreground"
|
||||
>{{ subtitle }}</span>
|
||||
</div>
|
||||
<div v-if="loading" class="p-6">
|
||||
<div
|
||||
v-if="loading"
|
||||
class="p-6"
|
||||
>
|
||||
<LoadingState />
|
||||
</div>
|
||||
<div v-else class="h-[260px]">
|
||||
<DoughnutChart :data="chartData" :options="chartOptions" />
|
||||
<div
|
||||
v-else
|
||||
class="h-[260px]"
|
||||
>
|
||||
<DoughnutChart
|
||||
:data="chartData"
|
||||
:options="chartOptions"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -11,36 +11,70 @@
|
||||
<SelectValue placeholder="指标" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="requests">请求数</SelectItem>
|
||||
<SelectItem value="tokens">Tokens</SelectItem>
|
||||
<SelectItem value="cost">成本</SelectItem>
|
||||
<SelectItem value="requests">
|
||||
请求数
|
||||
</SelectItem>
|
||||
<SelectItem value="tokens">
|
||||
Tokens
|
||||
</SelectItem>
|
||||
<SelectItem value="cost">
|
||||
成本
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</template>
|
||||
|
||||
<div v-if="loading" class="p-6">
|
||||
<div
|
||||
v-if="loading"
|
||||
class="p-6"
|
||||
>
|
||||
<LoadingState />
|
||||
</div>
|
||||
<div v-else-if="items.length === 0" class="p-6">
|
||||
<EmptyState title="暂无数据" description="当前时间范围内没有统计结果" />
|
||||
<div
|
||||
v-else-if="items.length === 0"
|
||||
class="p-6"
|
||||
>
|
||||
<EmptyState
|
||||
title="暂无数据"
|
||||
description="当前时间范围内没有统计结果"
|
||||
/>
|
||||
</div>
|
||||
<Table v-else>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead class="w-16">排名</TableHead>
|
||||
<TableHead class="w-16">
|
||||
排名
|
||||
</TableHead>
|
||||
<TableHead>名称</TableHead>
|
||||
<TableHead class="text-right">请求数</TableHead>
|
||||
<TableHead class="text-right">Tokens</TableHead>
|
||||
<TableHead class="text-right">成本</TableHead>
|
||||
<TableHead class="text-right">
|
||||
请求数
|
||||
</TableHead>
|
||||
<TableHead class="text-right">
|
||||
Tokens
|
||||
</TableHead>
|
||||
<TableHead class="text-right">
|
||||
成本
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow v-for="item in items" :key="item.id">
|
||||
<TableCell class="font-medium">{{ item.rank }}</TableCell>
|
||||
<TableRow
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
>
|
||||
<TableCell class="font-medium">
|
||||
{{ item.rank }}
|
||||
</TableCell>
|
||||
<TableCell>{{ item.name }}</TableCell>
|
||||
<TableCell class="text-right">{{ item.requests }}</TableCell>
|
||||
<TableCell class="text-right">{{ formatTokens(item.tokens) }}</TableCell>
|
||||
<TableCell class="text-right">{{ formatCurrency(item.cost) }}</TableCell>
|
||||
<TableCell class="text-right">
|
||||
{{ item.requests }}
|
||||
</TableCell>
|
||||
<TableCell class="text-right">
|
||||
{{ formatTokens(item.tokens) }}
|
||||
</TableCell>
|
||||
<TableCell class="text-right">
|
||||
{{ formatCurrency(item.cost) }}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
<template>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-sm font-semibold">{{ title }}</h3>
|
||||
<span class="text-xs text-muted-foreground" v-if="subtitle">{{ subtitle }}</span>
|
||||
<h3 class="text-sm font-semibold">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<span
|
||||
v-if="subtitle"
|
||||
class="text-xs text-muted-foreground"
|
||||
>{{ subtitle }}</span>
|
||||
</div>
|
||||
<div v-if="loading" class="p-6">
|
||||
<div
|
||||
v-if="loading"
|
||||
class="p-6"
|
||||
>
|
||||
<LoadingState />
|
||||
</div>
|
||||
<div v-else class="h-[260px]">
|
||||
<LineChart :data="chartData" :options="chartOptions" />
|
||||
<div
|
||||
v-else
|
||||
class="h-[260px]"
|
||||
>
|
||||
<LineChart
|
||||
:data="chartData"
|
||||
:options="chartOptions"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,18 +1,39 @@
|
||||
<template>
|
||||
<Card class="p-4 space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-sm font-semibold">{{ title }}</h3>
|
||||
<span class="text-xs text-muted-foreground" v-if="subtitle">{{ subtitle }}</span>
|
||||
<h3 class="text-sm font-semibold">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<span
|
||||
v-if="subtitle"
|
||||
class="text-xs text-muted-foreground"
|
||||
>{{ subtitle }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="p-4">
|
||||
<div
|
||||
v-if="loading"
|
||||
class="p-4"
|
||||
>
|
||||
<LoadingState />
|
||||
</div>
|
||||
<div v-else-if="providers.length === 0" class="p-4">
|
||||
<EmptyState title="暂无数据" description="暂无月卡配额数据" />
|
||||
<div
|
||||
v-else-if="providers.length === 0"
|
||||
class="p-4"
|
||||
>
|
||||
<EmptyState
|
||||
title="暂无数据"
|
||||
description="暂无月卡配额数据"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="space-y-4">
|
||||
<div v-for="provider in providers" :key="provider.id" class="space-y-2">
|
||||
<div
|
||||
v-else
|
||||
class="space-y-4"
|
||||
>
|
||||
<div
|
||||
v-for="provider in providers"
|
||||
:key="provider.id"
|
||||
class="space-y-2"
|
||||
>
|
||||
<div class="flex items-center justify-between text-xs">
|
||||
<span class="font-medium">{{ provider.name }}</span>
|
||||
<span class="text-muted-foreground">
|
||||
|
||||
Reference in New Issue
Block a user