CrossingPanel.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <template>
  2. <div class="crossing-panel">
  3. <div class="intersection-video-wrap">
  4. <IntersectionMapVideos :mapData="intersectionData" :videoUrls="currentRoute.cornerVideos" />
  5. </div>
  6. <div class="signal-timing-wrap">
  7. <div class="header" v-if="false">
  8. <div class="title-area">
  9. <span class="main-title">方案状态</span>
  10. <span class="sub-info">(周期: {{ cycleLength }} 相位差: 0 协调时间: 0)</span>
  11. </div>
  12. <div class="checkbox-area" v-if="false">
  13. <div class="checkbox-mock" :class="{ 'is-checked': followPhase }"
  14. @click="followPhase = !followPhase">
  15. <span v-if="followPhase" style="color: #fff; font-size: 12px; margin-left: 1px;">✓</span>
  16. </div>
  17. <span>跟随相位</span>
  18. </div>
  19. </div>
  20. <SignalTimingChart :cycleLength="cycleLength" :currentTime="currentSec" :phaseData="mockPhaseData" />
  21. </div>
  22. </div>
  23. </template>
  24. <script>
  25. import SignalTimingChart from '@/components/ui/SignalTimingChart.vue';
  26. import IntersectionMapVideos from '@/components/ui/IntersectionMapVideos.vue';
  27. import { getIntersectionData } from '@/mock/data';
  28. export default {
  29. name: 'CrossingPanel',
  30. components: {
  31. SignalTimingChart,
  32. IntersectionMapVideos
  33. },
  34. props: {
  35. },
  36. data() {
  37. return {
  38. followPhase: false,
  39. intersectionData: {},
  40. currentRoute: {
  41. id: 1, name: '靖远路与北公路交叉口 1', level: '一级', mode: '快进', time: '30s',
  42. mainVideo: require('@/assets/videos/video1.mp4'),
  43. cornerVideos: { nw: require('@/assets/videos/video1.mp4'), ne: require('@/assets/videos/video2.mp4'), sw: require('@/assets/videos/video2.mp4'), se: require('@/assets/videos/video1.mp4') }
  44. },
  45. cycleLength: 140,
  46. currentSec: 15,
  47. mockPhaseData: [
  48. // ================= 上轨道 (Track 0) =================
  49. // S1阶段 (0-30s): P1 直行
  50. [0, 0, 23, 'P1', 30, 'green', 'UP'],
  51. [0, 23, 26, '', 3, 'stripe', ''],
  52. [0, 26, 29, '', 3, 'yellow', ''],
  53. [0, 29, 30, '', 1, 'red', ''],
  54. // S2阶段 (30-60s): P2 左转
  55. [0, 30, 53, 'P2', 30, 'green', 'TURN_LEFT'],
  56. [0, 53, 56, '', 3, 'stripe', ''],
  57. [0, 56, 59, '', 3, 'yellow', ''],
  58. [0, 59, 60, '', 1, 'red', ''],
  59. // S3阶段 (60-110s): P3 侧向左转 (使用向左箭头)
  60. [0, 60, 103, 'P3', 50, 'green', 'TURN_LEFT'],
  61. [0, 103, 106, '', 3, 'stripe', ''],
  62. [0, 106, 109, '', 3, 'yellow', ''],
  63. [0, 109, 110, '', 1, 'red', ''],
  64. // S4阶段 (110-140s): P4 掉头
  65. [0, 110, 133, 'P4', 30, 'green', 'UTURN'],
  66. [0, 133, 136, '', 3, 'stripe', ''],
  67. [0, 136, 139, '', 3, 'yellow', ''],
  68. [0, 139, 140, '', 1, 'red', ''],
  69. // ================= 下轨道 (Track 1) =================
  70. // S1阶段 (0-30s): P5 直行
  71. [1, 0, 23, 'P5', 30, 'green', 'UP'],
  72. [1, 23, 26, '', 3, 'stripe', ''],
  73. [1, 26, 29, '', 3, 'yellow', ''],
  74. [1, 29, 30, '', 1, 'red', ''],
  75. // S2阶段 (30-60s): P6 左转
  76. [1, 30, 53, 'P6', 30, 'green', 'TURN_LEFT'],
  77. [1, 53, 56, '', 3, 'stripe', ''],
  78. [1, 56, 59, '', 3, 'yellow', ''],
  79. [1, 59, 60, '', 1, 'red', ''],
  80. // S3阶段 (60-110s): P7 侧向右转 (使用向右箭头)
  81. [1, 60, 103, 'P7', 50, 'green', 'TURN_RIGHT'],
  82. [1, 103, 106, '', 3, 'stripe', ''],
  83. [1, 106, 109, '', 3, 'yellow', ''],
  84. [1, 109, 110, '', 1, 'red', ''],
  85. // S4阶段 (110-140s): P8 左转
  86. [1, 110, 133, 'P8', 30, 'green', 'TURN_LEFT'],
  87. [1, 133, 136, '', 3, 'stripe', ''],
  88. [1, 136, 139, '', 3, 'yellow', ''],
  89. [1, 139, 140, '', 1, 'red', '']
  90. ]
  91. }
  92. },
  93. async mounted() {
  94. this.intersectionData = await getIntersectionData();
  95. },
  96. }
  97. </script>
  98. <style scoped>
  99. .crossing-panel {
  100. display: flex;
  101. flex-direction: column;
  102. }
  103. .intersection-video-wrap {
  104. width: 100%;
  105. height: 100px;
  106. flex: auto;
  107. }
  108. .signal-timing-wrap {
  109. flex: 1;
  110. --s: 1;
  111. width: 100%;
  112. height: 80px;
  113. min-width: 0;
  114. background-color: transparent;
  115. box-sizing: border-box;
  116. position: relative;
  117. display: flex;
  118. flex-direction: column;
  119. overflow: hidden;
  120. padding: calc(var(--s) * 10px);
  121. }
  122. .header {
  123. display: flex;
  124. justify-content: space-between;
  125. align-items: center;
  126. margin-bottom: calc(var(--s) * 15px);
  127. color: #e0e6f1;
  128. flex-shrink: 0;
  129. }
  130. .title-area {
  131. font-size: calc(var(--s) * 16px);
  132. }
  133. .main-title {
  134. font-size: calc(var(--s) * 18px);
  135. font-weight: bold;
  136. margin-right: calc(var(--s) * 10px);
  137. }
  138. .sub-info {
  139. font-size: calc(var(--s) * 12px);
  140. opacity: 0.8;
  141. }
  142. .checkbox-area {
  143. font-size: calc(var(--s) * 12px);
  144. display: flex;
  145. align-items: center;
  146. cursor: pointer;
  147. opacity: 0.7;
  148. user-select: none;
  149. }
  150. .checkbox-area:hover {
  151. opacity: 1;
  152. }
  153. .checkbox-mock {
  154. width: calc(var(--s) * 14px);
  155. height: calc(var(--s) * 14px);
  156. border: 1px solid rgba(255, 255, 255, 0.5);
  157. margin-right: calc(var(--s) * 6px);
  158. border-radius: 2px;
  159. display: flex;
  160. align-items: center;
  161. justify-content: center;
  162. }
  163. .checkbox-mock.is-checked {
  164. background-color: #4da8ff;
  165. border-color: #4da8ff;
  166. }
  167. .chart-container {
  168. width: 100%;
  169. min-width: 0;
  170. flex: 1;
  171. min-height: 80px;
  172. overflow: hidden;
  173. }
  174. .loading-overlay {
  175. flex: 1;
  176. display: flex;
  177. align-items: center;
  178. justify-content: center;
  179. color: #758599;
  180. font-size: 14px;
  181. }
  182. </style>