feat: Add facilities page with data, styles, and functionality for resource sharing

This commit is contained in:
zhangyuheng
2026-03-05 11:43:35 +08:00
parent f7a875fe21
commit 8bdcdcd739
5 changed files with 957 additions and 0 deletions

474
css/pages/facilities.css Normal file
View File

@@ -0,0 +1,474 @@
/* Page-Specific Styles for Facilities */
.facilities-hero {
margin-top: 44px; /* Navbar height */
padding: 100px 20px 60px;
text-align: center;
background: linear-gradient(135deg, #e0c3fc 0%, #8ec5fc 100%);
color: #1d1d1f;
}
.facilities-hero h1 {
font-size: 48px;
font-weight: 700;
margin-bottom: 16px;
letter-spacing: -0.02em;
}
.hero-subtitle {
font-size: 20px;
font-weight: 400;
opacity: 0.8;
}
/* Container */
.facilities-container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
/* Controls - Redesigned */
.controls-section {
background: var(--card-bg);
padding: 30px;
border-radius: var(--radius-large);
box-shadow: 0 4px 20px rgba(0,0,0,0.05);
margin-bottom: 40px;
}
.controls-header-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
flex-wrap: wrap;
gap: 20px;
}
.section-title {
font-size: 24px;
font-weight: 600;
color: var(--text-primary);
margin: 0;
}
.search-box {
position: relative;
max-width: 400px;
width: 100%;
}
.search-box i {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
color: var(--text-secondary);
}
.search-box input {
width: 100%;
padding: 10px 16px 10px 44px;
border: 1px solid rgba(0,0,0,0.1);
border-radius: 12px;
font-size: 15px;
background: #f5f5f7;
transition: var(--transition);
}
.search-box input:focus {
outline: none;
background: #fff;
border-color: var(--accent-color);
box-shadow: 0 0 0 4px rgba(0, 113, 227, 0.1);
}
.filters-wrapper {
display: flex;
flex-direction: column;
gap: 16px;
border-top: 1px solid rgba(0,0,0,0.05);
padding-top: 20px;
}
.filter-group {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 12px;
}
.filter-label {
font-weight: 600;
font-size: 14px;
color: var(--text-secondary);
min-width: 70px; /* Align labels */
display: flex;
align-items: center;
gap: 6px;
}
.filter-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.filter-tag {
background: #fff;
border: 1px solid rgba(0,0,0,0.1);
padding: 6px 14px;
border-radius: 18px;
font-size: 13px;
color: var(--text-secondary);
cursor: pointer;
transition: var(--transition);
display: flex;
align-items: center;
gap: 6px;
}
.filter-tag:hover {
background: #f5f5f7;
color: var(--text-primary);
border-color: rgba(0,0,0,0.2);
}
.filter-tag.active {
background: var(--text-primary); /* Use black/dark for active like Apple tags usually do, or accent */
color: white;
border-color: var(--text-primary);
}
/* Facilities Grid & Cards */
.facilities-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 24px;
}
.facility-card {
background: var(--card-bg);
border-radius: var(--radius-medium);
padding: 24px;
box-shadow: 0 2px 12px rgba(0,0,0,0.04); /* Softer shadow */
transition: var(--transition);
cursor: pointer;
display: flex;
flex-direction: column;
justify-content: space-between;
border: 1px solid rgba(0,0,0,0.03);
}
.facility-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 32px rgba(0,0,0,0.08);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 12px;
}
.card-title {
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
flex: 1;
margin-right: 10px;
line-height: 1.3;
}
/* Status Pill in Card */
.status-indicator-badge {
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
font-weight: 600;
padding: 4px 8px;
border-radius: 12px;
white-space: nowrap;
}
.status-indicator-badge.status-online { background-color: #e8fceb; color: #15803d; }
.status-indicator-badge.status-maintenance { background-color: #fff8d6; color: #b45309; }
.status-indicator-badge.status-offline { background-color: #feebeb; color: #b91c1c; }
.status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
}
.status-online .status-dot { background-color: #22c55e; }
.status-maintenance .status-dot { background-color: #f59e0b; }
.status-offline .status-dot { background-color: #ef4444; }
.card-intro {
font-size: 14px;
color: var(--text-secondary);
margin-bottom: 24px;
line-height: 1.5;
flex-grow: 1;
}
.card-meta {
display: flex;
gap: 8px;
flex-wrap: wrap;
border-top: 1px solid #f0f0f0;
padding-top: 16px;
}
.meta-tag {
font-size: 11px;
background: #f5f5f7;
padding: 4px 10px;
border-radius: 6px;
color: var(--text-secondary);
font-weight: 500;
}
/* Modal */
.modal {
display: none;
position: fixed;
z-index: 2000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.facility-modal-content {
background-color: #fff;
margin: 40px auto;
border-radius: var(--radius-large);
max-width: 720px;
width: 90%;
padding: 0; /* Remove padding to handle header separately */
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.3);
position: relative;
max-height: 90vh;
overflow-y: auto;
display: flex;
flex-direction: column;
}
.close-modal {
position: absolute;
top: 20px;
right: 24px;
font-size: 24px;
color: var(--text-secondary);
cursor: pointer;
transition: 0.2s;
z-index: 10;
background: rgba(255,255,255,0.8);
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.close-modal:hover {
background: #f0f0f0;
color: var(--text-primary);
}
.modal-header {
padding: 40px 40px 24px;
background: linear-gradient(to bottom, #fff, #fafafa);
border-bottom: 1px solid rgba(0,0,0,0.05);
}
.modal-title {
font-size: 32px;
font-weight: 700;
margin-bottom: 16px;
line-height: 1.2;
}
.modal-badges {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.large-badge {
padding: 6px 14px;
border-radius: 8px;
font-size: 13px;
font-weight: 600;
display: flex;
align-items: center;
gap: 6px;
}
.badge-status-online { background: #e8fceb; color: #15803d; }
.badge-status-maintenance { background: #fff8d6; color: #b45309; }
.badge-status-offline { background: #feebeb; color: #b91c1c; }
.badge-type { background: #e0f2fe; color: #0369a1; }
.modal-body {
padding: 30px 40px 50px;
}
.modal-section {
margin-top: 32px;
}
.modal-section-title {
font-size: 16px;
font-weight: 700;
margin-bottom: 16px;
color: var(--text-primary);
display: flex;
align-items: center;
gap: 10px;
border-left: 4px solid var(--accent-color);
padding-left: 12px;
}
.modal-section-title i {
color: var(--accent-color);
width: 20px;
text-align: center;
}
.modal-intro {
font-size: 18px;
line-height: 1.6;
color: var(--text-primary);
margin-bottom: 30px;
font-weight: 400;
}
.map-link {
display: inline-flex;
align-items: center;
gap: 6px;
color: #fff;
background: var(--accent-color);
padding: 6px 16px;
border-radius: 20px;
text-decoration: none;
font-weight: 500;
font-size: 13px;
margin-left: 12px;
transition: 0.2s;
}
.map-link:hover {
background: #005bb5;
transform: translateY(-1px);
}
.contributors-list {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.contributor-tag {
display: flex;
align-items: center;
background: #ffffff;
border: 1px solid #eee;
padding: 6px 14px;
border-radius: 30px;
font-size: 14px;
color: var(--text-primary);
box-shadow: 0 2px 4px rgba(0,0,0,0.02);
}
.contributor-tag img {
width: 24px;
height: 24px;
border-radius: 50%;
margin-right: 10px;
background: #eee;
}
/* Instructions & Notes */
.instruction-content, .notes-content {
background: #f9f9fa;
padding: 24px;
border-radius: 16px;
border: 1px solid rgba(0,0,0,0.03);
}
.instruction-content p, .notes-content p {
font-size: 15px;
margin-bottom: 12px;
color: var(--text-primary);
line-height: 1.7;
}
.instruction-content p:last-child, .notes-content p:last-child {
margin-bottom: 0;
}
.instruction-content img, .notes-content img {
max-width: 100%;
border-radius: 12px;
margin: 12px 0 20px;
border: 1px solid rgba(0,0,0,0.05);
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
}
.no-results-message {
text-align: center;
padding: 60px;
color: var(--text-secondary);
font-size: 16px;
background: var(--card-bg);
border-radius: var(--radius-medium);
}
.is-hidden {
display: none !important;
}
@media (max-width: 768px) {
.facilities-hero h1 {
font-size: 32px;
}
.controls-header-row {
flex-direction: column;
align-items: stretch;
}
.search-box {
max-width: 100%;
}
.filter-label {
min-width: auto;
margin-bottom: 4px;
}
.facility-modal-content {
margin: 0;
width: 100%;
height: 100%;
max-height: 100%;
border-radius: 0;
}
.close-modal {
top: 15px;
right: 15px;
}
.modal-body {
padding: 24px 24px 80px;
}
.modal-header {
padding: 60px 24px 20px;
}
}

106
data/facilities.json Normal file
View File

@@ -0,0 +1,106 @@
[
{
"id": "sand-duper",
"title": "公共刷沙机",
"intro": "位于末地的高效刷沙机,支持沙子、红沙、混凝土粉等重力方块的复制。",
"type": "resource",
"dimension": "end",
"status": "online",
"coordinates": {
"x": 1200,
"y": 64,
"z": -500
},
"contributors": ["Alice", "Bob"],
"instructions": [
{"type": "text", "content": "1. 携带需要复制的重力方块(沙子、红沙、混凝土粉等)。"},
{"type": "text", "content": "2. 前往末地主岛刷沙机位置。"},
{"type": "text", "content": "3. 按照指示牌站在指定AFK点位。"},
{"type": "text", "content": "4. 打开拉杆启动机器,确保不要移动。"},
{"type": "text", "content": "5. 收集掉落到末地传送门的物品。"}
],
"notes": [
{"type": "text", "content": "请勿在服务器卡顿严重时使用。"},
{"type": "text", "content": "使用完毕后请务必关闭机器。"}
]
},
{
"id": "gold-farm",
"title": "基岩层猪人塔",
"intro": "位于下界基岩上层的高效金粒与经验获取设施。",
"type": "xp",
"dimension": "nether",
"status": "maintenance",
"coordinates": {
"x": 0,
"y": 250,
"z": 0
},
"contributors": ["Charlie", "David"],
"instructions": [
{"type": "text", "content": "1. 通过地狱交通前往0,0坐标并上到基岩层。"},
{"type": "text", "content": "2. 站在中心挂机点。"},
{"type": "text", "content": "3. 挥剑攻击猪人以获取经验。"}
],
"notes": [
{"type": "text", "content": "目前收集系统正在改造中,只能获取经验,物品会丢失。"}
]
},
{
"id": "iron-farm",
"title": "堆叠式刷铁机",
"intro": "主世界出生点附近的高效铁锭生产设施。",
"type": "resource",
"dimension": "overworld",
"status": "online",
"coordinates": {
"x": 100,
"y": 150,
"z": 100
},
"contributors": ["Eve"],
"instructions": [
{"type": "text", "content": "直接从箱子中拿取铁锭即可。"}
],
"notes": []
},
{
"id": "nether-hub",
"title": "地狱交通中心",
"intro": "连接各个主要生物群系和资源点的冰道枢纽。",
"type": "infrastructure",
"dimension": "nether",
"status": "online",
"coordinates": {
"x": 0,
"y": 120,
"z": 0
},
"contributors": ["Frank", "Grace", "Heidi"],
"instructions": [
{"type": "text", "content": "请携带船只以便快速移动。"},
{"type": "text", "content": "请勿破坏冰道。"}
],
"notes": [
{"type": "text", "content": "前往主岛的线路暂时封闭。"}
]
},
{
"id": "broken-farm",
"title": "旧版刷怪塔",
"intro": "已废弃的旧版本刷怪设施,不再维护。",
"type": "xp",
"dimension": "overworld",
"status": "offline",
"coordinates": {
"x": -500,
"y": 64,
"z": -500
},
"contributors": ["OldPlayer"],
"instructions": [],
"notes": [
{"type": "text", "content": "该设施已损坏,请前往新的刷怪塔。"}
]
}
]

122
facilities.html Normal file
View File

@@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>共享资源 - 白鹿原 Minecraft 服务器</title>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="css/style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="css/pages/facilities.css">
</head>
<body>
<div id="navbar-component"></div>
<div class="facilities-hero">
<h1>全服共享资源</h1>
<p class="hero-subtitle">共同建设,共同分享,让生存更轻松。</p>
</div>
<div class="facilities-container">
<!-- Controls -->
<div class="controls-section">
<div class="controls-header-row">
<h2 class="section-title">设施列表</h2>
<div class="search-box">
<i class="fas fa-search"></i>
<input type="text" id="facility-search" placeholder="搜索设施名称...">
</div>
</div>
<div class="filters-wrapper">
<div class="filter-group">
<div class="filter-label"><i class="fas fa-layer-group"></i> 类型</div>
<div class="filter-tags" id="type-filters">
<button class="filter-tag active" data-filter="all">全部</button>
<button class="filter-tag" data-filter="resource"><i class="fas fa-cube"></i> 资源</button>
<button class="filter-tag" data-filter="xp"><i class="fas fa-star"></i> 经验</button>
<button class="filter-tag" data-filter="infrastructure"><i class="fas fa-road"></i> 基建</button>
</div>
</div>
<div class="filter-group">
<div class="filter-label"><i class="fas fa-globe"></i> 维度</div>
<div class="filter-tags" id="dimension-filters">
<button class="filter-tag active" data-filter="all">全部</button>
<button class="filter-tag" data-filter="overworld">主世界</button>
<button class="filter-tag" data-filter="nether">下界</button>
<button class="filter-tag" data-filter="end">末地</button>
</div>
</div>
</div>
</div>
<!-- Facilities Grid -->
<div class="facilities-grid" id="facilities-list">
<!-- JS will inject cards here -->
</div>
<div id="no-results" class="no-results-message is-hidden">
没有找到匹配的设施
</div>
</div>
<!-- Facility Modal -->
<div id="facility-modal" class="modal">
<div class="modal-content facility-modal-content">
<span class="close-modal">&times;</span>
<div class="modal-header">
<h3 class="modal-title" id="modal-title">设施名称</h3>
<div class="modal-badges" id="modal-badges">
<!-- Badges injected by JS -->
</div>
</div>
<div class="modal-body">
<p class="modal-intro" id="modal-intro">设施简介...</p>
<div class="modal-section">
<h4 class="modal-section-title"><i class="fas fa-map-marker-alt"></i> 位置信息</h4>
<p>
<span id="modal-dimension"></span>:
<span id="modal-coords"></span>
<a href="#" target="_blank" id="modal-map-link" class="map-link">
<i class="fas fa-map-marked-alt"></i> 查看地图
</a>
</p>
</div>
<div class="modal-section">
<h4 class="modal-section-title"><i class="fas fa-users-cog"></i> 贡献/维护人员</h4>
<div class="contributors-list" id="modal-contributors">
<!-- Contributors injected by JS -->
</div>
</div>
<div class="modal-section">
<h4 class="modal-section-title"><i class="fas fa-book-open"></i> 使用说明</h4>
<div class="instruction-content" id="modal-instructions">
<!-- Instructions injected by JS -->
</div>
</div>
<div class="modal-section">
<h4 class="modal-section-title"><i class="fas fa-exclamation-triangle"></i> 注意事项</h4>
<div class="notes-content" id="modal-notes">
<!-- Notes injected by JS -->
</div>
</div>
</div>
</div>
</div>
<div id="footer-component"></div>
<script src="js/components.js"></script>
<script src="js/facilities_script.js"></script>
</body>
</html>

View File

@@ -14,6 +14,7 @@ const Components = {
<div class="nav-links desktop-only"> <div class="nav-links desktop-only">
<a href="/doc.html">文档</a> <a href="/doc.html">文档</a>
<a href="/map.html">地图</a> <a href="/map.html">地图</a>
<a href="/facilities.html">设施</a>
<a href="/photo.html">相册</a> <a href="/photo.html">相册</a>
<a href="/stats.html">数据</a> <a href="/stats.html">数据</a>
<a href="/sponsor.html">赞助</a> <a href="/sponsor.html">赞助</a>
@@ -30,6 +31,7 @@ const Components = {
<div class="mobile-menu-links"> <div class="mobile-menu-links">
<a href="/doc.html">文档</a> <a href="/doc.html">文档</a>
<a href="/map.html">地图</a> <a href="/map.html">地图</a>
<a href="/facilities.html">设施</a>
<a href="/photo.html">相册</a> <a href="/photo.html">相册</a>
<a href="/stats.html">数据</a> <a href="/stats.html">数据</a>
<a href="/sponsor.html">赞助</a> <a href="/sponsor.html">赞助</a>

253
js/facilities_script.js Normal file
View File

@@ -0,0 +1,253 @@
document.addEventListener('DOMContentLoaded', () => {
let facilitiesData = [];
const grid = document.getElementById('facilities-list');
const noResults = document.getElementById('no-results');
const statusFilters = document.getElementById('type-filters'); // Wait, I named it type-filters in HTML
const dimensionFilters = document.getElementById('dimension-filters');
const searchInput = document.getElementById('facility-search');
// Modal Elements
const modal = document.getElementById('facility-modal');
const closeModal = document.querySelector('.close-modal');
// Initial State
let currentFilters = {
type: 'all',
dimension: 'all',
search: ''
};
// 1. Fetch Data
fetch('data/facilities.json')
.then(response => response.json())
.then(data => {
facilitiesData = data;
renderGrid();
})
.catch(err => {
console.error('Error loading facilities:', err);
grid.innerHTML = '<p class="error">无法加载设施数据。</p>';
});
// 2. Event Listeners
// Type Filter
statusFilters.addEventListener('click', (e) => {
if (e.target.tagName === 'BUTTON') {
// Remove active class from siblings
Array.from(statusFilters.children).forEach(btn => btn.classList.remove('active'));
e.target.classList.add('active');
currentFilters.type = e.target.dataset.filter;
renderGrid();
}
});
// Dimension Filter
dimensionFilters.addEventListener('click', (e) => {
if (e.target.tagName === 'BUTTON') {
Array.from(dimensionFilters.children).forEach(btn => btn.classList.remove('active'));
e.target.classList.add('active');
currentFilters.dimension = e.target.dataset.filter;
renderGrid();
}
});
// Search
searchInput.addEventListener('input', (e) => {
currentFilters.search = e.target.value.toLowerCase().trim();
renderGrid();
});
// Modal Close
closeModal.addEventListener('click', () => {
modal.style.display = 'none';
document.body.style.overflow = 'auto'; // Enable scrolling
});
window.addEventListener('click', (e) => {
if (e.target === modal) {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
// 3. Render Functions
function renderGrid() {
grid.innerHTML = '';
const filtered = facilitiesData.filter(item => {
const matchType = currentFilters.type === 'all' || item.type === currentFilters.type;
const matchDim = currentFilters.dimension === 'all' || item.dimension === currentFilters.dimension;
const matchSearch = !currentFilters.search ||
item.title.toLowerCase().includes(currentFilters.search) ||
item.intro.toLowerCase().includes(currentFilters.search);
return matchType && matchDim && matchSearch;
});
if (filtered.length === 0) {
noResults.classList.remove('is-hidden');
return;
} else {
noResults.classList.add('is-hidden');
}
filtered.forEach(item => {
const card = document.createElement('div');
card.className = 'facility-card';
card.onclick = () => openModal(item);
const statusColor = getStatusColor(item.status);
const statusText = getStatusText(item.status);
card.innerHTML = `
<div class="card-header">
<h3 class="card-title">${item.title}</h3>
<div class="status-indicator-badge status-${item.status}">
<div class="status-dot"></div>
<span>${statusText}</span>
</div>
</div>
<p class="card-intro">${item.intro}</p>
<div class="card-meta">
<span class="meta-tag">${getTypeText(item.type)}</span>
<span class="meta-tag">${getDimensionText(item.dimension)}</span>
</div>
`;
grid.appendChild(card);
});
}
function openModal(item) {
// Populate specific fields
document.getElementById('modal-title').innerText = item.title;
document.getElementById('modal-intro').innerText = item.intro;
// Badges
const badgesContainer = document.getElementById('modal-badges');
badgesContainer.innerHTML = '';
// Status Badge
const statusBadge = document.createElement('span');
statusBadge.className = `badge badge-status-${item.status} large-badge`;
statusBadge.innerHTML = `<i class="fas ${getStatusIcon(item.status)}"></i> ${getStatusText(item.status)}`;
badgesContainer.appendChild(statusBadge);
// Type Badge
const typeBadge = document.createElement('span');
typeBadge.className = 'badge badge-type large-badge';
typeBadge.innerHTML = `<i class="fas fa-cube"></i> ${getTypeText(item.type)}`;
badgesContainer.appendChild(typeBadge);
// Location
document.getElementById('modal-dimension').innerText = getDimensionText(item.dimension);
const coords = item.coordinates;
document.getElementById('modal-coords').innerText = `X: ${coords.x}, Y: ${coords.y}, Z: ${coords.z}`;
// Map Link
const mapLink = document.getElementById('modal-map-link');
const worldName = getMapWorldName(item.dimension);
// Format: #world:X:Y:Z:88:0:0:0:1:flat
mapLink.href = `https://mcmap.lunadeer.cn/#${worldName}:${coords.x}:${coords.y}:${coords.z}:500:0:0:0:1:flat`;
// Contributors
const contribList = document.getElementById('modal-contributors');
contribList.innerHTML = '';
if (item.contributors && item.contributors.length > 0) {
item.contributors.forEach(name => {
const tag = document.createElement('div');
tag.className = 'contributor-tag';
// Using minotar for avatar
tag.innerHTML = `<img src="https://minotar.net/avatar/${name}/20" alt="${name}">${name}`;
contribList.appendChild(tag);
});
} else {
contribList.innerHTML = '<span class="text-secondary">暂无记录</span>';
}
// Instructions
renderContentList(document.getElementById('modal-instructions'), item.instructions);
// Notes
renderContentList(document.getElementById('modal-notes'), item.notes);
modal.style.display = 'block';
document.body.style.overflow = 'hidden'; // Prevent scrolling background
}
function renderContentList(container, list) {
container.innerHTML = '';
if (!list || list.length === 0) {
container.innerHTML = '<p>无</p>';
return;
}
list.forEach(block => {
if (block.type === 'text') {
const p = document.createElement('p');
p.innerText = block.content;
container.appendChild(p);
} else if (block.type === 'image') {
const img = document.createElement('img');
img.src = block.content;
img.loading = 'lazy';
container.appendChild(img);
}
});
}
// Helpers
function getStatusText(status) {
const map = {
'online': '正常运行',
'maintenance': '维护中',
'offline': '暂时失效'
};
return map[status] || status;
}
function getStatusColor(status) {
const map = {
'online': 'status-online',
'maintenance': 'status-maintenance',
'offline': 'status-offline'
};
return map[status] || '';
}
function getStatusIcon(status) {
const map = {
'online': 'fa-check-circle',
'maintenance': 'fa-wrench',
'offline': 'fa-times-circle'
};
return map[status] || 'fa-info-circle';
}
function getTypeText(type) {
const map = {
'resource': '资源类',
'xp': '经验类',
'infrastructure': '基础设施'
};
return map[type] || type;
}
function getDimensionText(dim) {
const map = {
'overworld': '主世界',
'nether': '下界',
'end': '末地'
};
return map[dim] || dim;
}
function getMapWorldName(dim) {
const map = {
'overworld': 'world',
'nether': 'world_nether',
'end': 'world_the_end'
};
return map[dim] || 'world';
}
});