319 行
11 KiB
PHP
319 行
11 KiB
PHP
<?php
|
||
namespace RiderApi\Controller;
|
||
|
||
/**
|
||
* 骑手端地图控制器
|
||
*/
|
||
class MapController extends BaseController {
|
||
|
||
/**
|
||
* 获取附近地点
|
||
*/
|
||
public function getNearbyPlaces() {
|
||
$lat = floatval($this->getRequestParam('lat', 0));
|
||
$lng = floatval($this->getRequestParam('lng', 0));
|
||
$radius = intval($this->getRequestParam('radius', 1000)); // 默认1000米
|
||
$type = $this->getRequestParam('type', ''); // 地点类型
|
||
|
||
if (empty($lat) || empty($lng)) {
|
||
$this->ajaxReturn(array('code' => 0, 'msg' => '位置信息不能为空'));
|
||
}
|
||
|
||
// 这里可以调用第三方地图API(如高德、百度等)
|
||
// 暂时返回模拟数据
|
||
$places = array(
|
||
array(
|
||
'id' => 1,
|
||
'name' => '附近餐厅',
|
||
'address' => '示例地址1',
|
||
'lat' => $lat + 0.001,
|
||
'lng' => $lng + 0.001,
|
||
'distance' => 100,
|
||
'type' => 'restaurant'
|
||
),
|
||
array(
|
||
'id' => 2,
|
||
'name' => '附近商店',
|
||
'address' => '示例地址2',
|
||
'lat' => $lat - 0.001,
|
||
'lng' => $lng - 0.001,
|
||
'distance' => 200,
|
||
'type' => 'shop'
|
||
)
|
||
);
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '获取成功',
|
||
'data' => $places
|
||
));
|
||
}
|
||
|
||
/**
|
||
* 搜索地点
|
||
*/
|
||
public function searchPlaces() {
|
||
$keyword = trim($this->getRequestParam('keyword', ''));
|
||
$lat = floatval($this->getRequestParam('lat', 0));
|
||
$lng = floatval($this->getRequestParam('lng', 0));
|
||
$city = trim($this->getRequestParam('city', ''));
|
||
|
||
if (empty($keyword)) {
|
||
$this->ajaxReturn(array('code' => 0, 'msg' => '搜索关键词不能为空'));
|
||
}
|
||
|
||
// 这里可以调用第三方地图API进行地点搜索
|
||
// 暂时返回模拟数据
|
||
$places = array(
|
||
array(
|
||
'id' => 1,
|
||
'name' => $keyword . '相关地点1',
|
||
'address' => '搜索结果地址1',
|
||
'lat' => 39.908823,
|
||
'lng' => 116.397470,
|
||
'distance' => 500
|
||
),
|
||
array(
|
||
'id' => 2,
|
||
'name' => $keyword . '相关地点2',
|
||
'address' => '搜索结果地址2',
|
||
'lat' => 39.909823,
|
||
'lng' => 116.398470,
|
||
'distance' => 800
|
||
)
|
||
);
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '搜索成功',
|
||
'data' => $places
|
||
));
|
||
}
|
||
|
||
/**
|
||
* 路线规划
|
||
*/
|
||
public function planRoute() {
|
||
$riderId = $this->riderId;
|
||
$rider = $this->riderInfo;
|
||
|
||
// 获取请求参数
|
||
$startLat = floatval($this->getRequestParam('start_lat', 0));
|
||
$startLng = floatval($this->getRequestParam('start_lng', 0));
|
||
$endLat = floatval($this->getRequestParam('end_lat', 0));
|
||
$endLng = floatval($this->getRequestParam('end_lng', 0));
|
||
$startAddress = trim($this->getRequestParam('start_address', ''));
|
||
$endAddress = trim($this->getRequestParam('end_address', ''));
|
||
$waypoints = $this->getRequestParam('waypoints', array()); // 途经点
|
||
$strategy = $this->getRequestParam('strategy', 'fastest'); // 路线策略:fastest(最快), shortest(最短), avoid_traffic(避开拥堵)
|
||
|
||
// 参数验证
|
||
if (empty($startLat) || empty($startLng) || empty($endLat) || empty($endLng)) {
|
||
$this->ajaxReturn(array('code' => 0, 'msg' => '起点和终点坐标不能为空'));
|
||
}
|
||
|
||
// 验证坐标范围
|
||
if ($startLat < -90 || $startLat > 90 || $endLat < -90 || $endLat > 90) {
|
||
$this->ajaxReturn(array('code' => 0, 'msg' => '纬度范围错误'));
|
||
}
|
||
|
||
if ($startLng < -180 || $startLng > 180 || $endLng < -180 || $endLng > 180) {
|
||
$this->ajaxReturn(array('code' => 0, 'msg' => '经度范围错误'));
|
||
}
|
||
|
||
try {
|
||
// 调用路线规划服务
|
||
$routeResult = $this->calculateRoute($startLat, $startLng, $endLat, $endLng, $waypoints, $strategy);
|
||
|
||
if (!$routeResult) {
|
||
$this->ajaxReturn(array('code' => 0, 'msg' => '路线规划失败'));
|
||
}
|
||
|
||
// 保存路线规划记录
|
||
$this->saveRouteRecord($riderId, $startLat, $startLng, $endLat, $endLng, $startAddress, $endAddress, $routeResult);
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '路线规划成功',
|
||
'data' => $routeResult
|
||
));
|
||
|
||
} catch (\Exception $e) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '路线规划异常:' . $e->getMessage()
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 计算路线
|
||
*/
|
||
private function calculateRoute($startLat, $startLng, $endLat, $endLng, $waypoints = array(), $strategy = 'fastest') {
|
||
// 这里应该调用第三方地图API(如高德、百度等)进行实际的路线规划
|
||
// 目前返回模拟数据
|
||
|
||
// 计算直线距离(简化处理)
|
||
$distance = $this->calculateDistance($startLat, $startLng, $endLat, $endLng);
|
||
|
||
// 模拟路线数据
|
||
$route = array(
|
||
'distance' => round($distance, 2), // 距离(公里)
|
||
'duration' => round($distance / 30 * 60, 0), // 预估时间(分钟,按30km/h计算)
|
||
'polyline' => $this->generatePolyline($startLat, $startLng, $endLat, $endLng), // 路线坐标点
|
||
'steps' => $this->generateRouteSteps($startLat, $startLng, $endLat, $endLng), // 导航步骤
|
||
'strategy' => $strategy,
|
||
'traffic_info' => array(
|
||
'status' => 'smooth', // 路况:smooth(畅通), slow(缓慢), congested(拥堵)
|
||
'delay_time' => 0 // 延误时间(分钟)
|
||
)
|
||
);
|
||
|
||
return $route;
|
||
}
|
||
|
||
/**
|
||
* 计算两点间距离(公里)
|
||
*/
|
||
private function calculateDistance($lat1, $lng1, $lat2, $lng2) {
|
||
$earthRadius = 6371; // 地球半径(公里)
|
||
|
||
$lat1Rad = deg2rad($lat1);
|
||
$lng1Rad = deg2rad($lng1);
|
||
$lat2Rad = deg2rad($lat2);
|
||
$lng2Rad = deg2rad($lng2);
|
||
|
||
$deltaLat = $lat2Rad - $lat1Rad;
|
||
$deltaLng = $lng2Rad - $lng1Rad;
|
||
|
||
$a = sin($deltaLat / 2) * sin($deltaLat / 2) +
|
||
cos($lat1Rad) * cos($lat2Rad) *
|
||
sin($deltaLng / 2) * sin($deltaLng / 2);
|
||
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
|
||
|
||
return $earthRadius * $c;
|
||
}
|
||
|
||
/**
|
||
* 生成路线坐标点
|
||
*/
|
||
private function generatePolyline($startLat, $startLng, $endLat, $endLng) {
|
||
// 简化处理,生成几个中间点
|
||
$points = array();
|
||
$steps = 5;
|
||
|
||
for ($i = 0; $i <= $steps; $i++) {
|
||
$ratio = $i / $steps;
|
||
$lat = $startLat + ($endLat - $startLat) * $ratio;
|
||
$lng = $startLng + ($endLng - $startLng) * $ratio;
|
||
$points[] = array('lat' => $lat, 'lng' => $lng);
|
||
}
|
||
|
||
return $points;
|
||
}
|
||
|
||
/**
|
||
* 生成导航步骤
|
||
*/
|
||
private function generateRouteSteps($startLat, $startLng, $endLat, $endLng) {
|
||
return array(
|
||
array(
|
||
'instruction' => '从起点出发',
|
||
'distance' => 0,
|
||
'duration' => 0,
|
||
'lat' => $startLat,
|
||
'lng' => $startLng
|
||
),
|
||
array(
|
||
'instruction' => '直行',
|
||
'distance' => $this->calculateDistance($startLat, $startLng, $endLat, $endLng) * 1000,
|
||
'duration' => round($this->calculateDistance($startLat, $startLng, $endLat, $endLng) / 30 * 60, 0),
|
||
'lat' => $endLat,
|
||
'lng' => $endLng
|
||
),
|
||
array(
|
||
'instruction' => '到达目的地',
|
||
'distance' => 0,
|
||
'duration' => 0,
|
||
'lat' => $endLat,
|
||
'lng' => $endLng
|
||
)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 保存路线规划记录
|
||
*/
|
||
private function saveRouteRecord($riderId, $startLat, $startLng, $endLat, $endLng, $startAddress, $endAddress, $routeResult) {
|
||
$routeModel = M('rider_route_record');
|
||
|
||
$data = array(
|
||
'rider_id' => $riderId,
|
||
'start_lat' => $startLat,
|
||
'start_lng' => $startLng,
|
||
'end_lat' => $endLat,
|
||
'end_lng' => $endLng,
|
||
'start_address' => $startAddress,
|
||
'end_address' => $endAddress,
|
||
'distance' => $routeResult['distance'],
|
||
'duration' => $routeResult['duration'],
|
||
'strategy' => $routeResult['strategy'],
|
||
'route_data' => json_encode($routeResult),
|
||
'create_time' => date('Y-m-d H:i:s')
|
||
);
|
||
|
||
$routeModel->add($data);
|
||
}
|
||
|
||
/**
|
||
* 获取缓存信息
|
||
*/
|
||
public function getCacheInfo() {
|
||
$riderId = $this->riderId;
|
||
|
||
// 获取路线缓存数量
|
||
$routeModel = M('rider_route_record');
|
||
$routeCount = $routeModel->where(array('rider_id' => $riderId))->count();
|
||
|
||
$cacheInfo = array(
|
||
'route_cache_count' => $routeCount,
|
||
'cache_size' => round($routeCount * 0.5, 2) . 'MB', // 估算缓存大小
|
||
'last_clear_time' => '2024-01-01 00:00:00' // 最后清理时间
|
||
);
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '获取成功',
|
||
'data' => $cacheInfo
|
||
));
|
||
}
|
||
|
||
/**
|
||
* 清理缓存
|
||
*/
|
||
public function clearCache() {
|
||
$riderId = $this->riderId;
|
||
|
||
try {
|
||
// 清理路线记录缓存(保留最近30天的记录)
|
||
$routeModel = M('rider_route_record');
|
||
$thirtyDaysAgo = date('Y-m-d H:i:s', strtotime('-30 days'));
|
||
|
||
$deletedCount = $routeModel->where(array(
|
||
'rider_id' => $riderId,
|
||
'create_time' => array('lt', $thirtyDaysAgo)
|
||
))->delete();
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '缓存清理成功,清理了' . $deletedCount . '条记录'
|
||
));
|
||
|
||
} catch (\Exception $e) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '缓存清理失败:' . $e->getMessage()
|
||
));
|
||
}
|
||
}
|
||
} |