190 lines
5.5 KiB
PHP
190 lines
5.5 KiB
PHP
<?php
|
||
|
||
namespace app\api\server;
|
||
|
||
use think\Db;
|
||
use think\facade\Cache;
|
||
use think\facade\Config;
|
||
|
||
class CityService
|
||
{
|
||
// 腾讯地图API Key
|
||
// private $tencentMapKey = 'EVOBZ-VX7YU-QKJVR-BVESA-AVFT3-7JBWG';
|
||
private $tencentMapKey = '66NBZ-KH3W4-7QSUS-K5OBA-7P552-F7F6T';
|
||
|
||
public function list()
|
||
{
|
||
$cacheKey = 'city_cache_keys';
|
||
if (Cache::store('redis')->has($cacheKey)) {
|
||
return Cache::store('redis')->get($cacheKey);
|
||
}
|
||
//查询市级名称
|
||
$data = Db::name('dev_region')
|
||
->order('id', 'asc')
|
||
->field('id,parent_id,name')
|
||
->where('level',1)
|
||
->select();
|
||
if ($data) {
|
||
Cache::store('redis')->set($cacheKey, $data);
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
/**
|
||
* 根据经纬度获取所在城市
|
||
* @param float $lat 纬度
|
||
* @param float $lng 经度
|
||
* @return array
|
||
*/
|
||
public function getCityByLocation($lat, $lng)
|
||
{
|
||
// 参数验证
|
||
if (empty($lat) || empty($lng)) {
|
||
return [
|
||
'success' => false,
|
||
'msg' => '经纬度参数不能为空',
|
||
'data' => null
|
||
];
|
||
}
|
||
|
||
// 验证经纬度范围
|
||
if (!is_numeric($lat) || !is_numeric($lng)) {
|
||
return [
|
||
'success' => false,
|
||
'msg' => '经纬度格式错误',
|
||
'data' => null
|
||
];
|
||
}
|
||
|
||
$lat = floatval($lat);
|
||
$lng = floatval($lng);
|
||
|
||
if ($lat < -90 || $lat > 90 || $lng < -180 || $lng > 180) {
|
||
return [
|
||
'success' => false,
|
||
'msg' => '经纬度范围错误',
|
||
'data' => null
|
||
];
|
||
}
|
||
|
||
// 生成缓存key
|
||
$cacheKey = 'city_location_' . md5($lat . '_' . $lng);
|
||
|
||
// 尝试从缓存获取
|
||
if (Cache::store('redis')->has($cacheKey)) {
|
||
$cachedData = Cache::store('redis')->get($cacheKey);
|
||
return [
|
||
'success' => true,
|
||
'msg' => '获取成功',
|
||
'data' => $cachedData
|
||
];
|
||
}
|
||
|
||
// 调用腾讯地图逆地理编码API
|
||
$apiUrl = 'https://apis.map.qq.com/ws/geocoder/v1/';
|
||
$params = [
|
||
'location' => $lat . ',' . $lng,
|
||
'key' => $this->tencentMapKey,
|
||
'get_poi' => 0
|
||
];
|
||
|
||
$url = $apiUrl . '?' . http_build_query($params);
|
||
|
||
// 使用curl请求
|
||
$ch = curl_init();
|
||
curl_setopt($ch, CURLOPT_URL, $url);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||
|
||
$response = curl_exec($ch);
|
||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||
$error = curl_error($ch);
|
||
curl_close($ch);
|
||
|
||
if ($error) {
|
||
return [
|
||
'success' => false,
|
||
'msg' => '请求失败:' . $error,
|
||
'data' => null
|
||
];
|
||
}
|
||
|
||
if ($httpCode !== 200) {
|
||
return [
|
||
'success' => false,
|
||
'msg' => 'API请求失败,HTTP状态码:' . $httpCode,
|
||
'data' => null
|
||
];
|
||
}
|
||
|
||
$result = json_decode($response, true);
|
||
|
||
if (empty($result) || $result['status'] !== 0) {
|
||
return [
|
||
'success' => false,
|
||
'msg' => isset($result['message']) ? $result['message'] : '获取城市信息失败',
|
||
'data' => null
|
||
];
|
||
}
|
||
|
||
// 解析返回数据
|
||
$addressComponent = $result['result']['address_component'] ?? [];
|
||
$cityName = $addressComponent['city'] ?? '';
|
||
$provinceName = $addressComponent['province'] ?? '';
|
||
$districtName = $addressComponent['district'] ?? '';
|
||
$adcode = $addressComponent['adcode'] ?? '';
|
||
|
||
// 如果城市名称为空,尝试使用区县名称
|
||
if (empty($cityName) && !empty($districtName)) {
|
||
$cityName = $districtName;
|
||
}
|
||
|
||
// 查询数据库中的城市ID
|
||
$cityId = null;
|
||
$cityInfo = null;
|
||
|
||
if (!empty($cityName)) {
|
||
// 先尝试精确匹配
|
||
$cityInfo = Db::name('dev_region')
|
||
->where('name', $cityName)
|
||
->where('level', 2) // 市级
|
||
->find();
|
||
|
||
// 如果精确匹配失败,尝试模糊匹配
|
||
if (empty($cityInfo)) {
|
||
$cityInfo = Db::name('dev_region')
|
||
->where('name', 'like', '%' . $cityName . '%')
|
||
->where('level', 2)
|
||
->find();
|
||
}
|
||
|
||
if ($cityInfo) {
|
||
$cityId = $cityInfo['id'];
|
||
}
|
||
}
|
||
|
||
$data = [
|
||
'city_name' => $cityName,
|
||
'province_name' => $provinceName,
|
||
'district_name' => $districtName,
|
||
'adcode' => $adcode,
|
||
'city_id' => $cityId,
|
||
'city_info' => $cityInfo,
|
||
'formatted_address' => $result['result']['formatted_addresses']['recommend'] ?? '',
|
||
'location' => [
|
||
'lat' => $lat,
|
||
'lng' => $lng
|
||
]
|
||
];
|
||
|
||
// 缓存结果(缓存1小时)
|
||
Cache::store('redis')->set($cacheKey, $data, 3600);
|
||
return [
|
||
'success' => true,
|
||
'msg' => '获取成功',
|
||
'data' => $data
|
||
];
|
||
}
|
||
} |