mirror of
https://github.com/patdelphi/suanming.git
synced 2026-02-28 05:33:11 +08:00
feat: 完成从Supabase到本地化架构的迁移\n\n- 添加本地SQLite数据库支持\n- 实现本地认证系统(JWT + bcrypt)\n- 创建Express.js API服务器\n- 实现完整的命理分析算法\n- 替换Supabase客户端为本地API客户端\n- 保持前端接口兼容性\n- 添加本地服务器启动脚本
This commit is contained in:
111
server/database.js
Normal file
111
server/database.js
Normal file
@@ -0,0 +1,111 @@
|
||||
import Database from 'better-sqlite3';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// 创建数据库连接
|
||||
const dbPath = path.join(__dirname, '..', 'numerology.db');
|
||||
const db = new Database(dbPath);
|
||||
|
||||
// 启用外键约束
|
||||
db.pragma('foreign_keys = ON');
|
||||
|
||||
// 创建用户表
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
full_name TEXT,
|
||||
birth_date DATE,
|
||||
birth_time TIME,
|
||||
birth_place TEXT,
|
||||
gender TEXT CHECK (gender IN ('male', 'female')),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`);
|
||||
|
||||
// 创建分析记录表
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS readings (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
reading_type TEXT NOT NULL CHECK (reading_type IN ('bazi', 'ziwei', 'yijing', 'wuxing')),
|
||||
name TEXT,
|
||||
birth_date DATE,
|
||||
birth_time TIME,
|
||||
gender TEXT CHECK (gender IN ('male', 'female')),
|
||||
birth_place TEXT,
|
||||
input_data TEXT,
|
||||
results TEXT,
|
||||
analysis TEXT,
|
||||
status TEXT DEFAULT 'completed' CHECK (status IN ('pending', 'processing', 'completed', 'failed')),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
// 创建索引
|
||||
db.exec(`
|
||||
CREATE INDEX IF NOT EXISTS idx_readings_user_id ON readings(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_readings_type ON readings(reading_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_readings_created_at ON readings(created_at DESC);
|
||||
`);
|
||||
|
||||
// 数据库操作函数
|
||||
export const dbOperations = {
|
||||
// 用户相关操作
|
||||
createUser: db.prepare(`
|
||||
INSERT INTO users (email, password, full_name, birth_date, birth_time, birth_place, gender)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`),
|
||||
|
||||
getUserByEmail: db.prepare('SELECT * FROM users WHERE email = ?'),
|
||||
|
||||
getUserById: db.prepare('SELECT id, email, full_name, birth_date, birth_time, birth_place, gender, created_at FROM users WHERE id = ?'),
|
||||
|
||||
updateUser: db.prepare(`
|
||||
UPDATE users
|
||||
SET full_name = ?, birth_date = ?, birth_time = ?, birth_place = ?, gender = ?, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?
|
||||
`),
|
||||
|
||||
// 分析记录相关操作
|
||||
createReading: db.prepare(`
|
||||
INSERT INTO readings (user_id, reading_type, name, birth_date, birth_time, gender, birth_place, input_data, results, analysis)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`),
|
||||
|
||||
getReadingsByUserId: db.prepare(`
|
||||
SELECT * FROM readings
|
||||
WHERE user_id = ?
|
||||
ORDER BY created_at DESC
|
||||
`),
|
||||
|
||||
getReadingsByUserIdAndType: db.prepare(`
|
||||
SELECT * FROM readings
|
||||
WHERE user_id = ? AND reading_type = ?
|
||||
ORDER BY created_at DESC
|
||||
`),
|
||||
|
||||
getReadingById: db.prepare('SELECT * FROM readings WHERE id = ?'),
|
||||
|
||||
deleteReading: db.prepare('DELETE FROM readings WHERE id = ? AND user_id = ?'),
|
||||
|
||||
// 统计信息
|
||||
getUserReadingCount: db.prepare('SELECT COUNT(*) as count FROM readings WHERE user_id = ?'),
|
||||
|
||||
getReadingCountByType: db.prepare('SELECT reading_type, COUNT(*) as count FROM readings WHERE user_id = ? GROUP BY reading_type')
|
||||
};
|
||||
|
||||
// 优雅关闭数据库连接
|
||||
process.on('exit', () => db.close());
|
||||
process.on('SIGHUP', () => process.exit(128 + 1));
|
||||
process.on('SIGINT', () => process.exit(128 + 2));
|
||||
process.on('SIGTERM', () => process.exit(128 + 15));
|
||||
|
||||
export default db;
|
||||
Reference in New Issue
Block a user