|
|
@@ -21,28 +21,34 @@
|
|
|
>
|
|
|
<div
|
|
|
v-for="(slot, index) in visibleSlots"
|
|
|
- :key="'panel-' + slot.data.id"
|
|
|
+ :key="slot.type === 'empty' ? slot.data.id : 'panel-' + slot.data.id"
|
|
|
class="grid-cell"
|
|
|
- @dblclick="handleDblClick(slot)"
|
|
|
+ :class="{ 'empty-cell': slot.type === 'empty' }"
|
|
|
+ @dblclick="slot.type === 'panel' && handleDblClick(slot)"
|
|
|
>
|
|
|
- <div class="cell-header">
|
|
|
- <div class="drag-handle" title="拖拽换位" v-if="!expandedId">
|
|
|
- <span class="drag-icon">⠇</span>
|
|
|
+ <template v-if="slot.type === 'panel'">
|
|
|
+ <div class="cell-header">
|
|
|
+ <div class="drag-handle" title="拖拽换位" v-if="!expandedId">
|
|
|
+ <span class="drag-icon">⠇</span>
|
|
|
+ </div>
|
|
|
+ <CrossingDetailHeader
|
|
|
+ :currentRoute="slot.headerData ? { ...slot.headerData.currentRoute, name: slot.data.label || slot.headerData.currentRoute.name } : { name: slot.data.label || slot.data.name }"
|
|
|
+ :intersectionData="slot.headerData ? slot.headerData.intersectionData : {}"
|
|
|
+ :cycleLength="slot.headerData ? slot.headerData.cycleLength : 0"
|
|
|
+ />
|
|
|
+ <span class="cell-close" @click.stop="handleRemove(slot.data.id)">✕</span>
|
|
|
</div>
|
|
|
- <CrossingDetailHeader
|
|
|
- :currentRoute="slot.headerData ? { ...slot.headerData.currentRoute, name: slot.data.label || slot.headerData.currentRoute.name } : { name: slot.data.label || slot.data.name }"
|
|
|
- :intersectionData="slot.headerData ? slot.headerData.intersectionData : {}"
|
|
|
- :cycleLength="slot.headerData ? slot.headerData.cycleLength : 0"
|
|
|
- />
|
|
|
- <span class="cell-close" @click.stop="handleRemove(slot.data.id)">✕</span>
|
|
|
- </div>
|
|
|
- <div class="cell-body">
|
|
|
- <CrossingDetailPanel
|
|
|
- :id="slot.data.id"
|
|
|
- v-bind="slot.data"
|
|
|
- :preloadedData="slot.headerData"
|
|
|
- />
|
|
|
- </div>
|
|
|
+ <div class="cell-body">
|
|
|
+ <CrossingDetailPanel
|
|
|
+ :id="slot.data.id"
|
|
|
+ v-bind="slot.data"
|
|
|
+ :preloadedData="slot.headerData"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <div class="empty-placeholder">暂无路口</div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</draggable>
|
|
|
</div>
|
|
|
@@ -99,9 +105,15 @@ export default {
|
|
|
);
|
|
|
return found ? [found] : this.localSlots;
|
|
|
}
|
|
|
- return this.localSlots;
|
|
|
+ if (this.panelCount <= 1) return this.localSlots;
|
|
|
+ // 2个以上时,补空占位到 maxSlots
|
|
|
+ const slots = [...this.localSlots];
|
|
|
+ while (slots.length < this.maxSlots) {
|
|
|
+ slots.push({ type: 'empty', data: { id: '__empty_' + slots.length } });
|
|
|
+ }
|
|
|
+ return slots;
|
|
|
},
|
|
|
- // 根据实际选中数量决定网格:1→1x1, 2→2x1, 3~4→2x2
|
|
|
+ // 1个→全屏, 2个以上→按 maxSlots 布局
|
|
|
gridCols() {
|
|
|
if (this.expandedId) return 1;
|
|
|
if (this.panelCount <= 1) return 1;
|
|
|
@@ -109,8 +121,8 @@ export default {
|
|
|
},
|
|
|
gridRows() {
|
|
|
if (this.expandedId) return 1;
|
|
|
- if (this.panelCount <= 2) return 1;
|
|
|
- return 2;
|
|
|
+ if (this.panelCount <= 1) return 1;
|
|
|
+ return Math.ceil(this.maxSlots / 2);
|
|
|
},
|
|
|
gridStyle() {
|
|
|
return {
|
|
|
@@ -120,7 +132,8 @@ export default {
|
|
|
},
|
|
|
gridClass() {
|
|
|
if (this.expandedId) return 'slots-1';
|
|
|
- return 'slots-' + this.panelCount;
|
|
|
+ if (this.panelCount <= 1) return 'slots-1';
|
|
|
+ return 'slots-' + this.maxSlots;
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
@@ -336,4 +349,20 @@ export default {
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
+/* ===== 空占位格 ===== */
|
|
|
+.empty-cell {
|
|
|
+ border: 1px dashed rgba(255, 255, 255, 0.15);
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-placeholder {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 100%;
|
|
|
+ color: rgba(255, 255, 255, 0.2);
|
|
|
+ font-size: 14px;
|
|
|
+ user-select: none;
|
|
|
+}
|
|
|
+
|
|
|
</style>
|