🏁 Final commit: Project Token Usage Viewer completed

This commit is contained in:
2026-01-21 14:21:43 +08:00
parent b967deb4b1
commit a77fcdd3dc
24 changed files with 1087 additions and 651 deletions

363
README.md
View File

@@ -1,18 +1,29 @@
# Fullstack Starter (SQLite)
# Token Usage Viewer
一个基于 **TanStack Start + Bun + Tauri + SQLite**全栈桌面应用脚手架
一个基于 **TanStack Start + Bun + Tauri** 的桌面应用,用于监控 Claude API 账户的 Token 配额使用情况
包含一个完整的 **Todo List** 示例,展示了从前端到后端的完整数据流
采用 [OpenBridge Design System](https://github.com/oicl/openbridge-webcomponents) 设计规范,提供专业的航海仪表盘风格界面
## 功能特点
- **实时配额监控**: 显示 4 个账户的 Claude Opus 4.5 (Thinking) 模型配额使用情况
- **可视化仪表盘**: Apple Health 风格的圆环进度指示器
- **智能告警系统**:
- 当配额剩余 < 20% 时显示警告 (Warning)
- 当配额剩余 < 5% 时显示紧急告警 (Alarm)
- **主题切换**: 支持白天/夜间模式切换
- **自动刷新**: 配额数据每 5 分钟自动刷新
- **倒计时显示**: 显示配额重置剩余时间
## 技术栈
| 层级 | 技术 |
|------|------|
| 前端框架 | React 19 + TanStack Router (文件路由) |
| 前端框架 | React 19 + TanStack Router |
| UI 组件 | OpenBridge Web Components |
| 状态管理 | TanStack Query |
| 样式 | Tailwind CSS v4 |
| RPC 通信 | ORPC (类型安全,契约优先) |
| 数据库 | SQLite (Bun 内置) + Drizzle ORM |
| RPC 通信 | ORPC (类型安全) |
| 桌面壳 | Tauri v2 |
| 运行时 | Bun |
| 构建 | Vite + Turbo |
@@ -22,22 +33,19 @@
### 前置要求
- [Bun](https://bun.sh/) >= 1.0
- [Rust](https://www.rust-lang.org/) (Tauri 桌面应用需要)
- [Rust](https://www.rust-lang.org/) (Tauri 桌面应用需要)
### 安装与运行
```bash
# 1. 克隆项目
git clone <your-repo-url>
cd fullstack-starter-SQLite
cd openbridge-token-usage-viewer
# 2. 安装依赖
bun install
# 3. 初始化数据库
bun run db:init
# 4. 启动开发服务器
# 3. 启动开发服务器
bun run dev:vite # 仅 Web (http://localhost:3000)
bun run dev # Tauri 桌面应用 + Web
```
@@ -49,194 +57,165 @@ bun run build:vite # 构建 Web 版本
bun run build # 构建 Tauri 桌面安装包
```
构建产物位置:
- **MSI 安装包**: `src-tauri/target/release/bundle/msi/app-desktop_0.1.0_x64_en-US.msi`
- **NSIS 安装包**: `src-tauri/target/release/bundle/nsis/app-desktop_0.1.0_x64-setup.exe`
## 配置
### 环境变量
应用会按以下优先级读取 `TOKEN_USAGE_URL` 配置:
1. **系统环境变量** (最高优先级)
2. **可执行文件同目录的 `.env` 文件**
3. **默认值**: `http://10.0.1.1:8318/usage`
#### 方式 1: 环境变量
```bash
# Windows PowerShell
$env:TOKEN_USAGE_URL = "http://your-server:8318/usage"
.\app-desktop.exe
# Linux/macOS
TOKEN_USAGE_URL=http://your-server:8318/usage ./app-desktop
```
#### 方式 2: 配置文件
在可执行文件同目录创建 `.env` 文件:
```env
TOKEN_USAGE_URL=http://your-server:8318/usage
```
## 常用命令
| 命令 | 说明 |
|------|------|
| `bun dev` | 启动 Tauri + Vite 开发服务器 |
| `bun dev:vite` | 仅启动 Vite 开发服务器 |
| `bun dev:tauri` | 仅启动 Tauri (需先启动 Vite) |
| `bun build` | 完整构建 (Tauri 桌面应用) |
| `bun build:vite` | 仅构建 Web 版本 |
| `bun typecheck` | TypeScript 类型检查 |
| `bun fix` | 自动修复格式和 Lint 问题 |
## 故障排除
### 清理缓存与重置
如果遇到构建问题、端口占用或缓存问题,按以下步骤重置:
#### 1. 结束所有相关进程
```powershell
# Windows PowerShell (管理员)
taskkill /F /IM "app.exe" 2>$null
taskkill /F /IM "app-desktop.exe" 2>$null
taskkill /F /IM "bun.exe" 2>$null
taskkill /F /IM "node.exe" 2>$null
```
```bash
# Linux/macOS
pkill -f "app-desktop" || true
pkill -f "bun" || true
```
#### 2. 清除所有缓存
```bash
# Turbo 缓存
rm -rf .turbo
# Vite 缓存
rm -rf node_modules/.vite
rm -rf node_modules/.cache
# 构建输出
rm -rf .output
# Tauri sidecar binaries
rm -rf src-tauri/binaries/app-*
```
#### 3. 完全清理 (可选,需要重新编译 Rust耗时 2-5 分钟)
```bash
# 清除 Rust 编译缓存
rm -rf src-tauri/target
```
#### 4. 确认端口已释放
```bash
# Windows
netstat -ano | findstr :3000
# Linux/macOS
lsof -i :3000
```
#### 5. 重新构建
```bash
bun run build
```
### 常见问题
#### "An unhandled error happened!" 错误
1. 确保没有其他进程占用端口 3000
2. 尝试完全清理缓存后重新构建
3. 检查 `.env` 文件中的 `TOKEN_USAGE_URL` 配置是否正确
#### 端口被占用 (EADDRINUSE)
```powershell
# 查找占用端口的进程
netstat -ano | findstr :3000
# 结束进程 (替换 PID 为实际进程 ID)
taskkill /F /PID <PID>
```
#### MSI 安装后无法运行
1. 卸载旧版本: 控制面板 → 程序和功能 → 卸载 app-desktop
2. 重新安装新的 MSI
3. 确保安装目录有写入权限
## 项目结构
```
├── src/
│ ├── components/ # 可复用组件
│ │ ├── Error.tsx # 错误边界组件
│ │ ── NotFound.tsx # 404 页面组件
│ │
│ ├── db/ # 数据库层
│ │ ── index.ts # 数据库连接
│ └── schema/ # Drizzle 表定义
│ │ ├── index.ts # Schema 导出入口
│ │ └── todo.ts # Todo 表定义
│ ├── orpc/ # RPC 层 (后端 API)
│ │ ── contracts/ # 契约定义 (输入/输出 Schema)
└── todo.ts # Todo API 契约
│ │ ├── handlers/ # 业务逻辑实现
│ │ │ └── todo.ts # Todo CRUD 处理器
│ │ ├── middlewares/ # 中间件
│ │ │ └── db.ts # 数据库注入中间件
│ │ ├── contract.ts # 契约聚合
│ │ ├── router.ts # 路由聚合
│ │ ├── client.ts # 同构客户端 (SSR/CSR)
│ │ ├── server.ts # 服务端实例
│ │ └── index.ts # 导出入口
│ │
│ ├── routes/ # 页面路由 (文件路由)
│ │ ├── __root.tsx # 根布局
│ │ ├── index.tsx # 首页 (Todo List)
│ │ └── api/
│ │ └── rpc.$.ts # RPC HTTP 端点
│ │
│ ├── integrations/ # 第三方库集成
│ ├── lib/ # 工具函数
│ ├── env.ts # 环境变量验证
│ ├── router.tsx # 路由配置
│ └── styles.css # 全局样式
│ ├── components/
│ │ ├── HealthRing.tsx # 圆环进度指示器
│ │ ── TokenUsageDashboard.tsx # 主仪表盘
│ │ └── ...
│ ├── hooks/
│ │ ── useTheme.ts # 主题切换 Hook
├── orpc/
│ │ ├── contracts/usage.ts # API 契约
│ │ └── handlers/usage.ts # 数据获取逻辑
├── routes/
│ ├── __root.tsx # 根布局
│ │ ── index.tsx # 首页
└── env.ts # 环境变量配置
├── scripts/
── init-db.ts # 数据库初始化脚本
├── src-tauri/ # Tauri 桌面应用
── src/
│ │ ├── lib.rs # Tauri 入口
│ │ └── sidecar.rs # Sidecar 管理
│ ├── binaries/ # 编译后的 sidecar
│ └── tauri.conf.json # Tauri 配置
── src-tauri/ # Tauri 桌面应用配置
├── data/ # SQLite 数据库文件 (gitignore)
└── drizzle.config.ts # Drizzle 配置
── .output/ # Vite 构建输出
```
## 开发指南
### 添加新功能的步骤
以添加一个 "Note" 功能为例:
#### 1. 定义数据库 Schema
```typescript
// src/db/schema/note.ts
import { sql } from 'drizzle-orm'
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
export const noteTable = sqliteTable('note', {
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
content: text('content').notNull(),
createdAt: integer('created_at', { mode: 'timestamp' })
.notNull()
.default(sql`(unixepoch())`),
})
```
```typescript
// src/db/schema/index.ts
export * from './todo.ts'
export * from './note.ts' // 添加导出
```
#### 2. 定义 API 契约
```typescript
// src/orpc/contracts/note.ts
import { oc } from '@orpc/contract'
import { z } from 'zod'
export const note = {
list: oc.output(z.array(noteSchema)),
create: oc.input(z.object({ content: z.string() })).output(noteSchema),
}
```
#### 3. 实现业务逻辑
```typescript
// src/orpc/handlers/note.ts
import { os } from '@/orpc/server'
import { dbProvider } from '@/orpc/middlewares/db'
import { noteTable } from '@/db/schema'
export const list = os.note.list
.use(dbProvider)
.handler(async ({ context }) => {
return context.db.select().from(noteTable)
})
export const create = os.note.create
.use(dbProvider)
.handler(async ({ context, input }) => {
const [note] = await context.db.insert(noteTable).values(input).returning()
return note
})
```
#### 4. 注册到路由
```typescript
// src/orpc/contract.ts
import { note } from './contracts/note'
export const contract = { todo, note }
// src/orpc/router.ts
import * as note from './handlers/note'
export const router = os.router({ todo, note })
```
#### 5. 在页面中使用
```typescript
// src/routes/notes.tsx
import { orpc } from '@/orpc'
import { useSuspenseQuery, useMutation } from '@tanstack/react-query'
const NotesPage = () => {
const { data: notes } = useSuspenseQuery(orpc.note.list.queryOptions())
const createNote = useMutation(orpc.note.create.mutationOptions())
// ...
}
```
### 常用命令
| 命令 | 说明 |
|------|------|
| `bun run dev` | 启动 Tauri + Vite 开发服务器 |
| `bun run dev:vite` | 仅启动 Vite 开发服务器 |
| `bun run build` | 完整构建 (Tauri 桌面应用) |
| `bun run build:vite` | 仅构建 Web 版本 |
| `bun run db:init` | 初始化/重置数据库 |
| `bun run db:studio` | 打开 Drizzle Studio |
| `bun run typecheck` | TypeScript 类型检查 |
| `bun run fix` | 自动修复格式和 Lint 问题 |
### 代码规范
- **格式化**: 使用 Biome2 空格缩进,单引号
- **导入**: 使用 `@/*` 路径别名
- **组件**: 箭头函数组件
- **命名**: 文件 kebab-case组件 PascalCase
## 核心概念
### ORPC 数据流
```
前端组件
↓ useSuspenseQuery / useMutation
ORPC 客户端 (src/orpc/client.ts)
↓ 自动选择 SSR 直调 / CSR HTTP
契约验证 (src/orpc/contracts/)
↓ 输入/输出类型安全
处理器 (src/orpc/handlers/)
↓ 业务逻辑
中间件 (src/orpc/middlewares/)
↓ 注入数据库连接
Drizzle ORM
↓ 类型安全查询
SQLite 数据库
```
### 同构渲染
- **SSR**: 服务端直接调用 router无 HTTP 开销
- **CSR**: 客户端通过 `/api/rpc` 端点调用
### 数据库
- SQLite 文件存储在 `./data/app.db`
- 使用 WAL 模式提高并发性能
- 单例模式管理连接
## 许可证
MIT