From 802d1a6141ba86df00e211a3fad619165e17476e Mon Sep 17 00:00:00 2001 From: zhangyuheng Date: Tue, 17 Mar 2026 00:39:01 +0800 Subject: [PATCH] feat: add toggle for secret coordinates and dimension selection in town editor --- css/pages/towns.css | 55 ++++++++++++++++++++++++++++++ data/towns.json | 7 ++-- js/towns_script.js | 82 +++++++++++++++++++++++++++++++++++++-------- towns.html | 33 +++++++++++++++--- 4 files changed, 154 insertions(+), 23 deletions(-) diff --git a/css/pages/towns.css b/css/pages/towns.css index a8bc8a0..a3b0c78 100644 --- a/css/pages/towns.css +++ b/css/pages/towns.css @@ -1210,6 +1210,61 @@ color: var(--text-secondary); } +/* Toggle Switch */ +.town-editor-modal-content .toggle-label { + display: flex; + align-items: center; + justify-content: space-between; + font-weight: 600; + font-size: 14px; + color: var(--text-primary); + cursor: pointer; +} + +.toggle-switch { + position: relative; + width: 44px; + height: 24px; + flex-shrink: 0; +} + +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; + position: absolute; +} + +.toggle-slider { + position: absolute; + inset: 0; + background: #ccc; + border-radius: 24px; + transition: 0.25s; + cursor: pointer; +} + +.toggle-slider::before { + content: ""; + position: absolute; + width: 18px; + height: 18px; + left: 3px; + bottom: 3px; + background: #fff; + border-radius: 50%; + transition: 0.25s; + box-shadow: 0 1px 3px rgba(0,0,0,0.2); +} + +.toggle-switch input:checked + .toggle-slider { + background: var(--accent-color, #0071e3); +} + +.toggle-switch input:checked + .toggle-slider::before { + transform: translateX(20px); +} + /* Tags Input */ .town-editor-modal-content .tags-input-wrapper { display: flex; diff --git a/data/towns.json b/data/towns.json index 1b716ca..1d4438b 100644 --- a/data/towns.json +++ b/data/towns.json @@ -6,11 +6,8 @@ "from": "#95ea66", "to": "#4aa18b" }, - "coordinates": { - "x": 0, - "y": 64, - "z": 0 - }, + "dimension": "overworld", + "coordinatesSecret": true, "scale": "small", "townType": "building", "recruitment": "closed", diff --git a/js/towns_script.js b/js/towns_script.js index 279d9cc..2a5c809 100644 --- a/js/towns_script.js +++ b/js/towns_script.js @@ -211,13 +211,26 @@ document.addEventListener('DOMContentLoaded', () => { recruitBadge.innerHTML = ' ' + getRecruitText(item.recruitment); badgesContainer.appendChild(recruitBadge); - // Coordinates - var coords = item.coordinates; - document.getElementById('town-modal-coords').innerText = 'X: ' + coords.x + ', Y: ' + coords.y + ', Z: ' + coords.z; - - // Map Link + // Coordinates & Dimension + var coords = item.coordinates || { x: 0, y: 64, z: 0 }; + var dimension = item.dimension || 'overworld'; + var isSecret = item.coordinatesSecret === true; + var locationTitleEl = document.getElementById('town-modal-location-title'); + var dimensionEl = document.getElementById('town-modal-dimension'); + var coordsEl = document.getElementById('town-modal-coords'); var mapLink = document.getElementById('town-modal-map-link'); - mapLink.href = 'https://mcmap.lunadeer.cn/#world:' + coords.x + ':' + coords.y + ':' + coords.z + ':500:0:0:0:1:flat'; + + locationTitleEl.innerHTML = ' 位置信息'; + if (isSecret) { + dimensionEl.innerText = ''; + coordsEl.innerText = '保密'; + mapLink.style.display = 'none'; + } else { + dimensionEl.innerText = getDimensionText(dimension) + ': '; + coordsEl.innerText = 'X: ' + coords.x + ', Y: ' + coords.y + ', Z: ' + coords.z; + mapLink.style.display = ''; + mapLink.href = 'https://mcmap.lunadeer.cn/#' + getDimensionMapWorld(dimension) + ':' + coords.x + ':' + coords.y + ':' + coords.z + ':500:0:0:0:1:flat'; + } // Founders var foundersContainer = document.getElementById('town-modal-founders'); @@ -342,6 +355,16 @@ document.addEventListener('DOMContentLoaded', () => { return map[recruitment] || 'fa-info-circle'; } + function getDimensionText(dimension) { + var map = { 'overworld': '主世界', 'nether': '下界', 'the_end': '末地' }; + return map[dimension] || '主世界'; + } + + function getDimensionMapWorld(dimension) { + var map = { 'overworld': 'world', 'nether': 'world_nether', 'the_end': 'world_the_end' }; + return map[dimension] || 'world'; + } + function normalizeHexColor(value, fallback) { if (!value || typeof value !== 'string') return fallback; var trimmed = value.trim(); @@ -496,6 +519,11 @@ document.addEventListener('DOMContentLoaded', () => { setCustomSelectValue('editor-town-scale', item ? item.scale : 'small'); setCustomSelectValue('editor-town-type', item ? item.townType : 'building'); setCustomSelectValue('editor-town-recruit', item ? item.recruitment : 'welcome'); + setCustomSelectValue('editor-town-dimension', item && item.dimension ? item.dimension : 'overworld'); + + var secretCheckbox = document.getElementById('editor-town-secret'); + secretCheckbox.checked = item ? (item.coordinatesSecret === true) : false; + toggleCoordsRow(); document.getElementById('editor-town-x').value = item ? item.coordinates.x : ''; document.getElementById('editor-town-y').value = item ? item.coordinates.y : ''; @@ -701,7 +729,7 @@ document.addEventListener('DOMContentLoaded', () => { // --- Live Preview --- ['editor-town-title', 'editor-town-logo', 'editor-town-scale', 'editor-town-type', - 'editor-town-recruit', 'editor-town-x', 'editor-town-y', 'editor-town-z'].forEach(function(id) { + 'editor-town-recruit', 'editor-town-dimension', 'editor-town-x', 'editor-town-y', 'editor-town-z'].forEach(function(id) { var el = document.getElementById(id); el.addEventListener('input', updatePreview); el.addEventListener('change', updatePreview); @@ -713,6 +741,20 @@ document.addEventListener('DOMContentLoaded', () => { el.addEventListener('change', updatePreview); }); + // Secret coordinates toggle + function toggleCoordsRow() { + var secret = document.getElementById('editor-town-secret').checked; + var dimensionGroup = document.getElementById('editor-dimension-group'); + var coordsRow = document.getElementById('editor-coords-row'); + dimensionGroup.style.display = secret ? 'none' : ''; + coordsRow.style.display = secret ? 'none' : ''; + } + + document.getElementById('editor-town-secret').addEventListener('change', function() { + toggleCoordsRow(); + updatePreview(); + }); + function updatePreview() { var preview = document.getElementById('town-editor-preview-area'); var title = document.getElementById('editor-town-title').value || '未命名城镇'; @@ -723,6 +765,8 @@ document.addEventListener('DOMContentLoaded', () => { var x = document.getElementById('editor-town-x').value || '0'; var y = document.getElementById('editor-town-y').value || '64'; var z = document.getElementById('editor-town-z').value || '0'; + var dimension = document.getElementById('editor-town-dimension').value || 'overworld'; + var isSecret = document.getElementById('editor-town-secret').checked; var gradient = { from: normalizeHexColor(document.getElementById('editor-town-gradient-from').value, DEFAULT_GRADIENT.from), to: normalizeHexColor(document.getElementById('editor-town-gradient-to').value, DEFAULT_GRADIENT.to) @@ -748,8 +792,12 @@ document.addEventListener('DOMContentLoaded', () => { html += '
'; html += '
'; - html += '

位置信息

'; - html += '

主世界: X: ' + escapeHtml(x) + ', Y: ' + escapeHtml(y) + ', Z: ' + escapeHtml(z) + '

'; + html += '

' + (isSecret ? '位置信息(保密)' : '位置信息') + '

'; + if (isSecret) { + html += '

坐标保密

'; + } else { + html += '

' + escapeHtml(getDimensionText(dimension)) + ': X: ' + escapeHtml(x) + ', Y: ' + escapeHtml(y) + ', Z: ' + escapeHtml(z) + '

'; + } html += '
'; html += '
'; @@ -810,6 +858,7 @@ document.addEventListener('DOMContentLoaded', () => { return; } + var isSecret = document.getElementById('editor-town-secret').checked; var townObj = { title: title, logo: document.getElementById('editor-town-logo').value.trim(), @@ -817,11 +866,8 @@ document.addEventListener('DOMContentLoaded', () => { from: normalizeHexColor(document.getElementById('editor-town-gradient-from').value, DEFAULT_GRADIENT.from), to: normalizeHexColor(document.getElementById('editor-town-gradient-to').value, DEFAULT_GRADIENT.to) }, - coordinates: { - x: parseInt(document.getElementById('editor-town-x').value) || 0, - y: parseInt(document.getElementById('editor-town-y').value) || 64, - z: parseInt(document.getElementById('editor-town-z').value) || 0 - }, + dimension: document.getElementById('editor-town-dimension').value || 'overworld', + coordinatesSecret: isSecret, scale: document.getElementById('editor-town-scale').value, townType: document.getElementById('editor-town-type').value, recruitment: document.getElementById('editor-town-recruit').value, @@ -832,6 +878,14 @@ document.addEventListener('DOMContentLoaded', () => { }) }; + if (!isSecret) { + townObj.coordinates = { + x: parseInt(document.getElementById('editor-town-x').value) || 0, + y: parseInt(document.getElementById('editor-town-y').value) || 64, + z: parseInt(document.getElementById('editor-town-z').value) || 0 + }; + } + var jsonStr = JSON.stringify(townObj, null, 4); document.getElementById('town-json-output').value = jsonStr; jsonOutputModal.style.display = 'block'; diff --git a/towns.html b/towns.html index 3861753..1527050 100644 --- a/towns.html +++ b/towns.html @@ -140,10 +140,10 @@
-
-
+
+ +

开启后将隐藏坐标信息,适用于不希望公开位置的城镇。

+
+
+ +
+ +
+ 主世界 + +
+
+
主世界
+
下界
+
末地
+
+
+
+