first commit

This commit is contained in:
r2xrzh9q2z-lab
2026-02-02 11:07:09 +07:00
commit d1b931d547
286 changed files with 53992 additions and 0 deletions

185
models/menuHeader.js Normal file
View File

@@ -0,0 +1,185 @@
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);