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.

180 lines
5.4 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. <?php
  2. namespace App\Service\v3\Implementations;
  3. use App\Constants\v3\ErrorCode;
  4. use App\Exception\ErrorCodeException;
  5. use App\Model\v3\UserCollection;
  6. use App\Service\v3\Interfaces\LocationServiceInterface;
  7. use App\Model\v3\Area;
  8. use App\Model\v3\Market;
  9. use GuzzleHttp\Client;
  10. class LocationService implements LocationServiceInterface
  11. {
  12. public function do()
  13. {
  14. // TODO: Implement do() method.
  15. }
  16. public function check()
  17. {
  18. // TODO: Implement check() method.
  19. }
  20. public function undo()
  21. {
  22. // TODO: Implement undo() method.
  23. }
  24. public function getMarketListByLocation($lng,$lat)
  25. {
  26. $cityIds = Market::query()->pluck('city_id');
  27. $res = Area::query()->with('markets')->whereIn('id',$cityIds)->get();
  28. foreach ($res as &$v){
  29. if(!empty($lng) && !empty($lat)) {
  30. $v->distance_num = $this->getDistance($v->lng, $v->lat, $lng, $lat);
  31. $v->distance = $v->distance_num . ' km';
  32. } else {
  33. $v->distance_num = 0;
  34. $v->distance = '';
  35. }
  36. foreach ($v->markets as &$m)
  37. {
  38. if(!empty($lng) && !empty($lat)){
  39. $m->distance_num = $this->getDistance($m->lng, $m->lat, $lng, $lat);
  40. $m->distance = $m->distance_num.' km';
  41. }else{
  42. $m->distance_num = 0;
  43. $m->distance = '';
  44. }
  45. }
  46. }
  47. $res = collect($res->toArray())->sortBy(function ($area, $key) {
  48. return $area['distance_num'];
  49. });
  50. $res = collect($res->all())->map(function ($area, $key) {
  51. $markets = collect($area['markets'])->sortBy('distance_num');
  52. $area['markets'] = $markets->values()->all();
  53. return $area;
  54. });
  55. return $res->all();
  56. }
  57. public function searchMarket($keywords,$lng,$lat,$cityId = 2163)
  58. {
  59. $res = Market::query()->where([
  60. ['name','like','%'.$keywords.'%'],
  61. ['city_id','=',$cityId]
  62. ])
  63. ->get();
  64. foreach ($res as &$m){
  65. if(!empty($lng) && !empty($lat)){
  66. $m->distance_num = $this->getDistance($m->lng, $m->lat, $lng, $lat);
  67. $m->distance = $m->distance_num.' km';
  68. }else{
  69. $m->distance_num = 0;
  70. $m->distance = '';
  71. }
  72. }
  73. $res = collect($res->toArray())->sortBy(function ($area, $key) {
  74. return $area['distance_num'];
  75. });
  76. $res = collect($res->all())->map(function ($area, $key) {
  77. $markets = collect($area['markets'])->sortBy('distance_num');
  78. $area['markets'] = $markets->values()->all();
  79. return $area;
  80. });
  81. return $res->all();
  82. }
  83. public function getNearestMarket($lng,$lat)
  84. {
  85. $markets = Market::query()->get()->toArray();
  86. $result = [];
  87. $distinctMin = 0;
  88. foreach ($markets as &$market){
  89. $distinct = $this->getDistance($lng,$lat,$market['lng'],$market['lat'],1);
  90. $market['distinct'] = round(($distinct/1000),2).' km';
  91. if($distinct < $distinctMin || $distinctMin === 0) {
  92. $distinctMin = $distinct;
  93. $result = $market;
  94. }
  95. }
  96. return $result;
  97. }
  98. /**
  99. * @param $lng1
  100. * @param $lat1
  101. * @param $lng2
  102. * @param $lat2
  103. * @param int $unit 单位 1: 2:公里
  104. * @param int $decimal 精度 保留小数位数
  105. * @return false|float
  106. */
  107. public function getDistance($lng1, $lat1, $lng2, $lat2, $unit = 2, $decimal = 2)
  108. {
  109. $EARTH_RADIUS = 6370.996; // 地球半径系数
  110. $PI = 3.1415926535898;
  111. $radLat1 = $lat1 * $PI / 180.0;
  112. $radLat2 = $lat2 * $PI / 180.0;
  113. $radLng1 = $lng1 * $PI / 180.0;
  114. $radLng2 = $lng2 * $PI / 180.0;
  115. $a = $radLat1 - $radLat2;
  116. $b = $radLng1 - $radLng2;
  117. $distance = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
  118. $distance = $distance * $EARTH_RADIUS * 1000;
  119. if ($unit === 2) {
  120. $distance /= 1000;
  121. }
  122. return round($distance, $decimal);
  123. }
  124. //获取服务站信息
  125. function getMarketsInfo()
  126. {
  127. return Market::where('status',1)->get();
  128. }
  129. //获取骑行距离
  130. public function getDistanceByTencent($lng1, $lat1, $lng2, $lat2)
  131. {
  132. $url = 'https://apis.map.qq.com/ws/distance/v1/matrix/?mode=';
  133. /**
  134. * $tyep driving 驾车 walking 步行 bicycling 骑行 transit 公交
  135. */
  136. $type = 'bicycling';
  137. $key = config('map.tencent');
  138. $client = new Client([
  139. // Base URI is used with relative requests
  140. 'base_uri' => 'https://apis.map.qq.com/',
  141. // You can set any number of default request options.
  142. 'timeout' => 2.0,
  143. ]);
  144. $response = $client->request('GET', $url.$type.'&from='.$lat1.','.$lng1.'&to='.$lat2.','.$lng2.'&output=json&key='.$key);
  145. $response = $response->getBody()->getContents();
  146. $resultArr = json_decode($response,true);
  147. if($resultArr['status'] > 0)
  148. {
  149. throw new ErrorCodeException(ErrorCode::LOCATION_ERROR,$resultArr['message']);
  150. }
  151. $distance = $resultArr['result']['rows'][0]['elements'][0]['distance'];
  152. return $distance;
  153. }
  154. }