// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\api\model\store; use app\common\model\store\Shop as ShopModel; /** * 商家门店模型 * Class Shop * @package app\store\model\store */ class Shop extends ShopModel { /** * 隐藏字段 * @var array */ protected $hidden = [ 'is_delete', 'store_id', 'create_time', 'update_time' ]; /** * 获取门店列表 * @param array $param 查询参数 * @param int|null $limit 查询条数 * @return array|\think\Collection * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getList(array $param = [], int $limit = null) { // 查询构造器 $query = $this->getNewQuery(); // 设置列表查询条件 $filter = $this->getFilter($param); // 获取数量 $limit > 0 && $query->limit($limit); // 获取门店列表数据 $list = $query->with(['logoImage']) ->where($filter) ->where('is_delete', '=', 0) ->where('status', '=', 1) ->order(['sort' => 'asc', $this->getPk()]) ->select(); // 根据距离排序 if (!empty($param['longitude']) && !empty($param['latitude'])) { return $this->sortByDistance($list, $param['longitude'], $param['latitude']); } return $list; } /** * 设置列表查询条件 * @param array $param * @return array */ private function getFilter(array $param = []): array { // 默认查询参数 $params = $this->setQueryDefaultValue($param, [ 'isCheck' => -1, // 是否支持自提核销(0否 1支持) 'longitude' => '', // 用户位置: 经度 'latitude' => '', // 用户位置: 纬度 ]); // 检索查询条件 $filter = []; // 是否支持自提核销 $params['isCheck'] > -1 && $filter[] = ['is_check', '=', (int)$params['isCheck']]; return $filter; } /** * 根据距离排序 * @param $data * @param string $longitude 经度 * @param string $latitude 纬度 * @return array */ private function sortByDistance($data, string $longitude, string $latitude): array { // 根据距离排序 $list = $data->isEmpty() ? [] : $data->toArray(); $sortArr = []; foreach ($list as &$shop) { // 计算距离 $distance = self::getDistance((float)$longitude, (float)$latitude, (float)$shop['longitude'], (float)$shop['latitude']); // 排序列 $sortArr[] = $distance; $shop['distance'] = $distance; if ($distance >= 1000) { $distance = bcdiv((string)$distance, (string)1000, 2); $shop['distance_unit'] = $distance . 'km'; } else $shop['distance_unit'] = $distance . 'm'; } // 根据距离排序 array_multisort($sortArr, SORT_ASC, $list); return $list; } /** * 获取两个坐标点的距离 * @param float $ulon * @param float $ulat * @param float $slon * @param float $slat * @return float */ private static function getDistance(float $ulon, float $ulat, float $slon, float $slat): float { // 地球半径 $R = 6378137; // 将角度转为狐度 $radLat1 = deg2rad($ulat); $radLat2 = deg2rad($slat); $radLng1 = deg2rad($ulon); $radLng2 = deg2rad($slon); // 结果 $s = acos(cos($radLat1) * cos($radLat2) * cos($radLng1 - $radLng2) + sin($radLat1) * sin($radLat2)) * $R; // 精度 $s = round($s * 10000) / 10000; return round($s); } /** * 根据门店id集获取门店列表 * @param array $shopIds * @return \think\Collection|false * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getListByIds(array $shopIds) { if (empty($shopIds)) { return false; } // 筛选条件 $filter = [['shop_id', 'in', $shopIds]]; // 获取商品列表数据 return $this->with(['logoImage']) ->orderRaw('field(shop_id, ' . implode(',', $shopIds) . ')') ->where('is_delete', '=', '0') ->where('status', '=', '1') ->where($filter) ->select(); } }