添加根据经纬度获取城市

添加后台统计看板
This commit is contained in:
2025-12-26 16:26:15 +08:00
parent 028886c1fe
commit 6963216a85
9 changed files with 1668 additions and 8 deletions

View File

@@ -8,6 +8,9 @@ use think\facade\Config;
class CityService
{
// 腾讯地图API Key
private $tencentMapKey = 'EVOBZ-VX7YU-QKJVR-BVESA-AVFT3-7JBWG';
public function list()
{
$cacheKey = 'city_cache_keys';
@@ -25,4 +28,163 @@ class CityService
}
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
];
}
}