- Go 54.9%
- HTML 39.6%
- CSS 3.1%
- JavaScript 2.4%
| .idea | ||
| database | ||
| handlers | ||
| middleware | ||
| models | ||
| static | ||
| .env.exp | ||
| .gitignore | ||
| go.mod | ||
| go.sum | ||
| main.go | ||
| README.md | ||
HealthCheck
每日健康打卡系统 —— 记录健康状态,关注身体变化。
功能特性
- 多数据库支持: SQLite / MySQL / PostgreSQL / MSSQL
- 用户认证: 注册、邮箱验证、登录、忘记/重置密码
- JWT 认证: HS256 令牌,可配置过期时间
- API 令牌: 创建/查看/删除设备令牌,支持程序化访问
- 健康记录: 提交和查询心率、血氧、卡路里、步数、睡眠时长,自动刷新,折线图可视化
- 头像: Gravatar 集成(可配置镜像)+ 自定义上传(JPG/PNG/GIF, 最大 2MB)
- 邮件: SMTP(SSL 465 / STARTTLS 587),可配置发件人,调试日志
- 邮件模板: 存储在数据库中,管理员可在线编辑,支持
{{.Code}}和{{.Link}}占位符 - 管理员系统: 首个注册用户自动成为管理员;独立管理面板
- 展示卡片: 创建公开心率卡片,支持 3 种样式 + 折线图 + WebSocket 实时推送
- 超级管理员: ID=1 的用户为超级管理员,不可修改/删除
- 设备名追踪: 通过 API 令牌上传心率时自动记录设备名称
Quick Start
Prerequisites
- Go 1.22+
- SMTP server (optional, for email verification)
Setup
# Clone and enter directory
cd HealthCheck
# Copy .env and edit
cp .env.example .env
# Install dependencies
go mod tidy
# Build
go build -o healthcheck .
# Run
./healthcheck
Server starts at http://localhost:8080.
Environment Variables (.env)
| Variable | Default | Description |
|---|---|---|
DB_TYPE |
sqlite |
Database type: sqlite, mysql, postgres, mssql |
DB_DSN |
"" |
Custom DSN (leave empty for default) |
SMTP_HOST |
- | SMTP server hostname |
SMTP_PORT |
- | SMTP port (465 for SSL, 587 for STARTTLS) |
SMTP_USER |
- | SMTP authentication username |
SMTP_PASS |
- | SMTP authentication password |
SMTP_FROM |
- | From address in outgoing emails (e.g. name <email>) |
JWT_SECRET |
- | Secret key for JWT signing |
JWT_EXPIRY |
24h |
JWT token expiry duration |
SERVER_PORT |
8080 |
HTTP server port |
ADMIN_PAGE |
/manage |
Admin panel route path |
GRAVATAR_MIRROR |
https://www.gravatar.com/avatar/ |
Gravatar mirror URL |
DEBUG |
false |
Enable SMTP debug logging |
Frontend
Pages
| Route | Description |
|---|---|
/ |
Landing page |
/login.html |
Login |
/register.html |
Register |
/verify.html |
Email verification |
/forgot-password.html |
Forgot password |
/reset-password.html |
Reset password |
/dashboard.html |
Main console (profile, cards, tokens, health records) |
/manage (or ADMIN_PAGE) |
Admin panel (users, devices, records, templates) |
/card/{token} |
Public card view (heart rate badge with chart) |
Dashboard Features
- 个人信息: 展示/编辑头像、昵称、邮箱等
- 健康概览: 汇总展示最新心率、血氧、卡路里、步数、睡眠数据及来源设备
- 展示卡片: 创建公开心率卡片,支持 3 种样式和 3 种数据颗粒度,展示全部健康指标
- API 令牌: 管理设备访问令牌
- 心率记录: 实时列表(含所有指标)+ 折线图,每 5 秒自动刷新
- 管理面板入口: admin 用户可见「进入管理面板」按钮
Card Styles
| Style | 名称 | 描述 |
|---|---|---|
style1 |
深色渐变 | 深色背景 + 紫色渐变文字 + 折线图 |
style2 |
简约边框 | 白色背景 + 紫色边框 |
style3 |
渐变彩色 | 紫色渐变背景 + 白色文字 |
Card Granularity (数据颗粒度)
| Granularity | 描述 | WebSocket |
|---|---|---|
realtime |
实时最新心率 | ✅ 每 3 秒推送 |
hourly |
每小时平均 | ❌ 静态显示 |
daily |
每日平均 | ❌ 静态显示 |
Card URL format: /card/{token} — 显示 BPM、折线图、设备名、时间。
API Reference
All responses follow the format:
{
"success": true/false,
"message": "...",
"data": { ... }
}
Auth
Register
POST /api/register
Content-Type: application/json
{
"nickname": "My Server",
"email": "user@example.com",
"password": "password123"
}
Response 200:
{
"success": true,
"message": "Registered. Check your email for verification code."
}
Note: If email sending fails, the verification code is included in the message.
First registered user gets role: admin and becomes super admin (ID=1).
Verify Email
POST /api/verify-email
Content-Type: application/json
{
"email": "user@example.com",
"code": "123456"
}
Login
POST /api/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "password123"
}
Response 200:
{
"success": true,
"data": {
"token": "eyJhbGci...",
"expires_at": "2026-05-24T...",
"user_id": 1,
"nickname": "My Server",
"role": "admin"
}
}
Forgot Password
POST /api/forgot-password
Content-Type: application/json
{
"email": "user@example.com"
}
Sends a password reset link to the email.
Reset Password
POST /api/reset-password
Content-Type: application/json
{
"token": "reset-token-from-email",
"password": "newpassword123"
}
Profile
Requires Authorization: Bearer <jwt_token> header.
Get Profile
GET /api/profile
Response:
{
"success": true,
"data": {
"id": 1,
"nickname": "My Server",
"email": "user@example.com",
"email_verified": true,
"role": "admin",
"avatar_url": "https://www.gravatar.com/avatar/...",
"created_at": "2026-05-23T..."
}
}
健康记录
Requires JWT or API Token auth. API token uploads automatically record device name.
提交记录
POST /api/records
Content-Type: application/json
{
"bpm": 99,
"calories": 350.5,
"steps": 8521,
"sleep": 7.5,
"spo2": 98
}
All fields except bpm are optional. Devices can submit partial data.
查询记录
GET /api/records
Returns last 50 records with all metrics. Supports ?c=5 for custom count.
Response record format:
{
"id": 1,
"user_id": 1,
"bpm": 99,
"calories": 350.5,
"steps": 8521,
"sleep": 7.5,
"spo2": 98,
"device_name": "My Band",
"recorded_at": "...",
"created_at": "..."
}
Tokens (Device API Tokens)
Requires JWT auth.
List Tokens
GET /api/tokens
Create Token
POST /api/tokens
Content-Type: application/json
{
"name": "my-device",
"token": "optional-custom-token-string"
}
Delete Token
DELETE /api/tokens
Content-Type: application/json
{
"id": 1
}
Cards
Requires JWT auth.
List Cards
GET /api/cards
Create Card
POST /api/cards
Content-Type: application/json
{
"title": "My Health",
"style": "style1",
"granularity": "realtime"
}
Delete Card
DELETE /api/cards/{id}
View Card (Public)
GET /card/{token}
Returns an HTML page with BPM display, line chart, device name, and optional WebSocket for realtime updates.
Card WebSocket
GET /ws/card/{token}
WebSocket endpoint (only for realtime granularity cards). Pushes JSON every 3 seconds:
{
"bpm": 88,
"time": "14:30:00",
"device": "My Phone",
"spo2": 98,
"calories": 350.5,
"steps": 8521,
"sleep": 7.5
}
Avatar
Upload Avatar
Requires JWT auth.
POST /api/avatar/upload
Authorization: Bearer <jwt_token>
Content-Type: multipart/form-data
avatar: <file>
Supported formats: JPG, PNG, GIF. Max size: 2MB.
Serve Avatar
GET /api/avatar/{filename}
Avatar URL Resolution
- If user has uploaded a custom avatar:
/api/avatar/{filename} - Otherwise: Gravatar URL via configured
GRAVATAR_MIRROR
Admin
Requires JWT auth with role: admin. ID=1 is super admin and cannot be modified/deleted.
User Management
GET /api/admin/users # List all users
PUT /api/admin/users/{id} # Update user role {"role":"admin|user"}
DELETE /api/admin/users/{id} # Delete user
Device Management
GET /api/admin/devices # List all devices
DELETE /api/admin/devices/{id} # Delete device
Record Management
GET /api/admin/records # List all records (?c=50&o=0)
DELETE /api/admin/records/{id} # Delete record
Template Management
GET /api/admin/templates # List templates
GET /api/admin/templates/{name} # Get template
PUT /api/admin/templates/{name} # Update template
Request body for template update:
{
"subject": "Email Subject with {{.Code}}",
"body": "<h1>Your code: {{.Code}}</h1>"
}
Available template variables:
{{.Code}}— verification code (forverify_email){{.Link}}— reset link (forreset_password)
Default template names: verify_email, reset_password
Auth Methods
JWT Token: Include in header: Authorization: Bearer <jwt_token>
API Token: Include in header: Authorization: Bearer <api_token>
API tokens bypass email verification requirement.
Database
Default database is SQLite, stored at ./data/healthcheck.db.
Tables
| Table | Description |
|---|---|
users |
User accounts with roles |
heart_rates |
Health records with device name tracking |
devices |
API device tokens |
templates |
Email templates (admin editable) |
cards |
Public shareable heart rate cards |
Supported databases:
| DB_TYPE | Driver | Default DSN |
|---|---|---|
sqlite |
modernc.org/sqlite | ./data/healthcheck.db |
mysql |
go-sql-driver/mysql | user:password@tcp(localhost:3306)/healthcheck |
postgres |
lib/pq | host=127.0.0.1 dbname=healthcheck user=postgres password=password sslmode=disable |
mssql |
go-mssqldb | server=127.0.0.1;database=healthcheck;user id=sa;password=password; |
Project Structure
├── main.go # Entry point, route registration
├── .env # Configuration
├── database/
│ ├── database.go # Multi-dialect init, DDL, migrations
│ ├── users.go # User CRUD
│ ├── heart.go # Health record CRUD
│ ├── devices.go # Device token CRUD
│ ├── templates.go # Email template CRUD
│ ├── cards.go # Card CRUD
│ └── admin.go # Admin user/device/record queries
├── models/
│ └── models.go # Data structures, request/response types
├── handlers/
│ ├── auth.go # Register, verify, login, forgot/reset, profile
│ ├── heartbeat.go # Health record submit + query
│ ├── avatar.go # Gravatar + upload + serve
│ ├── token.go # Device token management
│ ├── admin.go # Template management
│ ├── admin_users.go # Admin users/devices/records CRUD
│ ├── card.go # Card CRUD + public card view
│ └── ws.go # WebSocket hub + card broadcast
├── middleware/
│ └── jwt.go # JWT generate/parse, Auth/Admin middleware, CORS
├── email/
│ └── email.go # SMTP (SSL + STARTTLS), template rendering
└── static/
├── index.html # Landing page
├── login.html # Login
├── register.html # Register
├── verify.html # Email verification
├── forgot-password.html
├── reset-password.html
├── dashboard.html # Main console (profile, cards, tokens, records)
├── admin.html # Admin panel (users, devices, records, templates)
├── css/style.css
└── js/api.js