|
|
@@ -10,8 +10,9 @@
|
|
|
</div>
|
|
|
<div class="legend-list">
|
|
|
<div class="legend-item all-select" @click="toggleAll">
|
|
|
- <div class="legend-dot"
|
|
|
- :style="{ backgroundColor: isAllSelected ? '#fff' : 'transparent', border: '1px solid #fff' }"></div>
|
|
|
+ <div class="legend-dot all-select-dot" :class="{ 'is-checked': isAllSelected }">
|
|
|
+ <i class="check-icon" v-if="isAllSelected"></i>
|
|
|
+ </div>
|
|
|
<div class="legend-label" style="font-weight: bold;">全选</div>
|
|
|
</div>
|
|
|
|
|
|
@@ -63,7 +64,7 @@ export default {
|
|
|
legend: {}
|
|
|
},
|
|
|
legendVisible: true,
|
|
|
- activeLegends: ["中心计划", "干线协调", "勤务路线", "定周期控制", "感应控制", "自适应控制", "手动控制", "特殊控制", "离线", "降级", "故障"],
|
|
|
+ activeLegends: ["中心计划", "干线协调", "勤务路线", "定周期控制", "感应控制", "自适应控制", "手动控制", "黄闪", "全红", "关灯", "离线", "降级", "故障"],
|
|
|
isComponentDestroyed: false,
|
|
|
drawSeq: 0,
|
|
|
driving: null,
|
|
|
@@ -78,9 +79,12 @@ export default {
|
|
|
{ name: "感应控制", color: "#FF864C", type: "normal" },
|
|
|
{ name: "自适应控制", color: "#9F6EFE", type: "normal" },
|
|
|
{ name: "手动控制", color: "#EB9F36", type: "normal" },
|
|
|
- { name: "特殊控制", color: "#A26218", type: "normal" },
|
|
|
+ { name: "黄闪", color: "#F4D03F", type: "normal" },
|
|
|
+ { name: "全红", color: "#E74C3C", type: "normal" },
|
|
|
+ { name: "关灯", color: "#5B6B7A", type: "normal" },
|
|
|
{ name: "离线", color: "#7A7A7A", type: "abnormal" },
|
|
|
- { name: "降级", color: "#D9C13B", type: "abnormal" },
|
|
|
+ // 降级 仍参与数据分类与地图绘制,但不出现在图例(hideInLegend: true)
|
|
|
+ { name: "降级", color: "#D9C13B", type: "abnormal", hideInLegend: true },
|
|
|
{ name: "故障", color: "#FF3938", type: "abnormal" }
|
|
|
],
|
|
|
intersectionData: [],
|
|
|
@@ -170,8 +174,11 @@ export default {
|
|
|
this.isInfoWindowHovered = false;
|
|
|
},
|
|
|
computed: {
|
|
|
+ // 全选状态:仅判断"图例上可见的项"是否全部启用,不受常隐项(如降级)影响
|
|
|
isAllSelected() {
|
|
|
- return this.activeLegends.length === this.statusConfig.length;
|
|
|
+ const visible = this.legendStatusConfig.map(i => i.name);
|
|
|
+ if (visible.length === 0) return false;
|
|
|
+ return visible.every(n => this.activeLegends.includes(n));
|
|
|
},
|
|
|
isHomePage() {
|
|
|
return this.$route && (this.$route.path === '/home' || this.$route.path === '/surve');
|
|
|
@@ -182,11 +189,24 @@ export default {
|
|
|
return { right, borderRadius: '6px' };
|
|
|
},
|
|
|
legendStatusConfig() {
|
|
|
- if (!this.mode) return this.statusConfig;
|
|
|
+ // 1. 按 mode 过滤
|
|
|
+ let list = this.statusConfig;
|
|
|
if (this.mode === '路口') {
|
|
|
- return this.statusConfig.filter(item => !['干线协调', '勤务路线'].includes(item.name));
|
|
|
+ list = list.filter(item => !['干线协调', '勤务路线'].includes(item.name));
|
|
|
+ } else if (this.mode && this.mode !== '路口') {
|
|
|
+ return [];
|
|
|
}
|
|
|
- return [];
|
|
|
+ // 2. hideInLegend 项一律不进图例(数据与地图绘制不受影响)
|
|
|
+ list = list.filter(item => !item.hideInLegend);
|
|
|
+ // 3. 仅展示路口/路线实际存在的控制模式:
|
|
|
+ // - 路线类(type: route)固定有线段配置,始终显示
|
|
|
+ // - 其余按 statusIntersections[name] 是否非空过滤
|
|
|
+ list = list.filter(item => {
|
|
|
+ if (item.type === 'route') return true;
|
|
|
+ const ints = this.statusIntersections && this.statusIntersections[item.name];
|
|
|
+ return ints && ints.length > 0;
|
|
|
+ });
|
|
|
+ return list;
|
|
|
},
|
|
|
// 自动计算并下发给所有 CSS 的变量字典
|
|
|
mapCssVars() {
|
|
|
@@ -232,7 +252,8 @@ export default {
|
|
|
const categories = {
|
|
|
"中心计划": [], "干线协调": [], "勤务路线": [],
|
|
|
"定周期控制": [], "感应控制": [], "自适应控制": [],
|
|
|
- "手动控制": [], "特殊控制": [],
|
|
|
+ "手动控制": [],
|
|
|
+ "黄闪": [], "全红": [], "关灯": [],
|
|
|
"离线": [], "降级": [], "故障": []
|
|
|
};
|
|
|
for (const item of this.intersectionData) {
|
|
|
@@ -250,7 +271,7 @@ export default {
|
|
|
updateMapByMode() {
|
|
|
switch (this.mode) {
|
|
|
case '路口':
|
|
|
- this.activeLegends = ["中心计划", "定周期控制", "感应控制", "自适应控制", "手动控制", "特殊控制", "离线", "降级", "故障"];
|
|
|
+ this.activeLegends = ["中心计划", "定周期控制", "感应控制", "自适应控制", "手动控制", "黄闪", "全红", "关灯", "离线", "降级", "故障"];
|
|
|
break;
|
|
|
case '干线':
|
|
|
this.activeLegends = ["干线协调"];
|
|
|
@@ -1257,20 +1278,28 @@ export default {
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
- * 切换所有图例的可见性
|
|
|
+ * 切换"所有图例可见项"的开关。常隐项(hideInLegend,如 降级)始终保留显示。
|
|
|
*/
|
|
|
toggleAll() {
|
|
|
- const targetState = !this.isAllSelected;
|
|
|
if (!this.isMapReady()) return;
|
|
|
+ const visibleNames = this.legendStatusConfig.map(i => i.name);
|
|
|
+ const alwaysOnNames = this.statusConfig
|
|
|
+ .filter(i => i.hideInLegend)
|
|
|
+ .map(i => i.name);
|
|
|
+ const targetState = !this.isAllSelected;
|
|
|
|
|
|
if (targetState) {
|
|
|
- this.activeLegends = this.statusConfig.map(item => item.name);
|
|
|
- Object.values(this.routeGroups).forEach(overlays => {
|
|
|
+ // 全选可见项 + 保留常隐项
|
|
|
+ this.activeLegends = Array.from(new Set([...alwaysOnNames, ...visibleNames]));
|
|
|
+ visibleNames.forEach(name => {
|
|
|
+ const overlays = this.routeGroups[name];
|
|
|
if (overlays && overlays.length > 0) this.map.add(overlays);
|
|
|
});
|
|
|
} else {
|
|
|
- this.activeLegends = [];
|
|
|
- Object.values(this.routeGroups).forEach(overlays => {
|
|
|
+ // 取消所有可见项,常隐项保留在 activeLegends,对应图层不动
|
|
|
+ this.activeLegends = [...alwaysOnNames];
|
|
|
+ visibleNames.forEach(name => {
|
|
|
+ const overlays = this.routeGroups[name];
|
|
|
if (overlays && overlays.length > 0) this.map.remove(overlays);
|
|
|
});
|
|
|
if (this.infoWindow) this.infoWindow.close();
|
|
|
@@ -1876,6 +1905,35 @@ export default {
|
|
|
height: 10px;
|
|
|
}
|
|
|
|
|
|
+/* 全选勾选框:未选时为透明带白边的方框,选中时填充蓝色并显示对勾 */
|
|
|
+.all-select .legend-dot.all-select-dot {
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ border-radius: 3px;
|
|
|
+ border: 1px solid #fff;
|
|
|
+ background: transparent;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ box-shadow: none;
|
|
|
+}
|
|
|
+
|
|
|
+.all-select .legend-dot.all-select-dot.is-checked {
|
|
|
+ background: #1890ff;
|
|
|
+ border-color: #1890ff;
|
|
|
+}
|
|
|
+
|
|
|
+/* 用两条边框拼一个真正居中的对勾,避免 ✓ 字符在不同字体下基线偏移 */
|
|
|
+.all-select .check-icon {
|
|
|
+ display: block;
|
|
|
+ width: 6px;
|
|
|
+ height: 9px;
|
|
|
+ border: solid #fff;
|
|
|
+ border-width: 0 2px 2px 0;
|
|
|
+ transform: translateY(-1px) rotate(45deg);
|
|
|
+ transform-origin: center;
|
|
|
+}
|
|
|
+
|
|
|
.legend-dot.is-status-wrapper {
|
|
|
width: 28px;
|
|
|
height: 28px;
|