Files
duolamaojiazhen/application/api/server/CityService.php
2026-01-01 15:19:18 +08:00

190 lines
5.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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
];
}
}