426 lines
15 KiB
PHP
426 lines
15 KiB
PHP
<?php
|
||
|
||
/**
|
||
* @author Any
|
||
* @description KISS
|
||
* @date 2020-12-2
|
||
* @version 1.0.0
|
||
*
|
||
* _____LOG_____
|
||
*
|
||
*/
|
||
|
||
namespace app\modules\api\models;
|
||
|
||
use function AlibabaCloud\Client\value;
|
||
use app\components\FlashStorage;
|
||
use app\components\SiteHelper;
|
||
use app\components\SysConst;
|
||
use app\models\Box;
|
||
use app\models\Coach;
|
||
use app\models\Goods;
|
||
use app\models\GoodsHub;
|
||
use app\models\Store;
|
||
use app\models\User;
|
||
use app\components\auth\AToken;
|
||
use app\components\EncryptHelper;
|
||
use app\modules\api\components\ApiHelper;
|
||
use app\modules\api\components\GetDistance;
|
||
use yii\data\Pagination;
|
||
|
||
|
||
class StoreForm extends ApiModel
|
||
{
|
||
|
||
public $limit;//条数
|
||
public $page; //页数
|
||
public $pageCount; // 总页数
|
||
|
||
public $store_id;
|
||
public $coach_id;
|
||
public $cx_mch_id;
|
||
public $user_id;
|
||
|
||
public function rules()
|
||
{
|
||
return [
|
||
[['limit', 'page', 'store_id'], 'integer'],
|
||
[['page'], 'default', 'value' => 1],
|
||
];
|
||
}
|
||
|
||
|
||
/**
|
||
* 门店列表
|
||
*/
|
||
public function search($cityId, $name, $lat, $lng)
|
||
{
|
||
if (!$this->validate()) {
|
||
return $this->getModelError();
|
||
}
|
||
|
||
$where = ['is_delete' => 0];
|
||
if ($cityId) {
|
||
$where['city_id'] = $cityId;
|
||
}
|
||
|
||
$query = Store::find()->where($where)->andFilterWhere(['OR', ['LIKE', 'name', $name]])
|
||
->select('id,name,province,province_id,city,city_id,region,region_id,cover_pic,pic_urls,location_detail,lat,lng,begin_time,end_time,status,store_mobile');
|
||
|
||
$count_query = clone $query;
|
||
$count = $count_query->count();
|
||
|
||
if (empty($this->limit)) {
|
||
$this->limit = 10;
|
||
}
|
||
if (empty($this->page)) {
|
||
$this->page = 1;
|
||
}
|
||
|
||
$pagination = new Pagination(['pageSize' => $this->limit, 'totalCount' => $count, 'page' => $this->page - 1]);
|
||
$list = $query->offset($pagination->offset)->limit($pagination->limit)->orderBy(['sort' => SORT_DESC])->asArray()->all();
|
||
$this->pageCount = $pagination->pageCount;
|
||
|
||
foreach ($list as $index => $item) {
|
||
$item['distance'] = '';
|
||
if (!empty($lat) && !empty($lng)) {
|
||
$item['distance'] = GetDistance::getDistance($lat, $lng, $item['lat'], $item['lng']);
|
||
}
|
||
|
||
$item['cover_pic'] = substr($item['cover_pic'], 0, 7) == 'http://' ? $item['cover_pic'] : SiteHelper::getFullUrl($item['cover_pic']);
|
||
|
||
// $item['cover_pic'] = SiteHelper::getFullUrl($item['cover_pic']);
|
||
|
||
|
||
$item['pic_urls'] = $this->fixPicUrls($item['pic_urls']);
|
||
|
||
$list[$index] = $item;
|
||
}
|
||
//是否已经全部加载
|
||
$end_flag = $this->page >= $pagination->pageCount ? true : false;
|
||
|
||
return [
|
||
'code' => 0,
|
||
'msg' => 'ok',
|
||
'data' => $list,
|
||
'count' => $count,
|
||
'page_size' => $this->limit,
|
||
'page_count' => $this->pageCount,
|
||
'page_no' => $this->page,
|
||
'end_flag' => $end_flag
|
||
];
|
||
}
|
||
|
||
|
||
protected function fixPicUrls($pic_urls)
|
||
{
|
||
$pic_urls = is_string($pic_urls) && !empty($pic_urls) ? json_decode($pic_urls, true) : $pic_urls;
|
||
foreach ($pic_urls as $index => $item) {
|
||
$item = SiteHelper::getFullUrl($item);
|
||
$pic_urls[$index] = $item;
|
||
}
|
||
return $pic_urls;
|
||
}
|
||
|
||
/**
|
||
* 门店信息
|
||
* @return array|\yii\db\ActiveRecord|null
|
||
*/
|
||
public function searchOne()
|
||
{
|
||
if (!$this->store_id) {
|
||
return [
|
||
'code' => 1,
|
||
'msg' => '门店ID不能为空'
|
||
];
|
||
}
|
||
// b.name as coach_name,b,content as coach_content,b.coach_photo
|
||
$storeData = Store::find()
|
||
->select('id,name,province,store_mobile,province_id,city,city_id,region,region_id,location_detail,lat,lng,begin_time,end_time,content,pic_urls')
|
||
->where(['id' => $this->store_id, 'is_delete' => 0, 'status' => 1])->asArray()->one();
|
||
$storeData['pic_arr'] = [];
|
||
if ($storeData['pic_urls']) {
|
||
$store_pics = json_decode($storeData['pic_urls'], true);
|
||
foreach ($store_pics as $k => $v) {
|
||
$storeData['pic_arr'][] = SiteHelper::getFullUrl($v);
|
||
}
|
||
unset($storeData['pic_urls']);
|
||
}
|
||
$box_list = Box::find()->select('id as box_id,name,money,cover_pic,device')->where(['store_id' => $this->store_id, 'is_delete' => 0, 'status' => 1])->asArray()->all();
|
||
|
||
|
||
foreach ($box_list as $key => $value) {
|
||
$value['device'] = json_decode($value['device'], true);
|
||
|
||
$value['cover_pic'] = substr($value['cover_pic'], 0, 7) == 'http://' ? $value['cover_pic'] : SiteHelper::getFullUrl($value['cover_pic']);
|
||
|
||
// $value['cover_pic'] = SiteHelper::getFullUrl($value['cover_pic']);
|
||
$box_list[$key] = $value;
|
||
}
|
||
$storeData['box_list'] = $box_list;
|
||
|
||
return $this->apiReturnSuccess('ok', $storeData);
|
||
}
|
||
|
||
|
||
/**
|
||
* 门店选择-绑定门店
|
||
* @return array
|
||
*/
|
||
public function storeBinding()
|
||
{
|
||
if (empty($this->store_id)) {
|
||
return $this->apiReturnError('门店ID不能为空');
|
||
}
|
||
$store = Store::findOne(['id' => $this->store_id]);
|
||
if ($store == null) {
|
||
return [
|
||
'code' => 1,
|
||
'msg' => '门店不存在'
|
||
];
|
||
}
|
||
$user = ApiHelper::findOneUser($this->user_id, $this->cx_mch_id);
|
||
if ($user == null) {
|
||
return [
|
||
'code' => 1,
|
||
'msg' => '用户不存在'
|
||
];
|
||
}
|
||
$user->store_id = $this->store_id;
|
||
if (!$user->save())
|
||
return $this->getModelError($user);
|
||
return [
|
||
'code' => 0,
|
||
'msg' => '绑定成功',
|
||
'data' => $this->store_id,
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 附近的门店
|
||
* @param $lat /纬度
|
||
* @param $lng /经度
|
||
* @return array
|
||
*/
|
||
public function storeHome($lat, $lng, $store_id = 0)
|
||
{
|
||
//保留用户购买的门店 有购买的门店 优先显示已购买门店 没有显示距离最近门店
|
||
|
||
$distance_num = 100000; # 距离 米
|
||
if (!empty($this->user_id)) {
|
||
$user = ApiHelper::findOneUser($this->user_id, $this->cx_mch_id);
|
||
if ($user == null) {
|
||
return [
|
||
'code' => 1,
|
||
'msg' => '用户不存在'
|
||
];
|
||
}
|
||
$this->store_id = $user['store_id'];
|
||
if ($this->store_id) {
|
||
$list = Store::find()->where(['id' => $this->store_id, 'is_delete' => 0])
|
||
->select('id,name,pic_urls,province,province_id,content,city,city_id,region,region_id,location_detail,lat,lng,begin_time,end_time,status')->asArray()->one();
|
||
if (!empty($list)) {
|
||
$list['begin_time'] = date('Y-m-d ') . $list['begin_time'];
|
||
$list['end_time'] = date('Y-m-d ') . $list['end_time'];
|
||
$list['distance'] = GetDistance::getDistance($lat, $lng, $list['lat'], $list['lng']);
|
||
$list['distance'] = str_replace('km', '', $list['distance']); // 转成浮点类型,去除km
|
||
|
||
|
||
$list['pic_urls'] = $this->fixPicUrls($list['pic_urls']);
|
||
|
||
$data = [
|
||
'id' => $list['id'],
|
||
'name' => $list['name'],
|
||
'content' => $list['content'],
|
||
'location_detail' => $list['location_detail'],
|
||
'juli' => $list['distance'],
|
||
'lat' => $list['lat'],
|
||
'lng' => $list['lng']
|
||
];
|
||
return $this->apiReturnSuccess('ok', $data);
|
||
}
|
||
}
|
||
|
||
if (empty($lat) || empty($lng)) {
|
||
// 返回默认数据
|
||
$list = Store::find()->where(['is_delete' => 0]);
|
||
if (!empty($store_id)) {
|
||
$list = $list->andWhere([
|
||
'id' => $store_id,
|
||
]);
|
||
}
|
||
$list = $list->select('id,name,pic_urls,province,province_id,content,city,city_id,region,region_id,location_detail,lat,lng,begin_time,end_time,status')
|
||
->asArray()->one();
|
||
$list['begin_time'] = date('Y-m-d ') . $list['begin_time'];
|
||
$list['end_time'] = date('Y-m-d ') . $list['end_time'];
|
||
$list['distance'] = GetDistance::getDistance($lat, $lng, $list['lat'], $list['lng']);
|
||
$list['distance'] = str_replace('km', '', $list['distance']); // 转成浮点类型,去除km
|
||
|
||
|
||
$list['pic_urls'] = $this->fixPicUrls($list['pic_urls']);
|
||
$data = [
|
||
'id' => $list['id'],
|
||
'name' => $list['name'],
|
||
'content' => $list['content'],
|
||
'location_detail' => $list['location_detail'],
|
||
'juli' => $list['distance'],
|
||
'lat' => $list['lat'],
|
||
'lng' => $list['lng']
|
||
];
|
||
return $this->apiReturnSuccess('ok', $data);
|
||
}
|
||
|
||
|
||
$record = $this->distance($lat, $lng, $distance_num);
|
||
$data = empty($record) ? [] : $record[0];
|
||
if ($data) {
|
||
$user->store_id = $data['id'];
|
||
if (!$user->save()) {
|
||
//默认门店 门店id 到时候替换
|
||
$storeData = Store::findOne(['id' => 11]);
|
||
$data = [
|
||
'id' => $storeData->id,
|
||
'name' => $storeData->name,
|
||
'content' => $storeData->content,
|
||
'location_detail' => $storeData->location_detail,
|
||
'juli' => strval(5),
|
||
'lat' => $storeData->lat,
|
||
'lng' => $storeData->lng
|
||
];
|
||
}
|
||
}
|
||
//转KM
|
||
if (isset($data['juli'])) {
|
||
$data['juli'] = $data['juli'] / 1000;
|
||
}
|
||
return $this->apiReturnSuccess('ok', $data);
|
||
}
|
||
|
||
$storeData = Store::findOne(['id' => 11]);
|
||
|
||
|
||
$data = [
|
||
'id' => $storeData->id,
|
||
'name' => $storeData->name,
|
||
'content' => $storeData->content,
|
||
'location_detail' => $storeData->location_detail,
|
||
'juli' => strval(5),
|
||
'lat' => $storeData->lat,
|
||
'lng' => $storeData->lng
|
||
];
|
||
|
||
return $this->apiReturnSuccess('ok', $data);
|
||
|
||
|
||
// 获取redis key
|
||
$redis_name = \Yii::$app->params['cacheKeyPrefix'] . ":api:store:zset";
|
||
$redis_lock_name = $redis_name . "_lock_v1";
|
||
$get = FlashStorage::getCache($redis_lock_name);
|
||
// 判断是否需要初始化
|
||
if (empty($get)) {
|
||
// 初始化
|
||
$select = Store::find()
|
||
->andWhere([
|
||
'is_delete' => 0,
|
||
])->select('id,lat,lng')->asArray()->all();
|
||
foreach ($select as $key => $val) {
|
||
try {
|
||
\Yii::$app->redis->geoadd($redis_name, $val['lng'], $val['lat'], $val['id']);
|
||
} catch (\Exception $e) {
|
||
|
||
}
|
||
}
|
||
FlashStorage::setCache($redis_lock_name, 1, 60 * 60 * 24 * 30);
|
||
}
|
||
|
||
try {
|
||
$res = \Yii::$app->redis->georadius($redis_name, $lng, $lat, $distance_num, 'm', 'ASC', 'WITHDIST', 'count', 1);
|
||
// 没有查找到,则到数据库里再找一次,每天仅一个人能够查找
|
||
$redis_lock_day_name = $redis_lock_name . "_" . date('d');
|
||
$get = FlashStorage::getCache($redis_lock_day_name);
|
||
if (empty($res) && empty($get)) {
|
||
// FlashStorage::setCache($redis_lock_day_name, 1, 60 * 60 * 24);
|
||
//当前位置经纬度 经度:117.215637 纬度:39.1373367
|
||
//表中经纬度字段 经度:longitude 纬度:latitude
|
||
//查询距离小于10公里的门店
|
||
//如果没有 就返回空
|
||
$record = $this->distance($lat, $lng, $distance_num);
|
||
if (!empty($record)) {
|
||
try {
|
||
\Yii::$app->redis->geoadd($redis_name, $record[0]['lng'], $record[0]['lat'], $record[0]['id']);
|
||
} catch (\Exception $e) {
|
||
|
||
}
|
||
$id = $record[0]['id'];
|
||
$km = $record[0]['juli'] / 1000;
|
||
// 删除缓存键
|
||
FlashStorage::deleteCache($redis_lock_name);
|
||
}
|
||
} else {
|
||
$id = $res[0][0];
|
||
$km = round($res[0][1] / 1000, 2);
|
||
}
|
||
if (empty($id)) {
|
||
$data = [];
|
||
} else {
|
||
$find = Store::findOne([
|
||
'id' => $id,
|
||
]);
|
||
$data = [
|
||
'id' => $find->id,
|
||
'name' => $find->name,
|
||
'location_detail' => $find->location_detail,
|
||
'juli' => strval($km),
|
||
'lat' => $find['lat'],
|
||
'lng' => $find['lng']
|
||
];
|
||
}
|
||
return $this->apiReturnSuccess('ok', $data);
|
||
} catch (\Exception $e) {
|
||
return $this->apiReturnError($e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 门店距离
|
||
*/
|
||
public function distance($lat, $lng, $distance_num)
|
||
{
|
||
$sql = "select * from(
|
||
SELECT id,`name`,location_detail,lat,lng,
|
||
ROUND(6378.138*2*ASIN(SQRT(POW(SIN(($lat * PI()/180 - lat * PI()/180)/2),2) + COS($lat * PI()/180) * COS(lat * PI()/180) * POW(SIN(($lng * PI()/180- lng * PI()/180)/2),2))) * 1000) AS juli
|
||
FROM cx_store where is_delete = 0) as tmp_table_name
|
||
order by juli limit 1";
|
||
$query = (new Store())->find();
|
||
$query->sql = $sql;
|
||
$create = $query->createCommand();
|
||
$record = $create->queryAll();
|
||
return $record;
|
||
}
|
||
|
||
|
||
/**
|
||
* 门店服务列表
|
||
*/
|
||
public function storeGoodsList()
|
||
{
|
||
$goodsArr = [];
|
||
$goodsArr = Goods::find()->alias('goods')
|
||
->innerJoin(['goodsHub' => GoodsHub::tableName()], 'goods.goods_hub_id=goodsHub.id')
|
||
->select('goods.id,goods.price,goods.plugin_sign,goodsHub.name as goods_name,goodsHub.cover_pic,goodsHub.detail')
|
||
->andWhere([
|
||
'goods.is_delete' => 0,
|
||
])
|
||
->andWhere(['!=', 'goods.plugin_sign', SysConst::$cxPluginSceneMemberMall])
|
||
->asArray()->all();
|
||
if ($goodsArr) {
|
||
foreach ($goodsArr as $key => $value) {
|
||
|
||
$goodsArr[$key]['cover_pic'] = substr($value['cover_pic'], 0, 7) == 'http://' ? $value['cover_pic'] : SiteHelper::getFullUrl($value['cover_pic']);
|
||
// $goodsArr[$key]['cover_pic'] = SiteHelper::getFullUrl($value['cover_pic']);
|
||
}
|
||
}
|
||
return $this->apiReturnSuccess('ok', $goodsArr);
|
||
}
|
||
|
||
} |