401 lines
14 KiB
PHP
401 lines
14 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\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();
|
||
}
|
||
|
||
/*if (!is_numeric($lat) || !is_numeric($lng)) {
|
||
return $this->apiReturnError('位置信息错误');
|
||
}
|
||
if (empty($lat) || empty($lng)) {
|
||
return $this->apiReturnError('位置信息不能为空');
|
||
}*/
|
||
|
||
$where = ['status' => 1, '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,location_detail,lat,lng,begin_time,end_time,status');
|
||
|
||
$count_query = clone $query;
|
||
$count = $count_query->count();
|
||
|
||
if (empty($this->limit)) {
|
||
$this->limit = 10;
|
||
}
|
||
if (empty($this->page)) {
|
||
$this->page = 1;
|
||
}
|
||
/*if (!$this->limit) {
|
||
$this->limit = $count;
|
||
$this->pageCount = $this->page;
|
||
$list = $query->orderBy(['sort' => SORT_DESC])->asArray()->all();
|
||
} else {
|
||
|
||
}*/
|
||
$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']);
|
||
}
|
||
$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
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 门店信息
|
||
* @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,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();
|
||
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']);
|
||
}
|
||
// $coachData = [];
|
||
// $coachData = Coach::find()->alias('c')
|
||
// ->innerJoin(['rt' => User::tableName()], 'c.user_id=rt.id')
|
||
// ->select('c.id as coach_id,c.title,c.content,c.coach_photo,c.qualification,rt.real_name,c.number,c.desc')
|
||
// ->andWhere([
|
||
// 'c.store_id' => $this->store_id,
|
||
// 'c.is_delete' => 0,
|
||
// 'c.status' => 1
|
||
// ])
|
||
// ->asArray()->all();
|
||
// foreach ($coachData as $key => $value) {
|
||
// $coachData[$key]['coach_photo'] = empty($value['coach_photo']) ? '' : SiteHelper::getFullUrl($value['coach_photo']);
|
||
// $coachData[$key]['qualification'] = empty($value['qualification']) ? '' : SiteHelper::getFullUrl($value['qualification']);
|
||
// $coachData[$key]['content'] = str_replace("/upload/0/1/upload/image", \Yii::$app->request->getHostInfo() . "/upload/0/1/upload/image", $coachData[$key]['content']);
|
||
// }
|
||
// $storeData['content'] = str_replace("/upload/0/1/upload/image", \Yii::$app->request->getHostInfo() . "/upload/0/1/upload/image", $storeData['content']);
|
||
// $storeData['coach_data'] = $coachData;
|
||
return $this->apiReturnSuccess('ok', $storeData);
|
||
}
|
||
|
||
/**
|
||
* 教练信息
|
||
*/
|
||
public function coachInfo()
|
||
{
|
||
if (!$this->coach_id) {
|
||
return [
|
||
'code' => 1,
|
||
'msg' => '教练ID不能为空'
|
||
];
|
||
}
|
||
$query = Coach::find()
|
||
->select('id,title,content,coach_photo,qualification,number,user_id')
|
||
->where(['id' => $this->coach_id, 'status' => 1])->asArray()->one();
|
||
if (!$query) {
|
||
return $this->apiReturnSuccess('ok', []);
|
||
}
|
||
$coachArr = User::findOne(['id' => $query['user_id']]);
|
||
$query['real_name'] = $coachArr['real_name'];
|
||
$query['coach_photo'] = SiteHelper::getFullUrl($query['coach_photo']);
|
||
$query['content'] = str_replace("", \Yii::$app->request->getHostInfo() . "/upload/", $query['content']);
|
||
return $this->apiReturnSuccess('ok', $query);
|
||
}
|
||
|
||
|
||
/**
|
||
* 门店选择-绑定门店
|
||
* @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)
|
||
{
|
||
//保留用户购买的门店 有购买的门店 优先显示已购买门店 没有显示距离最近门店
|
||
if (empty($lat) || empty($lng)) {
|
||
return $this->apiReturnError('位置信息不能为空');
|
||
}
|
||
$distance_num = 100000; # 距离 米
|
||
if ($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])
|
||
->select('id,name,province,province_id,city,city_id,region,region_id,location_detail,lat,lng,begin_time,end_time,status')->asArray()->one();
|
||
$list['begin_time'] = date('Y-m-d H:i:s', $list['begin_time']);
|
||
$list['end_time'] = date('Y-m-d H:i:s', $list['end_time']);
|
||
$list['distance'] = GetDistance::getDistance($lat, $lng, $list['lat'], $list['lng']);
|
||
$list['distance'] = str_replace('km', '', $list['distance']); // 转成浮点类型,去除km
|
||
$data = [
|
||
'id' => $list['id'],
|
||
'name' => $list['name'],
|
||
'location_detail' => $list['location_detail'],
|
||
'juli' => $list['distance'],
|
||
'lat' => $list['lat'],
|
||
'lng' => $list['lng']
|
||
];
|
||
return $this->apiReturnSuccess('ok', $data);
|
||
} else {
|
||
$record = $this->distance($lat, $lng, $distance_num);
|
||
$data = empty($record) ? [] : $record[0];
|
||
if ($data) {
|
||
$user->store_id = $data['id'];
|
||
if (!$user->save()) {
|
||
return [
|
||
'code' => 1,
|
||
'msg' => '附近无门店'
|
||
];
|
||
}
|
||
}
|
||
//转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,
|
||
'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) 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'] = SiteHelper::getFullUrl($value['cover_pic']);
|
||
}
|
||
}
|
||
return $this->apiReturnSuccess('ok', $goodsArr);
|
||
}
|
||
|
||
} |