feat(route-map): 新增线路预览页面并优化八向布线布局

- 新增全网线路图预览前端页面 `/web/map-preview.html`
- 调整布局物理参数与迭代次数优化排布效果
- 新增正交八向布线强制对齐逻辑
- 实现节点网格对齐与优化线路路径转角处理
- 调整锚点固定力度提升布局稳定性
This commit is contained in:
2026-07-15 02:54:11 +08:00
parent 620289e836
commit 4ea58772d3
2 changed files with 143 additions and 10 deletions
+63
View File
@@ -0,0 +1,63 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>全网线路图预览 - FSE铁路运输票务系统</title>
<link rel="icon" type="image/png" href="/FSE-ticket.png">
<style>
body { margin: 0; padding: 0; background: #f8fafc; display: flex; flex-direction: column; height: 100vh; font-family: system-ui, -apple-system, sans-serif; }
header { background: white; padding: 16px 24px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); display: flex; justify-content: space-between; align-items: center; z-index: 10; }
h1 { margin: 0; font-size: 18px; color: #0f172a; font-weight: 700; }
.btn { background: #3b82f6; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; text-decoration: none; font-size: 14px; font-weight: 500; transition: background 0.2s; }
.btn:hover { background: #2563eb; }
.btn-secondary { background: #e2e8f0; color: #475569; }
.btn-secondary:hover { background: #cbd5e1; }
.controls { display: flex; gap: 12px; }
#map-container { flex: 1; overflow: auto; display: flex; justify-content: center; align-items: center; padding: 32px; position: relative; }
#map-container svg { box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05); border-radius: 12px; background: white; max-width: none; transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1); transform-origin: center; }
.loading-hint { color: #64748b; font-size: 15px; position: absolute; }
</style>
</head>
<body>
<header>
<h1>全网线路图预览 (正交布线)</h1>
<div class="controls">
<a href="/index.html" class="btn btn-secondary">返回后台</a>
<button class="btn" onclick="loadMap()">重新生成</button>
</div>
</header>
<div id="map-container">
<div class="loading-hint">正在计算布局,请稍候...</div>
</div>
<script>
let scale = 1;
async function loadMap() {
const container = document.getElementById('map-container');
container.innerHTML = '<div class="loading-hint">正在计算正交布局,请稍候...</div>';
try {
const res = await fetch('/api/public/fares/map/light?t=' + Date.now());
const svg = await res.text();
container.innerHTML = svg;
scale = 1;
updateZoom();
} catch (e) {
container.innerHTML = '<div style="color: #ef4444;">加载失败</div>';
}
}
function updateZoom() {
const svg = document.querySelector('#map-container svg');
if(svg) svg.style.transform = `scale(${scale})`;
}
document.getElementById('map-container').addEventListener('wheel', (e) => {
if (e.ctrlKey || e.metaKey) {
e.preventDefault();
scale += e.deltaY * -0.002;
scale = Math.min(Math.max(0.125, scale), 4);
updateZoom();
}
}, { passive: false });
loadMap();
</script>
</body>
</html>