Initial project commit
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
/* Image Picker for Admin - media library modal + upload */
|
||||
(function () {
|
||||
var _currentField = null;
|
||||
var _modal = null;
|
||||
var _gallery = null;
|
||||
var _loading = null;
|
||||
|
||||
function ensureModal() {
|
||||
if (_modal) return;
|
||||
var html =
|
||||
'<div id="image-picker-modal" class="ip-modal-overlay" style="display:none">' +
|
||||
'<div class="ip-modal">' +
|
||||
'<div class="ip-modal-header">' +
|
||||
'<h3>素材库</h3>' +
|
||||
'<div class="ip-modal-header-actions">' +
|
||||
'<button class="btn btn-sm btn-outline-success" onclick="imagePickerModalUpload()">' +
|
||||
'<i class="fa-solid fa-upload"></i> 上传新图片</button>' +
|
||||
'<input type="file" id="ip-modal-file" accept="image/*" style="display:none" onchange="imagePickerModalFileSelected(this)">' +
|
||||
'<button class="btn btn-sm" onclick="imagePickerClose()">' +
|
||||
'<i class="fa-solid fa-times"></i> 关闭</button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="ip-modal-body">' +
|
||||
'<div id="ip-loading" class="ip-loading">加载中...</div>' +
|
||||
'<div id="ip-gallery" class="ip-gallery"></div>' +
|
||||
'<div id="ip-empty" class="ip-empty" style="display:none">暂无图片,请先上传</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
document.body.insertAdjacentHTML("beforeend", html);
|
||||
_modal = document.getElementById("image-picker-modal");
|
||||
_gallery = document.getElementById("ip-gallery");
|
||||
_loading = document.getElementById("ip-loading");
|
||||
|
||||
_modal.addEventListener("click", function (e) {
|
||||
if (e.target === _modal) imagePickerClose();
|
||||
});
|
||||
}
|
||||
|
||||
function loadGallery() {
|
||||
_loading.style.display = "block";
|
||||
_gallery.innerHTML = "";
|
||||
document.getElementById("ip-empty").style.display = "none";
|
||||
|
||||
fetch("/admin/api/media/list", { credentials: "same-origin" })
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) {
|
||||
_loading.style.display = "none";
|
||||
var images = data.images || [];
|
||||
if (images.length === 0) {
|
||||
document.getElementById("ip-empty").style.display = "block";
|
||||
return;
|
||||
}
|
||||
images.forEach(function (img) {
|
||||
var item = document.createElement("div");
|
||||
item.className = "ip-gallery-item";
|
||||
item.innerHTML =
|
||||
'<img src="' + img.url + '" alt="' + img.name + '">' +
|
||||
'<div class="ip-gallery-name">' + img.name + '</div>';
|
||||
item.addEventListener("click", function () {
|
||||
imagePickerSelect(img.url);
|
||||
});
|
||||
_gallery.appendChild(item);
|
||||
});
|
||||
})
|
||||
.catch(function () {
|
||||
_loading.style.display = "none";
|
||||
_gallery.innerHTML = '<div class="ip-empty">加载失败,请重试</div>';
|
||||
});
|
||||
}
|
||||
|
||||
window.imagePickerOpen = function (fieldId) {
|
||||
_currentField = fieldId;
|
||||
ensureModal();
|
||||
_modal.style.display = "flex";
|
||||
loadGallery();
|
||||
};
|
||||
|
||||
window.imagePickerClose = function () {
|
||||
if (_modal) _modal.style.display = "none";
|
||||
_currentField = null;
|
||||
};
|
||||
|
||||
window.imagePickerSelect = function (url) {
|
||||
if (!_currentField) return;
|
||||
setFieldValue(_currentField, url);
|
||||
imagePickerClose();
|
||||
};
|
||||
|
||||
window.imagePickerClear = function (fieldId) {
|
||||
setFieldValue(fieldId, "");
|
||||
};
|
||||
|
||||
window.imagePickerUpload = function (fieldId) {
|
||||
_currentField = fieldId;
|
||||
document.getElementById("file-" + fieldId).click();
|
||||
};
|
||||
|
||||
window.imagePickerFileSelected = function (fieldId, input) {
|
||||
if (!input.files || !input.files[0]) return;
|
||||
doUpload(input.files[0], fieldId);
|
||||
input.value = "";
|
||||
};
|
||||
|
||||
window.imagePickerModalUpload = function () {
|
||||
document.getElementById("ip-modal-file").click();
|
||||
};
|
||||
|
||||
window.imagePickerModalFileSelected = function (input) {
|
||||
if (!input.files || !input.files[0]) return;
|
||||
doUpload(input.files[0], _currentField, function () {
|
||||
loadGallery();
|
||||
});
|
||||
input.value = "";
|
||||
};
|
||||
|
||||
function doUpload(file, fieldId, callback) {
|
||||
var fd = new FormData();
|
||||
fd.append("file", file);
|
||||
|
||||
var btn = document.querySelector('.ip-modal-header-actions .btn-outline-success');
|
||||
if (btn) {
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> 上传中...';
|
||||
}
|
||||
|
||||
fetch("/admin/api/media/upload", {
|
||||
method: "POST",
|
||||
body: fd,
|
||||
credentials: "same-origin",
|
||||
})
|
||||
.then(function (r) {
|
||||
if (!r.ok) throw new Error("Upload failed");
|
||||
return r.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
if (fieldId) setFieldValue(fieldId, data.url);
|
||||
if (callback) callback();
|
||||
})
|
||||
.catch(function (err) {
|
||||
alert("上传失败: " + err.message);
|
||||
})
|
||||
.finally(function () {
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="fa-solid fa-upload"></i> 上传新图片';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setFieldValue(fieldId, url) {
|
||||
var input = document.getElementById(fieldId);
|
||||
if (input) input.value = url;
|
||||
|
||||
var preview = document.getElementById("preview-" + fieldId);
|
||||
var previewImg = document.getElementById("preview-img-" + fieldId);
|
||||
var urlDisplay = document.getElementById("url-display-" + fieldId);
|
||||
|
||||
if (url) {
|
||||
if (preview) preview.style.display = "block";
|
||||
if (previewImg) previewImg.src = url;
|
||||
if (urlDisplay) urlDisplay.textContent = url;
|
||||
} else {
|
||||
if (preview) preview.style.display = "none";
|
||||
if (previewImg) previewImg.src = "";
|
||||
if (urlDisplay) urlDisplay.textContent = "";
|
||||
}
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user