1], [['limit'], 'default', 'value' => 12], ['option', function ($attr, $params) { $data = Json::decode($this->option); if (!$data) { $this->addError($attr, "{$attr}数据格式错误。"); } $this->option = $data; }], ['option', function ($attr, $params) { if (!is_array($this->option)) { $this->addError($attr, "{$attr}必须是一个数组。"); return; } foreach ($this->option as $key => $opt) { if (!isset($opt['name']) || !isset($opt['value'])) { $this->addError($attr, "{$attr}[{$key}]['name']或{$attr}[{$key}]['value']不存在。"); return; } } }], ]; } public function list() { if (!$this->validate()) { return [ 'code' => 1, 'msg' => $this->getErrorSummary(false)[0] ]; } $query = Store::find()->where(['is_delete' => 0, 'is_alliance' => 1]); if ($this->keyword) { $query->andWhere(['like', 'name', $this->keyword]); } if ($this->common_cat_id > 0) { $query->andWhere(['like', 'category_id', $this->common_cat_id]); } if ($this->city_id) { $query->andWhere(['city_id' => $this->city_id]); } if ($this->district_id) { $query->andWhere(['district_id' => $this->district_id]); } if (is_array($this->option)) { foreach ($this->option as $choose) { $query->andWhere("JSON_CONTAINS(info,JSON_OBJECT('name',\"{$choose['name']}\"))") ->andWhere("JSON_CONTAINS(info, JSON_OBJECT('list',JSON_ARRAY(\"{$choose['value']}\")))"); } } //供应链排除独立运行的店铺 if (\Yii::$app->prod_is_dandianpu()) { $filter_store_id = Option::find()->where(['name' => 'self_mini', 'value' => 1])->select('store_id')->column(); $query->andWhere(['NOT IN', 'id', $filter_store_id]); } $latitude = $this->latitude ?: 0; $longitude = $this->longitude ?: 0; $query->select(['id', 'name', 'logo', 'coordinate', 'created_at', 'category_id', 'tags', 'sales', 'rank', 'per_spend', 'address', 'distance' => "acos(cos({$latitude}*pi()/180 )*cos(latitude*pi()/180)*cos({$longitude}*pi()/180 -longitude*pi()/180)+sin({$latitude}*pi()/180 )*sin(latitude*pi()/180))*6370996.81"]); // 0:默认排序 1:距离优先 2:好评优先 3:销量优先 4:低价优先 5:高价优先 if (empty($this->sort_type)) { // $list = $query->orderBy('created_at desc')->asArray()->all(); $list = $query->orderBy('distance asc')->asArray()->all(); } if ($this->sort_type == 2) { $list = $query->orderBy('rank desc')->asArray()->all(); } if ($this->sort_type == 3) { $list = $query->orderBy('sales desc')->asArray()->all(); } if ($this->sort_type == 4) { $list = $query->orderBy('per_spend asc')->asArray()->all(); } if ($this->sort_type == 5) { $list = $query->orderBy('per_spend desc')->asArray()->all(); } if (empty($list)) { $list = $query->asArray()->all(); } $distance = array(); if (!empty($this->sort_type)) { foreach ($list as $index => $item) { $list[$index]['distance'] = -1; if (!empty($item['coordinate'])) { list($lati, $long) = explode(',', $item['coordinate']); if ($long && $this->longitude) { $from = [$this->longitude, $this->latitude]; $to = [$long, $lati]; $list[$index]['distance'] = $this->get_distance($from, $to, false, 2); if ((($list[$index]['distance'] > $this->distance) && $this->distance > 0) || $list[$index]['distance'] == -1){ unset($list[$index]); continue; } } } $distance[] = $list[$index]['distance']; // if ($list[$index]['distance'] == -1){ // unset($list[$index]); // } else { // $distance[] = $list[$index]['distance']; // } } } if ($this->sort_type == 1) { $list = array_values($list); array_multisort($distance, SORT_ASC, $list); } $data = array_slice($list, ($this->page - 1) * $this->limit, $this->limit); foreach ($data as $index => $item) { $list[$index]['distance'] = -1; $data[$index]['goods_list'] = $this->goods_list($item); if ($this->distance($item['distance']) != -1) { $data[$index]['distance'] = '距离' . $this->distance($item['distance']); } else { $data[$index]['distance'] = ''; } $data[$index]['tags'] = !empty($item['tags']) ? Json::decode($item['tags']) : []; } $res = [ 'list' => $data, 'page_count' => ceil(count($list) / $this->limit), 'row_count' => count($list) ]; return [ 'code' => 0, 'msg' => 'success', 'data' => $res ]; } /** * 获取当前定位信息 */ private function locationInfo() { $tencent_map_key = Option::get('tencent_map_key', 0, 'saas', '')['value']; if (get_store_id() > 0) { $tencent_map_key = Option::get(OptionSetting::TENCENT_MAP_KEY, get_store_id(), 'pay', Option::get(OptionSetting::TENCENT_MAP_KEY, get_store_id(), 'store', '')['value'] ?: $tencent_map_key)['value']; } $place_url = 'https://apis.map.qq.com/ws/geocoder/v1/?location=' . $this->latitude . ',' . $this->longitude . '&key=' . $tencent_map_key; $json_place = file_get_contents($place_url); $place_arr = Json::decode($json_place); if ($place_arr && isset($place_arr['result'])) { $address = $place_arr['result']['ad_info']; $city = District::find()->select('id, name')->where(['name' => $address['city']])->one(); $district_list = District::find()->select('id, name')->where(['parent_id' => $city['id']])->asArray()->all(); $data['city'] = $city; $data['district_list'] = $district_list; $data['address'] = $address; $data['detail'] = $place_arr['result']['formatted_addresses']['recommend']; return [ 'code' => 0, 'msg' => '定位成功', 'data' => $data ]; } else { return [ 'code' => 1, 'msg' => '定位失败' ]; } } public function config() { if (!$this->validate()) { return [ 'code' => 1, 'msg' => $this->getErrorSummary(false)[0] ]; } $location = $this->locationInfo(); if ($location['code'] > 0) { return $location; } $data = [ 'code' => 0, 'msg' => 'success', 'data' => [ 'location' => $location['data'] ] ]; $saas_category = SaasCategory::find()->where(['is_delete' => 0])->orderBy('sort DESC')->asArray()->all(); $category_data = []; foreach ($saas_category as $category) { $category_data[] = [ 'cat_num' => Store::find()->where(['is_delete' => 0, 'category_id' => $category['id']])->count(), 'common_cat_id' => $category['id'], 'cat_name' => $category['name'], 'pic' => $category['icon'], 'config' => Json::decode($category['option']) ]; } $data['data']['search'] = $category_data; $data['data']['banner'] = Banner::find()->andWhere(['is_delete' => 0, 'type' => Banner::TYPE_SAAS])->select('pic_url, title, page_url, open_type')->orderBy('sort ASC')->asArray()->all(); return $data; } /** * 根据起点坐标和终点坐标测距离 * @param [array] $from [起点坐标(经纬度),例如:array(118.012951,36.810024)] * @param [array] $to [终点坐标(经纬度)] * @param [bool] $km 是否以公里为单位 false:米 true:公里(千米) * @param [int] $decimal 精度 保留小数位数 * @return [string] 距离数值 */ public function get_distance($from, $to, $km = true, $decimal = 2) { sort($from); sort($to); $EARTH_RADIUS = 6370.996; // 地球半径系数 $distance = $EARTH_RADIUS * 2 * asin(sqrt(pow(sin(($from[0] * pi() / 180 - $to[0] * pi() / 180) / 2), 2) + cos($from[0] * pi() / 180) * cos($to[0] * pi() / 180) * pow(sin(($from[1] * pi() / 180 - $to[1] * pi() / 180) / 2), 2))) * 1000; if ($km) { $distance = $distance / 1000; } return round($distance, $decimal); } private static function distance($distance) { if ($distance == -1) { return -1; } if ($distance > 1000) { $distance = round($distance / 1000, 2) . 'km'; } else { if ($distance <= 0) { $distance = '0m'; } else { $distance .= 'm'; } } return $distance; } private function goods_list($params){ if ($params['category_id'] == 1) { $goods_list = FoodGoods::find()->where(['store_id' => $params['id'], 'is_delete' => 0])->select(['name', 'JSON_UNQUOTE(JSON_EXTRACT(cover_pic, \'$[0].url\')) as pic', 'price', 'original_price'])->orderBy('virtual_sales desc, sort desc')->limit(6)->asArray()->all(); } else { $goods_list = Goods::find()->where(['store_id' => $params['id'], 'is_delete' => 0, 'status' => 1])->select(['name', 'price', 'original_price', 'cover_pic'])->orderBy('virtual_sales desc, sort desc')->limit(6)->asArray()->all(); } return $goods_list; } public function sales() { // 上月第一天 // $last_month_first_day = strtotime(date('Y-m-01') . ' -1 month'); // 上月最后一天 // $last_month_last_day = strtotime(date('Y-m-01') . ' -1 day'); // 本月第一天 $start_time = strtotime(date("Y-m-01")); // 当前时间 $end_time = time(); $stores = Store::findAll(['is_delete' => 0]); if ($stores) { foreach ($stores as $store) { $cache_key = 'cache_store_sales_num_' . $store->id; // 点餐 if ($store->category_id == 1) { $count = FoodOrder::find()->where(['is_pay' => 1, 'store_id' => $store->id])->andWhere(['>=', 'created_at', $start_time])->andWhere(['<=', 'created_at', $end_time])->count(); cache()->set($cache_key, $count); } else { $normal_count = Order::find()->where(['is_pay' => 1, 'store_id' => $store->id])->andWhere(['>=', 'created_at', $start_time])->andWhere(['<=', 'created_at', $end_time])->count(); $scan_count = \app\plugins\scanCodePay\models\Order::find()->where(['is_pay' => 1, 'store_id' => $store->id])->andWhere(['>=', 'created_at', $start_time])->andWhere(['<=', 'created_at', $end_time])->count(); cache()->set($cache_key, $normal_count + $scan_count); } // var_dump(cache()->get($cache_key)); } } exit(); } }