zhanghaijun лет назад: 2
Родитель
Сommit
ea91f0eb7f

+ 34 - 0
train-server/src/main/java/top/haijunit/train/domain/constant/TowardEnum.java

@@ -0,0 +1,34 @@
+package top.haijunit.train.domain.constant;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Objects;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/26 20:37
+ * @description [一句话描述该类的功能]
+ */
+@Getter
+@AllArgsConstructor
+public enum TowardEnum {
+
+    FORWARD(1, "正向"), REVERSE(2, "反向");
+
+    @JsonValue
+    private final Integer code;
+    private final String describe;
+
+    @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
+    public static TowardEnum getByCode(Integer code) {
+        for (TowardEnum genderEnum : values()) {
+            if (Objects.equals(genderEnum.getCode(), code)) {
+                return genderEnum;
+            }
+        }
+        return null;
+    }
+}

+ 26 - 0
train-server/src/main/java/top/haijunit/train/domain/convert/TowardConverter.java

@@ -0,0 +1,26 @@
+package top.haijunit.train.domain.convert;
+
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
+import top.haijunit.train.domain.constant.DirectionEnum;
+import top.haijunit.train.domain.constant.TowardEnum;
+
+import java.util.Optional;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/26 20:40
+ * @description [一句话描述该类的功能]
+ */
+@Converter(autoApply = true)
+public class TowardConverter implements AttributeConverter<TowardEnum, Integer> {
+    @Override
+    public Integer convertToDatabaseColumn(TowardEnum direction) {
+        return Optional.of(direction).map(TowardEnum::getCode).orElse(TowardEnum.FORWARD.getCode());
+    }
+
+    @Override
+    public TowardEnum convertToEntityAttribute(Integer code) {
+        return TowardEnum.getByCode(code);
+    }
+}

+ 4 - 0
train-server/src/main/java/top/haijunit/train/domain/entity/SignalEntity.java

@@ -4,9 +4,11 @@ import jakarta.persistence.Entity;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
+import liquibase.database.core.Ingres9Database;
 import lombok.Data;
 import top.haijunit.train.domain.constant.DirectionEnum;
 import top.haijunit.train.domain.constant.SignalStateEnum;
+import top.haijunit.train.domain.constant.TowardEnum;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
@@ -33,6 +35,8 @@ public class SignalEntity implements Serializable {
     private Long selectionId;
     // 类型:上行、下行
     private DirectionEnum direction;
+    // 朝向 正向|反向
+    private TowardEnum toward;
     // 车站编号
     private Long stationId;
 }

+ 4 - 1
train-server/src/main/java/top/haijunit/train/domain/repository/SignStopRepository.java

@@ -1,9 +1,11 @@
 package top.haijunit.train.domain.repository;
 
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
 import top.haijunit.train.domain.entity.SignStopEntity;
 
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -14,6 +16,7 @@ import java.util.List;
 @Repository
 public interface SignStopRepository extends JpaRepository<SignStopEntity, Long> {
 
-    public List<SignStopEntity> findAllByStationId(Long stationId);
+    @Query(value = "select * from db_stop_sign where selection_id in (?1)", nativeQuery = true)
+    public List<SignStopEntity> findAllByStationId(List<Long> stationId);
 }
 

+ 4 - 0
train-server/src/main/java/top/haijunit/train/listener/ReportTimeHandle.java

@@ -52,6 +52,10 @@ public class ReportTimeHandle {
     @Async
     @Scheduled(fixedDelay = 1000)
     public void runRouteCompute() {
+        if (TrainSimulationHolder.getRouteMap().isEmpty()) {
+            routeComputerService.init();
+            return;
+        }
         for (TrainItem trainItem : TrainSimulationHolder.getTrainItem()) {
             routeComputerService.run(trainItem);
         }

+ 5 - 4
train-server/src/main/java/top/haijunit/train/listener/TrainApplication.java

@@ -14,6 +14,7 @@ import top.haijunit.train.simulation.domain.SectionItem;
 import top.haijunit.train.simulation.domain.TrainItem;
 import top.haijunit.train.simulation.train.TrainSimulationHolder;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -32,10 +33,10 @@ public class TrainApplication implements ApplicationRunner {
 
     @Override
     public void run(ApplicationArguments args) {
-        // List<TrainEntity> list = trainRepository.findAll();
-        List<TrainEntity> list = trainRepository.findAllById(new ArrayList<>() {{
-            add(110004L);
-        }});
+        List<TrainEntity> list = trainRepository.findAll();
+        // List<TrainEntity> list = trainRepository.findAllById(new ArrayList<>() {{
+        //     add(110004L);
+        // }});
         for (TrainEntity train : list) {
             try {
                 SectionItem sectionItem = sectionService.getSection(train.getSectionId());

+ 24 - 12
train-server/src/main/java/top/haijunit/train/service/SectionService.java

@@ -15,9 +15,9 @@ import top.haijunit.train.simulation.domain.SectionItem;
 import top.haijunit.train.utils.NumberUtil;
 
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * @author zhanghaijun
@@ -43,7 +43,7 @@ public class SectionService {
     public SectionItem getSection(Long sectionId, BigDecimal offset, BigDecimal distance) {
         SectionItem sectionItem = this.getSection(sectionId);
         BigDecimal decimal = NumberUtil.add(offset, NumberUtil.mul(distance, sectionItem.getDirection().getFactor()));
-        if (NumberUtil.isGreaterOrEqual(decimal, sectionItem.getSectionLength())) {
+        if (NumberUtil.isGreater(decimal, sectionItem.getSectionLength())) {
             Long sId = switch (sectionItem.getDirection()) {
                 case UP -> sectionItem.getSectionPreId();
                 case DOWN -> sectionItem.getSectionNextId();
@@ -61,6 +61,13 @@ public class SectionService {
         return StreamUtils.filter(getAllSection(), item -> item.getRouteId().equals(routeId));
     }
 
+    public List<SectionItem> getSectionAll(Collection<Long> routeIds) {
+        if (CollUtil.isEmpty(routeIds)) {
+            return new ArrayList<>();
+        }
+        return StreamUtils.filter(getAllSection(), item -> CollUtil.contains(routeIds, item.getRouteId()));
+    }
+
     public Long getRouteNextId(Long sectionId) {
         SectionItem sectionItem = this.getSection(sectionId);
         RouteEntity route = routeRepository.findById(sectionItem.getRouteId()).orElseThrow(() -> new IllegalArgumentException(String.format("未找到进路数据,进路Id: %s", sectionItem.getRouteId())));
@@ -90,10 +97,15 @@ public class SectionService {
     public List<SectionItem> getAllSection() {
         List<SectionItem> sectionList = new ArrayList<>();
         List<RouteEntity> routeList = routeRepository.findAll();
+        Map<Long, SelectionEntity> selectionMap = selectionRepository.findAll().stream().collect(Collectors.toMap(SelectionEntity::getId, Function.identity(), (v1, v2) -> v1));
         for (RouteEntity route : routeList) {
-            List<SelectionEntity> selectionList = selectionRepository.findAllById(route.getSelectionList());
-            for (int i = 0; i < selectionList.size(); i++) {
-                SelectionEntity selection = selectionList.get(i);
+            ArrayList<Long> selectionIds = route.getSelectionList();
+            for (int i = 0; i < selectionIds.size(); i++) {
+                Long sectionId = selectionIds.get(i);
+                SelectionEntity selection = selectionMap.get(sectionId);
+                if (null == selection) {
+                    throw new IllegalArgumentException(String.format("未找到区段数据,区段Id: %s", sectionId));
+                }
                 // 区段数据
                 SectionItem sectionItem = new SectionItem();
                 sectionItem.setSectionId(selection.getId());
@@ -110,14 +122,14 @@ public class SectionService {
                 if (i == 0) {
                     // 进路的第一个区段
                     sectionItem.setSectionPreId(this.getRouteSectionLast(route.getId()));
-                    sectionItem.setSectionNextId(Optional.of(selectionList.get(i + 1)).map(SelectionEntity::getId).orElse(-1L));
-                } else if (i + 1 >= selectionList.size()) {
+                    sectionItem.setSectionNextId(selectionIds.get(i + 1));
+                } else if (i + 1 >= selectionIds.size()) {
                     // 进路的最后一个区段
-                    sectionItem.setSectionPreId(Optional.of(selectionList.get(i - 1)).map(SelectionEntity::getId).orElse(-1L));
+                    sectionItem.setSectionPreId(selectionIds.get(i - 1));
                     sectionItem.setSectionNextId(this.getRouteSectionFirst(route.getNextId()));
                 } else {
-                    sectionItem.setSectionPreId(Optional.of(selectionList.get(i - 1)).map(SelectionEntity::getId).orElse(-1L));
-                    sectionItem.setSectionNextId(Optional.of(selectionList.get(i + 1)).map(SelectionEntity::getId).orElse(-1L));
+                    sectionItem.setSectionPreId(selectionIds.get(i - 1));
+                    sectionItem.setSectionNextId(selectionIds.get(i + 1));
                 }
                 sectionList.add(sectionItem);
             }

+ 6 - 1
train-server/src/main/java/top/haijunit/train/service/SelectionService.java

@@ -1,5 +1,6 @@
 package top.haijunit.train.service;
 
+import cn.hutool.core.collection.CollUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -86,6 +87,10 @@ public class SelectionService {
     }
 
     public HashMap<Long, SignStopEntity> getStopSignalMap(List<Long> selectionAllList) {
-        return signStopRepository.findAllById(selectionAllList).stream().collect(HashMap::new, (map, entity) -> map.put(entity.getSelectionId(), entity), HashMap::putAll);
+        if(CollUtil.isEmpty(selectionAllList)){
+            return new HashMap<>();
+        }
+        List<SignStopEntity> list = signStopRepository.findAllByStationId(selectionAllList);
+        return list.stream().collect(HashMap::new, (map, entity) -> map.put(entity.getSelectionId(), entity), HashMap::putAll);
     }
 }

+ 37 - 20
train-server/src/main/java/top/haijunit/train/simulation/train/RouteComputerService.java

@@ -3,6 +3,7 @@ package top.haijunit.train.simulation.train;
 import cn.hutool.core.collection.CollUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import top.haijunit.common.utils.ErrorUtil;
 import top.haijunit.common.utils.StreamUtils;
@@ -13,9 +14,7 @@ import top.haijunit.train.simulation.domain.SectionItem;
 import top.haijunit.train.simulation.domain.TrainItem;
 import top.haijunit.train.utils.NumberUtil;
 
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -31,6 +30,14 @@ public class RouteComputerService {
     private final RouteService routeService;
     private final SectionService sectionService;
 
+    public synchronized void init() {
+        Collection<TrainItem> trainItems = TrainSimulationHolder.getTrainItem();
+        for (TrainItem trainItem : trainItems) {
+            List<SectionItem> trainSectionList = getTrainSectionList(trainItem);
+            TrainSimulationHolder.addRouteList(trainItem.getTrainId(), this.getSectionList(new LinkedList<>(trainSectionList), trainItem));
+        }
+    }
+
     public void run(TrainItem train) {
         try {
             LinkedList<SectionItem> list = routeCompute(train);
@@ -53,21 +60,12 @@ public class RouteComputerService {
         // 4、下一条进路是否包括道岔,道岔状态是否正确
         // 5、将下一条进路状态置为锁定状态
         // 6、释放车尾已过的进路
-        LinkedList<SectionItem> routeList = this.getSectionList(train);
-        if (CollUtil.isEmpty(routeList)) {
-            log.info("初始化进路计算,列车: {}", train.getTrainId());
-            // 车头所在的区段
-            SectionItem sectionHead = sectionService.getSection(train.getBlockId());
-            sectionHead.setSectionStatus(SectionStatusEnum.OCCUPY);
-            // 车尾所在的区段
-            SectionItem sectionTail = sectionService.getSection(train.getBlockId(), train.getOffset(), NumberUtil.mul(train.getTrainLength(), -1));
-            routeList.addFirst(sectionHead);
-            if (!sectionHead.getSectionId().equals(sectionTail.getSectionId())) {
-                sectionTail.setSectionStatus(SectionStatusEnum.OCCUPY);
-                routeList.addLast(sectionTail);
-            }
+        LinkedList<SectionItem> routeListAll = TrainSimulationHolder.getRouteList(train.getTrainId());
+        if (CollUtil.isEmpty(routeListAll)) {
+            routeListAll.addAll(getTrainSectionList(train));
         }
-        if (!sectionService.isTrigger(train.getBlockId(), train.getOffset())) {
+        LinkedList<SectionItem> routeList = this.getSectionList(routeListAll, train);
+        if (routeList.size() > 1 && !sectionService.isTrigger(train.getBlockId(), train.getOffset())) {
             // 没有触发进路
             return routeList;
         }
@@ -94,8 +92,27 @@ public class RouteComputerService {
         return routeList;
     }
 
-    private LinkedList<SectionItem> getSectionList(TrainItem train) {
-        LinkedList<SectionItem> routeList = TrainSimulationHolder.getRouteList(train.getTrainId());
+    private List<SectionItem> getTrainSectionList(TrainItem train) {
+        log.info("初始化进路计算,列车: {}", train.getTrainId());
+        // 车头所在的区段
+        SectionItem sectionHead = sectionService.getSection(train.getBlockId());
+        // 车尾所在的区段
+        SectionItem sectionTail = sectionService.getSection(train.getBlockId(), train.getOffset(), NumberUtil.mul(train.getTrainLength(), -1));
+        List<SectionItem> sectionAll = sectionService.getSectionAll(new ArrayList<>() {{
+            add(sectionHead.getRouteId());
+            add(sectionTail.getRouteId());
+        }});
+        for (SectionItem sectionItem : sectionAll) {
+            if (sectionItem.getSectionId().equals(sectionHead.getSectionId()) || sectionItem.getSectionId().equals(sectionTail.getSectionId())) {
+                sectionHead.setSectionStatus(SectionStatusEnum.OCCUPY);
+            } else {
+                sectionHead.setSectionStatus(SectionStatusEnum.LOCK);
+            }
+        }
+        return sectionAll;
+    }
+
+    private LinkedList<SectionItem> getSectionList(LinkedList<SectionItem> routeList, TrainItem train) {
         if (CollUtil.isEmpty(routeList)) {
             return new LinkedList<>();
         }
@@ -111,7 +128,7 @@ public class RouteComputerService {
                 isPass = false;
                 current.setSectionStatus(SectionStatusEnum.OCCUPY);
             } else {
-                current.setSectionStatus(SectionStatusEnum.IDLE);
+                current.setSectionStatus(SectionStatusEnum.LOCK);
             }
             if (isPass) {
                 iterator.remove();

+ 13 - 8
train-server/src/main/java/top/haijunit/train/simulation/train/TrainComputerService.java

@@ -67,12 +67,12 @@ public class TrainComputerService {
             HashMap<Long, SignStopEntity> stopSignalMap = selectionService.getStopSignalMap(list.stream().map(SectionItem::getSectionId).collect(Collectors.toList()));
             SectionItem currentSection = sectionOptional.get();
             BigDecimal currentAllOffset = NumberUtil.add(train.getOffset(), NumberUtil.mul(train.getDirection().getFactor(), distance.abs()));
-            if (list.size() > 1) {
-                for (int i = 1; i < list.size(); i++) {
-                    SectionItem sectionItem = list.get(i);
-                    SignStopEntity stopSign = stopSignalMap.get(sectionItem.getSectionId());
-                    if (null != stopSign && NumberUtil.isIn(stopSign.getSelectionOff(), NumberUtil.min(BigDecimal.ZERO, currentAllOffset), NumberUtil.max(BigDecimal.ZERO, currentAllOffset))) {
-                        // 存在停车标
+            for (int i = 0; i < list.size(); i++) {
+                SectionItem sectionItem = list.get(i);
+                SignStopEntity stopSign = stopSignalMap.get(sectionItem.getSectionId());
+                if (null != stopSign) {
+                    // 存在停车标
+                    if (NumberUtil.isGreater(stopSign.getSelectionOff(), train.getOffset()) && NumberUtil.isLessOrEqual(stopSign.getSelectionOff(), currentAllOffset)) {
                         train.setSpeed(BigDecimal.ZERO);
                         train.setAcceleration(BigDecimal.ZERO);
                         train.setBlockId(sectionItem.getSectionId());
@@ -82,9 +82,11 @@ public class TrainComputerService {
                         train.setUpdateTimeMillis(nowMillis);
                         return train;
                     }
-                    currentAllOffset = NumberUtil.sub(currentAllOffset, currentSection.getSectionLength());
-                    currentSection = sectionItem;
                 }
+                if (i != list.size() - 1) {
+                    currentAllOffset = NumberUtil.sub(currentAllOffset, sectionItem.getSectionLength());
+                }
+                currentSection = sectionItem;
             }
             train.setSpeed(CalculatorUtil.velocity(train.getSpeed(), train.getAcceleration(), train.getUpdateTimeMillis(), nowMillis).abs());
             train.setOffset(currentAllOffset.abs());
@@ -92,6 +94,9 @@ public class TrainComputerService {
             train.setBlockNo(currentSection.getSectionName());
             train.setDirection(currentSection.getDirection());
             train.setUpdateTimeMillis(nowMillis);
+        } else {
+            // 停车后更新时间
+            train.setUpdateTimeMillis(nowMillis);
         }
         // 计算MA
         List<BigDecimal> list = this.getDistanceMa(sectionList, train.getBlockId(), train.getOffset(), 0);

+ 4 - 1
train-server/src/main/java/top/haijunit/train/simulation/train/TrainSimulationHolder.java

@@ -47,7 +47,10 @@ public class TrainSimulationHolder {
 
     public static boolean isRouteIdle(Long routeId) {
         for (Map.Entry<Long, LinkedList<SectionItem>> entry : TRAVEL_ROUTE_MAP.entrySet()) {
-            return entry.getValue().stream().noneMatch(item -> item.getRouteId().equals(routeId) && !item.getSectionStatus().equals(SectionStatusEnum.IDLE));
+            boolean match = entry.getValue().stream().noneMatch(item -> item.getRouteId().equals(routeId) && !item.getSectionStatus().equals(SectionStatusEnum.IDLE));
+            if (!match) {
+                return false;
+            }
         }
         return true;
     }

+ 1 - 0
train-server/src/main/resources/db/changelog/train/db-server-train.xml

@@ -14,6 +14,7 @@
             <column name="color_state" type="${number.type}" defaultValueNumeric="1" remarks="状态:红、绿、黄、红黄"/>
             <column name="selection_id" type="${autoing.type}" defaultValueNumeric="0" remarks="区段号"/>
             <column name="direction" type="${number.type}" defaultValueNumeric="1" remarks="上行、下行"/>
+            <column name="toward" type="${number.type}" defaultValueNumeric="1" remarks="朝向,正向|方向"/>
             <column name="station_id" type="${autoing.type}" defaultValueNumeric="0" remarks="归属车站/编码"/>
         </createTable>
     </changeSet>

+ 17 - 17
train-server/src/main/resources/db/changelog/train/db_signal.txt

@@ -1,19 +1,19 @@
-id,name,kilometer,color_state,selection_id,direction,station_id
-101001,S0101,150,1,103002,1,104001
-101002,S0103,450,1,103004,1,104001
-101003,S0102,150,1,103015,2,104001
-101004,S0104,450,1,103017,2,104001
-101005,S0105,595.63,1,103006,1,104001
-101006,S0106,595.63,1,103019,2,104001
+id,name,kilometer,color_state,selection_id,direction,toward,station_id
+101001,S0101,150,1,103002,1,1,104001
+101002,S0103,450,1,103004,1,1,104001
+101003,S0102,150,1,103015,2,1,104001
+101004,S0104,450,1,103017,2,1,104001
+101005,S0105,595.63,1,103006,1,2,104001
+101006,S0106,595.63,1,103019,2,2,104001
 
-101007,S0201,3595.63,1,103006,1,104002
-101008,S0202,3595.63,1,103019,2,104002
-101009,S0203,3741.26,1,103008,1,104002
-101010,S0204,3741.26,1,103021,2,104002
+101007,S0201,3595.63,1,103006,1,1,104002
+101008,S0202,3595.63,1,103019,2,1,104002
+101009,S0203,3741.26,1,103008,1,2,104002
+101010,S0204,3741.26,1,103021,2,2,104002
 
-101011,S0301,6741.26,1,103008,1,104003
-101012,S0302,6741.26,1,103021,2,104003
-101013,S0303,6886.89,1,103010,1,104003
-101014,S0304,6886.89,1,103023,2,104003
-101015,S0305,7186.89,1,103012,1,104003
-101016,S0306,7186.89,1,103025,2,104003
+101011,S0301,6741.26,1,103008,1,1,104003
+101012,S0302,6741.26,1,103021,2,1,104003
+101013,S0303,6886.89,1,103010,1,2,104003
+101014,S0304,6886.89,1,103023,2,2,104003
+101015,S0305,7186.89,1,103012,1,1,104003
+101016,S0306,7186.89,1,103025,2,1,104003

+ 36 - 20
train-web/src/pages/train/controller/DrawTrack.ts

@@ -1,5 +1,5 @@
 import {crtPath} from '../core/Utils'
-import {DirectionEnum, RouteItem, SectionStatusEnum, SelectionItem, SignalItem, SignalStateEnum, SwitchItem} from "@/types/train-travel";
+import {DirectionEnum, RouteItem, SectionStatusEnum, SelectionItem, SignalItem, SignalStateEnum, SwitchItem, TowardEnum} from "@/types/train-travel";
 import {LINE_DOWN, LINE_UP} from './Constant'
 import {useStoreSocket} from '@/store/socket'
 
@@ -13,6 +13,8 @@ export class DrawTrack {
 
   // 绘制道岔
   drawSwitchList(list: SwitchItem[]): void {
+    const storeSocket = useStoreSocket();
+    const routeList: RouteItem[] = storeSocket.getRouteList;
     for (let i: number = 0; i < list.length; i++) {
       const item: SwitchItem = list[i];
       if (item.type % 2 === 1) {
@@ -22,6 +24,17 @@ export class DrawTrack {
         }
         this.canvas.save();
         this.canvas.beginPath();
+        this.canvas.strokeStyle = "#00FF00";
+        const sectionItem: RouteItem | undefined = routeList.find(s => s.sectionId == item.stationId)
+        if (sectionItem?.sectionStatus == SectionStatusEnum.OCCUPY) {
+          this.canvas.strokeStyle = "#FF0000";
+        } else if (sectionItem?.sectionStatus == SectionStatusEnum.IDLE) {
+          this.canvas.strokeStyle = "#898989";
+        } else if (sectionItem?.sectionStatus == SectionStatusEnum.LOCK) {
+          this.canvas.strokeStyle = "#00FF00";
+        } else {
+          this.canvas.strokeStyle = "#898989";
+        }
         crtPath(this.canvas, [item.kilometer, LINE_UP, filter[0].kilometer, LINE_DOWN]);
         this.canvas.stroke();
       }
@@ -34,16 +47,13 @@ export class DrawTrack {
     const routeList: RouteItem[] = storeSocket.getRouteList;
     upList.forEach((signal: SignalItem): void => {
       const routeItem: RouteItem | undefined = routeList.find(item => item.sectionId == signal.selectionId);
-      // if (signal.name == 'S0104') {
-      //   console.log(signal.name, routeItem, routeList);
-      // }
-      this.drawSignal(signal.name, signal.kilometer, signal.direction, routeItem);
+      this.drawSignal(signal.name, signal.kilometer, signal.direction, signal.toward, routeItem);
     });
   }
 
   // 绘制信号灯
-  drawSignal(name: string = "", x: number = 0, direction: DirectionEnum = DirectionEnum.UP, routeItem: RouteItem | undefined): void {
-    const space: number = direction == DirectionEnum.UP ? 10 : -10;
+  drawSignal(name: string, x: number, direction: DirectionEnum, toward: TowardEnum, routeItem: RouteItem | undefined): void {
+    const space: number = toward == TowardEnum.REVERSE ? -10 : 10;
     const y: number = direction == DirectionEnum.UP ? LINE_UP : LINE_DOWN;
     this.canvas.save();
     this.canvas.beginPath();
@@ -52,19 +62,22 @@ export class DrawTrack {
     crtPath(this.canvas, [x, y - 1.5 * space, x - 0.5 * space, y - 1.5 * space], false);
     this.canvas.arc(x - space, y - 1.5 * space, Math.abs(space * 0.5), 0, Math.PI * 2);
     this.canvas.lineWidth = 0.5;
-    switch (routeItem?.sectionStatus) {
-      case SectionStatusEnum.LOCK:
-        this.canvas.fillStyle = "#00FF00";
-        break;
-      case SectionStatusEnum.IDLE:
-        this.canvas.fillStyle = "#FF0000";
-        break;
-      case SectionStatusEnum.OCCUPY:
-        this.canvas.fillStyle = "#FF0000";
-        break;
-      default:
-        this.canvas.fillStyle = "#FF0000";
-        break;
+    this.canvas.fillStyle = "#FF0000";
+    if ((direction == DirectionEnum.UP && toward == TowardEnum.FORWARD) || (direction == DirectionEnum.DOWN && toward == TowardEnum.REVERSE)) {
+      switch (routeItem?.sectionStatus) {
+        case SectionStatusEnum.LOCK:
+          this.canvas.fillStyle = "#00FF00";
+          break;
+        case SectionStatusEnum.IDLE:
+          this.canvas.fillStyle = "#FF0000";
+          break;
+        case SectionStatusEnum.OCCUPY:
+          this.canvas.fillStyle = "#FF0000";
+          break;
+        default:
+          this.canvas.fillStyle = "#FF0000";
+          break;
+      }
     }
     this.canvas.strokeStyle = "#000000";
     this.canvas.fill();
@@ -81,6 +94,9 @@ export class DrawTrack {
     const routeList: RouteItem[] = storeSocket.getRouteList;
     for (let i: number = 0; i < selectionList.length; i++) {
       const item: SelectionItem = selectionList[i];
+      if (item.switch) {
+        continue;
+      }
       let Y: number = 0;
       switch (item.direction) {
         case DirectionEnum.UP:

+ 5 - 5
train-web/src/pages/train/controller/DrewTrain.ts

@@ -1,7 +1,7 @@
 import TrainImg from "./train.svg"
-import {LINE_DOWN, LINE_UP} from "@/pages/train/controller/Constant";
-import {DirectionEnum, SelectionItem, TrainItem} from "@/types/train-travel.ts";
-import {StoreTrain} from '@/store/modules/train.ts'
+import { LINE_DOWN, LINE_UP } from "@/pages/train/controller/Constant";
+import { DirectionEnum, SelectionItem, TrainItem } from "@/types/train-travel.ts";
+import { StoreTrain } from '@/store/modules/train.ts'
 
 
 export class DrewTrain {
@@ -42,8 +42,8 @@ export class DrewTrain {
     this.canvas.restore();
     this.canvas.save();
     const titleArray: string[] = [];
-    titleArray.push("列车:" + Number(train.trainNo).toFixed(2));
-    titleArray.push("速度:" + Number(train.speed).toFixed(2) + "  加速度:" + Number(train.acceleration).toFixed(2));
+    titleArray.push("列车:" + train.trainNo);
+    titleArray.push("速度:" + (Number(train.speed) * 3.6).toFixed(2));
     this.drawTitle(position - (trainWidth * 0.5), (position_y - 35), 150, 50, titleArray);
     this.canvas.save();
     // };

+ 2 - 2
train-web/src/pages/train/index.vue

@@ -48,8 +48,8 @@ const drawAll = function (): void {
   drawTrack.drawLine(storeTrain.getSelectionUpList);
   drawTrack.drawLine(storeTrain.getSelectionDownList);
   // 绘制信号灯
-  drawTrack.drawSignalList(storeTrain.getSignalUpList, true);
-  drawTrack.drawSignalList(storeTrain.getSignalDownList, false);
+  drawTrack.drawSignalList(storeTrain.getSignalUpList);
+  drawTrack.drawSignalList(storeTrain.getSignalDownList);
   // 绘制道岔
   drawTrack.drawSwitchList(storeTrain.getSwitchList);
 

+ 8 - 2
train-web/src/types/train-travel.ts

@@ -19,6 +19,11 @@ export enum SectionStatusEnum {
   LOCK = 3, //锁闭 白光带 #FFFFFF
 }
 
+export enum TowardEnum {
+  FORWARD = 1,  // 正向
+  REVERSE = 2,  // 反向
+}
+
 export enum SignalStateEnum {
   RED = 1, // 禁止通行
   GREEN = 2, // 允许通行
@@ -40,6 +45,7 @@ export type SignalItem = {
   colorState: number,
   selectionId: number,
   direction: number,
+  toward: TowardEnum,
   stationId: number
 }
 // 区段
@@ -54,7 +60,7 @@ export type SelectionItem = {
   zfState: boolean;
   stationId: number;
   status: SectionStatusEnum;
-  isSwitch: boolean;
+  switch: boolean;
 }
 // 道岔
 export type SwitchItem = {
@@ -66,7 +72,7 @@ export type SwitchItem = {
   nextSelectionId: string;
   nextSideSelectionId: string;
   switchTie: number,
-  stationId: string;
+  stationId: number;
 }
 // 列车
 export type TrainItem = {