diff --git a/web/index.html b/web/index.html
index 2076e3544..4b99e07db 100644
--- a/web/index.html
+++ b/web/index.html
@@ -5,29 +5,6 @@
Codex Proxy RS
-
diff --git a/web/src/composables/useJsonDownload.ts b/web/src/composables/useDownload.ts
similarity index 94%
rename from web/src/composables/useJsonDownload.ts
rename to web/src/composables/useDownload.ts
index 8685d6abd..3b16e5f24 100644
--- a/web/src/composables/useJsonDownload.ts
+++ b/web/src/composables/useDownload.ts
@@ -2,7 +2,7 @@
import { useObjectUrl } from '@vueuse/core'
import { nextTick, shallowRef } from 'vue'
-export function useJsonDownload() {
+export function useDownload() {
const object = shallowRef(null)
const objectUrl = useObjectUrl(object)
diff --git a/web/src/directives/loading.ts b/web/src/directives/loading.ts
index 0b50e2091..316d47b9f 100644
--- a/web/src/directives/loading.ts
+++ b/web/src/directives/loading.ts
@@ -137,7 +137,7 @@ function syncLoading(element: LoadingElement, binding: DirectiveBinding = {
+export const loading: Directive = {
mounted: syncLoading,
updated: syncLoading,
beforeUnmount: hideLoading,
diff --git a/web/src/main.ts b/web/src/main.ts
index dd50eb67d..e08835ed0 100644
--- a/web/src/main.ts
+++ b/web/src/main.ts
@@ -5,8 +5,8 @@ import '@fontsource-variable/jetbrains-mono'
import App from './App.vue'
import { router } from './router'
import { pinia } from './stores'
-import { loadingDirective } from './directives/loading'
+import { loading } from './directives/loading'
import './styles/index.css'
-createApp(App).directive('loading', loadingDirective).use(pinia).use(router).mount('#app')
+createApp(App).directive('loading', loading).use(pinia).use(router).mount('#app')
diff --git a/web/src/stores/modules/ui.ts b/web/src/stores/modules/ui.ts
index 9de5bbe8f..340ee258b 100644
--- a/web/src/stores/modules/ui.ts
+++ b/web/src/stores/modules/ui.ts
@@ -1,9 +1,10 @@
-import { usePreferredDark, usePreferredReducedMotion, useTimeoutFn } from '@vueuse/core'
+import { useDark, usePreferredReducedMotion, useTimeoutFn } from '@vueuse/core'
import { defineStore } from 'pinia'
-import { computed, shallowRef, watch } from 'vue'
+import { computed, shallowRef } from 'vue'
type ThemeMode = 'system' | 'light' | 'dark'
type ThemeName = 'light' | 'dark'
+type ColorModeStorageValue = 'auto' | ThemeName
type ThemeTransitionOrigin = { x: number; y: number }
type ViewTransition = {
ready: Promise
@@ -20,14 +21,7 @@ export const useUiStore = defineStore(
const sidebarCollapsed = shallowRef(false)
const themeMode = shallowRef('system')
const themeRevision = shallowRef(0)
- const prefersDark = usePreferredDark()
const preferredMotion = usePreferredReducedMotion()
- const systemTheme = computed(() => (prefersDark.value ? 'dark' : 'light'))
-
- const effectiveTheme = computed(() =>
- themeMode.value === 'system' ? systemTheme.value : themeMode.value,
- )
-
let themeApplied = false
let themeTransitionOrigin: ThemeTransitionOrigin | undefined
let themeTransitionRequested = false
@@ -39,6 +33,22 @@ export const useUiStore = defineStore(
{ immediate: false },
)
+ const colorModeStorage = computed({
+ get: () => (themeMode.value === 'system' ? 'auto' : themeMode.value),
+ set: (mode) => {
+ themeMode.value = mode === 'auto' ? 'system' : mode
+ },
+ })
+
+ const isDark = useDark({
+ storageRef: colorModeStorage,
+ onChanged: (dark) => {
+ applyTheme(dark ? 'dark' : 'light')
+ },
+ })
+
+ const effectiveTheme = computed(() => (isDark.value ? 'dark' : 'light'))
+
function toggleSidebar() {
sidebarCollapsed.value = !sidebarCollapsed.value
}
@@ -124,7 +134,9 @@ export const useUiStore = defineStore(
}
function initializeTheme() {
- applyTheme(effectiveTheme.value)
+ if (!themeApplied) {
+ applyTheme(effectiveTheme.value)
+ }
}
function setThemeMode(mode: ThemeMode) {
@@ -142,8 +154,6 @@ export const useUiStore = defineStore(
themeMode.value = effectiveTheme.value === 'dark' ? 'light' : 'dark'
}
- watch(effectiveTheme, applyTheme, { immediate: true })
-
return {
sidebarCollapsed,
themeMode,
diff --git a/web/src/views/accounts/composables/useAccountMutations.ts b/web/src/views/accounts/composables/useAccountMutations.ts
index d96b1fc86..b48560b48 100644
--- a/web/src/views/accounts/composables/useAccountMutations.ts
+++ b/web/src/views/accounts/composables/useAccountMutations.ts
@@ -14,7 +14,7 @@ import {
updateAccount,
} from '@/api'
import { toast } from '@/components/base/BaseToast'
-import { useJsonDownload } from '@/composables/useJsonDownload'
+import { useDownload } from '@/composables/useDownload'
import { withMinimumDuration } from '@/utils/async'
export function useAccountMutations(options: {
@@ -24,7 +24,7 @@ export function useAccountMutations(options: {
selectedIds: Ref>
totalAccounts: Ref
}) {
- const { downloadJson } = useJsonDownload()
+ const { downloadJson } = useDownload()
const loading = ref(true)
const accounts = ref([])
const accountSummary = ref({
diff --git a/web/src/views/dashboard/composables/useDashboard.ts b/web/src/views/dashboard/composables/useDashboard.ts
index a4b257b3c..af3e78e9d 100644
--- a/web/src/views/dashboard/composables/useDashboard.ts
+++ b/web/src/views/dashboard/composables/useDashboard.ts
@@ -239,7 +239,11 @@ export function useDashboard(): any {
points.map((point) => point.cachedTokensValue),
'warning',
),
- trend: trendState(cache.todayHitRateValue ?? 0, cache.yesterdayHitRateValue ?? 0, 'warning'),
+ trend: trendState(
+ cache.todayHitRateValue ?? 0,
+ cache.yesterdayHitRateValue ?? 0,
+ 'warning',
+ ),
details: [
{ label: '总缓存命中', value: cache.totalHitRate, tone: 'warning' },
{