diff --git a/web/ticket-order.js b/web/ticket-order.js index cf63188..ff7087f 100644 --- a/web/ticket-order.js +++ b/web/ticket-order.js @@ -106,6 +106,9 @@ return; } + const nodeSlotWidth = window.innerWidth <= 768 ? 58 : 70; + const trackPadding = Math.round(nodeSlotWidth / 2); + // 1. Render Line Tabs let tabsHtml = `
`; allLinesData.forEach(line => { @@ -143,44 +146,64 @@ const activeLine = allLinesData.find(l => String(l.id) === String(activeLineId)) || allLinesData[0]; const stopsRaw = Array.isArray(activeLine.stops) ? activeLine.stops : (Array.isArray(activeLine.站点列表) ? activeLine.站点列表 : []); const stops = stopsRaw.map(c => String(c || '').trim()).filter(Boolean); + const visibleStops = stops.filter(code => code !== '-'); let stationsHtml = `
`; stationsHtml += `
`; - 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 += ` +
+
${arrowsHtml}
+
+ `; } 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;