feat: add toggle for secret coordinates and dimension selection in town editor

This commit is contained in:
zhangyuheng
2026-03-17 00:39:01 +08:00
parent 4dda002f76
commit 802d1a6141
4 changed files with 154 additions and 23 deletions

View File

@@ -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;

View File

@@ -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",

View File

@@ -211,13 +211,26 @@ document.addEventListener('DOMContentLoaded', () => {
recruitBadge.innerHTML = '<i class="fas ' + getRecruitIcon(item.recruitment) + '"></i> ' + 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 = '<i class="fas fa-map-marker-alt"></i> 位置信息';
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 += '<div class="preview-detail-body">';
html += '<div class="preview-section">';
html += '<h4 class="preview-section-title"><i class="fas fa-map-marker-alt"></i> 位置信息</h4>';
html += '<p class="preview-inline-text">主世界: X: ' + escapeHtml(x) + ', Y: ' + escapeHtml(y) + ', Z: ' + escapeHtml(z) + '</p>';
html += '<h4 class="preview-section-title"><i class="fas fa-map-marker-alt"></i> ' + (isSecret ? '位置信息(保密)' : '位置信息') + '</h4>';
if (isSecret) {
html += '<p class="preview-inline-text">坐标保密</p>';
} else {
html += '<p class="preview-inline-text">' + escapeHtml(getDimensionText(dimension)) + ': X: ' + escapeHtml(x) + ', Y: ' + escapeHtml(y) + ', Z: ' + escapeHtml(z) + '</p>';
}
html += '</div>';
html += '<div class="preview-section">';
@@ -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';

View File

@@ -140,10 +140,10 @@
</div>
<div class="town-modal-body">
<div class="modal-section">
<h4 class="modal-section-title"><i class="fas fa-map-marker-alt"></i> 位置信息</h4>
<div class="modal-section" id="town-modal-location-section">
<h4 class="modal-section-title" id="town-modal-location-title"><i class="fas fa-map-marker-alt"></i> 位置信息</h4>
<p>
主世界:
<span id="town-modal-dimension"></span>
<span id="town-modal-coords"></span>
<a href="#" target="_blank" id="town-modal-map-link" class="town-map-link">
<i class="fas fa-map-marked-alt"></i> 查看地图
@@ -261,7 +261,32 @@
</div>
</div>
</div>
<div class="form-row coords-row">
<div class="form-group">
<label class="toggle-label">
<span>坐标保密</span>
<div class="toggle-switch">
<input type="checkbox" id="editor-town-secret">
<span class="toggle-slider"></span>
</div>
</label>
<p class="field-hint">开启后将隐藏坐标信息,适用于不希望公开位置的城镇。</p>
</div>
<div class="form-group" id="editor-dimension-group">
<label>所在世界</label>
<div class="custom-select">
<input type="hidden" id="editor-town-dimension" value="overworld">
<div class="custom-select-trigger">
<span class="custom-select-text">主世界</span>
<i class="fas fa-chevron-down"></i>
</div>
<div class="custom-select-options">
<div class="custom-option selected" data-value="overworld">主世界</div>
<div class="custom-option" data-value="nether">下界</div>
<div class="custom-option" data-value="the_end">末地</div>
</div>
</div>
</div>
<div class="form-row coords-row" id="editor-coords-row">
<div class="form-group">
<label for="editor-town-x">X 坐标</label>
<input type="number" id="editor-town-x" placeholder="0">