修复地图渲染的问题

This commit is contained in:
CN-JS-HuiBai
2026-04-06 00:45:17 +08:00
parent cc3c67eae9
commit b2f14528a9
2 changed files with 100 additions and 75 deletions

View File

@@ -205,8 +205,10 @@
</h2> </h2>
</div> </div>
<div class="chart-legend"> <div class="chart-legend">
<span class="legend-item" id="legendRx" style="cursor: pointer;" title="点击切换 接收 (RX) 显示/隐藏"><span class="legend-dot legend-rx"></span>接收 (RX)</span> <span class="legend-item" id="legendRx" style="cursor: pointer;" title="点击切换 接收 (RX) 显示/隐藏"><span
<span class="legend-item" id="legendTx" style="cursor: pointer;" title="点击切换 发送 (TX) 显示/隐藏"><span class="legend-dot legend-tx"></span>发送 (TX)</span> class="legend-dot legend-rx"></span>接收 (RX)</span>
<span class="legend-item" id="legendTx" style="cursor: pointer;" title="点击切换 发送 (TX) 显示/隐藏"><span
class="legend-dot legend-tx"></span>发送 (TX)</span>
<span class="legend-item disabled" id="legendP95" style="cursor: pointer;" title="点击切换 P95 线显示/隐藏"> <span class="legend-item disabled" id="legendP95" style="cursor: pointer;" title="点击切换 P95 线显示/隐藏">
<span class="legend-dot legend-p95"></span>95计费 (<span id="p95LabelText">上行</span>) <span class="legend-dot legend-p95"></span>95计费 (<span id="p95LabelText">上行</span>)
</span> </span>
@@ -252,7 +254,8 @@
</h2> </h2>
<div class="chart-header-actions"> <div class="chart-header-actions">
<button class="btn-icon" id="btnExpandGlobe" title="放大显示"> <button class="btn-icon" id="btnExpandGlobe" title="放大显示">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width: 18px; height: 18px;"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
style="width: 18px; height: 18px;">
<path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" /> <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" />
</svg> </svg>
</button> </button>
@@ -291,8 +294,8 @@
</h2> </h2>
<div class="chart-header-right"> <div class="chart-header-right">
<div class="search-box"> <div class="search-box">
<input type="search" id="serverSearchFilter" name="q-filter-server" placeholder="检索服务器名称..." autocomplete="one-time-code" <input type="search" id="serverSearchFilter" name="q-filter-server" placeholder="检索服务器名称..."
spellcheck="false"> autocomplete="one-time-code" spellcheck="false">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="search-icon"> stroke-linejoin="round" class="search-icon">
<circle cx="11" cy="11" r="8"></circle> <circle cx="11" cy="11" r="8"></circle>
@@ -371,7 +374,8 @@
<div class="form-row"> <div class="form-row">
<div class="form-group" style="flex: 0.8;"> <div class="form-group" style="flex: 0.8;">
<label for="sourceType">类型</label> <label for="sourceType">类型</label>
<select id="sourceType" style="padding: 10px 14px; background: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-primary); outline: none;"> <select id="sourceType"
style="padding: 10px 14px; background: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-primary); outline: none;">
<option value="prometheus">Prometheus</option> <option value="prometheus">Prometheus</option>
<option value="blackbox">Blackbox Exporter</option> <option value="blackbox">Blackbox Exporter</option>
</select> </select>
@@ -390,9 +394,12 @@
<label for="sourceDesc">描述 (可选)</label> <label for="sourceDesc">描述 (可选)</label>
<input type="text" id="sourceDesc" placeholder="数据源描述" autocomplete="off"> <input type="text" id="sourceDesc" placeholder="数据源描述" autocomplete="off">
</div> </div>
<div class="form-group" id="serverSourceOption" style="display: flex; align-items: flex-end; padding-bottom: 8px;"> <div class="form-group" id="serverSourceOption"
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 0.85rem; color: var(--text-secondary); white-space: nowrap;"> style="display: flex; align-items: flex-end; padding-bottom: 8px;">
<input type="checkbox" id="isServerSource" checked style="width: 16px; height: 16px; accent-color: var(--accent-indigo);"> <label
style="display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 0.85rem; color: var(--text-secondary); white-space: nowrap;">
<input type="checkbox" id="isServerSource" checked
style="width: 16px; height: 16px; accent-color: var(--accent-indigo);">
<span>用于服务器展示</span> <span>用于服务器展示</span>
</label> </label>
</div> </div>
@@ -454,14 +461,17 @@
<option value="both">统计上行+下行 (Sum)</option> <option value="both">统计上行+下行 (Sum)</option>
</select> </select>
</div> </div>
<h3 style="margin-top: 30px; border-top: 1px solid var(--border-color); padding-top: 20px;">Blackbox 延迟连线管理</h3> <h3 style="margin-top: 30px; border-top: 1px solid var(--border-color); padding-top: 20px;">Blackbox
延迟连线管理</h3>
<div class="latency-routes-manager"> <div class="latency-routes-manager">
<!-- Add Route Form --> <!-- Add Route Form -->
<div class="add-route-mini-form" style="background: rgba(255,255,255,0.02); padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 1px solid var(--border-color);"> <div class="add-route-mini-form"
style="background: rgba(255,255,255,0.02); padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 1px solid var(--border-color);">
<div class="form-row"> <div class="form-row">
<div class="form-group" style="flex: 1.5;"> <div class="form-group" style="flex: 1.5;">
<label>数据源 (Blackbox)</label> <label>数据源 (Blackbox)</label>
<select id="routeSourceSelect" style="padding: 10px 14px; background: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-primary);"> <select id="routeSourceSelect"
style="padding: 10px 14px; background: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-primary);">
<option value="">-- 选择数据源 --</option> <option value="">-- 选择数据源 --</option>
</select> </select>
</div> </div>
@@ -481,17 +491,23 @@
</div> </div>
<div class="form-actions" style="padding-bottom: 0; display: flex; gap: 8px;"> <div class="form-actions" style="padding-bottom: 0; display: flex; gap: 8px;">
<button class="btn btn-add" id="btnAddRoute" style="padding: 10px 24px;">添加线路</button> <button class="btn btn-add" id="btnAddRoute" style="padding: 10px 24px;">添加线路</button>
<button class="btn btn-test" id="btnCancelEditRoute" style="display: none; padding: 10px 15px; background: rgba(0,0,0,0.3);">取消</button> <button class="btn btn-test" id="btnCancelEditRoute"
style="display: none; padding: 10px 15px; background: rgba(0,0,0,0.3);">取消</button>
</div> </div>
</div> </div>
</div> </div>
<!-- Routes List --> <!-- Routes List -->
<div class="latency-routes-list-container"> <div class="latency-routes-list-container">
<h4 style="font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase;; margin-bottom: 10px;">已配置线路</h4> <h4
<div id="latencyRoutesList" class="latency-routes-list" style="display: flex; flex-direction: column; gap: 10px;"> style="font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase;; margin-bottom: 10px;">
已配置线路</h4>
<div id="latencyRoutesList" class="latency-routes-list"
style="display: flex; flex-direction: column; gap: 10px;">
<!-- Routes will be injected here --> <!-- Routes will be injected here -->
<div class="route-empty" style="text-align: center; padding: 20px; color: var(--text-muted); font-size: 0.85rem; background: rgba(0,0,0,0.1); border-radius: 8px;">暂无线路</div> <div class="route-empty"
style="text-align: center; padding: 20px; color: var(--text-muted); font-size: 0.85rem; background: rgba(0,0,0,0.1); border-radius: 8px;">
暂无线路</div>
</div> </div>
</div> </div>
</div> </div>
@@ -547,8 +563,7 @@
<!-- Metric Items are injected here --> <!-- Metric Items are injected here -->
<div class="detail-metrics-list" id="detailMetricsList"></div> <div class="detail-metrics-list" id="detailMetricsList"></div>
<div class="detail-partitions-container metric-item" id="detailPartitionsContainer" <div class="detail-partitions-container metric-item" id="detailPartitionsContainer" style="display: none;">
style="display: none;">
<div class="metric-item-header" id="partitionHeader"> <div class="metric-item-header" id="partitionHeader">
<div class="metric-label-group"> <div class="metric-label-group">
<span class="metric-label">磁盘分区详情 (已挂载)</span> <span class="metric-label">磁盘分区详情 (已挂载)</span>

View File

@@ -569,23 +569,32 @@
const resp = await fetch('https://cdn.jsdelivr.net/npm/echarts@4.9.0/map/json/world.json'); const resp = await fetch('https://cdn.jsdelivr.net/npm/echarts@4.9.0/map/json/world.json');
const worldJSON = await resp.json(); const worldJSON = await resp.json();
// Transform to Pacific-centered: shift longitudes < -20 to 340-360 range // Transform to Pacific-centered correctly
// This puts America on the right of Asia const transformCoords = (coords) => {
if (!Array.isArray(coords)) return;
if (typeof coords[0] === 'number') return; // Point
if (typeof coords[0][0] === 'number') { // Ring
// Calculate average to decide if we should shift the whole ring
let sum = 0;
coords.forEach(pt => sum += pt[0]);
let avg = sum / coords.length;
if (avg < -20) {
coords.forEach(pt => pt[0] += 360);
}
// Fix internal wrap-around jumps to keep polygons contiguous
for (let i = 1; i < coords.length; i++) {
let prev = coords[i - 1][0];
while (coords[i][0] - prev > 180) coords[i][0] -= 360;
while (coords[i][0] - prev < -180) coords[i][0] += 360;
}
} else {
coords.forEach(transformCoords);
}
};
worldJSON.features.forEach(feature => { worldJSON.features.forEach(feature => {
if (feature.geometry.type === 'Polygon') { if (feature.geometry && feature.geometry.coordinates) {
feature.geometry.coordinates.forEach(ring => { transformCoords(feature.geometry.coordinates);
ring.forEach(coords => {
if (coords[0] < -20) coords[0] += 360;
});
});
} else if (feature.geometry.type === 'MultiPolygon') {
feature.geometry.coordinates.forEach(polygon => {
polygon.forEach(ring => {
ring.forEach(coords => {
if (coords[0] < -20) coords[0] += 360;
});
});
});
} }
}); });
@@ -625,19 +634,20 @@
geo: { geo: {
map: 'world', map: 'world',
roam: true, roam: true,
center: [165, 20], // Centered in Pacific center: [160, 25], // Centered slightly better for global view
zoom: 1.1, zoom: 1.1,
aspectScale: 0.85, // Adjust aspect ratio to reduce vertical stretching in northern regions
emphasis: { emphasis: {
label: { show: false }, label: { show: false },
itemStyle: { areaColor: isLight ? '#f0f2f5' : '#2d334d' } itemStyle: { areaColor: isLight ? '#f0f2f5' : '#2d334d' }
}, },
itemStyle: { itemStyle: {
areaColor: isLight ? '#eef0f5' : '#1a1d2d', areaColor: isLight ? '#f4f6fa' : '#1a1d2e',
borderColor: isLight ? '#cbd5e1' : '#2d334d', borderColor: isLight ? '#cbd5e1' : '#2d334d',
borderWidth: 1 borderWidth: 1
}, },
select: { select: {
itemStyle: { areaColor: isLight ? '#f0f2f5' : '#2d334d' } itemStyle: { areaColor: isLight ? '#f4f8ff' : '#2d334d' }
} }
}, },
series: [{ series: [{