Merge pull request #6 from dexcoder6/main

fix(frontend): 修复移动端菜单栏和使用记录页面 UI 问题
This commit is contained in:
Wesley Liddick
2025-12-19 02:59:05 -05:00
committed by GitHub
5 changed files with 43 additions and 15 deletions

View File

@@ -207,7 +207,7 @@ const pageDescription = computed(() => {
}); });
function toggleMobileSidebar() { function toggleMobileSidebar() {
appStore.toggleSidebar(); appStore.toggleMobileSidebar();
} }
function toggleDropdown() { function toggleDropdown() {

View File

@@ -36,6 +36,7 @@
class="sidebar-link mb-1" class="sidebar-link mb-1"
:class="{ 'sidebar-link-active': isActive(item.path) }" :class="{ 'sidebar-link-active': isActive(item.path) }"
:title="sidebarCollapsed ? item.label : undefined" :title="sidebarCollapsed ? item.label : undefined"
@click="handleMenuItemClick"
> >
<component :is="item.icon" class="w-5 h-5 flex-shrink-0" /> <component :is="item.icon" class="w-5 h-5 flex-shrink-0" />
<transition name="fade"> <transition name="fade">
@@ -58,6 +59,7 @@
class="sidebar-link mb-1" class="sidebar-link mb-1"
:class="{ 'sidebar-link-active': isActive(item.path) }" :class="{ 'sidebar-link-active': isActive(item.path) }"
:title="sidebarCollapsed ? item.label : undefined" :title="sidebarCollapsed ? item.label : undefined"
@click="handleMenuItemClick"
> >
<component :is="item.icon" class="w-5 h-5 flex-shrink-0" /> <component :is="item.icon" class="w-5 h-5 flex-shrink-0" />
<transition name="fade"> <transition name="fade">
@@ -77,6 +79,7 @@
class="sidebar-link mb-1" class="sidebar-link mb-1"
:class="{ 'sidebar-link-active': isActive(item.path) }" :class="{ 'sidebar-link-active': isActive(item.path) }"
:title="sidebarCollapsed ? item.label : undefined" :title="sidebarCollapsed ? item.label : undefined"
@click="handleMenuItemClick"
> >
<component :is="item.icon" class="w-5 h-5 flex-shrink-0" /> <component :is="item.icon" class="w-5 h-5 flex-shrink-0" />
<transition name="fade"> <transition name="fade">
@@ -142,9 +145,9 @@ const appStore = useAppStore();
const authStore = useAuthStore(); const authStore = useAuthStore();
const sidebarCollapsed = computed(() => appStore.sidebarCollapsed); const sidebarCollapsed = computed(() => appStore.sidebarCollapsed);
const mobileOpen = computed(() => appStore.mobileOpen);
const isAdmin = computed(() => authStore.isAdmin); const isAdmin = computed(() => authStore.isAdmin);
const isDark = ref(document.documentElement.classList.contains('dark')); const isDark = ref(document.documentElement.classList.contains('dark'));
const mobileOpen = ref(false);
// Site settings // Site settings
const siteName = ref('Sub2API'); const siteName = ref('Sub2API');
@@ -303,7 +306,15 @@ function toggleTheme() {
} }
function closeMobile() { function closeMobile() {
mobileOpen.value = false; appStore.setMobileOpen(false);
}
function handleMenuItemClick() {
if (mobileOpen.value) {
setTimeout(() => {
appStore.setMobileOpen(false);
}, 150);
}
} }
function isActive(path: string): boolean { function isActive(path: string): boolean {

View File

@@ -12,6 +12,7 @@ export const useAppStore = defineStore('app', () => {
// ==================== State ==================== // ==================== State ====================
const sidebarCollapsed = ref<boolean>(false); const sidebarCollapsed = ref<boolean>(false);
const mobileOpen = ref<boolean>(false);
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const toasts = ref<Toast[]>([]); const toasts = ref<Toast[]>([]);
@@ -50,6 +51,21 @@ export const useAppStore = defineStore('app', () => {
sidebarCollapsed.value = collapsed; sidebarCollapsed.value = collapsed;
} }
/**
* Toggle mobile sidebar open state
*/
function toggleMobileSidebar(): void {
mobileOpen.value = !mobileOpen.value;
}
/**
* Set mobile sidebar open state explicitly
* @param open - Whether mobile sidebar should be open
*/
function setMobileOpen(open: boolean): void {
mobileOpen.value = open;
}
/** /**
* Set global loading state * Set global loading state
* @param isLoading - Whether app is in loading state * @param isLoading - Whether app is in loading state
@@ -257,6 +273,7 @@ export const useAppStore = defineStore('app', () => {
return { return {
// State // State
sidebarCollapsed, sidebarCollapsed,
mobileOpen,
loading, loading,
toasts, toasts,
@@ -275,6 +292,8 @@ export const useAppStore = defineStore('app', () => {
// Actions // Actions
toggleSidebar, toggleSidebar,
setSidebarCollapsed, setSidebarCollapsed,
toggleMobileSidebar,
setMobileOpen,
setLoading, setLoading,
showToast, showToast,
showSuccess, showSuccess,

View File

@@ -43,13 +43,12 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg> </svg>
</div> </div>
<div> <div class="min-w-0 flex-1">
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">{{ t('usage.totalCost') }}</p> <p class="text-xs font-medium text-gray-500 dark:text-gray-400">{{ t('usage.totalCost') }}</p>
<div class="flex items-baseline gap-2"> <p class="text-xl font-bold text-green-600 dark:text-green-400">${{ (usageStats?.total_actual_cost || 0).toFixed(4) }}</p>
<p class="text-xl font-bold text-green-600 dark:text-green-400">${{ (usageStats?.total_actual_cost || 0).toFixed(4) }}</p> <p class="text-xs text-gray-500 dark:text-gray-400">
<span class="text-xs text-gray-400 dark:text-gray-500 line-through">${{ (usageStats?.total_cost || 0).toFixed(4) }}</span> {{ t('usage.actualCost') }} / <span class="line-through">${{ (usageStats?.total_cost || 0).toFixed(4) }}</span> {{ t('usage.standardCost') }}
</div> </p>
<p class="text-xs text-gray-500 dark:text-gray-400">{{ t('usage.actualCost') }} / {{ t('usage.standardCost') }}</p>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -43,13 +43,12 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg> </svg>
</div> </div>
<div> <div class="min-w-0 flex-1">
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">{{ t('usage.totalCost') }}</p> <p class="text-xs font-medium text-gray-500 dark:text-gray-400">{{ t('usage.totalCost') }}</p>
<div class="flex items-baseline gap-2"> <p class="text-xl font-bold text-green-600 dark:text-green-400">${{ (usageStats?.total_actual_cost || 0).toFixed(4) }}</p>
<p class="text-xl font-bold text-green-600 dark:text-green-400">${{ (usageStats?.total_actual_cost || 0).toFixed(4) }}</p> <p class="text-xs text-gray-500 dark:text-gray-400">
<span class="text-xs text-gray-400 dark:text-gray-500 line-through">${{ (usageStats?.total_cost || 0).toFixed(4) }}</span> {{ t('usage.actualCost') }} / <span class="line-through">${{ (usageStats?.total_cost || 0).toFixed(4) }}</span> {{ t('usage.standardCost') }}
</div> </p>
<p class="text-xs text-gray-500 dark:text-gray-400">{{ t('usage.actualCost') }} / {{ t('usage.standardCost') }}</p>
</div> </div>
</div> </div>
</div> </div>