Cập nhật chế độ quản lí scene trong dashboard của người dùng

This commit is contained in:
2026-06-08 20:25:00 +07:00
parent d1aa2209a7
commit 37f1984e8b
6 changed files with 218 additions and 57 deletions
+57 -10
View File
@@ -568,21 +568,67 @@ router.put('/scenes/:id', protect, uploadSinglePanorama, async (req, res) => {
*/
router.delete('/scenes/:id', protect, async (req, res) => {
try {
const scene = await Scene.findById(req.params.id);
if (!scene || scene.createdBy.toString() !== req.user._id.toString()) {
return res.status(403).json({ message: 'Not authorized' });
const rootSceneId = req.params.id;
const rootScene = await Scene.findById(rootSceneId);
if (!rootScene) {
return res.status(404).json({ message: 'Scene không tồn tại' });
}
// Delete physical file if exists
const asset = await Asset.findById(scene.assetId);
if (asset && fs.existsSync(asset.filePath)) {
fs.unlinkSync(asset.filePath);
// Kiểm tra quyền: Người tạo hoặc Admin
const isAdmin = req.user.role === 'Chủ sở hữu' || req.user.role === 'admin';
const isOwner = rootScene.createdBy.toString() === req.user._id.toString();
if (!isAdmin && !isOwner) {
return res.status(403).json({ message: 'Bạn không có quyền xóa scene này' });
}
await Asset.findByIdAndDelete(scene.assetId);
await Scene.findByIdAndDelete(req.params.id);
// 1. Tìm tất cả scene con dây chuyền (BFS)
let scenesToDelete = [rootSceneId.toString()];
let queue = [rootSceneId.toString()];
res.json({ message: 'Scene deleted successfully' });
while (queue.length > 0) {
const parentId = queue.shift();
const childHotspots = await Hotspot.find({ parent_scene_id: parentId });
for (const hs of childHotspots) {
if (hs.target_scene_id) {
const targetIdStr = hs.target_scene_id.toString();
if (!scenesToDelete.includes(targetIdStr)) {
scenesToDelete.push(targetIdStr);
queue.push(targetIdStr);
}
}
}
}
// 2. Xử lý xóa Asset và File vật lý cho toàn bộ danh sách
const scenes = await Scene.find({ _id: { $in: scenesToDelete } });
const assetIds = scenes.map(s => s.assetId).filter(id => id);
const assets = await Asset.find({ _id: { $in: assetIds } });
for (const asset of assets) {
if (asset.filePath && fs.existsSync(asset.filePath)) {
try { fs.unlinkSync(asset.filePath); } catch (e) { console.error(e); }
}
}
// 3. Xóa Hotspot: Cả hotspot xuất phát từ và trỏ đến các scene bị xóa
await Hotspot.deleteMany({
$or: [
{ parent_scene_id: { $in: scenesToDelete } },
{ target_scene_id: { $in: scenesToDelete } }
]
});
// 4. Xóa dữ liệu trong DB
await Asset.deleteMany({ _id: { $in: assetIds } });
await Scene.deleteMany({ _id: { $in: scenesToDelete } });
res.json({
message: scenesToDelete.length > 1
? `Đã xóa vĩnh viễn scene và ${scenesToDelete.length - 1} scene con liên quan.`
: 'Đã xóa scene thành công.'
});
} catch (error) {
res.status(500).json({ message: error.message });
}
@@ -633,6 +679,7 @@ router.put('/me/profile', protect, async (req, res) => {
router.get('/me/scenes', protect, async (req, res) => {
try {
const scenes = await Scene.find({ createdBy: req.user._id })
.populate('createdBy', 'username')
.populate('assetId')
.sort({ createdAt: -1 });
res.json(scenes);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 MiB