283 lines
8.5 KiB
PHP
283 lines
8.5 KiB
PHP
<?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,
|
|
];
|
|
}
|
|
|
|
}
|