feat: preview image task inputs in admin

This commit is contained in:
QiuSW
2026-07-20 08:58:34 +08:00
parent 2e222a2aef
commit 8eec0e3db7
9 changed files with 382 additions and 5 deletions
@@ -0,0 +1,110 @@
.image-task-gallery {
margin: 20px 0;
}
.image-task-gallery__grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(144px, 1fr));
gap: 12px;
max-width: 760px;
}
.image-task-gallery__item {
margin: 0;
}
.image-task-gallery__trigger {
display: grid;
width: 144px;
height: 144px;
padding: 0;
overflow: hidden;
cursor: zoom-in;
background: #f6f7f8;
border: 1px solid var(--hairline-color, #d8dadd);
border-radius: 6px;
place-items: center;
}
.image-task-gallery__trigger:focus-visible,
.image-task-preview-dialog__close:focus-visible {
outline: 3px solid var(--focus-color, #417690);
outline-offset: 2px;
}
.image-task-gallery__trigger img {
display: block;
width: 100%;
height: 100%;
object-fit: contain;
}
.image-task-gallery__trigger.is-unavailable img {
display: none;
}
.image-task-gallery__unavailable {
padding: 12px;
color: var(--body-quiet-color, #666);
font-size: 12px;
text-align: center;
}
.image-task-gallery__item figcaption {
margin-top: 6px;
color: var(--body-quiet-color, #666);
font-size: 12px;
}
.image-task-preview-dialog {
width: min(960px, calc(100vw - 32px));
max-height: calc(100vh - 32px);
padding: 16px;
color: var(--body-fg, #333);
background: var(--body-bg, #fff);
border: 0;
border-radius: 6px;
box-shadow: 0 16px 48px rgb(0 0 0 / 30%);
}
.image-task-preview-dialog::backdrop {
background: rgb(0 0 0 / 55%);
}
.image-task-preview-dialog__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-bottom: 12px;
}
.image-task-preview-dialog__header h2 {
margin: 0;
font-size: 16px;
}
.image-task-preview-dialog__close {
min-width: 32px;
min-height: 32px;
padding: 4px 8px;
color: var(--button-fg, #fff);
cursor: pointer;
background: var(--button-bg, #417690);
border: 0;
border-radius: 4px;
}
.image-task-preview-dialog__image {
display: block;
width: auto;
max-width: 100%;
max-height: calc(100vh - 136px);
margin: 0 auto;
object-fit: contain;
}
.image-task-preview-dialog__error {
margin: 0;
color: var(--error-fg, #ba2121);
}
@@ -0,0 +1,60 @@
(function () {
"use strict";
function markImageUnavailable(image) {
const trigger = image.closest(".image-task-gallery__trigger");
if (!trigger) {
return;
}
trigger.classList.add("is-unavailable");
const message = trigger.querySelector(".image-task-gallery__unavailable");
if (message) {
message.hidden = false;
}
}
document.addEventListener("DOMContentLoaded", function () {
const dialog = document.querySelector("[data-image-preview-dialog]");
if (!dialog) {
return;
}
const previewImage = dialog.querySelector("[data-image-preview-image]");
const previewLabel = dialog.querySelector("[data-image-preview-label]");
const previewError = dialog.querySelector("[data-image-preview-error]");
const closeButton = dialog.querySelector("[data-image-preview-close]");
document.querySelectorAll(".image-task-gallery__trigger img").forEach(function (image) {
image.addEventListener("error", function () {
markImageUnavailable(image);
});
});
document.querySelectorAll("[data-image-preview]").forEach(function (trigger) {
trigger.addEventListener("dblclick", function () {
previewLabel.textContent = trigger.dataset.imageLabel || "图片预览";
previewImage.alt = trigger.dataset.imageLabel || "图片预览";
previewError.hidden = true;
previewImage.hidden = false;
previewImage.src = trigger.dataset.imageUrl;
dialog.showModal();
});
});
previewImage.addEventListener("error", function () {
previewImage.hidden = true;
previewError.hidden = false;
});
closeButton.addEventListener("click", function () {
dialog.close();
});
dialog.addEventListener("click", function (event) {
if (event.target === dialog) {
dialog.close();
}
});
});
})();