|
|
@@ -29,13 +29,18 @@
|
|
|
<div class="drag-handle" title="拖拽换位" v-if="!expandedId">
|
|
|
<span class="drag-icon">⠇</span>
|
|
|
</div>
|
|
|
- <span class="cell-title">{{ slot.data.label || slot.data.name || '' }}</span>
|
|
|
- <span class="cell-close" @click.stop="handleRemove(slot.data.id)">×</span>
|
|
|
+ <CrossingDetailHeader
|
|
|
+ :currentRoute="slot.headerData ? slot.headerData.currentRoute : { name: slot.data.label || slot.data.name }"
|
|
|
+ :intersectionData="slot.headerData ? slot.headerData.intersectionData : {}"
|
|
|
+ :cycleLength="slot.headerData ? slot.headerData.cycleLength : 0"
|
|
|
+ :onClose="() => handleRemove(slot.data.id)"
|
|
|
+ />
|
|
|
</div>
|
|
|
<div class="cell-body">
|
|
|
<CrossingDetailPanel
|
|
|
:id="slot.data.id"
|
|
|
v-bind="slot.data"
|
|
|
+ :preloadedData="slot.headerData"
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -46,12 +51,15 @@
|
|
|
<script>
|
|
|
import draggable from 'vuedraggable';
|
|
|
import CrossingDetailPanel from '@/components/ui/CrossingDetailPanel.vue';
|
|
|
+import CrossingDetailHeader from '@/components/ui/CrossingDetailHeader.vue';
|
|
|
+import { apiGetCrossingDetailData } from '@/api';
|
|
|
|
|
|
export default {
|
|
|
name: 'CrossingMultiView',
|
|
|
components: {
|
|
|
draggable,
|
|
|
- CrossingDetailPanel
|
|
|
+ CrossingDetailPanel,
|
|
|
+ CrossingDetailHeader
|
|
|
},
|
|
|
props: {
|
|
|
crossings: {
|
|
|
@@ -75,7 +83,8 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
localSlots: [],
|
|
|
- expandedId: null
|
|
|
+ expandedId: null,
|
|
|
+ rebuildVersion: 0
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -123,8 +132,15 @@ export default {
|
|
|
maxSlots() { this.rebuildSlots(); }
|
|
|
},
|
|
|
methods: {
|
|
|
- rebuildSlots() {
|
|
|
- this.localSlots = this.crossings.map(c => ({ type: 'panel', data: c }));
|
|
|
+ async rebuildSlots() {
|
|
|
+ // 保留已加载过的 headerData,避免重复请求
|
|
|
+ const oldMap = {};
|
|
|
+ this.localSlots.forEach(s => {
|
|
|
+ if (s.data && s.headerData) oldMap[s.data.id] = s.headerData;
|
|
|
+ });
|
|
|
+ this.localSlots = this.crossings.map(c => ({
|
|
|
+ type: 'panel', data: c, headerData: oldMap[c.id] || null
|
|
|
+ }));
|
|
|
// 如果展开的路口被外部移除了,退出展开
|
|
|
if (this.expandedId) {
|
|
|
const stillExists = this.crossings.find(c => c.id === this.expandedId);
|
|
|
@@ -133,6 +149,22 @@ export default {
|
|
|
this.$nextTick(() => {
|
|
|
window.dispatchEvent(new Event('resize'));
|
|
|
});
|
|
|
+ // 只对还没有 headerData 的路口发请求
|
|
|
+ const needLoad = this.localSlots
|
|
|
+ .map((s, i) => (!s.headerData ? { index: i, id: s.data.id } : null))
|
|
|
+ .filter(Boolean);
|
|
|
+ if (needLoad.length === 0) return;
|
|
|
+ const version = ++this.rebuildVersion;
|
|
|
+ const results = await Promise.all(
|
|
|
+ needLoad.map(item => apiGetCrossingDetailData(item.id).catch(() => null))
|
|
|
+ );
|
|
|
+ if (version !== this.rebuildVersion) return;
|
|
|
+ results.forEach((data, i) => {
|
|
|
+ const slotIndex = needLoad[i].index;
|
|
|
+ if (data && this.localSlots[slotIndex]) {
|
|
|
+ this.$set(this.localSlots[slotIndex], 'headerData', data);
|
|
|
+ }
|
|
|
+ });
|
|
|
},
|
|
|
|
|
|
handleDblClick(slot) {
|