feat:新增地图视图效果,接口待对接

This commit is contained in:
2025-08-08 14:51:45 +08:00
parent 67eb4e5516
commit c5b8026fba
49 changed files with 2811 additions and 884 deletions
+163
View File
@@ -0,0 +1,163 @@
// 高德地图工具类
const AMAP_KEY = '4c513a688938fd89b88b296e867f66ec'
class AmapUtil {
constructor() {
this.key = AMAP_KEY
}
// 逆地理编码 - 根据经纬度获取地址信息
async regeocode(longitude, latitude) {
try {
const res = await uni.request({
url: 'https://restapi.amap.com/v3/geocode/regeo',
method: 'GET',
data: {
key: this.key,
location: `${longitude},${latitude}`,
poitype: '',
radius: 1000,
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) {
console.error('逆地理编码异常:', error)
return {
success: false,
message: '网络异常'
}
}
}
// 地理编码 - 根据地址获取经纬度
async geocode(address, city = '') {
try {
const res = await uni.request({
url: 'https://restapi.amap.com/v3/geocode/geo',
method: 'GET',
data: {
key: this.key,
address: address,
city: 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) {
console.error('地理编码异常:', error)
return {
success: false,
message: '网络异常'
}
}
}
// 搜索POI
async searchPOI(keywords, location = '', radius = 3000, city = '') {
try {
const res = await uni.request({
url: 'https://restapi.amap.com/v3/place/text',
method: 'GET',
data: {
key: this.key,
keywords: keywords,
location: location,
radius: radius,
city: 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) {
console.error('POI搜索异常:', error)
return {
success: false,
message: '网络异常'
}
}
}
// 路径规划
async getRoute(origin, destination, strategy = 0) {
try {
const res = await uni.request({
url: 'https://restapi.amap.com/v3/direction/driving',
method: 'GET',
data: {
key: this.key,
origin: origin,
destination: destination,
strategy: 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) {
console.error('路径规划异常:', error)
return {
success: false,
message: '网络异常'
}
}
}
// 计算两点间距离
calculateDistance(lat1, lng1, lat2, lng2) {
const radLat1 = lat1 * Math.PI / 180.0
const radLat2 = lat2 * Math.PI / 180.0
const a = radLat1 - radLat2
const b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0
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 * 10000) / 10000
return s
}
}
export default new AmapUtil()
+194
View File
@@ -0,0 +1,194 @@
// 高德静态地图API工具类
const AMAP_KEY = '4c513a688938fd89b88b296e867f66ec'
class StaticMapUtil {
constructor() {
this.key = AMAP_KEY
this.baseUrl = 'https://restapi.amap.com/v3/staticmap'
}
/**
* 生成静态地图URL
* @param {Object} options 地图配置选项
* @returns {String} 静态地图URL
*/
generateMapUrl(options = {}) {
const defaultOptions = {
location: '116.397128,39.916527', // 默认中心点(北京)
zoom: 13, // 缩放级别
size: '750*500', // 图片尺寸
scale: 2, // 高清显示
markers: [], // 标记点
labels: [], // 文字标注
paths: [], // 路径
traffic: 0, // 交通路况 0-不显示 1-显示
format: 'png' // 图片格式
}
const config = { ...defaultOptions, ...options }
let url = `${this.baseUrl}?key=${this.key}`
url += `&location=${config.location}`
url += `&zoom=${config.zoom}`
url += `&size=${config.size}`
url += `&scale=${config.scale}`
url += `&traffic=${config.traffic}`
url += `&format=${config.format}`
// 添加标记点
if (config.markers && config.markers.length > 0) {
const markersStr = config.markers.map(marker => {
let markerStr = ''
if (marker.size) markerStr += `size:${marker.size}|`
if (marker.color) markerStr += `color:${marker.color}|`
if (marker.label) markerStr += `label:${marker.label}|`
markerStr += `${marker.longitude},${marker.latitude}`
return markerStr
}).join('|')
url += `&markers=${encodeURIComponent(markersStr)}`
}
// 添加文字标注
if (config.labels && config.labels.length > 0) {
const labelsStr = config.labels.map(label => {
let labelStr = ''
if (label.content) labelStr += `content:${label.content}|`
if (label.font) labelStr += `font:${label.font}|`
if (label.bold) labelStr += `bold:${label.bold}|`
if (label.fontSize) labelStr += `fontSize:${label.fontSize}|`
if (label.fontColor) labelStr += `fontColor:${label.fontColor}|`
if (label.background) labelStr += `background:${label.background}|`
labelStr += `${label.longitude},${label.latitude}`
return labelStr
}).join('|')
url += `&labels=${encodeURIComponent(labelsStr)}`
}
return url
}
/**
* 为场地列表生成静态地图URL
* @param {Array} positions 场地列表
* @param {Object} options 额外选项
* @returns {String} 静态地图URL
*/
generatePositionsMapUrl(positions = [], options = {}) {
if (!positions || positions.length === 0) {
return this.generateMapUrl(options)
}
// 计算地图中心点和缩放级别
const center = this.calculateCenter(positions)
const zoom = this.calculateOptimalZoom(positions, center)
// 生成标记点
const markers = positions.map((position, index) => ({
longitude: parseFloat(position.longitude),
latitude: parseFloat(position.latitude),
size: 'mid',
color: position.status === 'online' ? 'green' : 'red',
label: String.fromCharCode(65 + (index % 26)) // A, B, C...
}))
return this.generateMapUrl({
location: `${center.longitude},${center.latitude}`,
zoom: zoom,
markers: markers,
...options
})
}
/**
* 计算多个点的中心位置
* @param {Array} positions 位置数组
* @returns {Object} 中心点坐标
*/
calculateCenter(positions) {
if (positions.length === 0) {
return { longitude: 116.397128, latitude: 39.916527 }
}
const validPositions = positions.filter(p => p.longitude && p.latitude)
if (validPositions.length === 0) {
return { longitude: 116.397128, latitude: 39.916527 }
}
const sum = validPositions.reduce((acc, pos) => ({
longitude: acc.longitude + parseFloat(pos.longitude),
latitude: acc.latitude + parseFloat(pos.latitude)
}), { longitude: 0, latitude: 0 })
return {
longitude: (sum.longitude / validPositions.length).toFixed(6),
latitude: (sum.latitude / validPositions.length).toFixed(6)
}
}
/**
* 计算最佳缩放级别
* @param {Array} positions 位置数组
* @param {Object} center 中心点
* @returns {Number} 缩放级别
*/
calculateOptimalZoom(positions, center) {
if (positions.length <= 1) return 15
const validPositions = positions.filter(p => p.longitude && p.latitude)
if (validPositions.length <= 1) return 15
// 计算最大距离
let maxDistance = 0
validPositions.forEach(pos => {
const distance = this.getDistance(
center.latitude, center.longitude,
parseFloat(pos.latitude), parseFloat(pos.longitude)
)
maxDistance = Math.max(maxDistance, distance)
})
// 根据最大距离确定缩放级别
if (maxDistance < 1) return 16 // 1km内
if (maxDistance < 2) return 15 // 2km内
if (maxDistance < 5) return 14 // 5km内
if (maxDistance < 10) return 13 // 10km内
if (maxDistance < 20) return 12 // 20km内
if (maxDistance < 50) return 11 // 50km内
return 10 // 50km以上
}
/**
* 计算两点间距离(公里)
* @param {Number} lat1 纬度1
* @param {Number} lng1 经度1
* @param {Number} lat2 纬度2
* @param {Number} lng2 经度2
* @returns {Number} 距离(公里)
*/
getDistance(lat1, lng1, lat2, lng2) {
const radLat1 = lat1 * Math.PI / 180.0
const radLat2 = lat2 * Math.PI / 180.0
const a = radLat1 - radLat2
const b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0
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 * 10000) / 10000
return s
}
/**
* 预加载地图图片
* @param {String} mapUrl 地图URL
* @returns {Promise} 图片加载Promise
*/
preloadMapImage(mapUrl) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => resolve(mapUrl)
img.onerror = reject
img.src = mapUrl
})
}
}
export default new StaticMapUtil()