Files
laravel_swoole/app/Services/System/CityService.php
2026-02-19 10:39:38 +08:00

238 lines
5.9 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\Services\System;
use App\Models\System\City;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Validator;
class CityService
{
public function getList(array $params): array
{
$query = City::query();
if (!empty($params['parent_code'])) {
$query->where('parent_code', $params['parent_code']);
}
if (!empty($params['keyword'])) {
$query->where(function ($q) use ($params) {
$q->where('title', 'like', '%' . $params['keyword'] . '%')
->orWhere('code', 'like', '%' . $params['keyword'] . '%');
});
}
$query->orderBy('id');
$pageSize = $params['page_size'] ?? 20;
$list = $query->paginate($pageSize);
return [
'list' => $list->items(),
'total' => $list->total(),
'page' => $list->currentPage(),
'page_size' => $list->perPage(),
];
}
public function getTree(): array
{
return $this->buildTree(City::orderBy('id')->get());
}
public function getChildren(string $parentCode): array
{
return City::where('parent_code', $parentCode)
->orderBy('id')
->get()
->toArray();
}
public function getByCode(string $code): ?City
{
return City::where('code', $code)->first();
}
public function getById(int $id): ?City
{
return City::find($id);
}
public function create(array $data): City
{
Validator::make($data, [
'title' => 'required|string|max:100',
'code' => 'required|string|max:50|unique:system_city,code',
'parent_code' => 'sometimes|nullable|exists:system_city,code',
])->validate();
$city = City::create($data);
$this->clearCache();
return $city;
}
public function update(int $id, array $data): City
{
$city = City::findOrFail($id);
Validator::make($data, [
'title' => 'sometimes|required|string|max:100',
'code' => 'sometimes|required|string|max:50|unique:system_city,code,' . $id,
'parent_code' => 'sometimes|nullable|exists:system_city,code',
])->validate();
// 防止循环引用
if (isset($data['parent_code']) && $data['parent_code'] === $city->code) {
throw new \Exception('不能将城市设置为自己的子级');
}
$city->update($data);
$this->clearCache();
return $city;
}
public function delete(int $id): bool
{
$city = City::findOrFail($id);
if ($city->children()->exists()) {
throw new \Exception('该城市下有子级数据,不能删除');
}
$city->delete();
$this->clearCache();
return true;
}
public function batchDelete(array $ids): bool
{
City::whereIn('id', $ids)->delete();
$this->clearCache();
return true;
}
/**
* 获取所有顶级城市(省/直辖市/自治区)
*/
public function getTopLevel(): array
{
return City::whereNull('parent_code')
->orderBy('id')
->get()
->toArray();
}
/**
* 根据父级编码获取城市
*/
public function getByParentCode(string $parentCode): array
{
return City::where('parent_code', $parentCode)
->orderBy('id')
->get()
->toArray();
}
/**
* 获取城市的完整路径(从顶级到当前)
*/
public function getPath(string $code): array
{
$path = [];
$city = $this->getByCode($code);
while ($city) {
array_unshift($path, $city);
$city = $city->parent;
}
return $path;
}
/**
* 获取城市的所有子孙
*/
public function getDescendants(string $code): array
{
$descendants = [];
$this->collectDescendants($code, $descendants);
return $descendants;
}
private function collectDescendants(string $parentCode, array &$result): void
{
$children = City::where('parent_code', $parentCode)->get();
foreach ($children as $child) {
$result[] = $child;
$this->collectDescendants($child->code, $result);
}
}
private function buildTree($cities, string $parentCode = ''): array
{
$tree = [];
foreach ($cities as $city) {
if ($city->parent_code == $parentCode) {
$children = $this->buildTree($cities, $city->code);
if (!empty($children)) {
$city['children'] = $children;
}
$tree[] = $city;
}
}
return $tree;
}
private function clearCache(): void
{
Cache::forget('system:cities:tree');
}
public function getCachedTree(): array
{
$cacheKey = 'system:cities:tree';
$tree = Cache::get($cacheKey);
if ($tree === null) {
$tree = $this->getTree();
Cache::put($cacheKey, $tree, 3600);
}
return $tree;
}
/**
* 获取省份(兼容旧接口)
*/
public function getProvinces(): array
{
return $this->getTopLevel();
}
/**
* 获取城市(兼容旧接口)
*/
public function getCities(int $provinceId): array
{
// 由于新结构使用code关联这里需要根据id找到对应的code
$province = City::find($provinceId);
if (!$province) {
return [];
}
return $this->getByParentCode($province->code);
}
/**
* 获取区县(兼容旧接口)
*/
public function getDistricts(int $cityId): array
{
$city = City::find($cityId);
if (!$city) {
return [];
}
return $this->getByParentCode($city->code);
}
}