initDb.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. const fs = require('fs');
  2. const path = require('path');
  3. const { pool } = require('./database');
  4. const bcrypt = require('bcryptjs');
  5. const User = require('../models/User');
  6. async function initDatabase() {
  7. try {
  8. // 读取并执行迁移文件
  9. const migrationsDir = path.join(__dirname, 'migrations');
  10. const migrationFiles = fs.readdirSync(migrationsDir).sort();
  11. for (const file of migrationFiles) {
  12. if (file.endsWith('.sql')) {
  13. const migrationPath = path.join(migrationsDir, file);
  14. const migrationSQL = fs.readFileSync(migrationPath, 'utf8');
  15. console.log(`执行数据库迁移: ${file}`);
  16. await pool.query(migrationSQL);
  17. }
  18. }
  19. // 创建数据库
  20. await pool.query('CREATE DATABASE IF NOT EXISTS notebot');
  21. await pool.query('USE notebot');
  22. // 创建用户表
  23. await pool.query(`
  24. CREATE TABLE IF NOT EXISTS users (
  25. id INT AUTO_INCREMENT PRIMARY KEY,
  26. username VARCHAR(50) NOT NULL UNIQUE,
  27. password VARCHAR(255) NOT NULL,
  28. role ENUM('admin', 'user') DEFAULT 'user',
  29. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  30. )
  31. `);
  32. // 创建群组表
  33. await pool.query(`
  34. CREATE TABLE IF NOT EXISTS groups (
  35. id INT AUTO_INCREMENT PRIMARY KEY,
  36. group_id VARCHAR(255) NOT NULL UNIQUE,
  37. group_name VARCHAR(255) NOT NULL,
  38. group_type ENUM('personal', 'group', 'supergroup') NOT NULL DEFAULT 'group' COMMENT '群组类型:个人用户/私聊群组/超级群组',
  39. creator_id VARCHAR(255) NOT NULL,
  40. is_active BOOLEAN DEFAULT true,
  41. last_join_time DATETIME DEFAULT CURRENT_TIMESTAMP,
  42. last_leave_time DATETIME DEFAULT CURRENT_TIMESTAMP,
  43. created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  44. updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  45. )
  46. `);
  47. // 修改群组表,添加新字段
  48. try {
  49. await pool.query(`
  50. ALTER TABLE groups
  51. MODIFY COLUMN group_type ENUM('personal', 'group', 'supergroup') NOT NULL DEFAULT 'group' COMMENT '群组类型:个人用户/私聊群组/超级群组',
  52. ADD COLUMN fee_rate DECIMAL(5,2) DEFAULT 0.00 COMMENT '费率' AFTER group_type,
  53. ADD COLUMN exchange_rate DECIMAL(10,4) DEFAULT 1.0000 COMMENT '汇率' AFTER fee_rate,
  54. ADD COLUMN admin_id INT NOT NULL COMMENT '管理员ID' AFTER exchange_rate,
  55. ADD COLUMN last_join_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '机器人最后加入时间' AFTER is_active,
  56. ADD COLUMN last_leave_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '机器人最后离开时间' AFTER last_join_time,
  57. ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间' AFTER last_leave_time
  58. `);
  59. } catch (error) {
  60. // 如果列已存在,忽略错误
  61. if (!error.message.includes('Duplicate column name')) {
  62. throw error;
  63. }
  64. }
  65. // 添加外键约束
  66. // try {
  67. // await pool.query(`
  68. // ALTER TABLE groups
  69. // ADD CONSTRAINT fk_groups_creator
  70. // FOREIGN KEY (creator_id) REFERENCES users(id),
  71. // ADD CONSTRAINT fk_groups_admin
  72. // FOREIGN KEY (admin_id) REFERENCES users(id)
  73. // `);
  74. // } catch (error) {
  75. // // 如果约束已存在,忽略错误
  76. // if (!error.message.includes('Duplicate key name')) {
  77. // throw error;
  78. // }
  79. // }
  80. // 创建入款出款记录表
  81. await pool.query(`
  82. CREATE TABLE IF NOT EXISTS money_records (
  83. id INT AUTO_INCREMENT PRIMARY KEY,
  84. time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  85. amount DECIMAL(10,2) NOT NULL COMMENT '金额',
  86. operator_id INT NOT NULL COMMENT '操作人ID',
  87. responder_id INT NOT NULL COMMENT '回复人ID',
  88. group_id VARCHAR(50) NOT NULL COMMENT '关联群组ID',
  89. type ENUM('deposit', 'withdrawal') NOT NULL COMMENT '类型:入款/出款',
  90. status ENUM('pending', 'approved', 'rejected') DEFAULT 'pending' COMMENT '状态',
  91. FOREIGN KEY (operator_id) REFERENCES users(id),
  92. FOREIGN KEY (responder_id) REFERENCES users(id),
  93. FOREIGN KEY (group_id) REFERENCES groups(group_id),
  94. INDEX idx_group_time (group_id, time)
  95. )
  96. `);
  97. // // 创建交易表
  98. // await pool.query(`
  99. // CREATE TABLE IF NOT EXISTS transactions (
  100. // id INT AUTO_INCREMENT PRIMARY KEY,
  101. // group_id VARCHAR(50) NOT NULL,
  102. // group_name VARCHAR(100) NOT NULL,
  103. // type ENUM('deposit', 'withdrawal') NOT NULL,
  104. // amount DECIMAL(10,2) NOT NULL,
  105. // time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  106. // INDEX idx_group_time (group_id, time)
  107. // )
  108. // `);
  109. // 检查是否存在管理员用户
  110. const adminUser = await User.findByUsername('admin');
  111. if (!adminUser) {
  112. console.log('创建默认管理员用户...');
  113. // 创建默认管理员用户
  114. const adminData = {
  115. username: 'admin',
  116. password: 'admin123', // 默认密码
  117. role: 'admin'
  118. };
  119. await User.create(adminData);
  120. console.log('默认管理员用户创建成功');
  121. } else {
  122. console.log('管理员用户已存在');
  123. }
  124. console.log('数据库初始化完成');
  125. } catch (error) {
  126. console.error('数据库初始化失败:', error);
  127. throw error;
  128. }
  129. }
  130. module.exports = initDatabase;