fix:高德地图探索
This commit is contained in:
parent
652a32b797
commit
9bc4889309
@ -18,7 +18,7 @@ spring:
|
|||||||
master:
|
master:
|
||||||
type: com.alibaba.druid.pool.DruidDataSource
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://localhost:3306/fastbee?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
url: jdbc:mysql://1.116.124.85:3306/fastbee?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||||
username: root
|
username: root
|
||||||
password: fastbee
|
password: fastbee
|
||||||
druid:
|
druid:
|
||||||
@ -56,7 +56,7 @@ spring:
|
|||||||
# ds0: # 配置 mysql 数据源
|
# ds0: # 配置 mysql 数据源
|
||||||
# type: com.alibaba.druid.pool.DruidDataSource
|
# type: com.alibaba.druid.pool.DruidDataSource
|
||||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
# url: jdbc:mysql://localhost:3306/fastbee?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
# url: jdbc:mysql://1.116.124.85:3306/fastbee?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||||
# username: root
|
# username: root
|
||||||
# password: fastbee
|
# password: fastbee
|
||||||
# filters: stat,wall
|
# filters: stat,wall
|
||||||
@ -100,9 +100,9 @@ spring:
|
|||||||
|
|
||||||
# redis 配置
|
# redis 配置
|
||||||
redis:
|
redis:
|
||||||
host: localhost # 地址
|
host: 1.116.124.85 # 地址
|
||||||
port: 6379 # 端口,默认为6379
|
port: 6379 # 端口,默认为6379
|
||||||
database: 3 # 数据库索引
|
database: 0 # 数据库索引
|
||||||
password: fastbee # 密码
|
password: fastbee # 密码
|
||||||
timeout: 10s # 连接超时时间
|
timeout: 10s # 连接超时时间
|
||||||
lettuce:
|
lettuce:
|
||||||
@ -115,7 +115,7 @@ spring:
|
|||||||
mqtt:
|
mqtt:
|
||||||
username: fastbee # 账号
|
username: fastbee # 账号
|
||||||
password: fastbee # 密码
|
password: fastbee # 密码
|
||||||
host-url: tcp://localhost:1883 # mqtt连接tcp地址
|
host-url: tcp://1.116.124.85:1883 # mqtt连接tcp地址
|
||||||
client-id: ${random.int} # 客户端Id,不能相同,采用随机数 ${random.value}
|
client-id: ${random.int} # 客户端Id,不能相同,采用随机数 ${random.value}
|
||||||
default-topic: test # 默认主题
|
default-topic: test # 默认主题
|
||||||
timeout: 30 # 超时时间
|
timeout: 30 # 超时时间
|
||||||
@ -123,7 +123,7 @@ spring:
|
|||||||
clearSession: true # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
|
clearSession: true # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
|
||||||
# EMQX API配置需要在运行emqx之后去EMQX管理后台手动创建API Key和Secret,并配置到application.yml中
|
# EMQX API配置需要在运行emqx之后去EMQX管理后台手动创建API Key和Secret,并配置到application.yml中
|
||||||
emqx:
|
emqx:
|
||||||
host: localhost # EMQX服务器地址
|
host: 1.116.124.85 # EMQX服务器地址
|
||||||
port: 18083
|
port: 18083
|
||||||
ApiKey: emqx.key.123 # EMQX API Key
|
ApiKey: emqx.key.123 # EMQX API Key
|
||||||
ApiSecret: emqx.api.123
|
ApiSecret: emqx.api.123
|
||||||
|
|||||||
@ -72,7 +72,7 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
log.info("recv - {}", result);
|
log.info("recv - {}", result);
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendGet ConnectException, url={},param={}", url, param, e);
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -123,13 +123,13 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
log.info("recv - {}", result);
|
log.info("recv - {}", result);
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendPost ConnectException, url={},param={}", url, param, e);
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendPost SocketTimeoutException, url={},param={}", url, param, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendPost IOException, url={},param={}", url, param, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
|
log.error("调用HttpsUtil.sendPost Exception, url={},param={}", url, param, e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
@ -139,7 +139,7 @@ public class HttpUtils {
|
|||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
log.error("调用in.close Exception, url={},param={}", url, param, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
@ -177,13 +177,13 @@ public class HttpUtils {
|
|||||||
conn.disconnect();
|
conn.disconnect();
|
||||||
br.close();
|
br.close();
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendSSLPost ConnectException, url={},param={}", url, param, e);
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url={},param={}", url, param, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
|
log.error("调用HttpUtils.sendSSLPost IOException, url={},param={}", url, param, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
|
log.error("调用HttpsUtil.sendSSLPost Exception, url={},param={}", url, param, e);
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
@ -213,13 +213,13 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
log.info("recv - {}", result);
|
log.info("recv - {}", result);
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + json, e);
|
log.error("调用HttpUtils.sendPost ConnectException, url={},param={}", url, json, e);
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + json, e);
|
log.error("调用HttpUtils.sendPost SocketTimeoutException, url={},param={}", url, json, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + json, e);
|
log.error("调用HttpUtils.sendPost IOException, url={},param={}", url, json, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + json, e);
|
log.error("调用HttpsUtil.sendPost Exception, url={},param={}", url, json, e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
|
|||||||
@ -43,7 +43,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService {
|
|||||||
/**
|
/**
|
||||||
* 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)
|
* 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)
|
||||||
*/
|
*/
|
||||||
@PostConstruct
|
//@PostConstruct
|
||||||
public void init() throws SchedulerException, TaskException {
|
public void init() throws SchedulerException, TaskException {
|
||||||
scheduler.clear();
|
scheduler.clear();
|
||||||
// 设备定时任务
|
// 设备定时任务
|
||||||
|
|||||||
@ -47,7 +47,6 @@ public class DeviceOtherMsgHandler {
|
|||||||
* @param bo
|
* @param bo
|
||||||
*/
|
*/
|
||||||
public void messageHandler(DeviceReportBo bo) {
|
public void messageHandler(DeviceReportBo bo) {
|
||||||
String type = "";
|
|
||||||
String name = topicsUtils.parseTopicName(bo.getTopicName());
|
String name = topicsUtils.parseTopicName(bo.getTopicName());
|
||||||
if (StringUtils.isEmpty(name) || name.endsWith(TopicType.FUNCTION_GET.getTopicSuffix())) return;
|
if (StringUtils.isEmpty(name) || name.endsWith(TopicType.FUNCTION_GET.getTopicSuffix())) return;
|
||||||
ReportDataBo data = this.buildReportData(bo);
|
ReportDataBo data = this.buildReportData(bo);
|
||||||
|
|||||||
@ -43,10 +43,10 @@ public class MessageEncoderWrapper extends ChannelOutboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
output = null;
|
output = null;
|
||||||
} catch (EncoderException e) {
|
} catch (EncoderException e) {
|
||||||
log.error("消息编码异常" + packet.message, e);
|
log.error("消息编码异常{}", packet.message, e);
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
log.error("消息编码异常" + packet.message, e);
|
log.error("消息编码异常{}", packet.message, e);
|
||||||
throw new EncoderException(e);
|
throw new EncoderException(e);
|
||||||
} finally {
|
} finally {
|
||||||
if (output != null) {
|
if (output != null) {
|
||||||
|
|||||||
@ -133,7 +133,7 @@ public class RegisterReqHandler extends ReqAbstractHandler implements Initializi
|
|||||||
rPort = viaHeader.getPort();
|
rPort = viaHeader.getPort();
|
||||||
}
|
}
|
||||||
SipDevice device = new SipDevice();
|
SipDevice device = new SipDevice();
|
||||||
;
|
|
||||||
device.setStreammode("UDP");
|
device.setStreammode("UDP");
|
||||||
device.setDeviceSipId(sipId);
|
device.setDeviceSipId(sipId);
|
||||||
device.setIp(received);
|
device.setIp(received);
|
||||||
@ -156,7 +156,7 @@ public class RegisterReqHandler extends ReqAbstractHandler implements Initializi
|
|||||||
sipSender.transmitRequest(Sipreq.getLocalAddress().getHostAddress(), response);
|
sipSender.transmitRequest(Sipreq.getLocalAddress().getHostAddress(), response);
|
||||||
// 注册成功
|
// 注册成功
|
||||||
if (registerFlag == 1) {
|
if (registerFlag == 1) {
|
||||||
log.info("注册成功! sipId:" + device.getDeviceSipId());
|
log.info("注册成功! sipId:{}", device.getDeviceSipId());
|
||||||
device.setRegistertime(DateUtils.getNowDate());
|
device.setRegistertime(DateUtils.getNowDate());
|
||||||
sipDeviceService.updateDevice(device);
|
sipDeviceService.updateDevice(device);
|
||||||
List<SipDeviceChannel> channels = sipDeviceChannelService.selectSipDeviceChannelByDeviceSipId(device.getDeviceSipId());
|
List<SipDeviceChannel> channels = sipDeviceChannelService.selectSipDeviceChannelByDeviceSipId(device.getDeviceSipId());
|
||||||
@ -166,7 +166,7 @@ public class RegisterReqHandler extends ReqAbstractHandler implements Initializi
|
|||||||
//添加到统一设备管理 默认添加到admin账号下
|
//添加到统一设备管理 默认添加到admin账号下
|
||||||
int result = deviceService.insertDeviceAuto(device.getDeviceSipId(), 1L, sipConfig.getProductId());
|
int result = deviceService.insertDeviceAuto(device.getDeviceSipId(), 1L, sipConfig.getProductId());
|
||||||
if (result == 1) {
|
if (result == 1) {
|
||||||
log.info("-----------sip设备认证成功,并自动添加设备到系统,SipId:" + device.getDeviceSipId() + "---------------");
|
log.info("-----------sip设备认证成功,并自动添加设备到系统,SipId:{}---------------", device.getDeviceSipId());
|
||||||
}
|
}
|
||||||
iotdev = new Device();
|
iotdev = new Device();
|
||||||
}
|
}
|
||||||
@ -177,10 +177,10 @@ public class RegisterReqHandler extends ReqAbstractHandler implements Initializi
|
|||||||
// 重新注册更新设备和通道,以免设备替换或更新后信息无法更新
|
// 重新注册更新设备和通道,以免设备替换或更新后信息无法更新
|
||||||
onRegister(device);
|
onRegister(device);
|
||||||
} else {
|
} else {
|
||||||
log.info("未找到改设备! deviceId:" + device.getDeviceId());
|
log.info("未找到改设备! deviceId:{}", device.getDeviceId());
|
||||||
}
|
}
|
||||||
} else if (registerFlag == 2) {
|
} else if (registerFlag == 2) {
|
||||||
log.info("注销成功! deviceId:" + device.getDeviceId());
|
log.info("注销成功! deviceId:{}", device.getDeviceId());
|
||||||
mqttService.publishStatus(device, 4);
|
mqttService.publishStatus(device, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
package com.fastbee.iot.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 坐标点
|
||||||
|
* @Date: 2026-01-23
|
||||||
|
* @Author: zhugongping
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Position {
|
||||||
|
|
||||||
|
@ApiModelProperty("经度")
|
||||||
|
private double lng; // longitude
|
||||||
|
|
||||||
|
@ApiModelProperty("纬度")
|
||||||
|
private double lat; // latitude
|
||||||
|
}
|
||||||
@ -46,6 +46,7 @@ import com.fastbee.iot.model.gateWay.ProductSubGatewayVO;
|
|||||||
import com.fastbee.iot.model.gateWay.SubDeviceListVO;
|
import com.fastbee.iot.model.gateWay.SubDeviceListVO;
|
||||||
import com.fastbee.iot.service.*;
|
import com.fastbee.iot.service.*;
|
||||||
import com.fastbee.iot.tdengine.service.ILogService;
|
import com.fastbee.iot.tdengine.service.ILogService;
|
||||||
|
import com.fastbee.iot.util.CoordinateTransform;
|
||||||
import com.fastbee.system.mapper.SysDeptMapper;
|
import com.fastbee.system.mapper.SysDeptMapper;
|
||||||
import com.fastbee.system.service.ISysUserService;
|
import com.fastbee.system.service.ISysUserService;
|
||||||
import org.quartz.SchedulerException;
|
import org.quartz.SchedulerException;
|
||||||
@ -1581,9 +1582,10 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据IP获取地址
|
* 根据IP获取地址
|
||||||
*
|
* 流程是:
|
||||||
* @param ip
|
* 调用太平洋网络IP查询接口,根据IP获取城市名称
|
||||||
* @return
|
* 调用百度地图地理编码API,根据城市名称获取经纬度
|
||||||
|
* @param ip IP
|
||||||
*/
|
*/
|
||||||
private void setLocation(String ip, Device device) {
|
private void setLocation(String ip, Device device) {
|
||||||
String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
|
String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
|
||||||
@ -1607,9 +1609,10 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置经纬度
|
* 根据地理编码获取经纬度
|
||||||
|
* 调用百度地理编码获取的是BD09
|
||||||
*
|
*
|
||||||
* @param city
|
* @param city 地理编码,如:北京市海淀区上地十街10号
|
||||||
*/
|
*/
|
||||||
private void setLatitudeAndLongitude(String city, Device device) throws UnsupportedEncodingException {
|
private void setLatitudeAndLongitude(String city, Device device) throws UnsupportedEncodingException {
|
||||||
String BAIDU_URL = "http://api.map.baidu.com/geocoding/v3/";
|
String BAIDU_URL = "http://api.map.baidu.com/geocoding/v3/";
|
||||||
@ -1620,8 +1623,10 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
if (!StringUtils.isEmpty(baiduResponse)) {
|
if (!StringUtils.isEmpty(baiduResponse)) {
|
||||||
JSONObject baiduObject = JSONObject.parseObject(baiduResponse);
|
JSONObject baiduObject = JSONObject.parseObject(baiduResponse);
|
||||||
JSONObject location = baiduObject.getJSONObject("result").getJSONObject("location");
|
JSONObject location = baiduObject.getJSONObject("result").getJSONObject("location");
|
||||||
device.setLongitude(location.getBigDecimal("lng"));
|
// 将 BD09转为GCJ02 (百度坐标系转火星坐标系)
|
||||||
device.setLatitude(location.getBigDecimal("lat"));
|
double[] gcj02 = CoordinateTransform.bd09ToGcj02(location.getDouble("lng"), location.getDouble("lat"));
|
||||||
|
device.setLongitude(BigDecimal.valueOf(gcj02[0]));
|
||||||
|
device.setLatitude(BigDecimal.valueOf(gcj02[1]));
|
||||||
System.out.println(device.getSerialNumber() + "- 设置经度:" + location.getBigDecimal("lng") + ",设置纬度:"
|
System.out.println(device.getSerialNumber() + "- 设置经度:" + location.getBigDecimal("lng") + ",设置纬度:"
|
||||||
+ location.getBigDecimal("lat"));
|
+ location.getBigDecimal("lat"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -318,13 +318,13 @@ public class ToolServiceImpl implements IToolService {
|
|||||||
if (productModel.getStatus() == 2) {
|
if (productModel.getStatus() == 2) {
|
||||||
return returnUnauthorized(mqttModel, "设备简单认证,设备处于禁用状态");
|
return returnUnauthorized(mqttModel, "设备简单认证,设备处于禁用状态");
|
||||||
}
|
}
|
||||||
log.info("-----------设备简单认证成功,clientId:" + mqttModel.getClientId() + "---------------");
|
log.info("-----------设备简单认证成功,clientId:{}---------------", mqttModel.getClientId());
|
||||||
return ResponseEntity.ok().body("ok");
|
return ResponseEntity.ok().body("ok");
|
||||||
} else {
|
} else {
|
||||||
// 自动添加设备
|
// 自动添加设备
|
||||||
int result = deviceService.insertDeviceAuto(mqttModel.getDeviceNumber(), mqttModel.getUserId(), mqttModel.getProductId());
|
int result = deviceService.insertDeviceAuto(mqttModel.getDeviceNumber(), mqttModel.getUserId(), mqttModel.getProductId());
|
||||||
if (result == 1) {
|
if (result == 1) {
|
||||||
log.info("-----------设备简单认证成功,并自动添加设备到系统,clientId:" + mqttModel.getClientId() + "---------------");
|
log.info("-----------设备简单认证成功,并自动添加设备到系统,clientId:{}---------------", mqttModel.getClientId());
|
||||||
return ResponseEntity.ok().body("ok");
|
return ResponseEntity.ok().body("ok");
|
||||||
}
|
}
|
||||||
return returnUnauthorized(mqttModel, "设备简单认证,自动添加设备失败");
|
return returnUnauthorized(mqttModel, "设备简单认证,自动添加设备失败");
|
||||||
|
|||||||
@ -0,0 +1,223 @@
|
|||||||
|
package com.fastbee.iot.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 坐标系转换工具类(WGS-84 ⇄ GCJ-02 ⇄ BD-09)
|
||||||
|
* 基于 double 类型实现,适用于 LBS、地图开发等场景
|
||||||
|
* 精度:约 1~10 米级
|
||||||
|
* GPS 是 WGS-84
|
||||||
|
* 国内地图要 GCJ-02(火星坐标系)
|
||||||
|
* 百度再加一层 BD-09
|
||||||
|
* OSM 坚持用 WGS-84
|
||||||
|
* @Date: 2026-01-23
|
||||||
|
* @Author: zhugongping
|
||||||
|
**/
|
||||||
|
public class CoordinateTransform {
|
||||||
|
|
||||||
|
// ====================== 常量定义 ======================
|
||||||
|
|
||||||
|
private static final double PI = Math.PI;
|
||||||
|
private static final double A = 6378245.0; // 长半轴 (km)
|
||||||
|
private static final double EE = 0.00669342162296594323; // 扁率平方
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否在国内(粗略判断,用于避免国外偏移)
|
||||||
|
* @param lng 经度
|
||||||
|
* @param lat 纬度
|
||||||
|
* @return true:国内;false:国外
|
||||||
|
*/
|
||||||
|
private static boolean inOfChina(double lng, double lat) {
|
||||||
|
return (lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弧度转角度
|
||||||
|
private static double radToDeg(double rad) {
|
||||||
|
return rad * 180.0 / PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 角度转弧度
|
||||||
|
private static double degToRad(double deg) {
|
||||||
|
return deg * PI / 180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 求两点间距离(简化球面距离,单位:米)
|
||||||
|
private static double distance(double lng1, double lat1, double lng2, double lat2) {
|
||||||
|
double dLat = degToRad(lat2 - lat1);
|
||||||
|
double dLng = degToRad(lng2 - lng1);
|
||||||
|
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||||
|
Math.cos(degToRad(lat1)) * Math.cos(degToRad(lat2)) *
|
||||||
|
Math.sin(dLng / 2) * Math.sin(dLng / 2);
|
||||||
|
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||||
|
return A * c; // A 是地球半径(米)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== WGS-84 → GCJ-02 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WGS-84 转 GCJ-02(火星坐标系)
|
||||||
|
*/
|
||||||
|
public static double[] wgs84ToGcj02(double wgsLng, double wgsLat) {
|
||||||
|
if (!inOfChina(wgsLng, wgsLat)) {
|
||||||
|
return new double[]{wgsLng, wgsLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
double dLat = transformLat(wgsLng - 105.0, wgsLat - 35.0);
|
||||||
|
double dLng = transformLng(wgsLng - 105.0, wgsLat - 35.0);
|
||||||
|
|
||||||
|
double radLat = degToRad(wgsLat);
|
||||||
|
double magic = Math.sin(radLat);
|
||||||
|
magic = 1 - EE * magic * magic;
|
||||||
|
double sqrtMagic = Math.sqrt(magic);
|
||||||
|
|
||||||
|
dLat = (dLat * 180.0) / ((A * (1 - EE)) / (magic * sqrtMagic) * PI);
|
||||||
|
dLng = (dLng * 180.0) / (A / sqrtMagic * Math.cos(radLat) * PI);
|
||||||
|
|
||||||
|
return new double[]{wgsLng + dLng, wgsLat + dLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== GCJ-02 → WGS-84 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GCJ-02 转 WGS-84(近似还原,存在微小误差)
|
||||||
|
*/
|
||||||
|
public static double[] gcj02ToWgs84(double gcjLng, double gcjLat) {
|
||||||
|
if (!inOfChina(gcjLng, gcjLat)) {
|
||||||
|
return new double[]{gcjLng, gcjLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
double[] gps = wgs84ToGcj02(gcjLng, gcjLat);
|
||||||
|
double dLng = gps[0] - gcjLng;
|
||||||
|
double dLat = gps[1] - gcjLat;
|
||||||
|
return new double[]{gcjLng - dLng, gcjLat - dLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== GCJ-02 → BD-09 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GCJ-02 转 BD-09(百度坐标系)
|
||||||
|
*/
|
||||||
|
public static double[] gcj02ToBd09(double gcjLng, double gcjLat) {
|
||||||
|
double z = Math.sqrt(gcjLng * gcjLng + gcjLat * gcjLat) + 0.00002 * Math.sin(gcjLat * PI);
|
||||||
|
double theta = Math.atan2(gcjLat, gcjLng) + 0.000003 * Math.cos(gcjLng * PI);
|
||||||
|
double bdLng = z * Math.cos(theta) + 0.0065;
|
||||||
|
double bdLat = z * Math.sin(theta) + 0.006;
|
||||||
|
return new double[]{bdLng, bdLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== BD-09 → GCJ-02 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BD-09 转 GCJ-02
|
||||||
|
*/
|
||||||
|
public static double[] bd09ToGcj02(double bdLng, double bdLat) {
|
||||||
|
double x = bdLng - 0.0065;
|
||||||
|
double y = bdLat - 0.006;
|
||||||
|
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * PI);
|
||||||
|
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * PI);
|
||||||
|
double gcjLng = z * Math.cos(theta);
|
||||||
|
double gcjLat = z * Math.sin(theta);
|
||||||
|
return new double[]{gcjLng, gcjLat};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== WGS-84 ⇄ BD-09 快捷转换 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WGS-84 转 BD-09(先转 GCJ-02,再转 BD-09)
|
||||||
|
*/
|
||||||
|
public static double[] wgs84ToBd09(double wgsLng, double wgsLat) {
|
||||||
|
double[] gcj = wgs84ToGcj02(wgsLng, wgsLat);
|
||||||
|
return gcj02ToBd09(gcj[0], gcj[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BD-09 转 WGS-84(先转 GCJ-02,再转 WGS-84)
|
||||||
|
*/
|
||||||
|
public static double[] bd09ToWgs84(double bdLng, double bdLat) {
|
||||||
|
double[] gcj = bd09ToGcj02(bdLng, bdLat);
|
||||||
|
return gcj02ToWgs84(gcj[0], gcj[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 内部辅助函数 ====================
|
||||||
|
|
||||||
|
private static double transformLat(double lng, double lat) {
|
||||||
|
double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
|
||||||
|
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
|
||||||
|
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
|
||||||
|
ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double transformLng(double lng, double lat) {
|
||||||
|
double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
|
||||||
|
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
|
||||||
|
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
|
||||||
|
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 工具方法 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化坐标输出(保留6位小数)
|
||||||
|
*/
|
||||||
|
public static String formatCoord(double lng, double lat) {
|
||||||
|
return String.format("%.6f, %.6f", lng, lat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 四舍五入到指定位数
|
||||||
|
*/
|
||||||
|
public static double round(double value, int scale) {
|
||||||
|
double factor = Math.pow(10, scale);
|
||||||
|
return Math.round(value * factor) / factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打印转换结果(调试用)
|
||||||
|
*/
|
||||||
|
public static void printConvert(String fromType, double fromLng, double fromLat,
|
||||||
|
String toType, double[] result) {
|
||||||
|
System.out.printf("%s [%.6f, %.6f] → %s [%s]%n",
|
||||||
|
fromType, fromLng, fromLat,
|
||||||
|
toType, formatCoord(result[0], result[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 北京天安门 GPS 坐标(WGS-84)116.397428,39.90923
|
||||||
|
// 长沙市政府 BD-09 112.945473,28.234889
|
||||||
|
// 岩安测控 WGS-84 112.862816,28.125462
|
||||||
|
|
||||||
|
double wgsLng = 112.862816;
|
||||||
|
double wgsLat = 28.125462;
|
||||||
|
|
||||||
|
System.out.println("是否在国内 = " + inOfChina(wgsLng, wgsLat));
|
||||||
|
|
||||||
|
|
||||||
|
System.out.println("=== 坐标系转换测试 ===");
|
||||||
|
|
||||||
|
// WGS-84 → GCJ-02 111.94760023918425,28.812219998012168
|
||||||
|
double[] gcj = CoordinateTransform.wgs84ToGcj02(wgsLng, wgsLat);
|
||||||
|
CoordinateTransform.printConvert("WGS-84", wgsLng, wgsLat, "GCJ-02", gcj);
|
||||||
|
|
||||||
|
// GCJ-02 → BD-09
|
||||||
|
double[] bd = CoordinateTransform.gcj02ToBd09(gcj[0], gcj[1]);
|
||||||
|
CoordinateTransform.printConvert("GCJ-02", gcj[0], gcj[1], "BD-09", bd);
|
||||||
|
|
||||||
|
// BD-09 → GCJ-02
|
||||||
|
double[] gcjBack = CoordinateTransform.bd09ToGcj02(112.945473,28.234889);
|
||||||
|
CoordinateTransform.printConvert("BD-09", bd[0], bd[1], "GCJ-02", gcjBack);
|
||||||
|
|
||||||
|
// GCJ-02 → WGS-84 111.944921,28.809167
|
||||||
|
double[] wgsBack = CoordinateTransform.gcj02ToWgs84(111.944921,28.809167);
|
||||||
|
CoordinateTransform.printConvert("GCJ-02", gcjBack[0], gcjBack[1], "WGS-84", wgsBack);
|
||||||
|
|
||||||
|
// 直接计算 WGS-84 → BD-09
|
||||||
|
double[] directBd = CoordinateTransform.wgs84ToBd09(wgsLng, wgsLat);
|
||||||
|
CoordinateTransform.printConvert("WGS-84", wgsLng, wgsLat, "BD-09(Direct)", directBd);
|
||||||
|
|
||||||
|
// 计算偏移距离
|
||||||
|
double offset = CoordinateTransform.distance(wgsLng, wgsLat, gcj[0], gcj[1]);
|
||||||
|
System.out.printf("WGS-84 与 GCJ-02 偏移距离:%.2f 米%n", offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
23428
vue/package-lock.json
generated
23428
vue/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -44,8 +44,10 @@
|
|||||||
"axios": "0.24.0",
|
"axios": "0.24.0",
|
||||||
"clipboard": "2.0.8",
|
"clipboard": "2.0.8",
|
||||||
"codemirror": "^5.65.2",
|
"codemirror": "^5.65.2",
|
||||||
|
"coordtransform": "^2.1.2",
|
||||||
"core-js": "3.25.3",
|
"core-js": "3.25.3",
|
||||||
"echarts": "^5.4.0",
|
"echarts": "^5.4.0",
|
||||||
|
"echarts-extension-leaflet": "^1.2.2",
|
||||||
"echarts-liquidfill": "^3.0.6",
|
"echarts-liquidfill": "^3.0.6",
|
||||||
"element-china-area-data": "^4.1.1",
|
"element-china-area-data": "^4.1.1",
|
||||||
"element-ui": "2.15.10",
|
"element-ui": "2.15.10",
|
||||||
@ -62,6 +64,7 @@
|
|||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"jsonlint": "^1.6.3",
|
"jsonlint": "^1.6.3",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"minimatch": "^3.1.2",
|
"minimatch": "^3.1.2",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
|
|||||||
@ -1,28 +1,34 @@
|
|||||||
|
// 使用OpenStreetMap和Leaflet替代百度地图
|
||||||
export function loadBMap() {
|
export function loadBMap() {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (typeof BMap !== 'undefined') {
|
// eslint-disable-next-line no-undef
|
||||||
resolve(BMap)
|
if (typeof L !== 'undefined') {
|
||||||
return true
|
// eslint-disable-next-line no-undef
|
||||||
|
resolve(L);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
window.onBMapCallback = function() {
|
|
||||||
resolve(BMap)
|
// 加载Leaflet CSS
|
||||||
|
if (!document.querySelector('link[href*="leaflet.css"]')) {
|
||||||
|
const link = document.createElement('link');
|
||||||
|
link.rel = 'stylesheet';
|
||||||
|
link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';
|
||||||
|
link.integrity = 'sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=';
|
||||||
|
link.crossOrigin = '';
|
||||||
|
document.head.appendChild(link);
|
||||||
}
|
}
|
||||||
// 使用https协议需要添加一下meta标签
|
|
||||||
var protocolStr = document.location.protocol;
|
// 加载Leaflet JS
|
||||||
if(protocolStr == "https:")
|
const script = document.createElement('script');
|
||||||
{
|
script.type = 'text/javascript';
|
||||||
let meta = document.createElement('meta')
|
script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';
|
||||||
meta.httpEquiv = 'Content-Security-Policy'
|
script.integrity = 'sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=';
|
||||||
meta.content ='upgrade-insecure-requests'
|
script.crossOrigin = '';
|
||||||
meta.onerror = reject
|
script.onload = function() {
|
||||||
document.head.appendChild(meta)
|
// eslint-disable-next-line no-undef
|
||||||
}
|
resolve(L);
|
||||||
// 引入百度地图
|
};
|
||||||
let script = document.createElement('script')
|
script.onerror = reject;
|
||||||
script.type = 'text/javascript'
|
document.head.appendChild(script);
|
||||||
script.src =
|
});
|
||||||
'http://api.map.baidu.com/api?v=2.0&ak='+ process.env.VUE_APP_BAI_DU_AK +'&s=1&__ec_v__=20190126&callback=onBMapCallback'
|
|
||||||
script.onerror = reject
|
|
||||||
document.head.appendChild(script)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -319,10 +319,9 @@ import axios from 'axios';
|
|||||||
import { getDeviceStatistic } from '@/api/iot/device';
|
import { getDeviceStatistic } from '@/api/iot/device';
|
||||||
import { listNotice, getNotice } from '@/api/system/notice';
|
import { listNotice, getNotice } from '@/api/system/notice';
|
||||||
import CountTo from 'vue-count-to';
|
import CountTo from 'vue-count-to';
|
||||||
import { loadBMap } from '@/utils/map.js';
|
import 'leaflet/dist/leaflet.css';
|
||||||
//安装的是echarts完整包,里面包含百度地图扩展,路径为 echarts/extension/bmap/bmap.js,将其引入
|
import 'echarts-extension-leaflet';
|
||||||
//ECharts的百度地图扩展,可以在百度地图上展现点图,线图,热力图等可视化
|
import coordtransform from 'coordtransform';
|
||||||
// 注意:bmap扩展需要在BMap加载后再引入
|
|
||||||
import { getServer } from '@/api/monitor/server';
|
import { getServer } from '@/api/monitor/server';
|
||||||
import { listAllDeviceShort } from '@/api/iot/device';
|
import { listAllDeviceShort } from '@/api/iot/device';
|
||||||
import 'echarts-liquidfill';
|
import 'echarts-liquidfill';
|
||||||
@ -1157,23 +1156,10 @@ export default {
|
|||||||
/**加载地图*/
|
/**加载地图*/
|
||||||
loadMap() {
|
loadMap() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
loadBMap().then(() => {
|
// 使用 echarts-extension-leaflet,已在 import 时加载
|
||||||
if (typeof BMap === 'undefined') {
|
|
||||||
this.$message.error('百度地图API未正确加载');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 确保bmap扩展已加载
|
|
||||||
try {
|
|
||||||
require('echarts/extension/bmap/bmap');
|
|
||||||
} catch (e) {
|
|
||||||
// 忽略扩展加载错误
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.getmap();
|
this.getmap();
|
||||||
}, 500);
|
}, 300);
|
||||||
}).catch((error) => {
|
|
||||||
this.$message.error('百度地图加载失败,请检查API Key配置');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
/** 查询服务器信息 */
|
/** 查询服务器信息 */
|
||||||
@ -1229,13 +1215,14 @@ export default {
|
|||||||
|
|
||||||
/** 地图 */
|
/** 地图 */
|
||||||
getmap() {
|
getmap() {
|
||||||
if (typeof BMap === 'undefined') {
|
if (!this.$refs.map) {
|
||||||
this.$message.error('百度地图API未正确加载,请刷新页面重试');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.$refs.map) {
|
// 销毁旧的ECharts实例,避免多个实例叠加
|
||||||
return;
|
var existingChart = this.$echarts.getInstanceByDom(this.$refs.map);
|
||||||
|
if (existingChart) {
|
||||||
|
existingChart.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
var myChart = this.$echarts.init(this.$refs.map);
|
var myChart = this.$echarts.init(this.$refs.map);
|
||||||
@ -1258,8 +1245,14 @@ export default {
|
|||||||
let convertData = function (data, status) {
|
let convertData = function (data, status) {
|
||||||
var res = [];
|
var res = [];
|
||||||
for (var i = 0; i < data.length; i++) {
|
for (var i = 0; i < data.length; i++) {
|
||||||
var geoCoord = [data[i].longitude, data[i].latitude];
|
// 验证经纬度有效性
|
||||||
if (geoCoord && data[i].status == status) {
|
var lng = parseFloat(data[i].longitude);
|
||||||
|
var lat = parseFloat(data[i].latitude);
|
||||||
|
if (isNaN(lng) || isNaN(lat) || lng === 0 || lat === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var geoCoord = [lng, lat];
|
||||||
|
if (data[i].status == status) {
|
||||||
res.push({
|
res.push({
|
||||||
name: data[i].deviceName,
|
name: data[i].deviceName,
|
||||||
value: geoCoord,
|
value: geoCoord,
|
||||||
@ -1320,14 +1313,9 @@ export default {
|
|||||||
return { center: [centerLng, centerLat], zoom: zoom };
|
return { center: [centerLng, centerLat], zoom: zoom };
|
||||||
};
|
};
|
||||||
|
|
||||||
// 使用长沙作为默认中心点,如果有设备数据则使用计算的中心点
|
// 使用中国长沙作为地图中心点
|
||||||
let mapConfig = { center: [112.867037, 28.11857], zoom: 12 };
|
// 长沙坐标:经度 112.94, 纬度 28.23
|
||||||
if (this.deviceList && this.deviceList.length > 0) {
|
let mapConfig = { center: [112.94, 28.23], zoom: 5 };
|
||||||
const calculated = calculateMapCenter(this.deviceList);
|
|
||||||
if (calculated.center && calculated.center[0] > 0) {
|
|
||||||
mapConfig = calculated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
option = {
|
option = {
|
||||||
title: {
|
title: {
|
||||||
@ -1382,21 +1370,27 @@ export default {
|
|||||||
return htmlStr;
|
return htmlStr;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bmap: {
|
leaflet: {
|
||||||
center: mapConfig.center,
|
// echarts-extension-leaflet center 使用 [lng, lat] 格式
|
||||||
zoom: mapConfig.zoom,
|
// 长沙坐标:经度 112.94, 纬度 28.23
|
||||||
|
center: [112.94, 28.23],
|
||||||
|
zoom: 5,
|
||||||
roam: true,
|
roam: true,
|
||||||
// 确保地图正确初始化
|
tiles: [
|
||||||
enableMapClick: true,
|
{
|
||||||
// 暂时不使用自定义样式,确保地图能正常显示
|
// 使用高德地图瓦片(国内访问稳定)
|
||||||
// mapStyle: {
|
urlTemplate: 'https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
|
||||||
// styleJson: [...]
|
options: {
|
||||||
// },
|
subdomains: ['1', '2', '3', '4'],
|
||||||
|
attribution: '© 高德地图',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
type: 'scatter',
|
type: 'scatter',
|
||||||
coordinateSystem: 'bmap',
|
coordinateSystem: 'leaflet',
|
||||||
data: convertData(this.deviceList, 1),
|
data: convertData(this.deviceList, 1),
|
||||||
symbolSize: 15,
|
symbolSize: 15,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
@ -1405,7 +1399,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'scatter',
|
type: 'scatter',
|
||||||
coordinateSystem: 'bmap',
|
coordinateSystem: 'leaflet',
|
||||||
data: convertData(this.deviceList, 2),
|
data: convertData(this.deviceList, 2),
|
||||||
symbolSize: 15,
|
symbolSize: 15,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
@ -1414,7 +1408,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'scatter',
|
type: 'scatter',
|
||||||
coordinateSystem: 'bmap',
|
coordinateSystem: 'leaflet',
|
||||||
data: convertData(this.deviceList, 4),
|
data: convertData(this.deviceList, 4),
|
||||||
symbolSize: 15,
|
symbolSize: 15,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
@ -1423,7 +1417,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'effectScatter',
|
type: 'effectScatter',
|
||||||
coordinateSystem: 'bmap',
|
coordinateSystem: 'leaflet',
|
||||||
data: convertData(this.deviceList, 3),
|
data: convertData(this.deviceList, 3),
|
||||||
symbolSize: 15,
|
symbolSize: 15,
|
||||||
showEffectOn: 'render',
|
showEffectOn: 'render',
|
||||||
@ -1465,35 +1459,10 @@ export default {
|
|||||||
// 设置地图配置
|
// 设置地图配置
|
||||||
myChart.setOption(option, true);
|
myChart.setOption(option, true);
|
||||||
|
|
||||||
// 等待地图初始化后调整大小和刷新
|
// 等待地图初始化完成
|
||||||
setTimeout(() => {
|
this.$nextTick(() => {
|
||||||
myChart.resize();
|
myChart.resize();
|
||||||
|
});
|
||||||
const bmapModel = myChart.getModel().getComponent('bmap');
|
|
||||||
if (bmapModel && bmapModel.getBMap) {
|
|
||||||
const bmapInstance = bmapModel.getBMap();
|
|
||||||
if (bmapInstance) {
|
|
||||||
// 启用地图功能
|
|
||||||
bmapInstance.enableScrollWheelZoom(true);
|
|
||||||
bmapInstance.enableDoubleClickZoom(true);
|
|
||||||
bmapInstance.enableDragging(true);
|
|
||||||
|
|
||||||
// 设置中心点和缩放级别
|
|
||||||
const centerPoint = new BMap.Point(mapConfig.center[0], mapConfig.center[1]);
|
|
||||||
bmapInstance.setCenter(centerPoint);
|
|
||||||
bmapInstance.setZoom(mapConfig.zoom);
|
|
||||||
|
|
||||||
// 刷新地图确保瓦片加载
|
|
||||||
setTimeout(() => {
|
|
||||||
myChart.resize();
|
|
||||||
bmapInstance.reset();
|
|
||||||
bmapInstance.setCenter(centerPoint);
|
|
||||||
bmapInstance.setZoom(mapConfig.zoom);
|
|
||||||
myChart.resize();
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 800);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$message.error('地图初始化失败: ' + error.message);
|
this.$message.error('地图初始化失败: ' + error.message);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,7 +79,7 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// 从环境变量获取AK(这里需要手动设置,因为这是静态HTML文件)
|
// 从环境变量获取AK(这里需要手动设置,因为这是静态HTML文件)
|
||||||
// 实际项目中应该从 process.env.VUE_APP_BAI_DU_AK 获取
|
// 实际项目中应该从 process.env.VUE_APP_BAI_DU_AK 获取
|
||||||
const AK = 's9mUXN9a7bKgVu6U6Z3bXhKSxtz97YPI'; // 请替换为您的AK
|
const AK = 'FN2xbG1m5q9iwNq1heNF9nBOb2uhv3Om'; // 请替换为您的AK
|
||||||
|
|
||||||
// 更新状态显示
|
// 更新状态显示
|
||||||
function updateStatus(elementId, text, className) {
|
function updateStatus(elementId, text, className) {
|
||||||
|
|||||||
@ -1088,21 +1088,44 @@ export default {
|
|||||||
},
|
},
|
||||||
// 地图定位
|
// 地图定位
|
||||||
getmap() {
|
getmap() {
|
||||||
this.map = new BMap.Map('map');
|
// 清除旧地图实例
|
||||||
let point = null;
|
if (this.map) {
|
||||||
if (this.form.longitude != null && this.form.longitude != '' && this.form.latitude != null && this.form.latitude != '') {
|
this.map.remove();
|
||||||
point = new BMap.Point(this.form.longitude, this.form.latitude);
|
this.map = null;
|
||||||
} else {
|
|
||||||
point = new BMap.Point(116.404, 39.915);
|
|
||||||
}
|
}
|
||||||
this.map.centerAndZoom(point, 19);
|
|
||||||
this.map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放
|
|
||||||
this.map.addControl(new BMap.NavigationControl());
|
|
||||||
|
|
||||||
// 标注设备位置
|
// 使用Leaflet和高德地图
|
||||||
this.mk = new BMap.Marker(point);
|
let lat, lng;
|
||||||
this.map.addOverlay(this.mk);
|
let parsedLat = parseFloat(this.form.latitude);
|
||||||
this.map.panTo(point);
|
let parsedLng = parseFloat(this.form.longitude);
|
||||||
|
|
||||||
|
// 验证坐标有效性
|
||||||
|
if (!isNaN(parsedLat) && !isNaN(parsedLng) && parsedLat !== 0 && parsedLng !== 0) {
|
||||||
|
lat = parsedLat;
|
||||||
|
lng = parsedLng;
|
||||||
|
} else {
|
||||||
|
// 默认使用中国长沙坐标
|
||||||
|
lat = 28.23;
|
||||||
|
lng = 112.94;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建地图
|
||||||
|
this.map = L.map('map').setView([lat, lng], 15);
|
||||||
|
|
||||||
|
// 添加高德地图图层(国内访问稳定)
|
||||||
|
L.tileLayer('https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
|
||||||
|
subdomains: ['1', '2', '3', '4'],
|
||||||
|
attribution: '© 高德地图',
|
||||||
|
maxZoom: 18
|
||||||
|
}).addTo(this.map);
|
||||||
|
|
||||||
|
// 添加标记点
|
||||||
|
this.mk = L.marker([lat, lng]).addTo(this.map);
|
||||||
|
|
||||||
|
// 添加popup提示
|
||||||
|
if (this.form.deviceName) {
|
||||||
|
this.mk.bindPopup(`<b>${this.form.deviceName}</b><br>${this.form.networkAddress || ''}`).openPopup();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// 生成随机字母和数字
|
// 生成随机字母和数字
|
||||||
generateNum() {
|
generateNum() {
|
||||||
|
|||||||
@ -1185,20 +1185,40 @@ export default {
|
|||||||
},
|
},
|
||||||
// 地图定位
|
// 地图定位
|
||||||
getmap() {
|
getmap() {
|
||||||
this.map = new BMap.Map('map');
|
// 清除旧地图实例
|
||||||
let point = null;
|
if (this.map) {
|
||||||
if (this.form.longitude != null && this.form.longitude != '' && this.form.latitude != null && this.form.latitude != '') {
|
this.map.remove();
|
||||||
point = new BMap.Point(this.form.longitude, this.form.latitude);
|
this.map = null;
|
||||||
} else {
|
}
|
||||||
point = new BMap.Point(116.404, 39.915);
|
|
||||||
|
// 使用Leaflet和OpenStreetMap
|
||||||
|
let lat, lng;
|
||||||
|
if (this.form.latitude != null && this.form.latitude != '' && this.form.longitude != null && this.form.longitude != '') {
|
||||||
|
lat = parseFloat(this.form.latitude);
|
||||||
|
lng = parseFloat(this.form.longitude);
|
||||||
|
} else {
|
||||||
|
// 默认使用北京天安门坐标
|
||||||
|
lat = 39.915;
|
||||||
|
lng = 116.404;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建地图
|
||||||
|
this.map = L.map('map').setView([lat, lng], 15);
|
||||||
|
|
||||||
|
// 添加高德地图图层(国内访问稳定)
|
||||||
|
L.tileLayer('https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
|
||||||
|
subdomains: ['1', '2', '3', '4'],
|
||||||
|
attribution: '© 高德地图',
|
||||||
|
maxZoom: 18
|
||||||
|
}).addTo(this.map);
|
||||||
|
|
||||||
|
// 添加标记点
|
||||||
|
this.mk = L.marker([lat, lng]).addTo(this.map);
|
||||||
|
|
||||||
|
// 添加popup提示
|
||||||
|
if (this.form.deviceName) {
|
||||||
|
this.mk.bindPopup(`<b>${this.form.deviceName}</b><br>${this.form.networkAddress || ''}`).openPopup();
|
||||||
}
|
}
|
||||||
this.map.centerAndZoom(point, 19);
|
|
||||||
this.map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放
|
|
||||||
this.map.addControl(new BMap.NavigationControl());
|
|
||||||
// 标注设备位置
|
|
||||||
this.mk = new BMap.Marker(point);
|
|
||||||
this.map.addOverlay(this.mk);
|
|
||||||
this.map.panTo(point);
|
|
||||||
},
|
},
|
||||||
// 生成随机字母和数字
|
// 生成随机字母和数字
|
||||||
generateNum() {
|
generateNum() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user