mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 00:53:33 +00:00
feat: 支持Dark Mode
This commit is contained in:
@@ -3,8 +3,12 @@
|
||||
<div class="card p-4 sm:p-6">
|
||||
<div class="mb-4 flex flex-col gap-4 sm:mb-6">
|
||||
<div>
|
||||
<h3 class="mb-1 text-lg font-bold text-gray-900 sm:mb-2 sm:text-xl">账户管理</h3>
|
||||
<p class="text-sm text-gray-600 sm:text-base">管理您的 Claude 和 Gemini 账户及代理配置</p>
|
||||
<h3 class="mb-1 text-lg font-bold text-gray-900 dark:text-gray-100 sm:mb-2 sm:text-xl">
|
||||
账户管理
|
||||
</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 sm:text-base">
|
||||
管理您的 Claude 和 Gemini 账户及代理配置
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
<!-- 筛选器组 -->
|
||||
@@ -62,7 +66,7 @@
|
||||
placement="bottom"
|
||||
>
|
||||
<button
|
||||
class="group relative flex items-center justify-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm transition-all duration-200 hover:border-gray-300 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50 sm:w-auto"
|
||||
class="group relative flex items-center justify-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm transition-all duration-200 hover:border-gray-300 hover:shadow-md disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:border-gray-500 sm:w-auto"
|
||||
:disabled="accountsLoading"
|
||||
@click.ctrl.exact="loadAccounts(true)"
|
||||
@click.exact="loadAccounts(false)"
|
||||
@@ -96,26 +100,26 @@
|
||||
|
||||
<div v-if="accountsLoading" class="py-12 text-center">
|
||||
<div class="loading-spinner mx-auto mb-4" />
|
||||
<p class="text-gray-500">正在加载账户...</p>
|
||||
<p class="text-gray-500 dark:text-gray-400">正在加载账户...</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="sortedAccounts.length === 0" class="py-12 text-center">
|
||||
<div
|
||||
class="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gray-100"
|
||||
class="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gray-100 dark:bg-gray-700"
|
||||
>
|
||||
<i class="fas fa-user-circle text-xl text-gray-400" />
|
||||
</div>
|
||||
<p class="text-lg text-gray-500">暂无账户</p>
|
||||
<p class="mt-2 text-sm text-gray-400">点击上方按钮添加您的第一个账户</p>
|
||||
<p class="text-lg text-gray-500 dark:text-gray-400">暂无账户</p>
|
||||
<p class="mt-2 text-sm text-gray-400 dark:text-gray-500">点击上方按钮添加您的第一个账户</p>
|
||||
</div>
|
||||
|
||||
<!-- 桌面端表格视图 -->
|
||||
<div v-else class="table-container hidden md:block">
|
||||
<table class="w-full table-fixed">
|
||||
<thead class="bg-gray-50/80 backdrop-blur-sm">
|
||||
<thead class="bg-gray-50/80 backdrop-blur-sm dark:bg-gray-700/80">
|
||||
<tr>
|
||||
<th
|
||||
class="w-[22%] min-w-[180px] cursor-pointer px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 hover:bg-gray-100"
|
||||
class="w-[22%] min-w-[180px] cursor-pointer px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600"
|
||||
@click="sortAccounts('name')"
|
||||
>
|
||||
名称
|
||||
@@ -130,7 +134,7 @@
|
||||
<i v-else class="fas fa-sort ml-1 text-gray-400" />
|
||||
</th>
|
||||
<th
|
||||
class="w-[15%] min-w-[120px] cursor-pointer px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 hover:bg-gray-100"
|
||||
class="w-[15%] min-w-[120px] cursor-pointer px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600"
|
||||
@click="sortAccounts('platform')"
|
||||
>
|
||||
平台/类型
|
||||
@@ -145,7 +149,7 @@
|
||||
<i v-else class="fas fa-sort ml-1 text-gray-400" />
|
||||
</th>
|
||||
<th
|
||||
class="w-[12%] min-w-[100px] cursor-pointer px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 hover:bg-gray-100"
|
||||
class="w-[12%] min-w-[100px] cursor-pointer px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600"
|
||||
@click="sortAccounts('status')"
|
||||
>
|
||||
状态
|
||||
@@ -160,7 +164,7 @@
|
||||
<i v-else class="fas fa-sort ml-1 text-gray-400" />
|
||||
</th>
|
||||
<th
|
||||
class="w-[8%] min-w-[80px] cursor-pointer px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 hover:bg-gray-100"
|
||||
class="w-[8%] min-w-[80px] cursor-pointer px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600"
|
||||
@click="sortAccounts('priority')"
|
||||
>
|
||||
优先级
|
||||
@@ -175,33 +179,33 @@
|
||||
<i v-else class="fas fa-sort ml-1 text-gray-400" />
|
||||
</th>
|
||||
<th
|
||||
class="w-[10%] min-w-[100px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700"
|
||||
class="w-[10%] min-w-[100px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 dark:text-gray-300"
|
||||
>
|
||||
代理
|
||||
</th>
|
||||
<th
|
||||
class="w-[10%] min-w-[90px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700"
|
||||
class="w-[10%] min-w-[90px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 dark:text-gray-300"
|
||||
>
|
||||
今日使用
|
||||
</th>
|
||||
<th
|
||||
class="w-[10%] min-w-[100px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700"
|
||||
class="w-[10%] min-w-[100px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 dark:text-gray-300"
|
||||
>
|
||||
会话窗口
|
||||
</th>
|
||||
<th
|
||||
class="w-[8%] min-w-[80px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700"
|
||||
class="w-[8%] min-w-[80px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 dark:text-gray-300"
|
||||
>
|
||||
最后使用
|
||||
</th>
|
||||
<th
|
||||
class="w-[15%] min-w-[180px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700"
|
||||
class="w-[15%] min-w-[180px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 dark:text-gray-300"
|
||||
>
|
||||
操作
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200/50">
|
||||
<tbody class="divide-y divide-gray-200/50 dark:divide-gray-600/50">
|
||||
<tr v-for="account in sortedAccounts" :key="account.id" class="table-row">
|
||||
<td class="px-3 py-4">
|
||||
<div class="flex items-center">
|
||||
@@ -213,7 +217,7 @@
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="truncate text-sm font-semibold text-gray-900"
|
||||
class="truncate text-sm font-semibold text-gray-900 dark:text-gray-100"
|
||||
:title="account.name"
|
||||
>
|
||||
{{ account.name }}
|
||||
@@ -238,13 +242,16 @@
|
||||
</span>
|
||||
<span
|
||||
v-if="account.groupInfo"
|
||||
class="ml-1 inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-600"
|
||||
class="ml-1 inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-600 dark:bg-gray-700 dark:text-gray-400"
|
||||
:title="`所属分组: ${account.groupInfo.name}`"
|
||||
>
|
||||
<i class="fas fa-folder mr-1" />{{ account.groupInfo.name }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="truncate text-xs text-gray-500" :title="account.id">
|
||||
<div
|
||||
class="truncate text-xs text-gray-500 dark:text-gray-400"
|
||||
:title="account.id"
|
||||
>
|
||||
{{ account.id }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -376,12 +383,15 @@
|
||||
</span>
|
||||
<span
|
||||
v-if="account.status === 'blocked' && account.errorMessage"
|
||||
class="mt-1 max-w-xs truncate text-xs text-gray-500"
|
||||
class="mt-1 max-w-xs truncate text-xs text-gray-500 dark:text-gray-400"
|
||||
:title="account.errorMessage"
|
||||
>
|
||||
{{ account.errorMessage }}
|
||||
</span>
|
||||
<span v-if="account.accountType === 'dedicated'" class="text-xs text-gray-500">
|
||||
<span
|
||||
v-if="account.accountType === 'dedicated'"
|
||||
class="text-xs text-gray-500 dark:text-gray-400"
|
||||
>
|
||||
绑定: {{ account.boundApiKeysCount || 0 }} 个API Key
|
||||
</span>
|
||||
</div>
|
||||
@@ -403,7 +413,7 @@
|
||||
:style="{ width: 101 - (account.priority || 50) + '%' }"
|
||||
/>
|
||||
</div>
|
||||
<span class="min-w-[20px] text-xs font-medium text-gray-700">
|
||||
<span class="min-w-[20px] text-xs font-medium text-gray-700 dark:text-gray-200">
|
||||
{{ account.priority || 50 }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -425,19 +435,19 @@
|
||||
<div v-if="account.usage && account.usage.daily" class="space-y-1">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="h-2 w-2 rounded-full bg-green-500" />
|
||||
<span class="text-sm font-medium text-gray-900"
|
||||
<span class="text-sm font-medium text-gray-900 dark:text-gray-100"
|
||||
>{{ account.usage.daily.requests || 0 }} 次</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="h-2 w-2 rounded-full bg-blue-500" />
|
||||
<span class="text-xs text-gray-600"
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300"
|
||||
>{{ formatNumber(account.usage.daily.allTokens || 0) }} tokens</span
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-if="account.usage.averages && account.usage.averages.rpm > 0"
|
||||
class="text-xs text-gray-500"
|
||||
class="text-xs text-gray-500 dark:text-gray-400"
|
||||
>
|
||||
平均 {{ account.usage.averages.rpm.toFixed(2) }} RPM
|
||||
</div>
|
||||
@@ -460,11 +470,11 @@
|
||||
:style="{ width: account.sessionWindow.progress + '%' }"
|
||||
/>
|
||||
</div>
|
||||
<span class="min-w-[32px] text-xs font-medium text-gray-700">
|
||||
<span class="min-w-[32px] text-xs font-medium text-gray-700 dark:text-gray-200">
|
||||
{{ account.sessionWindow.progress }}%
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-xs text-gray-600">
|
||||
<div class="text-xs text-gray-600 dark:text-gray-300">
|
||||
<div>
|
||||
{{
|
||||
formatSessionWindow(
|
||||
@@ -488,7 +498,7 @@
|
||||
<span class="text-xs">N/A</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-600">
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
{{ formatLastUsed(account.lastUsedAt) }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm font-medium">
|
||||
@@ -590,9 +600,11 @@
|
||||
{{ account.name || account.email }}
|
||||
</h4>
|
||||
<div class="mt-0.5 flex items-center gap-2">
|
||||
<span class="text-xs text-gray-500">{{ account.platform }}</span>
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">{{
|
||||
account.platform
|
||||
}}</span>
|
||||
<span class="text-xs text-gray-400">|</span>
|
||||
<span class="text-xs text-gray-500">{{ account.type }}</span>
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">{{ account.type }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -612,20 +624,20 @@
|
||||
<!-- 使用统计 -->
|
||||
<div class="mb-3 grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">今日使用</p>
|
||||
<p class="text-sm font-semibold text-gray-900">
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">今日使用</p>
|
||||
<p class="text-sm font-semibold text-gray-900 dark:text-gray-100">
|
||||
{{ formatNumber(account.usage?.daily?.requests || 0) }} 次
|
||||
</p>
|
||||
<p class="mt-0.5 text-xs text-gray-500">
|
||||
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ formatNumber(account.usage?.daily?.allTokens || 0) }} tokens
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">总使用量</p>
|
||||
<p class="text-sm font-semibold text-gray-900">
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">总使用量</p>
|
||||
<p class="text-sm font-semibold text-gray-900 dark:text-gray-100">
|
||||
{{ formatNumber(account.usage?.total?.requests || 0) }} 次
|
||||
</p>
|
||||
<p class="mt-0.5 text-xs text-gray-500">
|
||||
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ formatNumber(account.usage?.total?.allTokens || 0) }} tokens
|
||||
</p>
|
||||
</div>
|
||||
@@ -640,22 +652,22 @@
|
||||
account.sessionWindow &&
|
||||
account.sessionWindow.hasActiveWindow
|
||||
"
|
||||
class="space-y-1.5 rounded-lg bg-gray-50 p-2"
|
||||
class="space-y-1.5 rounded-lg bg-gray-50 p-2 dark:bg-gray-700"
|
||||
>
|
||||
<div class="flex items-center justify-between text-xs">
|
||||
<span class="font-medium text-gray-600">会话窗口</span>
|
||||
<span class="font-medium text-gray-700">
|
||||
<span class="font-medium text-gray-600 dark:text-gray-300">会话窗口</span>
|
||||
<span class="font-medium text-gray-700 dark:text-gray-200">
|
||||
{{ account.sessionWindow.progress }}%
|
||||
</span>
|
||||
</div>
|
||||
<div class="h-2 w-full overflow-hidden rounded-full bg-gray-200">
|
||||
<div class="h-2 w-full overflow-hidden rounded-full bg-gray-200 dark:bg-gray-600">
|
||||
<div
|
||||
class="h-full bg-gradient-to-r from-blue-500 to-indigo-600 transition-all duration-300"
|
||||
:style="{ width: account.sessionWindow.progress + '%' }"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center justify-between text-xs">
|
||||
<span class="text-gray-500">
|
||||
<span class="text-gray-500 dark:text-gray-400">
|
||||
{{
|
||||
formatSessionWindow(
|
||||
account.sessionWindow.windowStart,
|
||||
@@ -675,8 +687,8 @@
|
||||
|
||||
<!-- 最后使用时间 -->
|
||||
<div class="flex items-center justify-between text-xs">
|
||||
<span class="text-gray-500">最后使用</span>
|
||||
<span class="text-gray-700">
|
||||
<span class="text-gray-500 dark:text-gray-400">最后使用</span>
|
||||
<span class="text-gray-700 dark:text-gray-200">
|
||||
{{ account.lastUsedAt ? formatRelativeTime(account.lastUsedAt) : '从未使用' }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -686,16 +698,16 @@
|
||||
v-if="account.proxyConfig && account.proxyConfig.type !== 'none'"
|
||||
class="flex items-center justify-between text-xs"
|
||||
>
|
||||
<span class="text-gray-500">代理</span>
|
||||
<span class="text-gray-700">
|
||||
<span class="text-gray-500 dark:text-gray-400">代理</span>
|
||||
<span class="text-gray-700 dark:text-gray-200">
|
||||
{{ account.proxyConfig.type.toUpperCase() }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 调度优先级 -->
|
||||
<div class="flex items-center justify-between text-xs">
|
||||
<span class="text-gray-500">优先级</span>
|
||||
<span class="font-medium text-gray-700">
|
||||
<span class="text-gray-500 dark:text-gray-400">优先级</span>
|
||||
<span class="font-medium text-gray-700 dark:text-gray-200">
|
||||
{{ account.priority || 50 }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user