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.
yanzong/app/api/model/store/Shop.php

162 lines
5.3 KiB

11 months ago
<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
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();
}
}