tp/app/index/controller/Article/NewsCenterController.php

283 lines
8.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
declare(strict_types=1);
namespace app\index\controller\Article;
use app\index\BaseController;
use Symfony\Component\VarDumper\VarDumper;
use think\exception\ValidateException;
use think\facade\Request;
use think\facade\Session;
use think\response\Json;
use think\db\exception\DbException;
use app\model\Cms\Articles;
use app\model\Cms\ArticlesCategory;
use tidy;
class NewsCenterController extends BaseController
{
/**
* 根据域名获取新闻数据
*
* 返回字段list 列表total 当前租户下已发布新闻总数count 当前筛选(全部或 cate下的条数翻页按 count 与 page_size。
*
* @return Json
*/
public function getCenterNews(): Json
{
$baseUrl = (string) $this->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,
];
}
}