# 《WaLiAPI - 本地 LLM API 网关》第2-4节:前端页面开发

作者:小傅哥
博客:https://bugstack.cn (opens new window)

沉淀、分享、成长,让自己和他人都能有所收获!😄

大家好,我是技术UP主小傅哥。

后端功能已经完备,这一节我们来完成前端界面。前端主要使用 AI IDE 工具生成(AI 新范式编程),本节的重点是:理解页面架构、掌握与后端命令的对接方式、学会用提示词驱动 AI 完成页面开发

# 一、本章诉求

  1. 搭建布局框架(Sidebar + 内容区)
  2. 完成六个页面:仪表盘、渠道、密钥、日志、用量、设置
  3. 封装 Tauri 命令调用层
  4. 掌握 AI 辅助前端开发的话术与验证方法

# 二、页面架构设计

# 2.1 整体布局

┌────────────────────────────────────────────────┐
│ ┌─────────┐ ┌────────────────────────────────┐ │
│ │ Sidebar │ │                                │ │
│ │ ─────── │ │        页面内容区                │ │
│ │ 仪表盘   │ │   (DashboardPage)              │ │
│ │ 用量    │ │   (UsagePage)                  │ │
│ │ 渠道    │ │   (ChannelsPage)               │ │
│ │ 密钥    │ │   (ApiKeysPage)                │ │
│ │ 日志    │ │   (LogsPage)                   │ │
│ │ 设置    │ │   (SettingsPage)               │ │
│ │ ─────── │ │                                │ │
│ │ 服务状态 │ │                                │ │
│ └─────────┘ └────────────────────────────────┘ │
└────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2.2 布局组件

src/components/layout/Layout.tsx

import { ReactNode } from "react";
import { Sidebar } from "./Sidebar";

export function Layout({ children }: { children: ReactNode }) {
  return (
    <div className="flex h-screen bg-background text-foreground">
      <Sidebar />
      <main className="flex-1 overflow-auto">{children}</main>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11

src/components/layout/Sidebar.tsx 核心结构:

import { NavLink } from "react-router-dom";
import { LayoutDashboard, BarChart3, Radio, Key, ScrollText, Settings } from "lucide-react";

const menuItems = [
  { path: "/", icon: LayoutDashboard, label: "仪表盘" },
  { path: "/usage", icon: BarChart3, label: "用量" },
  { path: "/channels", icon: Radio, label: "渠道" },
  { path: "/api-keys", icon: Key, label: "密钥" },
  { path: "/logs", icon: ScrollText, label: "日志" },
  { path: "/settings", icon: Settings, label: "设置" },
];

export function Sidebar() {
  return (
    <aside className="w-56 border-r border-border flex flex-col">
      <div className="p-4 font-bold text-lg">WaLiAPI</div>
      <nav className="flex-1 px-2 space-y-1">
        {menuItems.map((item) => (
          <NavLink
            key={item.path}
            to={item.path}
            className={({ isActive }) =>
              `flex items-center gap-3 px-3 py-2 rounded-lg transition-colors ${
                isActive ? "bg-accent text-accent-foreground" : "hover:bg-accent/50"
              }`
            }
          >
            <item.icon size={18} />
            <span>{item.label}</span>
          </NavLink>
        ))}
      </nav>
      {/* 底部:服务器运行状态指示(监听 server-started 事件) */}
    </aside>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36