const mongoose = require('mongoose'); const MenuSchema = new mongoose.Schema({ menuid: { type: String, required: true, unique: true }, // ID tùy chỉnh parent: { type: String, default: null }, // ID menu cha title: { type: String, required: true }, // Tên hiển thị url: { type: String, default: '' }, // Đường dẫn order: { type: Number, default: 0 }, // Thứ tự hiển thị type: { type: String, enum: ['static', 'page', 'level'], default: 'static' }, // Loại menu fetch: { type: Boolean, default: false }, // Có fetch programme không isActive: { type: Boolean, default: true } // Trạng thái hoạt động của menu }, { timestamps: false }); // Index để tối ưu query MenuSchema.index({ parent: 1, order: 1 }); MenuSchema.index({ type: 1 }); // Method để lấy menu tree MenuSchema.statics.getMenuTree = async function () { try { const allMenus = await this.find().sort({ order: 1 }).lean(); const menuMap = new Map(); const rootMenus = []; // Đưa tất cả menus vào map và xử lý URL dựa trên isActive allMenus.forEach(menu => { const activeUrl = menu.isActive === false ? '/maintenance/' : menu.url; menuMap.set(menu.menuid, { ...menu, url: activeUrl, // Sử dụng URL đã được xử lý children: [] }); }); // Xây dựng tree structure allMenus.forEach(menu => { const menuObj = menuMap.get(menu.menuid); if (!menu.parent) { rootMenus.push(menuObj); } else { const parent = menuMap.get(menu.parent); if (parent) { parent.children.push(menuObj); } } }); return rootMenus; } catch (error) { console.error('Error building menu tree:', error); throw error; } }; // Method để lấy menu tree với programmes MenuSchema.statics.getMenuTreeWithProgrammes = async function () { try { const menuTree = await this.getMenuTree(); // Thêm programmes cho các menu level for (const menu of menuTree) { await this.addProgrammesToMenu(menu); } return menuTree; } catch (error) { console.error('Error building menu tree with programmes:', error); throw error; } }; // Method để thêm programmes vào menu MenuSchema.statics.addProgrammesToMenu = async function (menuItem) { try { if (menuItem.type === 'level' && menuItem.fetch) { const programmes = await this.getProgrammesByMenuId(menuItem.menuid); menuItem.programmes = programmes; } if (menuItem.children && menuItem.children.length > 0) { for (const child of menuItem.children) { await this.addProgrammesToMenu(child); } } } catch (error) { console.error('Error adding programmes to menu:', error); throw error; } }; // Method để lấy programmes theo menu ID MenuSchema.statics.getProgrammesByMenuId = async function (menuId) { try { const Programme = require('./programme'); const Level = require('./level'); // Sử dụng trực tiếp menuId làm levelType vì menuid đã được đặt đúng khi tạo const levelType = menuId; const level = await Level.findOne({ type: levelType }); if (!level) return []; const programmes = await Programme.find({ level: level._id }) .select('name code level_type') .sort({ name: 1 }) .lean(); return programmes; } catch (error) { console.error('Error getting programmes by menu ID:', error); throw error; } }; // Method để tạo menu mới MenuSchema.statics.createMenu = async function (menuData) { try { const menu = new this(menuData); await menu.save(); return menu; } catch (error) { console.error('Error creating menu:', error); throw error; } }; // Method để cập nhật menu MenuSchema.statics.updateMenu = async function (menuId, updateData) { try { const menu = await this.findOneAndUpdate({ menuid: menuId }, updateData, { new: true }); return menu; } catch (error) { console.error('Error updating menu:', error); throw error; } }; // Method để xóa menu MenuSchema.statics.deleteMenu = async function (menuId) { try { // Xóa tất cả children trước await this.deleteMany({ parent: menuId }); // Sau đó xóa menu chính const result = await this.findOneAndDelete({ menuid: menuId }); return result; } catch (error) { console.error('Error deleting menu:', error); throw error; } }; // Method để sắp xếp lại order MenuSchema.statics.reorderMenus = async function (parentId, menuIds) { try { const updates = menuIds.map((menuId, index) => ({ updateOne: { filter: { menuid: menuId }, update: { order: index } } })); await this.bulkWrite(updates); console.log('Menus reordered successfully'); } catch (error) { console.error('Error reordering menus:', error); throw error; } }; // Method để lấy URL dựa trên trạng thái isActive MenuSchema.methods.getActiveUrl = function () { if (this.isActive === false) { return '/maintenance/'; } return this.url; }; // Method để kiểm tra trạng thái hoạt động MenuSchema.methods.isMenuActive = function () { return this.isActive !== false; }; module.exports = mongoose.model('MenuHeader', MenuSchema);