Cập nhật chế độ quản lí scene trong dashboard của người dùng
This commit is contained in:
+57
-10
@@ -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 |
Reference in New Issue
Block a user