const mongoose = require('mongoose'); // ... (Previous Models: School, User, Student, Course, Score, Class, Subject, Exam Models - No Change) const SchoolSchema = new mongoose.Schema({ name: String, code: String }); const School = mongoose.model('School', SchoolSchema); const UserSchema = new mongoose.Schema({ username: String, password: String, trueName: String, phone: String, email: String, schoolId: String, role: String, status: String, avatar: String, createTime: Date, teachingSubject: String, homeroomClass: String, studentNo: String, parentName: String, parentPhone: String, address: String, gender: String, seatNo: String, idCard: String, aiAccess: { type: Boolean, default: false }, // UPDATED: Stores Doubao Context State doubaoState: { responseId: String, // previous_response_id thinkingState: Boolean // Last thinking state (enabled/disabled) }, menuOrder: [String], classApplication: { type: { type: String }, targetClass: String, status: String }, pendingSchoolData: { name: String, code: String, type: { type: String } } }); const User = mongoose.model('User', UserSchema); // ... (Student, Course, Score, Class, Subject, Exam Models - No Change) const StudentSchema = new mongoose.Schema({ schoolId: String, studentNo: String, seatNo: String, name: String, gender: String, birthday: String, idCard: String, phone: String, className: String, status: String, parentName: String, parentPhone: String, address: String, teamId: String, drawAttempts: { type: Number, default: 0 }, dailyDrawLog: { date: String, count: { type: Number, default: 0 } }, flowerBalance: { type: Number, default: 0 }, // Seating Fields height: Number, vision: { type: String, default: 'Normal' }, // Normal, Near-Mild, Near-Severe, Far character: { type: String, default: 'Normal' }, // Active, Quiet, Normal seatRow: Number, seatCol: Number }); const Student = mongoose.model('Student', StudentSchema); const CourseSchema = new mongoose.Schema({ schoolId: String, courseCode: String, courseName: String, className: String, teacherName: String, teacherId: String, credits: Number, capacity: Number, enrolled: Number }); CourseSchema.index({ schoolId: 1, className: 1, courseName: 1 }, { unique: true }); const Course = mongoose.model('Course', CourseSchema); const ScoreSchema = new mongoose.Schema({ schoolId: String, studentName: String, studentNo: String, courseName: String, score: Number, semester: String, type: String, examName: String, status: String }); const Score = mongoose.model('Score', ScoreSchema); // UPDATED CLASS SCHEMA const ClassSchema = new mongoose.Schema({ schoolId: String, grade: String, className: String, teacherName: String, homeroomTeacherIds: [String], periodConfig: [{ period: Number, name: String, startTime: String, endTime: String }], seatingConfig: { rows: Number, cols: Number } }); const ClassModel = mongoose.model('Class', ClassSchema); const SubjectSchema = new mongoose.Schema({ schoolId: String, name: String, code: String, color: String, excellenceThreshold: Number, thresholds: { type: Map, of: Number } }); const SubjectModel = mongoose.model('Subject', SubjectSchema); const ExamSchema = new mongoose.Schema({ schoolId: String, name: String, date: String, type: String, semester: String }); const ExamModel = mongoose.model('Exam', ExamSchema); const ScheduleSchema = new mongoose.Schema({ schoolId: String, className: String, teacherName: String, subject: String, dayOfWeek: Number, period: Number, weekType: { type: String, default: 'ALL' } // ALL, ODD, EVEN }); const ScheduleModel = mongoose.model('Schedule', ScheduleSchema); const ConfigSchema = new mongoose.Schema({ key: String, systemName: String, semester: String, semesters: [String], allowRegister: Boolean, allowAdminRegister: Boolean, allowPrincipalRegister: Boolean, allowStudentRegister: Boolean, maintenanceMode: Boolean, emailNotify: Boolean, enableAI: { type: Boolean, default: true }, aiTotalCalls: { type: Number, default: 0 }, // Updated default to include DOUBAO aiProviderOrder: { type: [String], default: ['GEMINI', 'OPENROUTER', 'DOUBAO', 'GEMMA'] }, periodConfig: [{ period: Number, name: String, startTime: String, endTime: String }], apiKeys: { gemini: [String], openrouter: [String], doubao: [String] // NEW: Doubao Key Pool }, // NEW: Doubao Custom Models (Endpoints) doubaoModels: [{ modelId: String, // The Model ID (e.g. doubao-pro-32k) endpointId: String, // Endpoint ID (e.g. ep-2024xxxx) name: String // Friendly Name }], openRouterModels: [{ id: String, name: String, apiUrl: String, // NEW: Custom API URL for this model isCustom: { type: Boolean, default: false } }] }); const ConfigModel = mongoose.model('Config', ConfigSchema); // ... (Notification, GameSession, StudentReward, LuckyDrawConfig, etc.) const NotificationSchema = new mongoose.Schema({ schoolId: String, targetRole: String, targetUserId: String, title: String, content: String, type: String, createTime: { type: Date, default: Date.now } }); const NotificationModel = mongoose.model('Notification', NotificationSchema); const GameSessionSchema = new mongoose.Schema({ schoolId: String, className: String, isEnabled: Boolean, maxSteps: Number, teams: [{ id: String, name: String, score: Number, avatar: String, color: String, members: [String] }], rewardsConfig: [{ scoreThreshold: Number, rewardType: String, rewardName: String, rewardValue: { type: Number, default: 1 }, achievementId: String }] }); // Added rewardValue default const GameSessionModel = mongoose.model('GameSession', GameSessionSchema); const StudentRewardSchema = new mongoose.Schema({ schoolId: String, studentId: String, studentName: String, rewardType: String, name: String, count: { type: Number, default: 1 }, status: String, source: String, createTime: { type: Date, default: Date.now }, ownerId: String }); const StudentRewardModel = mongoose.model('StudentReward', StudentRewardSchema); const LuckyDrawConfigSchema = new mongoose.Schema({ schoolId: String, className: String, ownerId: String, prizes: [{ id: String, name: String, probability: Number, count: Number, icon: String }], dailyLimit: Number, cardCount: Number, defaultPrize: String, consolationWeight: { type: Number, default: 0 } }); const LuckyDrawConfigModel = mongoose.model('LuckyDrawConfig', LuckyDrawConfigSchema); const GameMonsterConfigSchema = new mongoose.Schema({ schoolId: String, className: String, ownerId: String, duration: { type: Number, default: 300 }, sensitivity: { type: Number, default: 25 }, difficulty: { type: Number, default: 5 }, useKeyboardMode: { type: Boolean, default: false }, rewardConfig: { enabled: Boolean, type: { type: String }, val: String, count: Number } }); const GameMonsterConfigModel = mongoose.model('GameMonsterConfig', GameMonsterConfigSchema); const GameZenConfigSchema = new mongoose.Schema({ schoolId: String, className: String, ownerId: String, durationMinutes: { type: Number, default: 40 }, threshold: { type: Number, default: 30 }, passRate: { type: Number, default: 90 }, rewardConfig: { enabled: Boolean, type: { type: String }, val: String, count: Number } }); const GameZenConfigModel = mongoose.model('GameZenConfig', GameZenConfigSchema); const AchievementConfigSchema = new mongoose.Schema({ schoolId: String, className: String, achievements: [{ id: String, name: String, icon: String, points: Number, description: String, addedBy: String, addedByName: String }], exchangeRules: [{ id: String, cost: Number, rewardType: String, rewardName: String, rewardValue: Number }] }); const AchievementConfigModel = mongoose.model('AchievementConfig', AchievementConfigSchema); const TeacherExchangeConfigSchema = new mongoose.Schema({ schoolId: String, teacherId: String, teacherName: String, rules: [{ id: String, cost: Number, rewardType: String, rewardName: String, rewardValue: Number }] }); const TeacherExchangeConfigModel = mongoose.model('TeacherExchangeConfig', TeacherExchangeConfigSchema); // Updated: Added points field const StudentAchievementSchema = new mongoose.Schema({ schoolId: String, studentId: String, studentName: String, achievementId: String, achievementName: String, achievementIcon: String, points: { type: Number, default: 0 }, semester: String, createTime: { type: Date, default: Date.now } }); const StudentAchievementModel = mongoose.model('StudentAchievement', StudentAchievementSchema); const AttendanceSchema = new mongoose.Schema({ schoolId: String, studentId: String, studentName: String, className: String, date: String, status: String, checkInTime: Date }); const AttendanceModel = mongoose.model('Attendance', AttendanceSchema); const LeaveRequestSchema = new mongoose.Schema({ schoolId: String, studentId: String, studentName: String, className: String, reason: String, startDate: String, endDate: String, status: { type: String, default: 'Pending' }, createTime: { type: Date, default: Date.now } }); const LeaveRequestModel = mongoose.model('LeaveRequest', LeaveRequestSchema); const SchoolCalendarSchema = new mongoose.Schema({ schoolId: String, className: String, type: String, startDate: String, endDate: String, name: String }); const SchoolCalendarModel = mongoose.model('SchoolCalendar', SchoolCalendarSchema); const WishSchema = new mongoose.Schema({ schoolId: String, studentId: String, studentName: String, className: String, teacherId: String, teacherName: String, content: String, status: { type: String, default: 'PENDING' }, createTime: { type: Date, default: Date.now }, fulfillTime: Date }); const WishModel = mongoose.model('Wish', WishSchema); const FeedbackSchema = new mongoose.Schema({ schoolId: String, creatorId: String, creatorName: String, creatorRole: String, targetId: String, targetName: String, content: String, type: String, status: { type: String, default: 'PENDING' }, reply: String, createTime: { type: Date, default: Date.now }, updateTime: Date }); const FeedbackModel = mongoose.model('Feedback', FeedbackSchema); const TodoSchema = new mongoose.Schema({ userId: String, content: String, isCompleted: { type: Boolean, default: false }, createTime: { type: Date, default: Date.now } }); const TodoModel = mongoose.model('Todo', TodoSchema); // NEW: Detailed AI Usage Stats const AIUsageSchema = new mongoose.Schema({ date: String, // Format: YYYY-MM-DD model: String, provider: String, count: { type: Number, default: 0 } }); // Optimize lookups by date and model AIUsageSchema.index({ date: 1, model: 1, provider: 1 }, { unique: true }); const AIUsageModel = mongoose.model('AIUsage', AIUsageSchema); // NEW: Persistent Chat History const ChatHistorySchema = new mongoose.Schema({ userId: { type: String, required: true, index: true }, role: { type: String, enum: ['user', 'model'], required: true }, text: { type: String, required: true }, timestamp: { type: Number, default: Date.now } }); // Create index for fast retrieval of latest messages ChatHistorySchema.index({ userId: 1, timestamp: -1 }); const ChatHistoryModel = mongoose.model('ChatHistory', ChatHistorySchema); module.exports = { School, User, Student, Course, Score, ClassModel, SubjectModel, ExamModel, ScheduleModel, ConfigModel, NotificationModel, GameSessionModel, StudentRewardModel, LuckyDrawConfigModel, GameMonsterConfigModel, GameZenConfigModel, AchievementConfigModel, TeacherExchangeConfigModel, StudentAchievementModel, AttendanceModel, LeaveRequestModel, SchoolCalendarModel, WishModel, FeedbackModel, TodoModel, AIUsageModel, ChatHistoryModel };