where('parent_id', $params['parent_id']); } if (!empty($params['level'])) { $query->where('level', $params['level']); } if (!empty($params['keyword'])) { $query->where(function ($q) use ($params) { $q->where('name', 'like', '%' . $params['keyword'] . '%') ->orWhere('code', 'like', '%' . $params['keyword'] . '%') ->orWhere('pinyin', 'like', '%' . $params['keyword'] . '%'); }); } if (isset($params['status']) && $params['status'] !== '') { $query->where('status', $params['status']); } $query->orderBy('sort')->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::where('status', true)->orderBy('sort')->get()); } public function getChildren(int $parentId): array { return City::where('parent_id', $parentId) ->where('status', true) ->orderBy('sort') ->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 getByPinyin(string $pinyin): array { return City::where('pinyin', 'like', '%' . $pinyin . '%') ->where('status', true) ->get() ->toArray(); } public function create(array $data): City { Validator::make($data, [ 'name' => 'required|string|max:100', 'code' => 'required|string|max:50|unique:system_cities,code', 'level' => 'required|integer|in:1,2,3', 'parent_id' => 'sometimes|exists:system_cities,id', ])->validate(); $city = City::create($data); $this->clearCache(); return $city; } public function update(int $id, array $data): City { $city = City::findOrFail($id); Validator::make($data, [ 'name' => 'sometimes|required|string|max:100', 'code' => 'sometimes|required|string|max:50|unique:system_cities,code,' . $id, 'level' => 'sometimes|required|integer|in:1,2,3', 'parent_id' => 'sometimes|exists:system_cities,id', ])->validate(); $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 batchUpdateStatus(array $ids, bool $status): bool { City::whereIn('id', $ids)->update(['status' => $status]); $this->clearCache(); return true; } private function buildTree(array $cities, int $parentId = 0): array { $tree = []; foreach ($cities as $city) { if ($city['parent_id'] == $parentId) { $children = $this->buildTree($cities, $city['id']); 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 City::where('level', 1) ->where('status', true) ->orderBy('sort') ->get() ->toArray(); } public function getCities(int $provinceId): array { return City::where('parent_id', $provinceId) ->where('level', 2) ->where('status', true) ->orderBy('sort') ->get() ->toArray(); } public function getDistricts(int $cityId): array { return City::where('parent_id', $cityId) ->where('level', 3) ->where('status', true) ->orderBy('sort') ->get() ->toArray(); } }