Omniledger 跨界记账中枢
项目介绍
Omniledger 是一款专业的跨境外汇投资组合追踪应用,帮助用户管理多币种资产组合,支持股票、加密货币和现金的全面持仓管理。系统采用高精度数值计算,确保金融数据计算的准确性。
核心优势
| 特性 |
说明 |
| 多资产类型 |
股票、加密货币、现金全覆盖 |
| 多币种管理 |
支持 USD/HKD/CNY/JPY 等多币种交易和换算 |
| 高精度计算 |
采用 Big.js 确保金融计算精度(36位精度,18位小数) |
| 实时持仓 |
自动聚合交易记录生成持仓报告 |
| 历史走势 |
每日快照记录,净值曲线可视化 |
| 主题切换 |
浅色/深色模式,流畅过渡动画 |
功能特性
仪表盘
- 总资产概览(人民币计价)
- 持仓盈亏与总盈亏实时计算
- 净值走势图表(Recharts 实现)
- 资产分布饼图
持仓明细
- 支持展开/收起每项资产的流水明细
- 显示:现价、市值、持仓量、摊薄成本、平均成本
- 浮动盈亏与累计盈亏(金额 + 百分比)
- 一键导出 CSV
交易记录
- 支持交易类型:买入(BUY)、卖出(SELL)、分红(DIVIDEND)、空投(AIRDROP)、手续费(FEE)
- 高精度数值存储
- 支持修改和删除交易
资产管理
- 添加/查看资产(STOCK/CRYPTO/CASH 三种类型)
- 统一的资产符号体系
- 批量导入历史价格
历史数据
- 自动记录每日组合快照
- 重构历史走势功能
- 支持导入历史价格数据
技术栈
前端
| 技术 |
版本 |
用途 |
| Next.js |
16.2.4 |
React 框架 |
| React |
19.2.4 |
UI 库 |
| TypeScript |
5.x |
类型安全 |
| Tailwind CSS |
3.4.17 |
样式框架 |
| Radix UI |
- |
UI 组件底层 |
| React Hook Form |
7.74.0 |
表单处理 |
| Zod |
4.3.6 |
数据验证 |
| Recharts |
3.8.1 |
图表库 |
| Lucide React |
1.11.0 |
图标库 |
| Sonner |
2.0.7 |
Toast 提示 |
后端
| 技术 |
版本 |
用途 |
| PostgreSQL |
16.0 |
数据库 |
| Drizzle ORM |
0.45.2 |
ORM 框架 |
| Big.js |
7.0.1 |
高精度计算 |
| Drizzle Kit |
0.31.10 |
数据库迁移 |
快速开始
环境要求
- Node.js 20+
- PostgreSQL 数据库
- npm / yarn / pnpm / bun
安装步骤
# 克隆项目
git clone <repository-url>
cd stock-portfolio_byQwen3.6
# 安装依赖
npm install
# 配置环境变量
cp .env.example .env.local
# 编辑 .env.local,配置数据库连接
# 数据库初始化
npm run db:generate # 生成迁移文件
npm run db:push # 推送 schema 到数据库
# 启动开发服务器
npm run dev
打开 http://localhost:3000 即可访问。
可用命令
| 命令 |
说明 |
npm run dev |
启动开发服务器 |
npm run build |
构建生产版本 |
npm run start |
启动生产服务器 |
npm run lint |
运行 ESLint 检查 |
npm run db:generate |
生成数据库迁移 |
npm run db:push |
推送数据库 Schema |
npm run db:studio |
打开 Drizzle Studio |
快速部署
Docker Compose
# 构建并启动
docker-compose up -d
# 查看日志
docker-compose logs -f
访问 http://localhost:8080
环境变量
DATABASE_URL=postgresql://user:password@localhost:5432/omniledger
项目结构
├── app/ # Next.js App Router
│ ├── dashboard/ # 仪表盘页面
│ │ ├── page.tsx # 持仓总览
│ │ ├── assets/page.tsx # 资产管理
│ │ ├── transactions/page.tsx # 交易历史
│ │ └── layout.tsx # 仪表盘布局
│ ├── layout.tsx # 根布局
│ ├── page.tsx # 根页面(重定向)
│ └── globals.css # 全局样式
├── src/
│ ├── actions/ # Server Actions
│ │ ├── asset.ts # 资产操作
│ │ ├── transaction.ts # 交易操作
│ │ ├── portfolio.ts # 持仓计算
│ │ ├── snapshots.ts # 组合快照
│ │ ├── exchange.ts # 汇率
│ │ └── market.ts # 市场数据
│ ├── components/
│ │ ├── dashboard/ # 仪表盘组件
│ │ │ ├── allocation-chart.tsx
│ │ │ └── net-worth-chart.tsx
│ │ ├── assets/ # 资产相关组件
│ │ ├── transactions/ # 交易相关组件
│ │ └── ui/ # shadcn/ui 组件
│ ├── db/
│ │ ├── index.ts # Drizzle 客户端
│ │ └── schema.ts # 数据库 Schema
│ └── lib/
│ ├── formatters.ts # 格式化工具
│ └── utils.ts # 通用工具
├── drizzle/ # 数据库迁移文件
├── scripts/ # 辅助脚本
├── public/ # 静态资源
└── package.json
数据库设计
表结构
users 用户表
| 字段 |
类型 |
说明 |
| id |
UUID |
主键 |
| username |
VARCHAR(50) |
用户名(唯一) |
| password_hash |
VARCHAR(255) |
密码哈希 |
| created_at |
TIMESTAMP |
创建时间 |
assets 资产表
| 字段 |
类型 |
说明 |
| id |
UUID |
主键 |
| symbol |
VARCHAR(20) |
资产符号(唯一) |
| name |
VARCHAR(100) |
资产名称 |
| type |
ENUM |
STOCK/CRYPTO/CASH |
| exchange |
VARCHAR(10) |
交易所(默认 US) |
| baseCurrency |
VARCHAR(10) |
基础货币 |
| latestPrice |
NUMERIC(36,18) |
最新价格 |
| created_at |
TIMESTAMP |
创建时间 |
transactions 交易表
| 字段 |
类型 |
说明 |
| id |
UUID |
主键 |
| assetId |
UUID |
关联资产 |
| txType |
ENUM |
BUY/SELL/DIVIDEND/AIRDROP/FEE |
| quantity |
NUMERIC(36,18) |
数量 |
| price |
NUMERIC(36,18) |
价格 |
| fee |
NUMERIC(36,18) |
手续费 |
| txCurrency |
VARCHAR(10) |
交易货币 |
| exchangeRate |
NUMERIC(20,8) |
汇率 |
| executedAt |
TIMESTAMP |
执行时间 |
| createdAt |
TIMESTAMP |
创建时间 |
exchange_rates 汇率表
| 字段 |
类型 |
说明 |
| id |
UUID |
主键 |
| fromCurrency |
VARCHAR(10) |
源货币 |
| toCurrency |
VARCHAR(10) |
目标货币 |
| rate |
NUMERIC(20,8) |
汇率 |
| updatedAt |
TIMESTAMP |
更新时间 |
portfolio_snapshots 组合快照表
| 字段 |
类型 |
说明 |
| id |
UUID |
主键 |
| date |
DATE |
日期(唯一) |
| totalValueCny |
NUMERIC(36,18) |
总值(CNY) |
| totalCostCny |
NUMERIC(36,18) |
总成本(CNY) |
| createdAt |
TIMESTAMP |
创建时间 |
| updatedAt |
TIMESTAMP |
更新时间 |
asset_prices_history 资产价格历史
| 字段 |
类型 |
说明 |
| id |
UUID |
主键 |
| assetId |
UUID |
关联资产 |
| price |
NUMERIC(36,18) |
价格 |
| date |
DATE |
日期 |
| updateTime |
TIMESTAMP |
更新时间 |
exchange_rates_history 汇率历史
| 字段 |
类型 |
说明 |
| id |
UUID |
主键 |
| fromCurrency |
VARCHAR(10) |
源货币 |
| toCurrency |
VARCHAR(10) |
目标货币 |
| rate |
NUMERIC(20,8) |
汇率 |
| fetchTime |
TIMESTAMP |
抓取时间 |
开发指南
添加新资产
- 进入「资产管理」页面
- 点击「添加资产」按钮
- 填写资产信息(符号、名称、类型、基础货币)
- 提交保存
记录交易
- 在「持仓总览」中点击资产的「添加」按钮
- 选择交易类型(买入/卖出/分红/空投/手续费)
- 填写交易详情(数量、价格、手续费、日期等)
- 提交保存
导入历史价格
- 在「持仓总览」中点击资产的「导入价格」按钮
- 从 Excel 复制粘贴数据,格式:
日期, 价格(每行一条)
- 点击开始导入
主题切换
点击页面右上角主题切换按钮,可在浅色/深色模式间切换。
许可证
MIT License