feat: 完善项目架构并增强分析页面功能
- 新增项目文档和 Docker 配置 - 添加 README.md 和 TODO.md 项目文档 - 为各服务添加 Dockerfile 和 docker-compose 配置 - 重构后端架构 - 新增 adapter 层(HTTP/Python 适配器) - 新增 repository 层(数据访问抽象) - 新增 router 模块统一管理路由 - 新增账单处理 handler - 扩展前端 UI 组件库 - 新增 Calendar、DateRangePicker、Drawer、Popover 等组件 - 集成 shadcn-svelte 组件库 - 增强分析页面功能 - 添加时间范围筛选器(支持本月默认值) - 修复 DateRangePicker 默认值显示问题 - 优化数据获取和展示逻辑 - 完善分析器服务 - 新增 FastAPI 服务接口 - 改进账单清理器实现
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import '../app.css';
|
||||
import { page } from '$app/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import { checkHealth } from '$lib/api';
|
||||
import * as Sidebar from '$lib/components/ui/sidebar';
|
||||
import * as DropdownMenu from '$lib/components/ui/dropdown-menu';
|
||||
import * as Avatar from '$lib/components/ui/avatar';
|
||||
@@ -14,7 +15,6 @@
|
||||
import BarChart3 from '@lucide/svelte/icons/bar-chart-3';
|
||||
import Settings from '@lucide/svelte/icons/settings';
|
||||
import HelpCircle from '@lucide/svelte/icons/help-circle';
|
||||
import Search from '@lucide/svelte/icons/search';
|
||||
import ChevronsUpDown from '@lucide/svelte/icons/chevrons-up-down';
|
||||
import Wallet from '@lucide/svelte/icons/wallet';
|
||||
import LogOut from '@lucide/svelte/icons/log-out';
|
||||
@@ -35,16 +35,32 @@
|
||||
let { children } = $props();
|
||||
|
||||
let themeMode = $state<ThemeMode>('system');
|
||||
let serverOnline = $state(true);
|
||||
let checkingHealth = $state(true);
|
||||
|
||||
async function checkServerHealth() {
|
||||
checkingHealth = true;
|
||||
serverOnline = await checkHealth();
|
||||
checkingHealth = false;
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
themeMode = loadThemeFromStorage();
|
||||
applyThemeToDocument(themeMode);
|
||||
|
||||
// 检查服务器状态
|
||||
checkServerHealth();
|
||||
// 每 30 秒检查一次
|
||||
const healthInterval = setInterval(checkServerHealth, 30000);
|
||||
|
||||
// 监听系统主题变化
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const handleChange = () => applyThemeToDocument(themeMode);
|
||||
mediaQuery.addEventListener('change', handleChange);
|
||||
return () => mediaQuery.removeEventListener('change', handleChange);
|
||||
return () => {
|
||||
mediaQuery.removeEventListener('change', handleChange);
|
||||
clearInterval(healthInterval);
|
||||
};
|
||||
});
|
||||
|
||||
function cycleTheme() {
|
||||
@@ -78,6 +94,18 @@
|
||||
if (href === '/') return pathname === '/';
|
||||
return pathname.startsWith(href);
|
||||
}
|
||||
// 根据路径获取页面标题
|
||||
function getPageTitle(pathname: string): string {
|
||||
const titles: Record<string, string> = {
|
||||
'/': '上传账单',
|
||||
'/review': '智能复核',
|
||||
'/bills': '账单管理',
|
||||
'/analysis': '数据分析',
|
||||
'/settings': '设置',
|
||||
'/help': '帮助'
|
||||
};
|
||||
return titles[pathname] || 'BillAI';
|
||||
}
|
||||
</script>
|
||||
|
||||
<Sidebar.Provider>
|
||||
@@ -237,18 +265,32 @@
|
||||
<header class="flex h-14 shrink-0 items-center gap-2 border-b px-4">
|
||||
<Sidebar.Trigger class="-ml-1" />
|
||||
<Separator orientation="vertical" class="mr-2 h-4" />
|
||||
<div class="flex items-center gap-2">
|
||||
<Search class="size-4 text-muted-foreground" />
|
||||
<span class="text-sm text-muted-foreground">搜索...</span>
|
||||
</div>
|
||||
<div class="ml-auto flex items-center gap-2">
|
||||
<div class="flex items-center gap-1.5 text-sm">
|
||||
<span class="relative flex h-2 w-2">
|
||||
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
|
||||
<span class="relative inline-flex rounded-full h-2 w-2 bg-green-500"></span>
|
||||
</span>
|
||||
<span class="text-muted-foreground">服务运行中</span>
|
||||
</div>
|
||||
<h1 class="text-lg font-semibold">{getPageTitle($page.url.pathname)}</h1>
|
||||
<div class="flex-1" />
|
||||
<div class="flex items-center gap-3">
|
||||
<button
|
||||
class="flex items-center gap-1.5 text-sm hover:opacity-80 transition-opacity"
|
||||
onclick={checkServerHealth}
|
||||
title="点击刷新状态"
|
||||
>
|
||||
{#if checkingHealth}
|
||||
<span class="relative flex h-2 w-2">
|
||||
<span class="relative inline-flex rounded-full h-2 w-2 bg-gray-400 animate-pulse"></span>
|
||||
</span>
|
||||
<span class="text-muted-foreground">检查中...</span>
|
||||
{:else if serverOnline}
|
||||
<span class="relative flex h-2 w-2">
|
||||
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
|
||||
<span class="relative inline-flex rounded-full h-2 w-2 bg-green-500"></span>
|
||||
</span>
|
||||
<span class="text-muted-foreground">服务运行中</span>
|
||||
{:else}
|
||||
<span class="relative flex h-2 w-2">
|
||||
<span class="relative inline-flex rounded-full h-2 w-2 bg-red-500"></span>
|
||||
</span>
|
||||
<span class="text-red-500">服务离线</span>
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user