feat:新增地图模块,用于查找附近设备场地

This commit is contained in:
2025-08-18 14:52:39 +08:00
parent c5b8026fba
commit 38eb05fefd
122 changed files with 8317 additions and 1768 deletions
-155
View File
@@ -1,155 +0,0 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const AMAP_KEY = "4c513a688938fd89b88b296e867f66ec";
class AmapUtil {
constructor() {
this.key = AMAP_KEY;
}
// 逆地理编码 - 根据经纬度获取地址信息
async regeocode(longitude, latitude) {
try {
const res = await common_vendor.index.request({
url: "https://restapi.amap.com/v3/geocode/regeo",
method: "GET",
data: {
key: this.key,
location: `${longitude},${latitude}`,
poitype: "",
radius: 1e3,
extensions: "base",
batch: false,
roadlevel: 0
}
});
if (res.statusCode === 200 && res.data.status === "1") {
return {
success: true,
data: res.data.regeocode
};
} else {
return {
success: false,
message: res.data.info || "逆地理编码失败"
};
}
} catch (error) {
common_vendor.index.__f__("error", "at utils/amap.js:38", "逆地理编码异常:", error);
return {
success: false,
message: "网络异常"
};
}
}
// 地理编码 - 根据地址获取经纬度
async geocode(address, city = "") {
try {
const res = await common_vendor.index.request({
url: "https://restapi.amap.com/v3/geocode/geo",
method: "GET",
data: {
key: this.key,
address,
city
}
});
if (res.statusCode === 200 && res.data.status === "1" && res.data.geocodes.length > 0) {
return {
success: true,
data: res.data.geocodes[0]
};
} else {
return {
success: false,
message: res.data.info || "地理编码失败"
};
}
} catch (error) {
common_vendor.index.__f__("error", "at utils/amap.js:71", "地理编码异常:", error);
return {
success: false,
message: "网络异常"
};
}
}
// 搜索POI
async searchPOI(keywords, location = "", radius = 3e3, city = "") {
try {
const res = await common_vendor.index.request({
url: "https://restapi.amap.com/v3/place/text",
method: "GET",
data: {
key: this.key,
keywords,
location,
radius,
city,
citylimit: true
}
});
if (res.statusCode === 200 && res.data.status === "1") {
return {
success: true,
data: res.data.pois || []
};
} else {
return {
success: false,
message: res.data.info || "搜索失败"
};
}
} catch (error) {
common_vendor.index.__f__("error", "at utils/amap.js:107", "POI搜索异常:", error);
return {
success: false,
message: "网络异常"
};
}
}
// 路径规划
async getRoute(origin, destination, strategy = 0) {
try {
const res = await common_vendor.index.request({
url: "https://restapi.amap.com/v3/direction/driving",
method: "GET",
data: {
key: this.key,
origin,
destination,
strategy,
extensions: "base"
}
});
if (res.statusCode === 200 && res.data.status === "1") {
return {
success: true,
data: res.data.route
};
} else {
return {
success: false,
message: res.data.info || "路径规划失败"
};
}
} catch (error) {
common_vendor.index.__f__("error", "at utils/amap.js:142", "路径规划异常:", error);
return {
success: false,
message: "网络异常"
};
}
}
// 计算两点间距离
calculateDistance(lat1, lng1, lat2, lng2) {
const radLat1 = lat1 * Math.PI / 180;
const radLat2 = lat2 * Math.PI / 180;
const a = radLat1 - radLat2;
const b = lng1 * Math.PI / 180 - lng2 * Math.PI / 180;
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * 6378.137;
s = Math.round(s * 1e4) / 1e4;
return s;
}
}
const AmapUtil$1 = new AmapUtil();
exports.AmapUtil = AmapUtil$1;
//# sourceMappingURL=../../.sourcemap/mp-weixin/utils/amap.js.map
+439
View File
@@ -0,0 +1,439 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const QQMAP_KEY = "RO5BZ-ECZ63-7US3C-RT5QW-TIDZE-2FF35";
const QQMapWX = function() {
const ERROR_CONF = {
KEY_ERR: 311,
KEY_ERR_MSG: "key格式错误",
PARAM_ERR: 310,
PARAM_ERR_MSG: "请求参数信息有误",
SYSTEM_ERR: 600,
SYSTEM_ERR_MSG: "系统错误",
WX_ERR_CODE: 1e3,
WX_OK_CODE: 200
};
const BASE_URL = "https://apis.map.qq.com/ws/";
const URL_SEARCH = BASE_URL + "place/v1/search";
const URL_SUGGESTION = BASE_URL + "place/v1/suggestion";
const URL_GET_GEOCODER = BASE_URL + "geocoder/v1/";
const URL_DISTANCE = BASE_URL + "distance/v1/";
const Utils = {
// 获取location参数
getLocationParam(location) {
if (typeof location == "string") {
const locationArr = location.split(",");
if (locationArr.length === 2) {
location = {
latitude: location.split(",")[0],
longitude: location.split(",")[1]
};
} else {
location = {};
}
}
return location;
},
// 验证location值
checkLocation(param) {
const location = this.getLocationParam(param.location);
if (!location || !location.latitude || !location.longitude) {
const errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + " location参数格式有误");
param.fail(errconf);
param.complete(errconf);
return false;
}
return true;
},
// 构造错误数据结构
buildErrorConfig(errCode, errMsg) {
return {
status: errCode,
message: errMsg
};
},
// 回调函数默认处理
polyfillParam(param) {
param.success = param.success || function() {
};
param.fail = param.fail || function() {
};
param.complete = param.complete || function() {
};
},
// 处理用户参数是否传入坐标进行不同的处理
locationProcess(param, locationsuccess, locationfail, locationcomplete) {
const that = this;
locationfail = locationfail || function(res) {
res.statusCode = ERROR_CONF.WX_ERR_CODE;
param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
};
locationcomplete = locationcomplete || function(res) {
if (res.statusCode == ERROR_CONF.WX_ERR_CODE) {
param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
}
};
if (!param.location) {
common_vendor.wx$1.getLocation({
type: "gcj02",
success: locationsuccess,
fail: locationfail,
complete: locationcomplete
});
} else if (that.checkLocation(param)) {
const location = Utils.getLocationParam(param.location);
locationsuccess(location);
}
},
// 构造微信请求参数
buildWxRequestConfig(param, options, feature) {
const that = this;
options.header = { "content-type": "application/json" };
options.method = "GET";
options.success = function(res) {
const data = res.data;
if (data.status === 0) {
that.handleData(param, data, feature);
} else {
param.fail(data);
}
};
options.fail = function(res) {
res.statusCode = ERROR_CONF.WX_ERR_CODE;
param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
};
options.complete = function(res) {
const statusCode = +res.statusCode;
switch (statusCode) {
case ERROR_CONF.WX_ERR_CODE: {
param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
break;
}
case ERROR_CONF.WX_OK_CODE: {
const data = res.data;
if (data.status === 0) {
param.complete(data);
} else {
param.complete(that.buildErrorConfig(data.status, data.message));
}
break;
}
default: {
param.complete(that.buildErrorConfig(ERROR_CONF.SYSTEM_ERR, ERROR_CONF.SYSTEM_ERR_MSG));
}
}
};
return options;
},
// 数据处理函数
handleData(param, data, feature) {
if (feature == "search") {
const searchResult = data.data;
const searchSimplify = [];
for (let i = 0; i < searchResult.length; i++) {
searchSimplify.push({
id: searchResult[i].id || null,
title: searchResult[i].title || null,
latitude: searchResult[i].location && searchResult[i].location.lat || null,
longitude: searchResult[i].location && searchResult[i].location.lng || null,
address: searchResult[i].address || null,
category: searchResult[i].category || null,
tel: searchResult[i].tel || null,
adcode: searchResult[i].ad_info && searchResult[i].ad_info.adcode || null,
city: searchResult[i].ad_info && searchResult[i].ad_info.city || null,
district: searchResult[i].ad_info && searchResult[i].ad_info.district || null,
province: searchResult[i].ad_info && searchResult[i].ad_info.province || null
});
}
param.success(data, {
searchResult,
searchSimplify
});
} else if (feature == "suggest") {
const suggestResult = data.data;
const suggestSimplify = [];
for (let i = 0; i < suggestResult.length; i++) {
suggestSimplify.push({
adcode: suggestResult[i].adcode || null,
address: suggestResult[i].address || null,
category: suggestResult[i].category || null,
city: suggestResult[i].city || null,
district: suggestResult[i].district || null,
id: suggestResult[i].id || null,
latitude: suggestResult[i].location && suggestResult[i].location.lat || null,
longitude: suggestResult[i].location && suggestResult[i].location.lng || null,
province: suggestResult[i].province || null,
title: suggestResult[i].title || null,
type: suggestResult[i].type || null
});
}
param.success(data, {
suggestResult,
suggestSimplify
});
} else if (feature == "reverseGeocoder") {
const reverseGeocoderResult = data.result;
const reverseGeocoderSimplify = {
address: reverseGeocoderResult.address || null,
latitude: reverseGeocoderResult.location && reverseGeocoderResult.location.lat || null,
longitude: reverseGeocoderResult.location && reverseGeocoderResult.location.lng || null,
adcode: reverseGeocoderResult.ad_info && reverseGeocoderResult.ad_info.adcode || null,
city: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.city || null,
district: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.district || null,
nation: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.nation || null,
province: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.province || null,
street: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.street || null,
street_number: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.street_number || null,
recommend: reverseGeocoderResult.formatted_addresses && reverseGeocoderResult.formatted_addresses.recommend || null,
rough: reverseGeocoderResult.formatted_addresses && reverseGeocoderResult.formatted_addresses.rough || null
};
param.success(data, {
reverseGeocoderResult,
reverseGeocoderSimplify
});
} else if (feature == "calculateDistance") {
const calculateDistanceResult = data.result.elements;
const distance = [];
for (let i = 0; i < calculateDistanceResult.length; i++) {
distance.push(calculateDistanceResult[i].distance);
}
param.success(data, {
calculateDistanceResult,
distance
});
} else {
param.success(data);
}
}
};
class QQMapWX2 {
constructor(options) {
if (!options.key) {
throw Error("key值不能为空");
}
this.key = options.key;
}
// 逆地址解析
reverseGeocoder(options) {
const that = this;
options = options || {};
Utils.polyfillParam(options);
const requestParam = {
coord_type: options.coord_type || 5,
get_poi: options.get_poi || 0,
output: "json",
key: that.key
};
if (options.poi_options) {
requestParam.poi_options = options.poi_options;
}
const locationsuccess = function(result) {
requestParam.location = result.latitude + "," + result.longitude;
common_vendor.wx$1.request(Utils.buildWxRequestConfig(options, {
url: URL_GET_GEOCODER,
data: requestParam
}, "reverseGeocoder"));
};
Utils.locationProcess(options, locationsuccess);
}
// POI周边检索
search(options) {
const that = this;
options = options || {};
Utils.polyfillParam(options);
if (!options.keyword) {
const errconf = Utils.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + " keyword参数格式有误");
options.fail(errconf);
options.complete(errconf);
return;
}
const requestParam = {
keyword: options.keyword,
orderby: options.orderby || "_distance",
page_size: options.page_size || 10,
page_index: options.page_index || 1,
output: "json",
key: that.key
};
if (options.address_format) {
requestParam.address_format = options.address_format;
}
if (options.filter) {
requestParam.filter = options.filter;
}
const distance = options.distance || "1000";
const auto_extend = options.auto_extend || 1;
const locationsuccess = function(result) {
requestParam.boundary = "nearby(" + result.latitude + "," + result.longitude + "," + distance + "," + auto_extend + ")";
common_vendor.wx$1.request(Utils.buildWxRequestConfig(options, {
url: URL_SEARCH,
data: requestParam
}, "search"));
};
Utils.locationProcess(options, locationsuccess);
}
// sug模糊检索
getSuggestion(options) {
const that = this;
options = options || {};
Utils.polyfillParam(options);
if (!options.keyword) {
const errconf = Utils.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + " keyword参数格式有误");
options.fail(errconf);
options.complete(errconf);
return;
}
const requestParam = {
keyword: options.keyword,
region: options.region || "全国",
region_fix: options.region_fix || 0,
policy: options.policy || 0,
page_size: options.page_size || 10,
page_index: options.page_index || 1,
get_subpois: options.get_subpois || 0,
output: "json",
key: that.key
};
if (options.address_format) {
requestParam.address_format = options.address_format;
}
if (options.filter) {
requestParam.filter = options.filter;
}
if (options.location) {
const locationsuccess = function(result) {
requestParam.location = result.latitude + "," + result.longitude;
common_vendor.wx$1.request(Utils.buildWxRequestConfig(options, {
url: URL_SUGGESTION,
data: requestParam
}, "suggest"));
};
Utils.locationProcess(options, locationsuccess);
} else {
common_vendor.wx$1.request(Utils.buildWxRequestConfig(options, {
url: URL_SUGGESTION,
data: requestParam
}, "suggest"));
}
}
// 距离计算
calculateDistance(options) {
const that = this;
options = options || {};
Utils.polyfillParam(options);
if (!options.to) {
const errconf = Utils.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + " to参数格式有误");
options.fail(errconf);
options.complete(errconf);
return;
}
const requestParam = {
mode: options.mode || "walking",
to: options.to,
output: "json",
key: that.key
};
if (options.from) {
options.location = options.from;
}
const locationsuccess = function(result) {
requestParam.from = result.latitude + "," + result.longitude;
common_vendor.wx$1.request(Utils.buildWxRequestConfig(options, {
url: URL_DISTANCE,
data: requestParam
}, "calculateDistance"));
};
Utils.locationProcess(options, locationsuccess);
}
}
return QQMapWX2;
}();
let qqmapInstance = null;
function initQQMap() {
if (!qqmapInstance) {
try {
qqmapInstance = new QQMapWX({
key: QQMAP_KEY
});
common_vendor.index.__f__("log", "at utils/mapUtils.js:398", "腾讯地图SDK初始化成功");
} catch (err) {
common_vendor.index.__f__("error", "at utils/mapUtils.js:400", "初始化腾讯地图SDK失败:", err);
}
}
return qqmapInstance;
}
function getQQMapInstance() {
return qqmapInstance || initQQMap();
}
function getUserLocation() {
return new Promise((resolve, reject) => {
common_vendor.wx$1.getLocation({
type: "gcj02",
success: (res) => {
resolve({
longitude: res.longitude,
latitude: res.latitude
});
},
fail: (error) => {
common_vendor.index.__f__("error", "at utils/mapUtils.js:423", "获取位置失败:", error);
reject(error);
}
});
});
}
function getRegeo(longitude, latitude) {
return new Promise((resolve, reject) => {
const qqmap = getQQMapInstance();
if (!qqmap) {
reject({ success: false, message: "腾讯地图SDK未初始化" });
return;
}
qqmap.reverseGeocoder({
location: {
latitude,
longitude
},
success: (data, result) => {
const reverseGeocoderSimplify = result.reverseGeocoderSimplify;
resolve({
success: true,
data: {
formatted_address: reverseGeocoderSimplify.address,
addressComponent: {
city: reverseGeocoderSimplify.city,
district: reverseGeocoderSimplify.district,
province: reverseGeocoderSimplify.province,
street: reverseGeocoderSimplify.street,
street_number: reverseGeocoderSimplify.street_number
}
}
});
},
fail: (error) => {
common_vendor.index.__f__("error", "at utils/mapUtils.js:462", "逆地理编码失败:", error);
reject({ success: false, message: error.message || "逆地理编码失败" });
}
});
});
}
function calculateDistanceSync(lat1, lng1, lat2, lng2) {
const R = 6371e3;
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLng = (lng2 - lng1) * 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(dLng / 2) * Math.sin(dLng / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return Math.round(R * c);
}
function testDistanceCalculation() {
const tiananmen = { lat: 39.908823, lng: 116.39747 };
const gugong = { lat: 39.916527, lng: 116.397128 };
const distance = calculateDistanceSync(tiananmen.lat, tiananmen.lng, gugong.lat, gugong.lng);
common_vendor.index.__f__("log", "at utils/mapUtils.js:586", "天安门到故宫的距离:", distance, "米");
common_vendor.index.__f__("log", "at utils/mapUtils.js:587", "转换为公里:", (distance / 1e3).toFixed(2), "公里");
return distance;
}
exports.calculateDistanceSync = calculateDistanceSync;
exports.getRegeo = getRegeo;
exports.getUserLocation = getUserLocation;
exports.testDistanceCalculation = testDistanceCalculation;
//# sourceMappingURL=../../.sourcemap/mp-weixin/utils/mapUtils.js.map