|
@@ -362,39 +362,70 @@ export default {
|
|
|
if (type === 'end') displayText = '终';
|
|
if (type === 'end') displayText = '终';
|
|
|
|
|
|
|
|
const isAbnormal = ["离线", "降级", "故障"].includes(config.name);
|
|
const isAbnormal = ["离线", "降级", "故障"].includes(config.name);
|
|
|
|
|
+ const isRoute = ["干线协调", "勤务路线"].includes(config.name);
|
|
|
|
|
|
|
|
// 动态计算尺寸:起终点最大,异常点次之,普通点最小
|
|
// 动态计算尺寸:起终点最大,异常点次之,普通点最小
|
|
|
- const size = (type === 'start' || type === 'end') ? '22px' : (isAbnormal ? '18px' : '14px');
|
|
|
|
|
|
|
+ const size = (type === 'start' || type === 'end') ? '22px' : (isAbnormal ? '30px' : '14px');
|
|
|
|
|
+ const sizeNumber = parseInt(size, 10);
|
|
|
|
|
+ const paddingNumber = (isAbnormal || type === 'start' || type === 'end') ? 0 : 2;
|
|
|
|
|
+ const outerSizeNumber = sizeNumber + paddingNumber * 2;
|
|
|
|
|
|
|
|
// 边框样式:起终点用实白边框
|
|
// 边框样式:起终点用实白边框
|
|
|
const borderStyle = (type === 'start' || type === 'end')
|
|
const borderStyle = (type === 'start' || type === 'end')
|
|
|
? '2px solid #fff'
|
|
? '2px solid #fff'
|
|
|
: '1.5px solid rgba(255,255,255,0.7)';
|
|
: '1.5px solid rgba(255,255,255,0.7)';
|
|
|
|
|
|
|
|
- const marker = new this.AMap.Marker({
|
|
|
|
|
- position: [lng, lat],
|
|
|
|
|
- // 这里的 type 已经从参数拿到了,不会报错了
|
|
|
|
|
- zIndex: (type === 'start' || type === 'end') ? 120 : (isAbnormal ? 110 : 100),
|
|
|
|
|
- content: `
|
|
|
|
|
|
|
+ // 生成异常状态的图标路径
|
|
|
|
|
+ let markerContent = '';
|
|
|
|
|
+ if (isAbnormal) {
|
|
|
|
|
+ const iconName = config.name === '离线' ? 'lixian' : config.name === '降级' ? 'jiangji' : 'guzhang';
|
|
|
|
|
+ markerContent = `
|
|
|
<div class="pure-light-node ${isAbnormal ? 'breathe' : ''}"
|
|
<div class="pure-light-node ${isAbnormal ? 'breathe' : ''}"
|
|
|
style="
|
|
style="
|
|
|
width: ${size};
|
|
width: ${size};
|
|
|
height: ${size};
|
|
height: ${size};
|
|
|
|
|
+ background: transparent;
|
|
|
|
|
+ box-shadow: none;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ box-sizing: content-box;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ padding: ${paddingNumber}px;
|
|
|
|
|
+ ">
|
|
|
|
|
+ <img src="${require(`@/assets/images/icon_${iconName}.png`)}" style="width: 100%; height: 100%; object-fit: contain;" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ `;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ markerContent = `
|
|
|
|
|
+ <div class="pure-light-node ${isAbnormal ? 'breathe' : ''} ${isRoute ? 'route-node' : ''}"
|
|
|
|
|
+ style="
|
|
|
|
|
+ width: ${size};
|
|
|
|
|
+ height: ${size};
|
|
|
background: ${config.color || '#999'};
|
|
background: ${config.color || '#999'};
|
|
|
- box-shadow: 0 0 8px ${config.color};
|
|
|
|
|
- border: ${borderStyle};
|
|
|
|
|
|
|
+ box-shadow: ${isRoute ? 'none' : `0 0 8px ${config.color}`};
|
|
|
|
|
+ border: ${isRoute ? 'none' : borderStyle};
|
|
|
|
|
+ box-sizing: content-box;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
color: #fff;
|
|
color: #fff;
|
|
|
border-radius: 50%;
|
|
border-radius: 50%;
|
|
|
cursor: pointer;
|
|
cursor: pointer;
|
|
|
- padding: 8px;
|
|
|
|
|
|
|
+ padding: ${paddingNumber}px;
|
|
|
">
|
|
">
|
|
|
<span style="transform: scale(0.8); font-weight: bold; font-size: 12px;">${displayText}</span>
|
|
<span style="transform: scale(0.8); font-weight: bold; font-size: 12px;">${displayText}</span>
|
|
|
</div>
|
|
</div>
|
|
|
- `,
|
|
|
|
|
- offset: new this.AMap.Pixel(-11, -11),
|
|
|
|
|
|
|
+ `;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const marker = new this.AMap.Marker({
|
|
|
|
|
+ position: [lng, lat],
|
|
|
|
|
+ // 这里的 type 已经从参数拿到了,不会报错了
|
|
|
|
|
+ zIndex: (type === 'start' || type === 'end') ? 120 : (isAbnormal ? 110 : 100),
|
|
|
|
|
+ content: markerContent,
|
|
|
|
|
+ offset: new this.AMap.Pixel(-Math.round(outerSizeNumber / 2), -Math.round(outerSizeNumber / 2)),
|
|
|
extData: {
|
|
extData: {
|
|
|
...config,
|
|
...config,
|
|
|
position: [lng, lat],
|
|
position: [lng, lat],
|
|
@@ -423,12 +454,22 @@ export default {
|
|
|
if (!this.isMapReady()) return;
|
|
if (!this.isMapReady()) return;
|
|
|
|
|
|
|
|
const infoWindowId = `info-window-${Date.now()}`;
|
|
const infoWindowId = `info-window-${Date.now()}`;
|
|
|
|
|
+ const isAbnormal = ["离线", "降级", "故障"].includes(data.name);
|
|
|
|
|
+ let statusDotContent = '';
|
|
|
|
|
+
|
|
|
|
|
+ if (isAbnormal) {
|
|
|
|
|
+ const iconName = data.name === '离线' ? 'lixian' : data.name === '降级' ? 'jiangji' : 'guzhang';
|
|
|
|
|
+ statusDotContent = `<img src="${require(`@/assets/images/icon_${iconName}.png`)}" style="width: 100%; height: 100%; object-fit: contain;" />`;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ statusDotContent = `<span>${data.name.charAt(0)}</span>`;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
const content = `
|
|
const content = `
|
|
|
<div class="custom-info-card" id="${infoWindowId}">
|
|
<div class="custom-info-card" id="${infoWindowId}">
|
|
|
<div class="close-btn" data-id="${infoWindowId}">✕</div>
|
|
<div class="close-btn" data-id="${infoWindowId}">✕</div>
|
|
|
<div class="card-header">
|
|
<div class="card-header">
|
|
|
- <div class="status-dot" style="background: ${data.statusColor}">
|
|
|
|
|
- <span>${data.name.charAt(0)}</span>
|
|
|
|
|
|
|
+ <div class="status-dot" style="background: ${isAbnormal ? 'transparent' : data.statusColor}; border: ${isAbnormal ? 'none' : ''}">
|
|
|
|
|
+ ${statusDotContent}
|
|
|
</div>
|
|
</div>
|
|
|
<span class="status-text">${data.statusLabel}</span>
|
|
<span class="status-text">${data.statusLabel}</span>
|
|
|
</div>
|
|
</div>
|
|
@@ -888,6 +929,29 @@ export default {
|
|
|
pointer-events: auto;
|
|
pointer-events: auto;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+::v-deep .pure-light-node.route-node {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ overflow: visible;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+::v-deep .pure-light-node.route-node::after {
|
|
|
|
|
+ content: "";
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 50%;
|
|
|
|
|
+ left: 50%;
|
|
|
|
|
+ width: 150%;
|
|
|
|
|
+ height: 3px;
|
|
|
|
|
+ background-color: inherit;
|
|
|
|
|
+ opacity: 0.8;
|
|
|
|
|
+ transform: translate(-50%, -50%) rotate(-45deg);
|
|
|
|
|
+ pointer-events: none;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+::v-deep .pure-light-node.route-node span {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ z-index: 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/* 异常状态增加稍微剧烈一点的呼吸感,但缩小范围 */
|
|
/* 异常状态增加稍微剧烈一点的呼吸感,但缩小范围 */
|
|
|
@keyframes light-breathe {
|
|
@keyframes light-breathe {
|
|
|
0% {
|
|
0% {
|
|
@@ -910,4 +974,4 @@ export default {
|
|
|
::v-deep .pure-light-node:not(.abnormal-node) {
|
|
::v-deep .pure-light-node:not(.abnormal-node) {
|
|
|
border: 1px solid rgba(255, 255, 255, 0.4);
|
|
border: 1px solid rgba(255, 255, 255, 0.4);
|
|
|
}
|
|
}
|
|
|
-</style>
|
|
|
|
|
|
|
+</style>
|