|
@@ -53,33 +53,87 @@ class NewsService implements NewsServiceInterface
|
|
|
*/
|
|
|
public function getCategoryList(array $data): array
|
|
|
{
|
|
|
- $page = (int) $data['page'] ?? 1;
|
|
|
- $perPage = (int) $data['pageSize'] ?? 10;
|
|
|
$search = $data['name'] ?? '';
|
|
|
- // 查找所有匹配的分类
|
|
|
- $matchedCategories = $this->findMatchedCategories($search);
|
|
|
- // 查找所有匹配分类的父级分类
|
|
|
- $allRequiredCategories = $this->findAllParents($matchedCategories);
|
|
|
- // 提取一级分类
|
|
|
- $topLevelCategories = [];
|
|
|
- foreach ($allRequiredCategories as $category) {
|
|
|
- if ($category->pid === 0) {
|
|
|
- $topLevelCategories[] = $category;
|
|
|
+ $page = (int)($data['page'] ?? 1);
|
|
|
+ $perPage = (int)($data['pageSize'] ?? 10);
|
|
|
+
|
|
|
+ // 1. 查出所有匹配的分类id
|
|
|
+ if ($search) {
|
|
|
+ $matchedIds = Category::where('name', 'like', "%{$search}%")->pluck('id')->toArray();
|
|
|
+ if (empty($matchedIds)) {
|
|
|
+ return Result::success(['rows' => [], 'total' => 0]);
|
|
|
+ }
|
|
|
+ // 2. 递归查所有父级,直到一级分类
|
|
|
+ $idsStr = implode(',', $matchedIds);
|
|
|
+ $sql = "
|
|
|
+ WITH RECURSIVE parents AS (
|
|
|
+ SELECT * FROM category WHERE id IN ($idsStr)
|
|
|
+ UNION ALL
|
|
|
+ SELECT c.* FROM category c
|
|
|
+ INNER JOIN parents p ON c.id = p.pid
|
|
|
+ )
|
|
|
+ SELECT * FROM parents
|
|
|
+ ";
|
|
|
+ $parents = Db::select($sql);
|
|
|
+ $parentIds = [];
|
|
|
+ foreach ($parents as $row) {
|
|
|
+ if ($row->pid == 0) {
|
|
|
+ $parentIds[] = $row->id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $parentIds = array_unique($parentIds);
|
|
|
+ } else {
|
|
|
+ // 没有搜索,一级分类就是根
|
|
|
+ $parentIds = Category::where('pid', 0)->pluck('id')->toArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 一级分类分页
|
|
|
+ $total = count($parentIds);
|
|
|
+ $parentIds = array_slice($parentIds, ($page - 1) * $perPage, $perPage);
|
|
|
+ if (empty($parentIds)) {
|
|
|
+ return Result::success(['rows' => [], 'total' => $total]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 递归查所有子孙
|
|
|
+ $idsStr = implode(',', $parentIds);
|
|
|
+ $sql = "
|
|
|
+ WITH RECURSIVE subcategories AS (
|
|
|
+ SELECT * FROM category WHERE id IN ($idsStr)
|
|
|
+ UNION ALL
|
|
|
+ SELECT c.* FROM category c
|
|
|
+ INNER JOIN subcategories s ON c.pid = s.id
|
|
|
+ )
|
|
|
+ SELECT * FROM subcategories ORDER BY updated_at DESC
|
|
|
+ ";
|
|
|
+ $allCategories = Db::select($sql);
|
|
|
+
|
|
|
+ // 5. 组装树结构
|
|
|
+ $categoryMap = [];
|
|
|
+ foreach ($allCategories as $cat) {
|
|
|
+ $cat = (array)$cat;
|
|
|
+ $cat['children'] = [];
|
|
|
+ $categoryMap[$cat['id']] = $cat;
|
|
|
+ }
|
|
|
+ foreach ($categoryMap as $id => &$cat) {
|
|
|
+ if ($cat['pid'] && isset($categoryMap[$cat['pid']])) {
|
|
|
+ $categoryMap[$cat['pid']]['children'][] = &$cat;
|
|
|
}
|
|
|
}
|
|
|
- // 分页处理
|
|
|
- $offset = ($page - 1) * $perPage;
|
|
|
- $paginatedTopLevelCategories = array_slice($topLevelCategories, $offset, $perPage);
|
|
|
+ unset($cat);
|
|
|
+
|
|
|
$categoryTree = [];
|
|
|
- foreach ($paginatedTopLevelCategories as $category) {
|
|
|
- $categoryTree[] = $this->buildCategoryTree($category, $allRequiredCategories);
|
|
|
+ foreach ($parentIds as $id) {
|
|
|
+ if (isset($categoryMap[$id])) {
|
|
|
+ $categoryTree[] = $categoryMap[$id];
|
|
|
+ }
|
|
|
}
|
|
|
- $return = [
|
|
|
+
|
|
|
+ return Result::success([
|
|
|
'rows' => $categoryTree,
|
|
|
- 'total' => count($topLevelCategories),
|
|
|
- ];
|
|
|
- return Result::success($return);
|
|
|
+ 'total' => $total,
|
|
|
+ ]);
|
|
|
}
|
|
|
+
|
|
|
private function findMatchedCategories($search)
|
|
|
{
|
|
|
if ($search) {
|