Files
happy-export/backend/db/db.js
T
Drsakura b9d6296591 feat(workspace): 日历瘦身 + 右侧「今日 to do / 选中日待办」双面板
日历
- 行高 92→72px,行程条只留 2 条(超出折成 +N 并压缩成小 chip),标题区与周标同步收窄
- 选中态重做:去掉了原来生硬的 2px 内描边,改成单元格内嵌圆角环 + 淡入缩放动画;
  「今天」改为日号描边圆环,与「选中」的实心日号区分开
- 侧栏宽度不足时(≤1200px)自动改为上下排布

右侧新增两块
- 「今日 to do」:备忘录性质。底部常驻加号输入框,回车即建;建完前面出现勾选框,
  勾选后划线变淡并沉到已完成组末尾(输入框始终在最后一行);可取消勾选回到未完成组;
  悬浮出现删除按钮;列表过长可滚动,勾选后自动滚进视野
- 「待办事项」:显示日历上选中那天的日程与节日(未选中时默认今天),
  带优先级点与说明,右上角「新建」直接为该日添加日程
- 原左栏重复的 [TASK QUEUE] 面板移到这里后删除,避免同名面板出现两次

后端
- todos 增加 list 列(schedule 日历日程 / memo 备忘录待办),老库启动时自动补列
- GET /api/todos 支持 list=memo;POST 支持 list,memo 不写日期
- 新增 PATCH /api/todos/:id(勾选完成/取消、改标题等)与 DELETE /api/todos/:id
2026-09-10 23:35:20 +08:00

79 lines
2.4 KiB
JavaScript

const Database = require('better-sqlite3-multiple-ciphers');
const fs = require('fs');
const path = require('path');
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, '../data');
const DB_PATH = path.join(DATA_DIR, 'trade.db');
// 确保数据目录存在
if (!fs.existsSync(DATA_DIR)) {
fs.mkdirSync(DATA_DIR, { recursive: true });
}
// 创建数据库连接
const db = new Database(DB_PATH);
// 启用外键约束
db.pragma('foreign_keys = ON');
// 性能优化
db.pragma('journal_mode = WAL');
db.pragma('synchronous = NORMAL');
// 初始化数据库结构
function initDatabase() {
const schema = fs.readFileSync(path.join(__dirname, 'schema.sql'), 'utf-8');
db.exec(schema);
console.log('✓ 数据库初始化完成');
}
// 检查数据库是否已初始化
const tableExists = db.prepare(
"SELECT name FROM sqlite_master WHERE type='table' AND name='users'"
).get();
if (!tableExists) {
initDatabase();
}
// ---------------------------------------------------------------------------
// 轻量迁移:schema.sql 只对新库生效,老库缺列在这里补。
// todos.list —— 'schedule' 日历日程 / 'memo' 今日待办备忘录(备忘录不带日期)
// ---------------------------------------------------------------------------
function ensureColumns() {
const todoColumns = db.pragma('table_info(todos)').map(column => column.name);
if (!todoColumns.includes('list')) {
db.exec("ALTER TABLE todos ADD COLUMN list TEXT NOT NULL DEFAULT 'schedule'");
console.log('✓ 迁移:todos.list 列已补齐');
}
}
ensureColumns();
// 创建默认管理员账号(如果不存在)
function createDefaultAdmin() {
const crypto = require('crypto');
const adminExists = db.prepare('SELECT id FROM users WHERE username = ?').get('admin');
if (!adminExists) {
// 生成默认密码哈希:admin123
const salt = crypto.randomBytes(16).toString('hex');
const hash = crypto.scryptSync('admin123', salt, 64).toString('hex');
const passwordHash = `scrypt$${salt}$${hash}`;
db.prepare(`
INSERT INTO users (username, password_hash, display_name, role, created_at)
VALUES (?, ?, ?, ?, ?)
`).run('admin', passwordHash, '管理员', 'admin', new Date().toISOString());
console.log('✓ 默认管理员账号已创建');
console.log(' 用户名: admin');
console.log(' 密码: admin123');
console.log(' 请登录后立即修改密码!');
}
}
createDefaultAdmin();
module.exports = db;