feat: add Guanghan module detail modal
Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
@@ -153,10 +153,93 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
body.modal-open { overflow: hidden; }
|
||||
|
||||
.modal-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 20;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
background: rgba(2, 7, 14, 0.82);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.modal-backdrop[aria-hidden="false"] { display: flex; }
|
||||
|
||||
.detail-dialog {
|
||||
position: relative;
|
||||
width: min(760px, 100%);
|
||||
max-height: min(820px, calc(100vh - 48px));
|
||||
overflow: auto;
|
||||
padding: 30px;
|
||||
border: 1px solid #405572;
|
||||
border-radius: 18px;
|
||||
outline: none;
|
||||
background: linear-gradient(145deg, #13233a, #0b1424 72%);
|
||||
box-shadow: 0 30px 100px rgba(0, 0, 0, 0.64);
|
||||
}
|
||||
|
||||
.detail-dialog:focus-visible { box-shadow: 0 0 0 3px var(--pressurized), 0 30px 100px rgba(0, 0, 0, 0.64); }
|
||||
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 14px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 1px solid #4e627e;
|
||||
border-radius: 50%;
|
||||
background: #182a43;
|
||||
color: var(--text);
|
||||
font: 500 1.65rem/1 system-ui, sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-close:hover,
|
||||
.modal-close:focus-visible { border-color: var(--pressurized); outline: none; background: #203754; }
|
||||
|
||||
.detail-kicker {
|
||||
margin: 0 46px 6px 0;
|
||||
color: var(--pressurized);
|
||||
font-size: 0.77rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#detail-title { margin: 0 50px 10px 0; font-size: 1.85rem; }
|
||||
#detail-role { margin: 0 0 22px; color: #c4d2e4; line-height: 1.7; }
|
||||
|
||||
.detail-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.detail-grid > div {
|
||||
min-width: 0;
|
||||
padding: 14px;
|
||||
border: 1px solid #293c57;
|
||||
border-radius: 10px;
|
||||
background: rgba(8, 18, 33, 0.7);
|
||||
}
|
||||
|
||||
.detail-grid dt { margin-bottom: 7px; color: #7f94b1; font-size: 0.75rem; }
|
||||
.detail-grid dd { margin: 0; color: #e1ebf8; line-height: 1.55; overflow-wrap: anywhere; }
|
||||
.detail-grid dd span { display: block; }
|
||||
.detail-grid dd span + span { margin-top: 4px; }
|
||||
|
||||
@media (max-width: 760px) {
|
||||
body { padding: 14px; }
|
||||
.topology-map { min-width: 980px; }
|
||||
.legend { justify-content: flex-start; }
|
||||
.modal-backdrop { padding: 12px; }
|
||||
.detail-dialog { padding: 25px 18px 20px; max-height: calc(100vh - 24px); }
|
||||
.detail-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@@ -331,6 +414,23 @@
|
||||
<p class="click-note">模块与车辆支持详情查看;走道、管线和散热面板仅用于表达拓扑关系。</p>
|
||||
</main>
|
||||
|
||||
<div class="modal-backdrop" id="detail-modal" aria-hidden="true">
|
||||
<section class="detail-dialog" role="dialog" aria-modal="true" aria-labelledby="detail-title" tabindex="-1">
|
||||
<button class="modal-close" type="button" aria-label="关闭详情">×</button>
|
||||
<p class="detail-kicker" id="detail-type"></p>
|
||||
<h2 id="detail-title"></h2>
|
||||
<p id="detail-role"></p>
|
||||
<dl class="detail-grid">
|
||||
<div><dt>安装位置</dt><dd id="detail-location"></dd></div>
|
||||
<div><dt>运行状态</dt><dd id="detail-status"></dd></div>
|
||||
<div><dt>关键参数</dt><dd id="detail-metrics"></dd></div>
|
||||
<div><dt>尺寸</dt><dd id="detail-dimensions"></dd></div>
|
||||
<div><dt>连接关系</dt><dd id="detail-connections"></dd></div>
|
||||
<div><dt>任务节点</dt><dd id="detail-mission"></dd></div>
|
||||
</dl>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const MODULE_DETAILS = {
|
||||
"core": {
|
||||
@@ -488,6 +588,61 @@
|
||||
mission: "BL-03 · 2024-09-23首次着陆;GHC-05转运广寒03模块"
|
||||
}
|
||||
};
|
||||
|
||||
const modal = document.querySelector("#detail-modal");
|
||||
const dialog = modal.querySelector(".detail-dialog");
|
||||
const closeButton = modal.querySelector(".modal-close");
|
||||
let opener = null;
|
||||
|
||||
function renderLines(element, items) {
|
||||
element.replaceChildren(...items.map((item) => {
|
||||
const line = document.createElement("span");
|
||||
line.textContent = item;
|
||||
return line;
|
||||
}));
|
||||
}
|
||||
|
||||
function openDetails(moduleId, trigger) {
|
||||
const detail = MODULE_DETAILS[moduleId];
|
||||
if (!detail) return;
|
||||
opener = trigger;
|
||||
document.querySelector("#detail-type").textContent = detail.type;
|
||||
document.querySelector("#detail-title").textContent = detail.name;
|
||||
document.querySelector("#detail-role").textContent = detail.role;
|
||||
document.querySelector("#detail-location").textContent = detail.location;
|
||||
document.querySelector("#detail-status").textContent = detail.status;
|
||||
renderLines(document.querySelector("#detail-metrics"), detail.metrics);
|
||||
renderLines(document.querySelector("#detail-dimensions"), detail.dimensions);
|
||||
renderLines(document.querySelector("#detail-connections"), detail.connections);
|
||||
document.querySelector("#detail-mission").textContent = detail.mission;
|
||||
modal.setAttribute("aria-hidden", "false");
|
||||
document.body.classList.add("modal-open");
|
||||
dialog.focus();
|
||||
}
|
||||
|
||||
function closeDetails() {
|
||||
modal.setAttribute("aria-hidden", "true");
|
||||
document.body.classList.remove("modal-open");
|
||||
opener?.focus();
|
||||
}
|
||||
|
||||
document.querySelectorAll("[data-module]").forEach((node) => {
|
||||
node.addEventListener("click", () => openDetails(node.dataset.module, node));
|
||||
node.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
openDetails(node.dataset.module, node);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
closeButton.addEventListener("click", closeDetails);
|
||||
modal.addEventListener("click", (event) => {
|
||||
if (event.target === modal) closeDetails();
|
||||
});
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape" && modal.getAttribute("aria-hidden") === "false") closeDetails();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user