const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const bcrypt = require('bcryptjs'); const dbPath = path.resolve(__dirname, 'database.sqlite'); const db = new sqlite3.Database(dbPath); const run = (sql, params = []) => { return new Promise((resolve, reject) => { db.run(sql, params, function(err) { if (err) reject(err); else resolve(this); }); }); }; const insertUser = async (user) => { await run( 'INSERT INTO users (id, name, password, role, class) VALUES (?, ?, ?, ?, ?)', [user.id, user.name, user.password, user.role, user.class] ); }; const insertStudent = async (student) => { await run( 'INSERT INTO students (id, name, class, major, grade, contact_info) VALUES (?, ?, ?, ?, ?, ?)', [student.id, student.name, student.class, student.major, student.grade, student.contact_info] ); }; const insertClass = async (cls) => { return await run( 'INSERT INTO classes (class_name, grade, major, teacher_id) VALUES (?, ?, ?, ?)', [cls.class_name, cls.grade, cls.major, cls.teacher_id] ); }; const insertCourse = async (course) => { return await run( 'INSERT INTO courses (course_code, course_name, credit, teacher_id, class_id, semester, academic_year, category) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [course.course_code, course.course_name, course.credit, course.teacher_id, course.class_id, course.semester, course.academic_year, course.category] ); }; const insertGrade = async (grade) => { await run( `INSERT INTO grades ( student_id, course_id, teacher_id, usual_score, midterm_score, final_score, total_score, grade_point, grade_level, remark ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ grade.student_id, grade.course_id, grade.teacher_id, grade.usual_score, grade.midterm_score, grade.final_score, grade.total_score, grade.grade_point, grade.grade_level, grade.remark ] ); }; // Helper to calculate grade point const calculateGradePoint = (score) => { if (score >= 90) return 4.0; if (score >= 85) return 3.7; if (score >= 82) return 3.3; if (score >= 78) return 3.0; if (score >= 75) return 2.7; if (score >= 72) return 2.3; if (score >= 68) return 2.0; if (score >= 64) return 1.5; if (score >= 60) return 1.0; return 0.0; }; const calculateGradeLevel = (score) => { if (score >= 90) return 'A'; if (score >= 80) return 'B'; if (score >= 70) return 'C'; if (score >= 60) return 'D'; return 'F'; }; const init = async () => { console.log('开始初始化 SQLite 数据库...'); const hashedPassword = await bcrypt.hash('123456', 10); try { // Drop tables await run('DROP TABLE IF EXISTS grades'); await run('DROP TABLE IF EXISTS courses'); await run('DROP TABLE IF EXISTS classes'); await run('DROP TABLE IF EXISTS students'); await run('DROP TABLE IF EXISTS users'); await run('DROP TABLE IF EXISTS operation_logs'); // Create tables console.log('创建表结构...'); await run(` CREATE TABLE users ( id TEXT PRIMARY KEY, name TEXT NOT NULL, password TEXT NOT NULL, role TEXT NOT NULL, class TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); await run(` CREATE TABLE students ( id TEXT PRIMARY KEY, name TEXT NOT NULL, class TEXT, major TEXT, grade TEXT, contact_info TEXT, FOREIGN KEY (id) REFERENCES users(id) ON DELETE CASCADE ) `); await run(` CREATE TABLE classes ( id INTEGER PRIMARY KEY AUTOINCREMENT, class_name TEXT NOT NULL, grade TEXT, major TEXT, teacher_id TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); await run(` CREATE TABLE courses ( id INTEGER PRIMARY KEY AUTOINCREMENT, course_code TEXT UNIQUE NOT NULL, course_name TEXT NOT NULL, credit REAL DEFAULT 2.0, teacher_id TEXT NOT NULL, class_id INTEGER NOT NULL, semester TEXT, academic_year TEXT, category TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); await run(` CREATE TABLE grades ( id INTEGER PRIMARY KEY AUTOINCREMENT, student_id TEXT NOT NULL, course_id INTEGER NOT NULL, teacher_id TEXT NOT NULL, usual_score REAL, midterm_score REAL, final_score REAL, total_score REAL, grade_point REAL, grade_level TEXT, remark TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')), UNIQUE(student_id, course_id) ) `); await run(` CREATE TABLE operation_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT, operation_type TEXT, operation_target TEXT, description TEXT, ip_address TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')) ) `); console.log('生成基础数据...'); // 1. Admin await insertUser({ id: 'admin', name: '系统管理员', password: hashedPassword, role: 'admin', class: null }); // 2. Teachers (20 teachers) const teachers = []; for (let i = 1; i <= 20; i++) { const id = `T${1000 + i}`; const name = `教师${String.fromCharCode(65 + (i % 26))}${i}`; await insertUser({ id, name, password: hashedPassword, role: 'teacher', class: null }); teachers.push(id); } // 3. Classes (10 classes) const majors = ['软件工程', '计算机科学', '信息管理']; const classIds = []; const classes = []; for (let i = 1; i <= 10; i++) { const major = majors[i % 3]; const gradeYear = 2021 + Math.floor((i-1)/5); // 2021, 2022 const className = `${major.substr(0, 2)}${gradeYear}${String(i).padStart(2, '0')}`; const teacherId = teachers[i % teachers.length]; const result = await insertClass({ class_name: className, grade: String(gradeYear), major: major, teacher_id: teacherId }); classIds.push(result.lastID); classes.push({ id: result.lastID, name: className, year: gradeYear, major }); } // 4. Students (50 per class -> 500 students) console.log('生成学生数据...'); const students = []; for (let clsIdx = 0; clsIdx < classes.length; clsIdx++) { const cls = classes[clsIdx]; for (let i = 1; i <= 50; i++) { const id = `${cls.year}${String(clsIdx + 1).padStart(2, '0')}${String(i).padStart(3, '0')}`; const name = `学生${cls.name.substr(0,1)}${i}`; await insertUser({ id, name, password: hashedPassword, role: 'student', class: cls.name }); await insertStudent({ id, name, class: cls.name, major: cls.major, grade: String(cls.year), contact_info: `13800${id.substr(0, 6)}` }); students.push({ id, classId: cls.id }); } } // 5. Courses and Grades console.log('生成课程和成绩数据...'); const courseNames = [ { name: '高等数学', credit: 4, category: '必修' }, { name: '大学英语', credit: 3, category: '必修' }, { name: '程序设计基础', credit: 4, category: '必修' }, { name: '数据结构', credit: 4, category: '必修' }, { name: '操作系统', credit: 3, category: '必修' }, { name: '计算机网络', credit: 3, category: '必修' }, { name: '数据库原理', credit: 3, category: '必修' }, { name: '软件工程导论', credit: 2, category: '必修' }, { name: 'Web开发技术', credit: 3, category: '选修' }, { name: '人工智能基础', credit: 2, category: '选修' }, { name: '大数据分析', credit: 2, category: '选修' }, { name: '音乐鉴赏', credit: 1, category: '通识' }, { name: '心理健康', credit: 1, category: '通识' }, { name: '职业规划', credit: 1, category: '通识' } ]; const semesters = ['2021-2022-1', '2021-2022-2', '2022-2023-1', '2022-2023-2', '2023-2024-1']; for (const cls of classes) { // For each class, assign some courses for (let semIdx = 0; semIdx < semesters.length; semIdx++) { const semester = semesters[semIdx]; // Select random 5-8 courses for this semester const semCourses = courseNames.sort(() => 0.5 - Math.random()).slice(0, 6); for (const cTemplate of semCourses) { const teacherId = teachers[Math.floor(Math.random() * teachers.length)]; const courseCode = `C${cls.id}${semIdx}${Math.floor(Math.random() * 1000)}`; const result = await insertCourse({ course_code: courseCode, course_name: cTemplate.name, credit: cTemplate.credit, teacher_id: teacherId, class_id: cls.id, semester: semester, academic_year: semester.substring(0, 9), category: cTemplate.category }); const courseId = result.lastID; // Generate grades for students in this class const classStudents = students.filter(s => s.classId === cls.id); // Batch insert could be faster, but let's keep it simple for now const stmt = db.prepare(`INSERT INTO grades ( student_id, course_id, teacher_id, usual_score, midterm_score, final_score, total_score, grade_point, grade_level, remark ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`); for (const stu of classStudents) { // 90% chance to have a grade if (Math.random() > 0.1) { const totalScore = Math.floor(Math.random() * 40) + 60; // 60-100 mostly // 10% chance to fail const finalTotal = Math.random() > 0.1 ? totalScore : Math.floor(Math.random() * 59); stmt.run([ stu.id, courseId, teacherId, finalTotal, // usual finalTotal, // midterm finalTotal, // final finalTotal, // total calculateGradePoint(finalTotal), calculateGradeLevel(finalTotal), '' ]); } } stmt.finalize(); } } } console.log('数据库初始化完成!'); db.close(); } catch (err) { console.error('Initialization failed:', err); process.exit(1); } }; init();