`;
- stationsHtml += `
`;
+ stationsHtml += `
`;
- // Draw highlighted route line if start and end are on the same line
- let routeStartIndex = -1;
- let routeEndIndex = -1;
-
- if (selection[0] && selection[1] && Array.isArray(currentRoute) && currentRoute.length > 0) {
- routeStartIndex = stops.indexOf(selection[0]);
- routeEndIndex = stops.indexOf(selection[1]);
-
- if (routeStartIndex !== -1 && routeEndIndex !== -1) {
- const startPos = Math.min(routeStartIndex, routeEndIndex);
- const endPos = Math.max(routeStartIndex, routeEndIndex);
- const leftOffset = 35 + startPos * 70; // 70px is the width of each station node
- const lineWidth = (endPos - startPos) * 70;
-
- // Base yellow highlight line
- stationsHtml += `
`;
-
- // Animated arrows
- const isForward = routeStartIndex < routeEndIndex;
- const arrowCount = Math.max(1, Math.floor(lineWidth / 40));
-
- stationsHtml += `
`;
- for (let i = 0; i < arrowCount; i++) {
- stationsHtml += ``;
- }
- stationsHtml += `
`;
+ const getVisibleStopIndex = (targetCode) => {
+ const targetCanonical = stationCanonicalByCode[String(targetCode || '').trim()] || String(targetCode || '').trim();
+ return visibleStops.findIndex(code => (stationCanonicalByCode[code] || code) === targetCanonical);
+ };
+
+ const fromIndex = getVisibleStopIndex(selection[0]);
+ const toIndex = getVisibleStopIndex(selection[1]);
+ const sameLineSelection = fromIndex >= 0
+ && toIndex >= 0
+ && selection[0]
+ && selection[1]
+ && (!Array.isArray(currentRouteTransfers) || currentRouteTransfers.length === 0);
+
+ if (sameLineSelection) {
+ const startIndex = Math.min(fromIndex, toIndex);
+ const endIndex = Math.max(fromIndex, toIndex);
+ const left = (startIndex * nodeSlotWidth) + trackPadding;
+ const width = Math.max((endIndex - startIndex) * nodeSlotWidth, 0);
+ const arrowCount = Math.max(1, Math.floor(width / 40));
+ let arrowsHtml = '';
+ for (let i = 0; i < arrowCount; i++) {
+ arrowsHtml += `
›`;
}
+ stationsHtml += `
+
+ `;
}
let hasStations = false;
- stops.forEach((code, index) => {
+ stops.forEach(code => {
if (code === '-') return;
hasStations = true;
@@ -209,28 +232,24 @@
let nodeSize = isTransfer ? '20px' : '14px';
let nodeBorder = isTransfer ? '4px' : '3px';
let badgeHtml = '';
- let nodeZIndex = 4;
if (isSelectedFrom) {
nodeColor = 'var(--success, #16a34a)';
nodeSize = '24px';
- nodeZIndex = 5;
badgeHtml = `
起点
`;
} else if (isSelectedTo) {
nodeColor = 'var(--danger, #dc2626)';
nodeSize = '24px';
- nodeZIndex = 5;
badgeHtml = `
终点
`;
} else if (inRoute) {
nodeColor = 'var(--primary, #facc15)';
- nodeZIndex = 5;
if (!isTransfer) nodeSize = '18px';
else nodeSize = '24px';
}
let transferDotsHtml = '';
if (isTransfer) {
- transferDotsHtml = `
`;
+ transferDotsHtml = `
`;
transferLines.slice(0, 3).forEach(l => {
transferDotsHtml += `
`;
});
@@ -240,14 +259,14 @@
stationsHtml += `
+ ">
@@ -268,7 +287,7 @@
${code}
-
${name}
+
${name}
${enName ? `
${enName}
` : ''}
@@ -441,6 +460,11 @@
// Load Map on Start
renderSystemMap();
+ window.addEventListener('resize', () => {
+ if (!allLinesData || allLinesData.length === 0) return;
+ renderTvmUI();
+ });
+
async function previewPrice(force = false){
const seq = ++previewSeq;
const type = document.querySelector('input[name="trainType"]:checked').value;