const Database = require('better-sqlite3'); const path = require('path'); const dbPath = path.join(__dirname, 'data', 'device_manager.db'); // 确保 data 目录存在 const fs = require('fs'); const dataDir = path.join(__dirname, 'data'); if (!fs.existsSync(dataDir)) { fs.mkdirSync(dataDir, { recursive: true }); } const db = new Database(dbPath); // 启用 WAL 模式提升性能 db.pragma('journal_mode = WAL'); // 初始化数据库表 function initDatabase() { // 设备表 db.exec(` CREATE TABLE IF NOT EXISTS devices ( id TEXT PRIMARY KEY, name TEXT NOT NULL, type TEXT NOT NULL, model TEXT, serial_number TEXT, status TEXT DEFAULT '正常', location TEXT, purchase_date TEXT, warranty_date TEXT, responsible_person TEXT, description TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')), updated_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); // 人员表 db.exec(` CREATE TABLE IF NOT EXISTS personnel ( id TEXT PRIMARY KEY, name TEXT NOT NULL, employee_id TEXT UNIQUE, department TEXT, position TEXT, phone TEXT, email TEXT, status TEXT DEFAULT '在职', entry_date TEXT, description TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')), updated_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); // 通知表 db.exec(` CREATE TABLE IF NOT EXISTS notifications ( id TEXT PRIMARY KEY, title TEXT NOT NULL, content TEXT NOT NULL, type TEXT DEFAULT '普通', priority TEXT DEFAULT '普通', is_read INTEGER DEFAULT 0, target TEXT DEFAULT '全部', created_at TEXT DEFAULT (datetime('now', 'localtime')), updated_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); // 用户表 db.exec(` CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, role TEXT DEFAULT 'user', display_name TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); // 用户表增加 personnel_id 关联字段(人员与账户 1:1) const userCols = db.prepare('PRAGMA table_info(users)').all(); if (!userCols.some(c => c.name === 'personnel_id')) { db.exec('ALTER TABLE users ADD COLUMN personnel_id TEXT'); } // 用户表增加最后登录时间字段(用于在线状态展示) if (!userCols.some(c => c.name === 'last_login')) { db.exec('ALTER TABLE users ADD COLUMN last_login TEXT'); } // 设备表增加报废相关字段 const deviceCols = db.prepare('PRAGMA table_info(devices)').all(); if (!deviceCols.some(c => c.name === 'scrap_reason')) { db.exec("ALTER TABLE devices ADD COLUMN scrap_reason TEXT DEFAULT ''"); db.exec("ALTER TABLE devices ADD COLUMN scrap_date TEXT DEFAULT ''"); db.exec("ALTER TABLE devices ADD COLUMN scrap_operator TEXT DEFAULT ''"); } // 维修记录表 db.exec(` CREATE TABLE IF NOT EXISTS maintenance_records ( id TEXT PRIMARY KEY, device_id TEXT NOT NULL, device_name TEXT DEFAULT '', type TEXT DEFAULT '报修', remark TEXT DEFAULT '', operator TEXT DEFAULT '', created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); // 设备操作日志表 db.exec(` CREATE TABLE IF NOT EXISTS device_logs ( id TEXT PRIMARY KEY, device_id TEXT NOT NULL, device_name TEXT DEFAULT '', action TEXT NOT NULL, detail TEXT DEFAULT '', operator TEXT DEFAULT '', created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); // 账户操作日志表 db.exec(` CREATE TABLE IF NOT EXISTS user_logs ( id TEXT PRIMARY KEY, username TEXT DEFAULT '', action TEXT NOT NULL, detail TEXT DEFAULT '', operator TEXT DEFAULT '', created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); // 会话表(单聊 direct / 群聊 group) db.exec(` CREATE TABLE IF NOT EXISTS conversations ( id TEXT PRIMARY KEY, type TEXT NOT NULL, name TEXT DEFAULT '', creator_id TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); // 会话成员表(last_read_message_id 用于未读计数) db.exec(` CREATE TABLE IF NOT EXISTS conversation_members ( conversation_id TEXT NOT NULL, user_id TEXT NOT NULL, role TEXT DEFAULT 'member', last_read_message_id INTEGER DEFAULT 0, joined_at TEXT DEFAULT (datetime('now', 'localtime')), PRIMARY KEY (conversation_id, user_id) ) `); // 消息表(自增 id 兼作排序游标) db.exec(` CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, conversation_id TEXT NOT NULL, sender_id TEXT NOT NULL, content TEXT NOT NULL, created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); // 插入示例数据 const deviceCount = db.prepare('SELECT COUNT(*) as count FROM devices').get(); if (deviceCount.count === 0) { const insertDevice = db.prepare(` INSERT INTO devices (id, name, type, model, serial_number, status, location, purchase_date, warranty_date, responsible_person, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `); insertDevice.run('d001', '联想ThinkPad X1 Carbon', '笔记本电脑', 'X1 Carbon Gen 11', 'SN2024001', '正常', '办公室A区', '2024-01-15', '2027-01-15', '张三', '高管使用笔记本电脑'); insertDevice.run('d002', '戴尔U2723QE显示器', '显示器', 'U2723QE', 'SN2024002', '正常', '办公室A区', '2024-02-20', '2027-02-20', '李四', '27寸4K显示器'); insertDevice.run('d003', 'HP LaserJet Pro打印机', '打印机', 'M404dn', 'SN2024003', '维修中', '打印室', '2023-06-10', '2026-06-10', '王五', '网络打印机'); insertDevice.run('d004', '华为交换机', '网络设备', 'S5735-L24T4S', 'SN2024004', '正常', '机房', '2023-03-01', '2028-03-01', '赵六', '24口千兆交换机'); insertDevice.run('d005', 'ThinkStation P360', '台式机', 'P360 Tower', 'SN2024005', '已报废', '仓库', '2022-01-01', '2025-01-01', '张三', '开发工作站'); } const personnelCount = db.prepare('SELECT COUNT(*) as count FROM personnel').get(); if (personnelCount.count === 0) { const insertPerson = db.prepare(` INSERT INTO personnel (id, name, employee_id, department, position, phone, email, status, entry_date, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `); insertPerson.run('p001', '张三', 'EMP001', '拍摄组', '拍摄设备主管', '13800138001', 'zhangsan@company.com', '在职', '2020-03-15', '负责拍摄设备与摄像器材管理'); insertPerson.run('p002', '李四', 'EMP002', '拍摄组', '摄影助理', '13800138002', 'lisi@company.com', '在职', '2021-06-01', '负责显示设备管理'); insertPerson.run('p003', '王五', 'EMP003', '后勤组', '后勤专员', '13800138003', 'wangwu@company.com', '在职', '2022-01-10', '负责办公设备与物资保障'); insertPerson.run('p004', '赵六', 'EMP004', '后勤组', '设备维护员', '13800138004', 'zhaoliu@company.com', '在职', '2019-09-01', '负责设备维护与保养'); insertPerson.run('p005', '钱七', 'EMP005', '监督组', '监督主管', '13800138005', 'qianqi@company.com', '在职', '2018-05-20', '负责设备使用监督与盘点核查'); } const notifCount = db.prepare('SELECT COUNT(*) as count FROM notifications').get(); if (notifCount.count === 0) { const insertNotif = db.prepare(` INSERT INTO notifications (id, title, content, type, priority, is_read, target) VALUES (?, ?, ?, ?, ?, ?, ?) `); insertNotif.run('n001', '设备盘点通知', '请各部门于本月底前完成设备盘点工作,并提交盘点报告。', '通知', '高', 0, '全部'); insertNotif.run('n002', '打印机维修通知', '打印室HP打印机正在进行维修,预计明天恢复使用。', '公告', '普通', 0, '全部'); insertNotif.run('n003', '新设备到货通知', '新采购的10台联想笔记本已到货,请相关人员前来领取。', '通知', '普通', 1, '拍摄组'); insertNotif.run('n004', '系统升级提醒', '设备管理系统将于本周六凌晨2点进行升级维护。', '提醒', '高', 0, '全部'); } // 初始化默认账户(管理员 + 示例普通用户) const userCount = db.prepare('SELECT COUNT(*) as count FROM users').get(); if (userCount.count === 0) { const insertUser = db.prepare(` INSERT INTO users (id, username, password, role, display_name, personnel_id) VALUES (?, ?, ?, ?, ?, ?) `); insertUser.run('u001', 'admin', 'admin123', 'admin', '系统管理员', null); insertUser.run('u002', 'zhangsan', '123456', 'user', '张三', 'p001'); } } initDatabase(); module.exports = db;