request->param('baseUrl', ''); if ($baseUrl !== '') { $this->tenantId = BaseController::getTenantIdByDomain($baseUrl); } $tid = $this->getTenantId(); if (empty($tid)) { return json([ 'code' => 400, 'msg' => '无法识别租户信息', 'list' => [], ]); } // param 合并 GET,避免个别环境下仅 get 取不到查询串 $cateId = (int) $this->request->param('cate', 0); $listPage = (int) $this->request->param('page', 0); $pageSizeReq = (int) $this->request->param('page_size', 0); // 点击左侧分类:文章 cate 可能挂在子分类上,需包含「该分类 + 其下所有子分类」id $categoryIdsForFilter = []; if ($cateId > 0) { $categoryIdsForFilter = $this->resolveCategoryBranchIds($cateId, $tid); if ($categoryIdsForFilter === []) { $categoryIdsForFilter = [$cateId]; } } $baseQuery = static function () use ($tid, $cateId, $categoryIdsForFilter) { $q = Articles::published() ->where('tid', $tid) ->where('delete_time', null); if ($cateId > 0 && $categoryIdsForFilter !== []) { $q->whereIn('cate', $categoryIdsForFilter); } return $q; }; // 当前租户下「全部」已发布新闻数(不受 cate 筛选影响) $totalTenantNews = (int) Articles::published() ->where('tid', $tid) ->where('delete_time', null) ->count(); // 当前列表条件下的总数:tid +(可选)cate,用于翻页总页数 = ceil(count / page_size) $countFiltered = (int) $baseQuery()->count(); $useListPagination = $listPage > 0 && $pageSizeReq > 0; if ($useListPagination) { // 新闻中心列表页:服务端分页;不要用查询参数名 page,避免与路由占位符冲突 $pageSizeReq = max(1, min($pageSizeReq, 50)); $listPage = max(1, $listPage); $articles = $baseQuery() ->order('publish_date', 'desc') ->page($listPage, $pageSizeReq) ->select(); } else { // 首页等:按 limit 取前 N 条(默认 8) $limit = (int) $this->request->param('limit', 8); if ($limit < 1) { $limit = 8; } if ($limit > 200) { $limit = 200; } $articles = $baseQuery() ->order('publish_date', 'desc') ->limit($limit) ->select(); } // 处理图片:如果文章 image 为空,则取分类的 image foreach ($articles as &$article) { if (empty($article['image']) && !empty($article['cate'])) { $category = ArticlesCategory::where('id', $article['cate']) ->where('delete_time', null) ->find(); if ($category && !empty($category['image'])) { $article['image'] = $category['image']; } } } unset($article); return json([ 'code' => 200, 'msg' => 'success', 'list' => $articles, // 当前租户下新闻总条数(全部状态为已发布) 'total' => $totalTenantNews, // 当前筛选(全部或某分类)下的条数,列表翻页按 count 与 page_size 计算 'count' => $countFiltered, ]); } /** * 解析分类筛选用的 id 列表:自身 + mete_articles_category 中 cid=该 id 的所有子孙(同 tid、未删除) */ private function resolveCategoryBranchIds(int $rootId, int $tid): array { if ($rootId <= 0 || $tid <= 0) { return []; } $root = ArticlesCategory::where('id', $rootId) ->where('tid', $tid) ->where('delete_time', null) ->find(); if (!$root) { return [$rootId]; } $ids = [$rootId]; $queue = [$rootId]; while ($queue !== []) { $pid = array_shift($queue); $children = ArticlesCategory::where('cid', $pid) ->where('tid', $tid) ->where('delete_time', null) ->column('id'); foreach ($children as $id) { $id = (int) $id; if ($id > 0 && !in_array($id, $ids, true)) { $ids[] = $id; $queue[] = $id; } } } return $ids; } /** * 获取新闻详情 * @param int $id 文章ID * @return Json */ public function getNewsDetail(int $id): Json { try { $baseUrl = $this->request->get('baseUrl', ''); if (!empty($baseUrl)) { $this->tenantId = BaseController::getTenantIdByDomain($baseUrl); } $tid = $this->getTenantId(); $query = Articles::published()->where('id', $id); if ($tid > 0) { $query->where('tid', $tid); } $article = $query->find(); if (!$article) { return json([ 'code' => 404, 'msg' => '文章不存在', 'list' => [], ]); } return json([ 'code' => 200, 'msg' => 'success', 'list' => $article, ]); } catch (\Exception $e) { return json([ 'code' => 500, 'msg' => '获取新闻详情失败:' . $e->getMessage(), 'list' => [], ]); } } /** * 获取上一篇下一篇 * @param int $id 文章ID * @param int $cate 分类ID * @return array */ private function getNextPreviousArticles(int $id, int $cate): array { $nextArticle = Articles::where('id', '<', $id) ->where('cate', $cate) ->where('delete_time', null) ->where('status', 2) ->field('id,title') ->find(); $previousArticle = Articles::where('id', '>', $id) ->where('cate', $cate) ->where('delete_time', null) ->where('status', 2) ->field('id,title') ->find(); return [ 'code' => 200, 'msg' => 'success', 'next' => $nextArticle, 'previous' => $previousArticle, ]; } /** * 通过分类 ID 获取分类名称 * @param int $cateId 分类ID * @return string */ private function getCategoryName(int $id): string { $categoryInfo = ArticlesCategory::where('id', $id) ->where('delete_time', null) ->find(); if (!$categoryInfo) { return '未分类'; } return $categoryInfo['name']; } /** * 获取相关文章 */ private function getRelatedArticles(int $id, int $cate): array { $articles = Articles::where('id', '<>', $id) ->where('cate', $cate) ->where('delete_time', null) ->where('status', 2) ->order('top', 'desc') ->order('recommend', 'desc') ->order('sort', 'desc') ->order('id', 'desc') ->limit(5) ->select(); foreach ($articles as &$article) { $article['cate'] = $this->getCategoryName($article['cate']); } return [ 'code' => 200, 'msg' => 'success', 'list' => $articles, ]; } }