// db.js —— 只做两件事:导出连接池;启动时建库/建表/插 admin require('dotenv').config() //自动寻找.env文件,并把里面的键值对全部导入进来 const mysql = require('mysql2/promise') const bcrypt = require('bcryptjs') //用来给密码做哈希加密 // ============ 1. 连接池 ============ // 业务代码里用 pool.query() / pool.execute(),会自动从池里取/还连接 const pool = mysql.createPool({ host: process.env.DB_HOST, port: Number(process.env.DB_PORT) || 3306, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, waitForConnections: true, // 池里没连接时排队等 connectionLimit: 10, // 最多 10 个连接 decimalNumbers: true, }) // ============ 2. 启动时初始化 ============ // 思路:先用一个"无 database"的连接建库,再回到 pool 建表、插 admin async function initDB() { const { DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME } = process.env // 2.1 建库(如果不存在) const conn = await mysql.createConnection({ host: DB_HOST, port: Number(DB_PORT) || 3306, user: DB_USER, password: DB_PASSWORD, }) await conn.query( `CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\` DEFAULT CHARACTER SET utf8mb4` ) await conn.end() // 2.2 建表 await pool.query(` CREATE TABLE IF NOT EXISTS users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, nickname VARCHAR(50) DEFAULT '', avatar VARCHAR(255) DEFAULT '', role VARCHAR(20) DEFAULT 'user', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 `) // 2.3 插 admin(仅当不存在时) const [rows] = await pool.query( 'SELECT id FROM users WHERE username = ?', ['admin'] ) if (rows.length === 0) { const hash = await bcrypt.hash('123456', 10) await pool.query( 'INSERT INTO users (username, password, nickname, role) VALUES (?, ?, ?, ?)', ['admin', hash, '超级管理员', 'admin'] ) console.log('[init] 已创建默认账号 admin / 123456') } else { console.log('[init] admin 已存在,跳过') } } module.exports = { pool, initDB }