diff --git a/javaTest/src/main/java/com/ft546/wcs/shadow/history/visualizer/SimulationVisualizationMapper.java b/javaTest/src/main/java/com/ft546/wcs/shadow/history/visualizer/SimulationVisualizationMapper.java
new file mode 100644
index 0000000..f7a1432
--- /dev/null
+++ b/javaTest/src/main/java/com/ft546/wcs/shadow/history/visualizer/SimulationVisualizationMapper.java
@@ -0,0 +1,371 @@
+package com.ft546.wcs.shadow.history.visualizer;
+
+import com.ft546.wcs.demo.model.Site;
+import com.ft546.wcs.demo.model.VehicleSnapshot;
+import com.ft546.wcs.shadow.history.HistoricalQueueDataset;
+import com.ft546.wcs.shadow.history.HistoricalQueueRecord;
+import com.ft546.wcs.shadow.history.simulation.HistoricalDispatchSimulationResult;
+import com.ft546.wcs.shadow.history.simulation.HistoricalSimulationInput;
+import com.ft546.wcs.shadow.history.simulation.HistoricalSimulationTask;
+import com.ft546.wcs.shadow.history.simulation.SimulationInvariantSummary;
+import com.ft546.wcs.shadow.history.simulation.SimulationMetrics;
+import com.ft546.wcs.shadow.history.simulation.SimulationTaskResult;
+import com.ft546.wcs.shadow.history.simulation.SimulationTaskStatus;
+import com.ft546.wcs.shadow.history.simulation.SimulationTickEvent;
+
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * 将调度仿真证据转换为前端可序列化的数据结构。
+ *
+ *
该类不调用规划器,也不修改仿真结果。页面看到的车辆、路径和事件均来自同一次 Java 仿真。
+ */
+public final class SimulationVisualizationMapper {
+ private static final String MODE = "OFFLINE_IN_MEMORY_SIMULATION";
+ private static final String BOUNDARY =
+ "纯内存离线仿真,不连接生产 SQL Server、PLC 或 WMS,也不替代现场 HIL/ACTIVE 验收";
+ private static final String PLANNER_VERSION = "GridPathPlanner-BFS/full-grid-v1";
+ private static final DateTimeFormatter TIME =
+ DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
+
+ private final HistoricalQueueDataset dataset;
+
+ public SimulationVisualizationMapper(HistoricalQueueDataset dataset) {
+ if (dataset == null) throw new IllegalArgumentException("dataset is required");
+ this.dataset = dataset;
+ }
+
+ /** 返回页面启动所需的地图、站点和初始车辆元数据。 */
+ public Map bootstrap(HistoricalSimulationInput input) {
+ requireInput(input);
+ Map payload = new LinkedHashMap();
+ payload.put("mode", MODE);
+ payload.put("boundary", BOUNDARY);
+ payload.put("plannerVersion", PLANNER_VERSION);
+ payload.put("mapSha256", dataset.getFullMapSha256());
+ payload.put("fullMapRows", dataset.getFullMapRows());
+ payload.put("passableMapRows", input.getGridMap().getSites().size());
+ payload.put("database", dataset.getDatabase());
+ payload.put("sourceTable", dataset.getSourceTable());
+ payload.put("pathInfoUsedForPlanning", false);
+
+ List orderedSites = new ArrayList(input.getGridMap().getSites().values());
+ Collections.sort(orderedSites, Comparator.comparing(Site::getId));
+ List