You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
5.0 KiB
169 lines
5.0 KiB
<?php
|
|
|
|
|
|
namespace App\Service\v3\Implementations;
|
|
use App\Constants\v3\ErrorCode;
|
|
use App\Exception\ErrorCodeException;
|
|
use App\Model\v3\UserCollection;
|
|
use App\Service\v3\Interfaces\LocationServiceInterface;
|
|
use App\Model\v3\Area;
|
|
use App\Model\v3\Market;
|
|
use GuzzleHttp\Client;
|
|
|
|
class LocationService implements LocationServiceInterface
|
|
{
|
|
|
|
public function do()
|
|
{
|
|
// TODO: Implement do() method.
|
|
}
|
|
|
|
public function check()
|
|
{
|
|
// TODO: Implement check() method.
|
|
}
|
|
|
|
public function undo()
|
|
{
|
|
// TODO: Implement undo() method.
|
|
}
|
|
|
|
public function getMarketListByLocation($lng,$lat)
|
|
{
|
|
$cityIds = Market::query()->pluck('city_id');
|
|
$res = Area::query()->with('markets')->whereIn('id',$cityIds)->get();
|
|
foreach ($res as &$v){
|
|
|
|
if(!empty($lng) && !empty($lat)) {
|
|
$v->distance_num = $this->getDistance($v->lng, $v->lat, $lng, $lat);
|
|
$v->distance = $v->distance_num . ' km';
|
|
} else {
|
|
$v->distance_num = 0;
|
|
$v->distance = '';
|
|
}
|
|
|
|
foreach ($v->markets as &$m)
|
|
{
|
|
if(!empty($lng) && !empty($lat)){
|
|
$m->distance_num = $this->getDistance($m->lng, $m->lat, $lng, $lat);
|
|
$m->distance = $m->distance_num.' km';
|
|
}else{
|
|
$m->distance_num = 0;
|
|
$m->distance = '';
|
|
}
|
|
}
|
|
}
|
|
|
|
$res = collect($res->toArray())->sortBy(function ($area, $key) {
|
|
return $area['distance_num'];
|
|
});
|
|
|
|
$res = collect($res->all())->map(function ($area, $key) {
|
|
$markets = collect($area['markets'])->sortBy('distance_num');
|
|
$area['markets'] = $markets->values()->all();
|
|
return $area;
|
|
});
|
|
|
|
return $res->all();
|
|
}
|
|
|
|
public function searchMarket($keywords,$lng,$lat,$cityId = 2163)
|
|
{
|
|
$res = Market::query()->where([
|
|
['name','like','%'.$keywords.'%'],
|
|
['city_id','=',$cityId]
|
|
])
|
|
->get();
|
|
foreach ($res as &$v){
|
|
if(!empty($lng) && !empty($lat)){
|
|
$v->distance = ($this->getDistance($v->lng,$v->lat,$lng,$lat)).' km';
|
|
}else{
|
|
$v->distance = '';
|
|
}
|
|
}
|
|
return $res;
|
|
}
|
|
|
|
public function getNearestMarket($lng,$lat)
|
|
{
|
|
$markets = Market::query()->get()->toArray();
|
|
$result = [];
|
|
$distinctMin = 0;
|
|
foreach ($markets as &$market){
|
|
$distinct = $this->getDistance($lng,$lat,$market['lng'],$market['lat'],1);
|
|
$market['distinct'] = round(($distinct/1000),2).' km';
|
|
if($distinct < $distinctMin || $distinctMin === 0) {
|
|
$distinctMin = $distinct;
|
|
$result = $market;
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param $lng1
|
|
* @param $lat1
|
|
* @param $lng2
|
|
* @param $lat2
|
|
* @param int $unit 单位 1:米 2:公里
|
|
* @param int $decimal 精度 保留小数位数
|
|
* @return false|float
|
|
*/
|
|
public function getDistance($lng1, $lat1, $lng2, $lat2, $unit = 2, $decimal = 2)
|
|
{
|
|
|
|
$EARTH_RADIUS = 6370.996; // 地球半径系数
|
|
$PI = 3.1415926535898;
|
|
|
|
$radLat1 = $lat1 * $PI / 180.0;
|
|
$radLat2 = $lat2 * $PI / 180.0;
|
|
|
|
$radLng1 = $lng1 * $PI / 180.0;
|
|
$radLng2 = $lng2 * $PI / 180.0;
|
|
|
|
$a = $radLat1 - $radLat2;
|
|
$b = $radLng1 - $radLng2;
|
|
|
|
$distance = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
|
|
$distance = $distance * $EARTH_RADIUS * 1000;
|
|
|
|
if ($unit === 2) {
|
|
$distance /= 1000;
|
|
}
|
|
|
|
return round($distance, $decimal);
|
|
}
|
|
|
|
//获取服务站信息
|
|
function getMarketsInfo()
|
|
{
|
|
return Market::where('status',1)->get();
|
|
}
|
|
|
|
//获取骑行距离
|
|
public function getDistanceByTencent($lng1, $lat1, $lng2, $lat2)
|
|
{
|
|
$url = 'https://apis.map.qq.com/ws/distance/v1/matrix/?mode=';
|
|
/**
|
|
* $tyep driving 驾车 walking 步行 bicycling 骑行 transit 公交
|
|
*/
|
|
$type = 'bicycling';
|
|
$key = config('map.tencent');
|
|
$client = new Client([
|
|
// Base URI is used with relative requests
|
|
'base_uri' => 'https://apis.map.qq.com/',
|
|
// You can set any number of default request options.
|
|
'timeout' => 2.0,
|
|
]);
|
|
$response = $client->request('GET', $url.$type.'&from='.$lat1.','.$lng1.'&to='.$lat2.','.$lng2.'&output=json&key='.$key);
|
|
$response = $response->getBody()->getContents();
|
|
$resultArr = json_decode($response,true);
|
|
if($resultArr['status'] > 0)
|
|
{
|
|
throw new ErrorCodeException(ErrorCode::LOCATION_ERROR,$resultArr['message']);
|
|
}
|
|
var_dump($resultArr);
|
|
$distance = $resultArr['result']['rows'][0]['elements'][0]['distance'];
|
|
return $distance;
|
|
}
|
|
}
|