Thêm tính năng hiển thị ảnh ở quản lí ảnh và media

This commit is contained in:
2026-06-08 18:08:49 +07:00
parent 9e2b4e636a
commit 965be4d0e7
3 changed files with 255 additions and 1 deletions
+111
View File
@@ -1200,6 +1200,114 @@ async function loadMyScenes() {
}
}
/**
* Tải và hiển thị kho ảnh/media của người dùng
*/
async function loadMyAssets() {
const token = localStorage.getItem('jwt');
const gridContainer = document.getElementById('media-library-list');
const currentUserId = localStorage.getItem('userId');
const userRole = localStorage.getItem('role');
gridContainer.innerHTML = '<p>Đang tải kho ảnh...</p>';
try {
const res = await fetch(`${API_BASE_URL}/me/assets`, {
headers: { 'Authorization': `Bearer ${token}` }
});
const assets = await res.json();
if (!res.ok) throw new Error(assets.message);
gridContainer.innerHTML = '';
if (assets.length === 0) {
gridContainer.innerHTML = '<p>Kho ảnh trống.</p>';
return;
}
assets.forEach(asset => {
const scene = asset.linkedScene;
const isTrash = !scene;
const parentNames = asset.parentScenes?.map(p => p.name || p.title).join(', ');
const card = document.createElement('div');
card.className = `media-card ${isTrash ? 'trash-item' : ''}`;
// Build inner HTML without the onclick for edit/delete buttons
let innerHtml = `
<div class="media-thumb">
<img src="${API_BASE_URL}/assets/view/${asset._id}?token=${token}" alt="Thumbnail">
${isTrash ? '<span class="badge-trash">Ảnh rác</span>' : ''}
</div>
<div class="media-info">
<strong>${scene ? (scene.name || scene.title) : 'Chưa gắn Scene'}</strong>
<p class="desc">${scene?.description || 'Không có mô tả'}</p>
${parentNames ? `<p class="parent-link">🔗 Liên kết từ: ${parentNames}</p>` : ''}
<span class="date">Tải lên: ${formatSystemDate(asset.createdAt)}</span>
</div>
<div class="media-actions">
</div>
`;
card.innerHTML = innerHtml;
// Add edit button and its event listener separately
if (scene && asset.uploadedBy === currentUserId) {
const editButton = document.createElement('button');
editButton.className = 'edit-btn-small';
editButton.innerText = 'Sửa Scene';
editButton.addEventListener('click', () => openEditFromMedia(scene)); // Pass scene object directly
card.querySelector('.media-actions').appendChild(editButton);
}
// Add delete button and its event listener
if (asset.uploadedBy === currentUserId || (isTrash && userRole === 'Chủ sở hữu')) {
const deleteButton = document.createElement('button');
deleteButton.className = 'delete-btn-small';
deleteButton.innerText = 'Xóa';
deleteButton.addEventListener('click', () => deleteAsset(asset._id));
card.querySelector('.media-actions').appendChild(deleteButton);
}
gridContainer.appendChild(card);
});
} catch (e) {
gridContainer.innerHTML = `<p style="color:#ff4d4d">Lỗi nạp media: ${e.message}</p>`;
}
}
/**
* Xóa ảnh khỏi kho media
*/
window.deleteAsset = async function(assetId) {
if (!confirm('Bạn có chắc chắn muốn xóa ảnh này? Nếu ảnh đang được gắn vào một cảnh, cảnh đó cũng sẽ bị xóa vĩnh viễn.')) {
return;
}
const token = localStorage.getItem('jwt');
try {
const res = await fetch(`${API_BASE_URL}/assets/${assetId}`, {
method: 'DELETE',
headers: { 'Authorization': `Bearer ${token}` }
});
const data = await res.json();
if (!res.ok) throw new Error(data.message);
alert(data.message);
loadMyAssets(); // Nạp lại kho ảnh
loadScenes(); // Nạp lại bản đồ nếu có scene bị xóa kèm theo
} catch (e) {
alert("Lỗi khi xóa: " + e.message);
}
};
window.openEditFromMedia = function(scene) {
if (!scene || !scene._id) {
alert("Không thể chỉnh sửa: Ảnh này không được gắn với một Scene hợp lệ.");
return;
}
openEditSceneModal(scene);
};
/**
* Opens a specific tab within the dashboard.
* @param {string} tabName - The ID of the tab pane to open (e.g., 'profile', 'my-scenes').
@@ -1225,6 +1333,9 @@ function openDashboardTab(tabName) {
if (tabName === 'my-scenes') {
loadMyScenes();
}
if (tabName === 'media-library') {
loadMyAssets();
}
}
// Đánh dấu nút tab được chọn là active