|
|
|
|
@ -237,6 +237,7 @@ export default {
|
|
|
|
|
}],
|
|
|
|
|
currentArea: null, // 当前放大的区域对象
|
|
|
|
|
warehousePoints: [], // 当前区域的仓库点位
|
|
|
|
|
hasLoadedWarehouses: false, // 是否已经加载了仓库数据
|
|
|
|
|
// mapData:[]
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
@ -259,6 +260,187 @@ export default {
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
// 计算两个经纬度点之间的距离(单位:度)
|
|
|
|
|
calculateDistance(lon1, lat1, lon2, lat2) {
|
|
|
|
|
const R = 6371 // 地球半径(公里)
|
|
|
|
|
const dLat = (lat2 - lat1) * Math.PI / 180
|
|
|
|
|
const dLon = (lon2 - lon1) * Math.PI / 180
|
|
|
|
|
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
|
|
|
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
|
|
|
|
|
Math.sin(dLon / 2) * Math.sin(dLon / 2)
|
|
|
|
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
|
|
|
|
|
return R * c // 返回距离(公里)
|
|
|
|
|
},
|
|
|
|
|
// 智能分配标签位置,避免重叠 - 简化版:只使用上下两个位置
|
|
|
|
|
assignLabelPositions(warehousePoints) {
|
|
|
|
|
if (!warehousePoints || warehousePoints.length === 0) {
|
|
|
|
|
return warehousePoints
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 距离阈值(经纬度差值),小于此距离的点位需要分开
|
|
|
|
|
// 两个点位相差约 0.000115,所以阈值要更小一些,但也要能检测到
|
|
|
|
|
const threshold = 0.0005 // 约50米,足够检测到这两个点位
|
|
|
|
|
// 坐标偏移量(经纬度差值)- 增大偏移量,确保在小缩放级别下也能看到明显偏移
|
|
|
|
|
// 0.003 约300米,0.005 约500米,在小缩放级别下也能明显看到分开
|
|
|
|
|
const offsetAmount = 0.005 // 约500米,确保视觉上明显分开
|
|
|
|
|
|
|
|
|
|
// 初始化所有点位的标签位置和偏移量
|
|
|
|
|
warehousePoints.forEach((point) => {
|
|
|
|
|
point.labelPosition = 'top' // 默认上方
|
|
|
|
|
point.labelOffset = [-15, -35] // 向左偏移15px,向上偏移35px
|
|
|
|
|
point.processed = false // 标记是否已处理
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 按顺序处理每个点位
|
|
|
|
|
warehousePoints.forEach((point, index) => {
|
|
|
|
|
// 如果已经处理过,跳过
|
|
|
|
|
if (point.processed) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查找距离很近的其他点位
|
|
|
|
|
const nearbyPoints = []
|
|
|
|
|
for (let i = 0; i < warehousePoints.length; i++) {
|
|
|
|
|
if (i === index || warehousePoints[i].processed) continue
|
|
|
|
|
|
|
|
|
|
const otherPoint = warehousePoints[i]
|
|
|
|
|
const deltaLon = point.value[0] - otherPoint.value[0]
|
|
|
|
|
const deltaLat = point.value[1] - otherPoint.value[1]
|
|
|
|
|
const distance = Math.sqrt(deltaLon * deltaLon + deltaLat * deltaLat)
|
|
|
|
|
|
|
|
|
|
if (distance < threshold) {
|
|
|
|
|
nearbyPoints.push({ point: otherPoint, index: i, distance })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果有很近的点位
|
|
|
|
|
if (nearbyPoints.length > 0) {
|
|
|
|
|
// 找到最近的点位
|
|
|
|
|
const closest = nearbyPoints.sort((a, b) => a.distance - b.distance)[0]
|
|
|
|
|
|
|
|
|
|
// 将当前点位向右下偏移,标签应该在下方(因为点位在下方)
|
|
|
|
|
const originalLon = point.value[0]
|
|
|
|
|
const originalLat = point.value[1]
|
|
|
|
|
point.value[0] = originalLon + offsetAmount // 向右偏移
|
|
|
|
|
point.value[1] = originalLat - offsetAmount * 0.7 // 向下偏移
|
|
|
|
|
point.labelPosition = 'bottom'
|
|
|
|
|
point.labelOffset = [-15, 15] // 向左偏移15px,向下偏移15px(标签在下方)
|
|
|
|
|
point.processed = true
|
|
|
|
|
|
|
|
|
|
// 另一个点位保持原位置(在上方),标签应该在上方
|
|
|
|
|
closest.point.labelPosition = 'top'
|
|
|
|
|
closest.point.labelOffset = [-15, -35] // 向左偏移15px,向上偏移35px(标签在上方)
|
|
|
|
|
closest.point.processed = true
|
|
|
|
|
|
|
|
|
|
console.log(`点位 ${point.name} 向右下偏移: 经度 ${originalLon} -> ${point.value[0]}, 纬度 ${originalLat} -> ${point.value[1]}, 标签在下方`)
|
|
|
|
|
console.log(`点位 ${closest.point.name} 保持原位置,标签在上方`)
|
|
|
|
|
} else {
|
|
|
|
|
// 没有很近的点位,保持默认设置
|
|
|
|
|
point.processed = true
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return warehousePoints
|
|
|
|
|
},
|
|
|
|
|
// 清除标签
|
|
|
|
|
clearLabels() {
|
|
|
|
|
if (this.myChart) {
|
|
|
|
|
// 只清除 graphic 元素,不影响其他配置
|
|
|
|
|
// 使用 replaceMerge 只替换 graphic 部分
|
|
|
|
|
this.myChart.setOption({
|
|
|
|
|
graphic: []
|
|
|
|
|
}, {
|
|
|
|
|
notMerge: false,
|
|
|
|
|
replaceMerge: ['graphic'] // 只替换 graphic 部分
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 使用 graphic 组件手动绘制标签
|
|
|
|
|
drawLabelsWithGraphic() {
|
|
|
|
|
if (!this.myChart || !this.warehousePoints || this.warehousePoints.length === 0) {
|
|
|
|
|
// 如果没有点位数据,清除标签
|
|
|
|
|
this.clearLabels()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 先清除之前的标签
|
|
|
|
|
this.clearLabels()
|
|
|
|
|
|
|
|
|
|
// 延迟一下,确保清除完成后再绘制新标签
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.drawLabelsInternal()
|
|
|
|
|
}, 50) // 增加延迟时间到 50ms
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
// 内部方法:实际绘制标签
|
|
|
|
|
drawLabelsInternal() {
|
|
|
|
|
if (!this.myChart || !this.warehousePoints || this.warehousePoints.length === 0) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const graphicElements = []
|
|
|
|
|
|
|
|
|
|
this.warehousePoints.forEach((point, index) => {
|
|
|
|
|
if (!point.name || !point.value || point.value.length !== 2) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 将地理坐标转换为像素坐标
|
|
|
|
|
const pixel = this.myChart.convertToPixel('geo', point.value)
|
|
|
|
|
if (!pixel || pixel.length !== 2 || isNaN(pixel[0]) || isNaN(pixel[1])) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取标签位置和偏移量
|
|
|
|
|
const labelOffset = point.labelOffset || [-15, -35]
|
|
|
|
|
|
|
|
|
|
// 计算标签的像素位置
|
|
|
|
|
let x = pixel[0] + labelOffset[0]
|
|
|
|
|
let y = pixel[1] + labelOffset[1]
|
|
|
|
|
|
|
|
|
|
// 字体大小
|
|
|
|
|
const fontSize = 11
|
|
|
|
|
|
|
|
|
|
// 创建文本元素,不使用背景和边框
|
|
|
|
|
graphicElements.push({
|
|
|
|
|
type: 'text',
|
|
|
|
|
id: `warehouse-label-${index}`,
|
|
|
|
|
z: 10000, // 提高层级,确保在地图区块之上
|
|
|
|
|
left: x,
|
|
|
|
|
top: y,
|
|
|
|
|
style: {
|
|
|
|
|
text: point.name, // 显示完整文字,不截断
|
|
|
|
|
fill: '#ff6600', // 橙色字体
|
|
|
|
|
fontSize: fontSize,
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
textAlign: 'left',
|
|
|
|
|
textVerticalAlign: 'middle'
|
|
|
|
|
},
|
|
|
|
|
onclick: () => {
|
|
|
|
|
this.getWuzi(point)
|
|
|
|
|
},
|
|
|
|
|
cursor: 'pointer'
|
|
|
|
|
})
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('绘制标签失败:', e, point)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 更新 graphic 配置
|
|
|
|
|
if (graphicElements.length > 0) {
|
|
|
|
|
this.myChart.setOption({
|
|
|
|
|
graphic: graphicElements
|
|
|
|
|
}, {
|
|
|
|
|
notMerge: false,
|
|
|
|
|
replaceMerge: ['graphic'] // 只替换 graphic 部分,确保清除旧的
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
// 如果没有元素,也要清除旧的
|
|
|
|
|
this.clearLabels()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async getList(id) {
|
|
|
|
|
this.list = []
|
|
|
|
|
const res = await index({
|
|
|
|
|
@ -487,6 +669,16 @@ export default {
|
|
|
|
|
this.myChart.on('click', params => {
|
|
|
|
|
// 判断是否点击的是地图区域
|
|
|
|
|
if (params.componentType === 'series' && params.seriesType === 'map') {
|
|
|
|
|
// 如果已经加载了仓库数据,阻止点击区域
|
|
|
|
|
if (this.hasLoadedWarehouses) {
|
|
|
|
|
if (this.$message) {
|
|
|
|
|
// this.$message.warning('请先点击"返回全图"后再选择其他区域')
|
|
|
|
|
} else {
|
|
|
|
|
// alert('请先点击"返回全图"后再选择其他区域')
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const areaName = params.name;
|
|
|
|
|
const areaObj = this.streetNameList.find(item => item.name === areaName);
|
|
|
|
|
if (areaObj) {
|
|
|
|
|
@ -497,8 +689,22 @@ export default {
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
async zoomToArea(areaObj) {
|
|
|
|
|
// 如果已经加载了仓库数据,提示用户先返回全图
|
|
|
|
|
if (this.hasLoadedWarehouses) {
|
|
|
|
|
if (this.$message) {
|
|
|
|
|
// this.$message.warning('请先点击"返回全图"后再选择其他区域')
|
|
|
|
|
} else {
|
|
|
|
|
// alert('请先点击"返回全图"后再选择其他区域')
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const that = this // 保存 this 引用,用于 label 配置中的函数
|
|
|
|
|
console.log('点击区域:', areaObj);
|
|
|
|
|
|
|
|
|
|
// 清除之前的标签
|
|
|
|
|
this.clearLabels();
|
|
|
|
|
|
|
|
|
|
// 1. 获取仓库点位数据
|
|
|
|
|
const warehouseList = await this.getList(areaObj.id);
|
|
|
|
|
console.log('获取到的仓库列表:', warehouseList);
|
|
|
|
|
@ -518,15 +724,45 @@ export default {
|
|
|
|
|
name: item.cangkumingcheng,
|
|
|
|
|
value: [jingdu, weidu],
|
|
|
|
|
id: item.id,
|
|
|
|
|
item: item
|
|
|
|
|
item: item,
|
|
|
|
|
labelPosition: null // 稍后分配
|
|
|
|
|
};
|
|
|
|
|
}).filter(point => point !== null); // 过滤掉无效的坐标点
|
|
|
|
|
|
|
|
|
|
// 3. 智能分配标签位置,避免重叠
|
|
|
|
|
this.warehousePoints = this.assignLabelPositions(this.warehousePoints);
|
|
|
|
|
|
|
|
|
|
console.log('生成的仓库点位:', this.warehousePoints);
|
|
|
|
|
console.log('标签位置分配:', this.warehousePoints.map(p => ({
|
|
|
|
|
name: p.name,
|
|
|
|
|
position: p.labelPosition,
|
|
|
|
|
offset: p.labelOffset,
|
|
|
|
|
value: p.value,
|
|
|
|
|
hasName: !!p.name
|
|
|
|
|
})));
|
|
|
|
|
console.log('有效仓库点位数量:', this.warehousePoints.length);
|
|
|
|
|
|
|
|
|
|
// 3. 只更新geo的center和zoom,添加仓库点位
|
|
|
|
|
// 验证每个点位都有 name 字段
|
|
|
|
|
this.warehousePoints.forEach((p, idx) => {
|
|
|
|
|
if (!p.name) {
|
|
|
|
|
console.error(`点位 ${idx} 缺少 name 字段:`, p)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 4. 只更新geo的center和zoom,添加仓库点位
|
|
|
|
|
console.log('设置地图配置,仓库点位数量:', this.warehousePoints.length);
|
|
|
|
|
console.log('准备传递给 scatter 的数据:', this.warehousePoints.map(p => ({ name: p.name, value: p.value, labelPosition: p.labelPosition, labelOffset: p.labelOffset })));
|
|
|
|
|
|
|
|
|
|
// 确保每个点位数据都包含 name 字段
|
|
|
|
|
this.warehousePoints = this.warehousePoints.map(p => ({
|
|
|
|
|
name: p.name || '未知仓库',
|
|
|
|
|
value: p.value,
|
|
|
|
|
labelPosition: p.labelPosition,
|
|
|
|
|
labelOffset: p.labelOffset,
|
|
|
|
|
id: p.id,
|
|
|
|
|
item: p.item
|
|
|
|
|
}))
|
|
|
|
|
console.log('处理后的 warehousePoints 数据:', this.warehousePoints.slice(0, 3)) // 只输出前3个用于调试
|
|
|
|
|
|
|
|
|
|
this.myChart.setOption({
|
|
|
|
|
series: [
|
|
|
|
|
@ -562,46 +798,136 @@ export default {
|
|
|
|
|
data: this.warehousePoints,
|
|
|
|
|
symbol: 'pin',
|
|
|
|
|
symbolSize: [16, 20],
|
|
|
|
|
zlevel: 1, // 提高 scatter 系列的层级
|
|
|
|
|
z: 1, // 提高 scatter 系列的 z 值
|
|
|
|
|
itemStyle: { color: 'orange' },
|
|
|
|
|
label: {
|
|
|
|
|
show: true,
|
|
|
|
|
formatter: '{b}',
|
|
|
|
|
position: 'top',
|
|
|
|
|
color: 'orange',
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
triggerEvent: true // 允许标签触发事件
|
|
|
|
|
formatter: function(params) {
|
|
|
|
|
// 必须显示仓库名称 - 优先从 warehousePoints 数组获取(这是最可靠的方式)
|
|
|
|
|
let name = ''
|
|
|
|
|
|
|
|
|
|
// 方案1:从 warehousePoints 数组获取(最可靠)
|
|
|
|
|
if (that.warehousePoints && params.dataIndex !== undefined && params.dataIndex >= 0 && params.dataIndex < that.warehousePoints.length) {
|
|
|
|
|
const pointData = that.warehousePoints[params.dataIndex]
|
|
|
|
|
if (pointData && pointData.name) {
|
|
|
|
|
name = pointData.name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 方案2:从 params.data 获取(ECharts scatter 系列的标准方式)
|
|
|
|
|
if (!name && params.data) {
|
|
|
|
|
if (typeof params.data === 'object' && params.data.name) {
|
|
|
|
|
name = params.data.name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 方案3:使用 params.name
|
|
|
|
|
if (!name && params.name) {
|
|
|
|
|
name = params.name
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果还是没有获取到,输出调试信息
|
|
|
|
|
if (!name) {
|
|
|
|
|
console.error('标签 formatter 无法获取名称:', {
|
|
|
|
|
dataIndex: params.dataIndex,
|
|
|
|
|
data: params.data,
|
|
|
|
|
name: params.name
|
|
|
|
|
})
|
|
|
|
|
name = '仓库' + (params.dataIndex !== undefined ? (params.dataIndex + 1) : '')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return name
|
|
|
|
|
},
|
|
|
|
|
position: function(params) {
|
|
|
|
|
// 使用预先分配的标签位置(只使用 top 或 bottom)
|
|
|
|
|
if (that.warehousePoints && params.dataIndex !== undefined && params.dataIndex >= 0 && params.dataIndex < that.warehousePoints.length) {
|
|
|
|
|
const pointData = that.warehousePoints[params.dataIndex]
|
|
|
|
|
if (pointData && pointData.labelPosition) {
|
|
|
|
|
return pointData.labelPosition
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 'top'
|
|
|
|
|
},
|
|
|
|
|
color: '#000000', // 改为黑色,确保可见
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
triggerEvent: true,
|
|
|
|
|
offset: function(params) {
|
|
|
|
|
// 使用预先分配的标签偏移量
|
|
|
|
|
if (that.warehousePoints && params.dataIndex !== undefined && params.dataIndex >= 0 && params.dataIndex < that.warehousePoints.length) {
|
|
|
|
|
const pointData = that.warehousePoints[params.dataIndex]
|
|
|
|
|
if (pointData && pointData.labelOffset && Array.isArray(pointData.labelOffset) && pointData.labelOffset.length === 2) {
|
|
|
|
|
return pointData.labelOffset
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return [0, -50]
|
|
|
|
|
},
|
|
|
|
|
padding: [4, 8],
|
|
|
|
|
backgroundColor: '#ffffff',
|
|
|
|
|
borderColor: '#ff6600',
|
|
|
|
|
borderWidth: 1,
|
|
|
|
|
borderRadius: 4,
|
|
|
|
|
shadowBlur: 4,
|
|
|
|
|
shadowColor: 'rgba(0, 0, 0, 0.2)'
|
|
|
|
|
},
|
|
|
|
|
emphasis: {
|
|
|
|
|
label: {
|
|
|
|
|
show: true
|
|
|
|
|
show: true,
|
|
|
|
|
fontSize: 14
|
|
|
|
|
},
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: '#ff8800'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
geo: {
|
|
|
|
|
center: areaObj.coord, // 直接使用streetNameList中的coord
|
|
|
|
|
zoom: areaObj.zoom // 直接使用streetNameList中的zoom
|
|
|
|
|
zoom: areaObj.zoom ? areaObj.zoom * 1.5 : 4.5 // 增加50%的缩放级别
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}, { notMerge: false, lazyUpdate: false });
|
|
|
|
|
|
|
|
|
|
// 强制刷新地图
|
|
|
|
|
this.myChart.resize();
|
|
|
|
|
|
|
|
|
|
// 使用 graphic 组件手动绘制标签
|
|
|
|
|
this.drawLabelsWithGraphic();
|
|
|
|
|
|
|
|
|
|
// 标记已经加载了仓库数据
|
|
|
|
|
this.hasLoadedWarehouses = true
|
|
|
|
|
|
|
|
|
|
// 监听地图变化事件(缩放、平移),重新绘制标签
|
|
|
|
|
this.myChart.off('georoam') // 先移除旧的事件监听
|
|
|
|
|
this.myChart.on('georoam', () => {
|
|
|
|
|
// 地图缩放或平移时,重新绘制标签
|
|
|
|
|
this.drawLabelsWithGraphic()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 重新绑定地图点击事件
|
|
|
|
|
this.myChart.off('click');
|
|
|
|
|
this.myChart.on('click', params => {
|
|
|
|
|
console.log('地图点击事件:', params)
|
|
|
|
|
|
|
|
|
|
// 优先处理仓库点位点击(包括图标和标签)
|
|
|
|
|
if (params.seriesName === '仓库点位') {
|
|
|
|
|
// 如果点击的是标签,需要通过 dataIndex 获取数据
|
|
|
|
|
if (params.dataIndex !== undefined && params.dataIndex !== null) {
|
|
|
|
|
if (params.seriesName === '仓库点位' || (params.componentType === 'series' && params.seriesType === 'scatter')) {
|
|
|
|
|
// 如果点击的是标签或图标,通过 dataIndex 获取数据
|
|
|
|
|
if (params.dataIndex !== undefined && params.dataIndex !== null && params.dataIndex >= 0) {
|
|
|
|
|
const warehouseData = this.warehousePoints[params.dataIndex]
|
|
|
|
|
if (warehouseData) {
|
|
|
|
|
console.log('点击仓库点位:', warehouseData.name)
|
|
|
|
|
this.getWuzi(warehouseData)
|
|
|
|
|
return // 阻止后续处理
|
|
|
|
|
}
|
|
|
|
|
} else if (params.data) {
|
|
|
|
|
// 如果点击的是图标,直接使用 data
|
|
|
|
|
this.getWuzi(params.data)
|
|
|
|
|
}
|
|
|
|
|
// 如果点击的是图标,直接使用 data
|
|
|
|
|
if (params.data) {
|
|
|
|
|
// 尝试从 data 中找到对应的点位数据
|
|
|
|
|
const warehouseData = this.warehousePoints.find(p =>
|
|
|
|
|
p.value[0] === params.data.value[0] && p.value[1] === params.data.value[1]
|
|
|
|
|
) || params.data
|
|
|
|
|
console.log('点击仓库图标:', warehouseData.name || warehouseData)
|
|
|
|
|
this.getWuzi(warehouseData)
|
|
|
|
|
return // 阻止后续处理
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -625,6 +951,10 @@ export default {
|
|
|
|
|
this.cangkuObj = {}
|
|
|
|
|
this.wuziTotal = 0
|
|
|
|
|
this.showData = false
|
|
|
|
|
this.hasLoadedWarehouses = false // 重置标记,允许再次选择区域
|
|
|
|
|
|
|
|
|
|
// 清除标签
|
|
|
|
|
this.clearLabels();
|
|
|
|
|
|
|
|
|
|
console.log('resetToFullMap - warehouseData:', this.warehouseData);
|
|
|
|
|
console.log('resetToFullMap - warehouseData.length:', this.warehouseData ? this.warehouseData.length : 0);
|
|
|
|
|
@ -807,6 +1137,16 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async loadShibenjiWarehouse() {
|
|
|
|
|
// 如果已经加载了仓库数据,提示用户先返回全图
|
|
|
|
|
if (this.hasLoadedWarehouses) {
|
|
|
|
|
if (this.$message) {
|
|
|
|
|
// this.$message.warning('请先点击"返回全图"后再选择其他区域')
|
|
|
|
|
} else {
|
|
|
|
|
// alert('请先点击"返回全图"后再选择其他区域')
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 加载市本级的仓库数据并放大地图
|
|
|
|
|
if (!this.shibenjiAreaId) {
|
|
|
|
|
if (this.$message) {
|
|
|
|
|
@ -825,9 +1165,13 @@ export default {
|
|
|
|
|
await this.loadWarehouseWithoutZoom(this.shibenjiAreaId)
|
|
|
|
|
},
|
|
|
|
|
async loadWarehouseWithoutZoom(areaId) {
|
|
|
|
|
const that = this // 保存 this 引用,用于 label 配置中的函数
|
|
|
|
|
// 加载仓库数据并放大地图
|
|
|
|
|
console.log('加载市本级仓库数据,区域ID:', areaId);
|
|
|
|
|
|
|
|
|
|
// 清除之前的标签
|
|
|
|
|
this.clearLabels();
|
|
|
|
|
|
|
|
|
|
// 1. 获取仓库点位数据
|
|
|
|
|
const warehouseList = await this.getList(areaId);
|
|
|
|
|
console.log('获取到的仓库列表:', warehouseList);
|
|
|
|
|
@ -847,14 +1191,32 @@ export default {
|
|
|
|
|
name: item.cangkumingcheng,
|
|
|
|
|
value: [jingdu, weidu],
|
|
|
|
|
id: item.id,
|
|
|
|
|
item: item
|
|
|
|
|
item: item,
|
|
|
|
|
labelPosition: null // 稍后分配
|
|
|
|
|
};
|
|
|
|
|
}).filter(point => point !== null); // 过滤掉无效的坐标点
|
|
|
|
|
|
|
|
|
|
// 3. 智能分配标签位置,避免重叠
|
|
|
|
|
this.warehousePoints = this.assignLabelPositions(this.warehousePoints);
|
|
|
|
|
|
|
|
|
|
console.log('生成的仓库点位:', this.warehousePoints);
|
|
|
|
|
console.log('标签位置分配:', this.warehousePoints.map(p => ({
|
|
|
|
|
name: p.name,
|
|
|
|
|
position: p.labelPosition,
|
|
|
|
|
offset: p.labelOffset,
|
|
|
|
|
value: p.value,
|
|
|
|
|
hasName: !!p.name
|
|
|
|
|
})));
|
|
|
|
|
console.log('有效仓库点位数量:', this.warehousePoints.length);
|
|
|
|
|
|
|
|
|
|
// 验证每个点位都有 name 字段
|
|
|
|
|
this.warehousePoints.forEach((p, idx) => {
|
|
|
|
|
if (!p.name) {
|
|
|
|
|
console.error(`点位 ${idx} 缺少 name 字段:`, p)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 3. 计算仓库点位的中心点,用于设置地图中心
|
|
|
|
|
// 4. 计算仓库点位的中心点,用于设置地图中心
|
|
|
|
|
let centerCoord = [120.585294, 31.299758] // 默认苏州中心点
|
|
|
|
|
let zoomLevel = 3.5 // 默认缩放级别
|
|
|
|
|
|
|
|
|
|
@ -866,13 +1228,13 @@ export default {
|
|
|
|
|
const sumLat = validPoints.reduce((sum, p) => sum + p.value[1], 0)
|
|
|
|
|
centerCoord = [sumLng / validPoints.length, sumLat / validPoints.length]
|
|
|
|
|
|
|
|
|
|
// 根据仓库数量调整缩放级别
|
|
|
|
|
// 根据仓库数量调整缩放级别(增加更多缩放)
|
|
|
|
|
if (validPoints.length === 1) {
|
|
|
|
|
zoomLevel = 4
|
|
|
|
|
zoomLevel = 5.5 // 进一步增加缩放
|
|
|
|
|
} else if (validPoints.length <= 3) {
|
|
|
|
|
zoomLevel = 3.5
|
|
|
|
|
zoomLevel = 5.0 // 进一步增加缩放
|
|
|
|
|
} else {
|
|
|
|
|
zoomLevel = 3
|
|
|
|
|
zoomLevel = 4.5 // 进一步增加缩放
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -912,18 +1274,86 @@ export default {
|
|
|
|
|
data: this.warehousePoints,
|
|
|
|
|
symbol: 'pin',
|
|
|
|
|
symbolSize: [16, 20],
|
|
|
|
|
zlevel: 1, // 提高 scatter 系列的层级
|
|
|
|
|
z: 1, // 提高 scatter 系列的 z 值
|
|
|
|
|
itemStyle: { color: 'orange' },
|
|
|
|
|
label: {
|
|
|
|
|
show: true,
|
|
|
|
|
formatter: '{b}',
|
|
|
|
|
position: 'top',
|
|
|
|
|
color: 'orange',
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
triggerEvent: true // 允许标签触发事件
|
|
|
|
|
formatter: function(params) {
|
|
|
|
|
// 必须显示仓库名称 - 优先从 warehousePoints 数组获取(这是最可靠的方式)
|
|
|
|
|
let name = ''
|
|
|
|
|
|
|
|
|
|
// 方案1:从 warehousePoints 数组获取(最可靠)
|
|
|
|
|
if (that.warehousePoints && params.dataIndex !== undefined && params.dataIndex >= 0 && params.dataIndex < that.warehousePoints.length) {
|
|
|
|
|
const pointData = that.warehousePoints[params.dataIndex]
|
|
|
|
|
if (pointData && pointData.name) {
|
|
|
|
|
name = pointData.name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 方案2:从 params.data 获取(ECharts scatter 系列的标准方式)
|
|
|
|
|
if (!name && params.data) {
|
|
|
|
|
if (typeof params.data === 'object' && params.data.name) {
|
|
|
|
|
name = params.data.name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 方案3:使用 params.name
|
|
|
|
|
if (!name && params.name) {
|
|
|
|
|
name = params.name
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果还是没有获取到,输出调试信息
|
|
|
|
|
if (!name) {
|
|
|
|
|
console.error('标签 formatter 无法获取名称:', {
|
|
|
|
|
dataIndex: params.dataIndex,
|
|
|
|
|
data: params.data,
|
|
|
|
|
name: params.name
|
|
|
|
|
})
|
|
|
|
|
name = '仓库' + (params.dataIndex !== undefined ? (params.dataIndex + 1) : '')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return name
|
|
|
|
|
},
|
|
|
|
|
position: function(params) {
|
|
|
|
|
// 使用预先分配的标签位置(只使用 top 或 bottom)
|
|
|
|
|
if (that.warehousePoints && params.dataIndex !== undefined && params.dataIndex >= 0 && params.dataIndex < that.warehousePoints.length) {
|
|
|
|
|
const pointData = that.warehousePoints[params.dataIndex]
|
|
|
|
|
if (pointData && pointData.labelPosition) {
|
|
|
|
|
return pointData.labelPosition
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 'top'
|
|
|
|
|
},
|
|
|
|
|
color: '#000000', // 改为黑色,确保可见
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
triggerEvent: true,
|
|
|
|
|
offset: function(params) {
|
|
|
|
|
// 使用预先分配的标签偏移量
|
|
|
|
|
if (that.warehousePoints && params.dataIndex !== undefined && params.dataIndex >= 0 && params.dataIndex < that.warehousePoints.length) {
|
|
|
|
|
const pointData = that.warehousePoints[params.dataIndex]
|
|
|
|
|
if (pointData && pointData.labelOffset && Array.isArray(pointData.labelOffset) && pointData.labelOffset.length === 2) {
|
|
|
|
|
return pointData.labelOffset
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return [0, -50]
|
|
|
|
|
},
|
|
|
|
|
padding: [4, 8],
|
|
|
|
|
backgroundColor: '#ffffff',
|
|
|
|
|
borderColor: '#ff6600',
|
|
|
|
|
borderWidth: 1,
|
|
|
|
|
borderRadius: 4,
|
|
|
|
|
shadowBlur: 4,
|
|
|
|
|
shadowColor: 'rgba(0, 0, 0, 0.2)'
|
|
|
|
|
},
|
|
|
|
|
emphasis: {
|
|
|
|
|
label: {
|
|
|
|
|
show: true
|
|
|
|
|
show: true,
|
|
|
|
|
fontSize: 14
|
|
|
|
|
},
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: '#ff8800'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -932,26 +1362,48 @@ export default {
|
|
|
|
|
center: centerCoord,
|
|
|
|
|
zoom: zoomLevel
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}, { notMerge: false, lazyUpdate: false });
|
|
|
|
|
|
|
|
|
|
// 强制刷新地图
|
|
|
|
|
this.myChart.resize();
|
|
|
|
|
|
|
|
|
|
// 使用 graphic 组件手动绘制标签
|
|
|
|
|
this.drawLabelsWithGraphic();
|
|
|
|
|
|
|
|
|
|
// 标记已经加载了仓库数据
|
|
|
|
|
this.hasLoadedWarehouses = true
|
|
|
|
|
|
|
|
|
|
// 监听地图变化事件(缩放、平移),重新绘制标签
|
|
|
|
|
this.myChart.off('georoam') // 先移除旧的事件监听
|
|
|
|
|
this.myChart.on('georoam', () => {
|
|
|
|
|
// 地图缩放或平移时,重新绘制标签
|
|
|
|
|
this.drawLabelsWithGraphic()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 重新绑定地图点击事件
|
|
|
|
|
this.myChart.off('click');
|
|
|
|
|
this.myChart.on('click', params => {
|
|
|
|
|
console.log('地图点击事件:', params)
|
|
|
|
|
|
|
|
|
|
// 优先处理仓库点位点击(包括图标和标签)
|
|
|
|
|
if (params.seriesName === '仓库点位') {
|
|
|
|
|
// 如果点击的是标签,需要通过 dataIndex 获取数据
|
|
|
|
|
if (params.dataIndex !== undefined && params.dataIndex !== null) {
|
|
|
|
|
if (params.seriesName === '仓库点位' || (params.componentType === 'series' && params.seriesType === 'scatter')) {
|
|
|
|
|
// 如果点击的是标签或图标,通过 dataIndex 获取数据
|
|
|
|
|
if (params.dataIndex !== undefined && params.dataIndex !== null && params.dataIndex >= 0) {
|
|
|
|
|
const warehouseData = this.warehousePoints[params.dataIndex]
|
|
|
|
|
if (warehouseData) {
|
|
|
|
|
console.log('点击仓库点位:', warehouseData.name)
|
|
|
|
|
this.getWuzi(warehouseData)
|
|
|
|
|
return // 阻止后续处理
|
|
|
|
|
}
|
|
|
|
|
} else if (params.data) {
|
|
|
|
|
// 如果点击的是图标,直接使用 data
|
|
|
|
|
this.getWuzi(params.data)
|
|
|
|
|
}
|
|
|
|
|
// 如果点击的是图标,直接使用 data
|
|
|
|
|
if (params.data) {
|
|
|
|
|
// 尝试从 data 中找到对应的点位数据
|
|
|
|
|
const warehouseData = this.warehousePoints.find(p =>
|
|
|
|
|
p.value[0] === params.data.value[0] && p.value[1] === params.data.value[1]
|
|
|
|
|
) || params.data
|
|
|
|
|
console.log('点击仓库图标:', warehouseData.name || warehouseData)
|
|
|
|
|
this.getWuzi(warehouseData)
|
|
|
|
|
return // 阻止后续处理
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|