feat: 支持Dark Mode

This commit is contained in:
shaw
2025-08-22 22:09:38 +08:00
parent 8328b6ddac
commit d2f0ac37a9
37 changed files with 3226 additions and 1155 deletions

View File

@@ -2,13 +2,18 @@
<div ref="triggerRef" class="relative">
<!-- 选择器主体 -->
<div
class="form-input flex w-full cursor-pointer items-center justify-between"
class="form-input flex w-full cursor-pointer items-center justify-between dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
:class="{ 'opacity-50': disabled }"
@click="!disabled && toggleDropdown()"
>
<span :class="modelValue ? 'text-gray-900' : 'text-gray-500'">{{ selectedLabel }}</span>
<span
:class="
modelValue ? 'text-gray-900 dark:text-gray-200' : 'text-gray-500 dark:text-gray-400'
"
>{{ selectedLabel }}</span
>
<i
class="fas fa-chevron-down text-gray-400 transition-transform duration-200"
class="fas fa-chevron-down text-gray-400 transition-transform duration-200 dark:text-gray-500"
:class="{ 'rotate-180': showDropdown }"
/>
</div>
@@ -26,27 +31,27 @@
<div
v-if="showDropdown"
ref="dropdownRef"
class="absolute z-50 flex flex-col rounded-lg border border-gray-200 bg-white shadow-lg"
class="absolute z-50 flex flex-col rounded-lg border border-gray-200 bg-white shadow-lg dark:border-gray-600 dark:bg-gray-800"
:style="dropdownStyle"
>
<!-- 搜索框 -->
<div class="flex-shrink-0 border-b border-gray-200 p-3">
<div class="flex-shrink-0 border-b border-gray-200 p-3 dark:border-gray-600">
<div class="relative">
<input
ref="searchInput"
v-model="searchQuery"
class="form-input w-full text-sm"
class="form-input w-full text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
placeholder="搜索账号名称..."
style="padding-left: 40px; padding-right: 36px"
type="text"
@input="handleSearch"
/>
<i
class="fas fa-search pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-gray-400"
class="fas fa-search pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-gray-400 dark:text-gray-500"
/>
<button
v-if="searchQuery"
class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-400"
type="button"
@click="clearSearch"
>
@@ -59,59 +64,67 @@
<div class="custom-scrollbar flex-1 overflow-y-auto">
<!-- 默认选项 -->
<div
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50"
:class="{ 'bg-blue-50': !modelValue }"
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
:class="{ 'bg-blue-50 dark:bg-blue-900/20': !modelValue }"
@click="selectAccount(null)"
>
<span class="text-gray-700">{{ defaultOptionText }}</span>
<span class="text-gray-700 dark:text-gray-300">{{ defaultOptionText }}</span>
</div>
<!-- 分组选项 -->
<div v-if="filteredGroups.length > 0">
<div class="bg-gray-50 px-4 py-2 text-xs font-semibold text-gray-500">调度分组</div>
<div
class="bg-gray-50 px-4 py-2 text-xs font-semibold text-gray-500 dark:bg-gray-700 dark:text-gray-400"
>
调度分组
</div>
<div
v-for="group in filteredGroups"
:key="`group:${group.id}`"
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50"
:class="{ 'bg-blue-50': modelValue === `group:${group.id}` }"
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
:class="{ 'bg-blue-50 dark:bg-blue-900/20': modelValue === `group:${group.id}` }"
@click="selectAccount(`group:${group.id}`)"
>
<div class="flex items-center justify-between">
<span class="text-gray-700">{{ group.name }}</span>
<span class="text-xs text-gray-500">{{ group.memberCount || 0 }} 个成员</span>
<span class="text-gray-700 dark:text-gray-300">{{ group.name }}</span>
<span class="text-xs text-gray-500 dark:text-gray-400"
>{{ group.memberCount || 0 }} 个成员</span
>
</div>
</div>
</div>
<!-- OAuth 账号 -->
<div v-if="filteredOAuthAccounts.length > 0">
<div class="bg-gray-50 px-4 py-2 text-xs font-semibold text-gray-500">
<div
class="bg-gray-50 px-4 py-2 text-xs font-semibold text-gray-500 dark:bg-gray-700 dark:text-gray-400"
>
{{ platform === 'claude' ? 'Claude OAuth 专属账号' : 'OAuth 专属账号' }}
</div>
<div
v-for="account in filteredOAuthAccounts"
:key="account.id"
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50"
:class="{ 'bg-blue-50': modelValue === account.id }"
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
:class="{ 'bg-blue-50 dark:bg-blue-900/20': modelValue === account.id }"
@click="selectAccount(account.id)"
>
<div class="flex items-center justify-between">
<div>
<span class="text-gray-700">{{ account.name }}</span>
<span class="text-gray-700 dark:text-gray-300">{{ account.name }}</span>
<span
class="ml-2 rounded-full px-2 py-0.5 text-xs"
:class="
account.isActive
? 'bg-green-100 text-green-700'
? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400'
: account.status === 'unauthorized'
? 'bg-orange-100 text-orange-700'
: 'bg-red-100 text-red-700'
? 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400'
: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400'
"
>
{{ getAccountStatusText(account) }}
</span>
</div>
<span class="text-xs text-gray-400">
<span class="text-xs text-gray-400 dark:text-gray-500">
{{ formatDate(account.createdAt) }}
</span>
</div>
@@ -120,33 +133,37 @@
<!-- Console 账号 Claude -->
<div v-if="platform === 'claude' && filteredConsoleAccounts.length > 0">
<div class="bg-gray-50 px-4 py-2 text-xs font-semibold text-gray-500">
<div
class="bg-gray-50 px-4 py-2 text-xs font-semibold text-gray-500 dark:bg-gray-700 dark:text-gray-400"
>
Claude Console 专属账号
</div>
<div
v-for="account in filteredConsoleAccounts"
:key="account.id"
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50"
:class="{ 'bg-blue-50': modelValue === `console:${account.id}` }"
class="cursor-pointer px-4 py-2 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
:class="{
'bg-blue-50 dark:bg-blue-900/20': modelValue === `console:${account.id}`
}"
@click="selectAccount(`console:${account.id}`)"
>
<div class="flex items-center justify-between">
<div>
<span class="text-gray-700">{{ account.name }}</span>
<span class="text-gray-700 dark:text-gray-300">{{ account.name }}</span>
<span
class="ml-2 rounded-full px-2 py-0.5 text-xs"
:class="
account.isActive
? 'bg-green-100 text-green-700'
? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400'
: account.status === 'unauthorized'
? 'bg-orange-100 text-orange-700'
: 'bg-red-100 text-red-700'
? 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400'
: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400'
"
>
{{ getAccountStatusText(account) }}
</span>
</div>
<span class="text-xs text-gray-400">
<span class="text-xs text-gray-400 dark:text-gray-500">
{{ formatDate(account.createdAt) }}
</span>
</div>
@@ -154,7 +171,10 @@
</div>
<!-- 无搜索结果 -->
<div v-if="searchQuery && !hasResults" class="px-4 py-8 text-center text-gray-500">
<div
v-if="searchQuery && !hasResults"
class="px-4 py-8 text-center text-gray-500 dark:text-gray-400"
>
<i class="fas fa-search mb-2 text-2xl" />
<p class="text-sm">没有找到匹配的账号</p>
</div>