forked from UKSOURCE/cms.hailearning.edu.vn
186 lines
5.2 KiB
JavaScript
186 lines
5.2 KiB
JavaScript
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);
|