简单高效的个人财务管理工具
在线演示 • 功能特性 • 快速开始 • Docker 部署 • 技术文档
PayNote 是一款免费开源的在线记账应用,帮助您轻松管理个人财务。支持 Docker 一键部署,数据完全由您掌控。
- 用户认证 - 安全的注册、登录系统
- 收支记录 - 记录每一笔收入和支出
- 分类管理 - 系统预设分类 + 自定义分类
- 预算管理 - 设置月度/季度/年度预算,实时追踪
- 统计报表 - 可视化图表展示财务状况
- 个人设置 - 自定义头像、修改密码
- 前端框架: Next.js 16 (App Router)
- UI 组件: shadcn/ui + Tailwind CSS
- 数据库: PostgreSQL 16
- ORM: Prisma 6
- 认证: NextAuth.js v5
- 图表: Recharts
- 表单验证: Zod 4
- Node.js 20+
- PostgreSQL 14+
- npm
- 克隆项目
git clone https://github.com/YforC/paynote.git
cd paynote- 安装依赖
npm install- 配置环境变量
cp .env.example .env编辑 .env 文件:
DATABASE_URL="postgresql://postgres:password@localhost:5432/paynote?schema=public"
AUTH_SECRET="your-secret-key-at-least-32-characters"
NEXTAUTH_URL="http://localhost:3000"- 初始化数据库
npx prisma migrate dev
npx prisma db seed- 启动开发服务器
npm run dev| 配置项 | 最低要求 | 推荐配置 |
|---|---|---|
| CPU | 1 核 | 2 核 |
| 内存 | 1 GB | 2 GB |
| 硬盘 | 10 GB SSD | 20 GB SSD |
| 系统 | Debian 12 / Ubuntu 22.04 | - |
apt update && apt upgrade -y
apt install -y docker.io docker-compose-plugin
systemctl enable docker
systemctl start dockermkdir -p ~/paynote && cd ~/paynotecat > docker-compose.yml << 'EOF'
services:
postgres:
image: postgres:16-alpine
container_name: paynote-db
restart: unless-stopped
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: paynote
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
migrate:
image: ${DOCKER_IMAGE_MIGRATE}
container_name: paynote-migrate
environment:
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/paynote?schema=public
depends_on:
postgres:
condition: service_healthy
app:
image: ${DOCKER_IMAGE}
container_name: paynote-app
restart: unless-stopped
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/paynote?schema=public
AUTH_SECRET: ${AUTH_SECRET}
NEXTAUTH_URL: ${NEXTAUTH_URL}
AUTH_TRUST_HOST: "true"
depends_on:
postgres:
condition: service_healthy
migrate:
condition: service_completed_successfully
volumes:
postgres_data:
EOFcat > .env << 'EOF'
DOCKER_IMAGE=你的DockerHub用户名/paynote:latest
DOCKER_IMAGE_MIGRATE=你的DockerHub用户名/paynote:migrate
POSTGRES_PASSWORD=设置一个强密码
AUTH_SECRET=用下面命令生成
NEXTAUTH_URL=http://你的服务器IP:3000
EOF生成 AUTH_SECRET:
openssl rand -base64 32编辑 .env 填写实际值:
nano .envdocker compose pull
docker compose up -d首次部署需要插入系统预设分类:
docker compose exec postgres psql -U postgres -d paynote -c "
INSERT INTO \"Category\" (\"id\", \"userId\", \"name\", \"type\", \"icon\", \"color\", \"isSystem\", \"createdAt\") VALUES
(gen_random_uuid()::text, NULL, '餐饮', 'EXPENSE', '🍽️', '#ef4444', true, NOW()),
(gen_random_uuid()::text, NULL, '交通', 'EXPENSE', '🚗', '#f97316', true, NOW()),
(gen_random_uuid()::text, NULL, '购物', 'EXPENSE', '🛒', '#eab308', true, NOW()),
(gen_random_uuid()::text, NULL, '娱乐', 'EXPENSE', '🎮', '#22c55e', true, NOW()),
(gen_random_uuid()::text, NULL, '居住', 'EXPENSE', '🏠', '#14b8a6', true, NOW()),
(gen_random_uuid()::text, NULL, '通讯', 'EXPENSE', '📱', '#06b6d4', true, NOW()),
(gen_random_uuid()::text, NULL, '医疗', 'EXPENSE', '🏥', '#3b82f6', true, NOW()),
(gen_random_uuid()::text, NULL, '教育', 'EXPENSE', '📚', '#8b5cf6', true, NOW()),
(gen_random_uuid()::text, NULL, '服饰', 'EXPENSE', '👔', '#d946ef', true, NOW()),
(gen_random_uuid()::text, NULL, '其他支出', 'EXPENSE', '📦', '#6b7280', true, NOW()),
(gen_random_uuid()::text, NULL, '工资', 'INCOME', '💰', '#22c55e', true, NOW()),
(gen_random_uuid()::text, NULL, '奖金', 'INCOME', '🎁', '#14b8a6', true, NOW()),
(gen_random_uuid()::text, NULL, '投资', 'INCOME', '📈', '#3b82f6', true, NOW()),
(gen_random_uuid()::text, NULL, '兼职', 'INCOME', '💼', '#8b5cf6', true, NOW()),
(gen_random_uuid()::text, NULL, '红包', 'INCOME', '🧧', '#ef4444', true, NOW()),
(gen_random_uuid()::text, NULL, '其他收入', 'INCOME', '💵', '#6b7280', true, NOW());
"# 查看服务状态
docker compose ps
# 查看应用日志
docker compose logs -f app访问 http://你的服务器IP:3000
# 查看服务状态
docker compose ps
# 启动服务
docker compose up -d
# 停止服务
docker compose down
# 重启服务
docker compose restart
# 查看日志
docker compose logs -f app
docker compose logs -f postgrescd ~/paynote
docker compose pull
docker compose up -d# 进入数据库
docker compose exec postgres psql -U postgres -d paynote
# 查看所有表
docker compose exec postgres psql -U postgres -d paynote -c "\dt"
# 查看分类数据
docker compose exec postgres psql -U postgres -d paynote -c "SELECT * FROM \"Category\";"
# 备份数据库
docker compose exec postgres pg_dump -U postgres paynote > backup_$(date +%Y%m%d).sql
# 恢复数据库
docker compose exec -T postgres psql -U postgres -d paynote < backup.sql# 停止并删除容器(保留数据)
docker compose down
# 停止并删除所有数据(慎用!)
docker compose down -v
# 清理未使用的镜像
docker image prune- 安装 Nginx 和 Certbot:
apt install -y nginx certbot python3-certbot-nginx- 创建 Nginx 配置:
cat > /etc/nginx/sites-available/paynote << 'EOF'
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
EOF
ln -s /etc/nginx/sites-available/paynote /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx- 获取 SSL 证书:
certbot --nginx -d your-domain.com- 更新 .env 中的 NEXTAUTH_URL:
NEXTAUTH_URL=https://your-domain.com- 重启应用:
docker compose restart appfallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstabpaynote/
├── prisma/ # Prisma 配置和迁移
│ ├── schema.prisma # 数据库模型
│ ├── seed.ts # 种子数据
│ └── migrations/ # 迁移文件
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (auth)/ # 认证页面(登录、注册)
│ │ ├── (dashboard)/ # 主应用页面
│ │ └── api/ # API 路由
│ ├── components/ # React 组件
│ ├── actions/ # Server Actions
│ └── lib/ # 工具函数和配置
├── docker-compose.yml # Docker Compose 配置
├── Dockerfile # 应用 Dockerfile
└── Dockerfile.migrate # 迁移 Dockerfile
MIT License