initDatabase.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. require('dotenv').config();
  2. const mysql = require('mysql2/promise');
  3. const dbConfig = {
  4. host: process.env.DB_HOST,
  5. port: process.env.DB_PORT,
  6. user: process.env.DB_USER,
  7. password: process.env.DB_PASSWORD,
  8. };
  9. async function initDatabase() {
  10. let connection;
  11. try {
  12. connection = await mysql.createConnection(dbConfig);
  13. console.log('数据库连接成功');
  14. // 创建数据库
  15. await connection.query(`CREATE DATABASE IF NOT EXISTS ${process.env.DB_NAME} DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`);
  16. console.log(`数据库 ${process.env.DB_NAME} 创建成功`);
  17. await connection.query(`USE ${process.env.DB_NAME}`);
  18. // 用户表
  19. await connection.query(`
  20. CREATE TABLE IF NOT EXISTS users (
  21. id VARCHAR(36) PRIMARY KEY,
  22. username VARCHAR(50) UNIQUE NOT NULL,
  23. password VARCHAR(255) NOT NULL,
  24. real_name VARCHAR(50) NOT NULL,
  25. email VARCHAR(100),
  26. phone VARCHAR(20),
  27. role ENUM('sales', 'sales_manager', 'sales_director', 'admin') NOT NULL DEFAULT 'sales',
  28. department VARCHAR(50),
  29. team VARCHAR(50),
  30. status ENUM('active', 'inactive') DEFAULT 'active',
  31. last_login TIMESTAMP NULL,
  32. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  33. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  34. INDEX idx_role (role),
  35. INDEX idx_department (department),
  36. INDEX idx_team (team)
  37. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  38. `);
  39. console.log('用户表创建成功');
  40. // 客户报备表
  41. await connection.query(`
  42. CREATE TABLE IF NOT EXISTS customers (
  43. id VARCHAR(36) PRIMARY KEY,
  44. customer_name VARCHAR(200) NOT NULL,
  45. industry VARCHAR(100),
  46. region VARCHAR(100),
  47. contact_person VARCHAR(50),
  48. contact_phone VARCHAR(20),
  49. demand_description TEXT,
  50. source VARCHAR(50),
  51. sales_owner VARCHAR(36) NOT NULL,
  52. report_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  53. protected_end_date TIMESTAMP,
  54. status ENUM('following', 'won', 'lost', 'released') DEFAULT 'following',
  55. last_followup TIMESTAMP,
  56. release_reason VARCHAR(200),
  57. is_in_pool BOOLEAN DEFAULT FALSE,
  58. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  59. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  60. FOREIGN KEY (sales_owner) REFERENCES users(id) ON DELETE RESTRICT,
  61. INDEX idx_customer_name (customer_name),
  62. INDEX idx_sales_owner (sales_owner),
  63. INDEX idx_status (status),
  64. INDEX idx_protected_end_date (protected_end_date),
  65. INDEX idx_is_in_pool (is_in_pool),
  66. FULLTEXT idx_ft_customer_name (customer_name)
  67. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  68. `);
  69. console.log('客户报备表创建成功');
  70. // 跟进记录表
  71. await connection.query(`
  72. CREATE TABLE IF NOT EXISTS followup_records (
  73. id VARCHAR(36) PRIMARY KEY,
  74. customer_id VARCHAR(36) NOT NULL,
  75. user_id VARCHAR(36) NOT NULL,
  76. followup_type ENUM('call', 'visit', 'email', 'wechat', 'other') DEFAULT 'call',
  77. content TEXT,
  78. next_plan TEXT,
  79. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  80. FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE CASCADE,
  81. FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
  82. INDEX idx_customer_id (customer_id),
  83. INDEX idx_user_id (user_id),
  84. INDEX idx_created_at (created_at)
  85. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  86. `);
  87. console.log('跟进记录表创建成功');
  88. // 公海池领取记录表
  89. await connection.query(`
  90. CREATE TABLE IF NOT EXISTS pool_claim_records (
  91. id VARCHAR(36) PRIMARY KEY,
  92. customer_id VARCHAR(36) NOT NULL,
  93. user_id VARCHAR(36) NOT NULL,
  94. claim_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  95. FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE CASCADE,
  96. FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
  97. INDEX idx_customer_id (customer_id),
  98. INDEX idx_user_id (user_id),
  99. INDEX idx_claim_time (claim_time)
  100. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  101. `);
  102. console.log('公海池领取记录表创建成功');
  103. // 审批流程表
  104. await connection.query(`
  105. CREATE TABLE IF NOT EXISTS approvals (
  106. id VARCHAR(36) PRIMARY KEY,
  107. type ENUM('extension', 'force_release', 'collaboration') NOT NULL,
  108. applicant_id VARCHAR(36) NOT NULL,
  109. approver_id VARCHAR(36),
  110. customer_id VARCHAR(36),
  111. reason TEXT,
  112. extension_days INT,
  113. status ENUM('pending', 'approved', 'rejected') DEFAULT 'pending',
  114. result_comment TEXT,
  115. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  116. processed_at TIMESTAMP,
  117. FOREIGN KEY (applicant_id) REFERENCES users(id) ON DELETE CASCADE,
  118. FOREIGN KEY (approver_id) REFERENCES users(id) ON DELETE SET NULL,
  119. FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE CASCADE,
  120. INDEX idx_applicant_id (applicant_id),
  121. INDEX idx_approver_id (approver_id),
  122. INDEX idx_status (status),
  123. INDEX idx_type (type)
  124. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  125. `);
  126. console.log('审批流程表创建成功');
  127. // 操作日志表
  128. await connection.query(`
  129. CREATE TABLE IF NOT EXISTS operation_logs (
  130. id VARCHAR(36) PRIMARY KEY,
  131. user_id VARCHAR(36),
  132. action VARCHAR(50) NOT NULL,
  133. target_type VARCHAR(50),
  134. target_id VARCHAR(36),
  135. details TEXT,
  136. ip_address VARCHAR(45),
  137. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  138. FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
  139. INDEX idx_user_id (user_id),
  140. INDEX idx_action (action),
  141. INDEX idx_created_at (created_at)
  142. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  143. `);
  144. console.log('操作日志表创建成功');
  145. // 附件表
  146. await connection.query(`
  147. CREATE TABLE IF NOT EXISTS attachments (
  148. id VARCHAR(36) PRIMARY KEY,
  149. customer_id VARCHAR(36) NOT NULL,
  150. filename VARCHAR(255) NOT NULL,
  151. original_name VARCHAR(255) NOT NULL,
  152. file_path VARCHAR(500) NOT NULL,
  153. file_size INT,
  154. mime_type VARCHAR(100),
  155. uploaded_by VARCHAR(36) NOT NULL,
  156. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  157. FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE CASCADE,
  158. FOREIGN KEY (uploaded_by) REFERENCES users(id) ON DELETE CASCADE,
  159. INDEX idx_customer_id (customer_id)
  160. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  161. `);
  162. console.log('附件表创建成功');
  163. // 插入默认管理员账号 (密码: admin123)
  164. const bcrypt = require('bcryptjs');
  165. const crypto = require('crypto');
  166. const adminPassword = await bcrypt.hash('admin123', 10);
  167. const adminId = crypto.randomUUID();
  168. await connection.query(`
  169. INSERT INTO users (id, username, password, real_name, role, department)
  170. VALUES (?, 'admin', ?, '系统管理员', 'admin', '管理部')
  171. ON DUPLICATE KEY UPDATE username=username
  172. `, [adminId, adminPassword]);
  173. console.log('默认管理员账号创建成功 (用户名: admin, 密码: admin123)');
  174. console.log('\n数据库初始化完成!');
  175. } catch (error) {
  176. console.error('数据库初始化失败:', error);
  177. process.exit(1);
  178. } finally {
  179. if (connection) {
  180. await connection.end();
  181. }
  182. }
  183. }
  184. initDatabase();