644 lines
22 KiB
PHP
Executable File
644 lines
22 KiB
PHP
Executable File
<?php
|
||
|
||
namespace app\model;
|
||
|
||
use think\model\relation\HasOne;
|
||
use think\Paginator;
|
||
|
||
class Article extends Base
|
||
{
|
||
public const STATUS_NORMAL = 1; // 正常
|
||
public const STATUS_DISABLE = 0; // 禁用
|
||
|
||
// 文章属性(默认)
|
||
protected static $defaultAttributeList = [
|
||
'top' => '置顶',
|
||
'hot' => '热门',
|
||
'recommend' => '推荐',
|
||
];
|
||
|
||
/**
|
||
* 栏目
|
||
* @return HasOne
|
||
*/
|
||
public function archivesCategory(): HasOne
|
||
{
|
||
return $this->hasOne(Category::class, 'id', 'category_id');
|
||
}
|
||
|
||
|
||
public static function getAttributeList(array $categoryIds = [])
|
||
{
|
||
$data = [];
|
||
$recommendCategoryList = [];
|
||
if (count(array_intersect($categoryIds, $recommendCategoryList)) > 0) {
|
||
$data['recommend'] = '推荐';
|
||
}
|
||
|
||
// 新闻动态
|
||
$communityCategoryIds = Category::getCategoryWithChildrenIds(Category::CATEGORY_NEWS);
|
||
if (count(array_intersect($categoryIds, $communityCategoryIds)) > 0) {
|
||
$data['top'] = '置顶';
|
||
$data['hot'] = '热门';
|
||
$data['recommend'] = '推荐';
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
/*********************************************
|
||
* 分割线
|
||
*********************************************/
|
||
|
||
|
||
//获取最高访问的文章列表
|
||
public static function getMostVisited($limit = 5)
|
||
{
|
||
if ($limit <= 0) {
|
||
$limit = 5;
|
||
}
|
||
return self::with(["archivesCategory"])
|
||
->order('views', 'desc')
|
||
->limit($limit)
|
||
->select();
|
||
}
|
||
|
||
//获取栏目下最新记录
|
||
public static function getLatestByCategory($categoryId, $limit = 5)
|
||
{
|
||
if (empty($categoryId)) {
|
||
return [];
|
||
}
|
||
if ($limit <= 0) {
|
||
$limit = 5;
|
||
}
|
||
return self::with(["archivesCategory"])
|
||
->where('category_id', $categoryId)
|
||
->order('id', 'desc')
|
||
->limit($limit)
|
||
->select();
|
||
}
|
||
|
||
//根据文章ID和栏目ID获取下一篇文章
|
||
public static function getNextArticleBySortAndCategoryId($sort, $categoryId)
|
||
{
|
||
return self::with(["archivesCategory"])
|
||
->where('sort', '<', $sort)
|
||
->where('category_id', $categoryId)
|
||
->where('status', 1)
|
||
->order('sort', 'desc')
|
||
->find();
|
||
}
|
||
|
||
//根据文章ID和栏目ID获取上一篇文章
|
||
public static function getPrevArticleBySortAndCategoryId($sort, $categoryId)
|
||
{
|
||
return self::with(["archivesCategory"])
|
||
->where('sort', '>', $sort)
|
||
->where('category_id', $categoryId)
|
||
->where('status', 1)
|
||
->order('sort', 'asc')
|
||
->find();
|
||
}
|
||
|
||
//根据栏目ID获取文章列表
|
||
public static function getListByCategory($categoryId, $limit = 10)
|
||
{
|
||
return self::with(["archivesCategory"])
|
||
->where('category_id', $categoryId)
|
||
->where('status', 1)
|
||
->order("sort", 'desc')
|
||
->limit($limit)
|
||
->select();
|
||
}
|
||
|
||
//根据栏目ID获取文章分页列表
|
||
public static function getListPageByCategory($categoryId, $per = 20, $keyword = '')
|
||
{
|
||
$where = [
|
||
['category_id', '=', $categoryId],
|
||
['status', '=', 1],
|
||
];
|
||
$param['category_id'] = $categoryId;
|
||
if ($keyword != '') {
|
||
$where[] = ['title', 'like', '%'.$keyword.'%'];
|
||
$param['keyword'] = $keyword;
|
||
}
|
||
$paginate = [
|
||
'list_rows' => $per,
|
||
'query' => $param
|
||
];
|
||
return self::with(["archivesCategory"])
|
||
->where($where)
|
||
->order("sort", 'desc')
|
||
->paginate($paginate, false);
|
||
}
|
||
|
||
//根据栏目ID获取文章数量(状态:正常)
|
||
public static function getNormalListCount($categoryId)
|
||
{
|
||
$where = [
|
||
['category_id', '=', $categoryId],
|
||
['status', '=', 1],
|
||
];
|
||
|
||
return self::where($where)
|
||
->count();
|
||
}
|
||
|
||
public static function onAfterInsert($article)
|
||
{
|
||
$article->sort = $article->id;
|
||
$article->create_time = $article->update_time = time();
|
||
$auth = session('auth');
|
||
$article->created = $article->updated = $auth['userName'];
|
||
$article->save();
|
||
}
|
||
|
||
/**
|
||
* 获取文章列表
|
||
* @param int $categoryId 分类ID
|
||
* @param int $per 每页数量
|
||
* @param string $keyword 关键词
|
||
* @param array $param 文章类型:置顶、热门、推荐 ['top','hot','recommend']
|
||
* @param int $status 文章状态,-1表示不限制
|
||
* @param array $orderList 排序
|
||
* @param bool $onlyChild 仅获取下级 默认true false=获取所有后代分类
|
||
* @return Paginator
|
||
*/
|
||
public static function getList($categoryId, $per = 20, $keyword = '', $param = [], $status = -1, $orderList = ['top' => 'desc','sort' => 'desc'], bool $onlyChild = true, $prev = '')
|
||
{
|
||
$whereMap = [];
|
||
$pageParam = [];
|
||
if (is_numeric($categoryId) && $categoryId > 0) {
|
||
$children = Category::getChildrenByParentId($categoryId, $onlyChild);
|
||
if (!empty($children)) {
|
||
$categoryIds = [$categoryId];
|
||
foreach ($children as $child) {
|
||
if ($child['model_id'] == Model::MODEL_ARTICLE) {
|
||
$categoryIds[] = $child['id'];
|
||
}
|
||
}
|
||
$whereMap[] = ['category_id', 'in', $categoryIds];
|
||
} else {
|
||
$whereMap[] = ['category_id', '=', $categoryId];
|
||
}
|
||
$pageParam['category_id'] = $categoryId;
|
||
}
|
||
if (!empty($keyword)) {
|
||
$whereMap[] = ['title', 'like', '%'.$keyword.'%'];
|
||
$pageParam['keyword'] = $keyword;
|
||
}
|
||
if (is_array($param) && count($param) > 0) {
|
||
$pageParam['param'] = $param;
|
||
foreach ($param as $vo) {
|
||
if (in_array($vo, ['top', 'hot', 'recommend', 'is_prev'], true)) {
|
||
$whereMap[] = ["{$vo}", '=', 1];
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!empty($prev) || $prev == '0') {
|
||
$whereMap[] = ['is_prev', '=', $prev];
|
||
$pageParam['is_prev'] = $prev;
|
||
}
|
||
|
||
$paginate = [
|
||
'list_rows' => $per,
|
||
'query' => $pageParam
|
||
];
|
||
|
||
return self::with(["archivesCategory"])
|
||
->when(count($whereMap) > 0, function ($query) use ($whereMap) {
|
||
$query->where($whereMap);
|
||
})
|
||
->when($status != -1, function ($query) use ($status) {
|
||
$query->where('status', $status);
|
||
})
|
||
->order($orderList)
|
||
->paginate($paginate, false);
|
||
}
|
||
|
||
/**
|
||
* @param array $where
|
||
* @return \think\Paginator
|
||
* @throws \think\db\exception\DbException
|
||
*/
|
||
public static function getListByWhere(array $where)
|
||
{
|
||
$categoryId = $where['category_id'];
|
||
$per = $where['size'];
|
||
$keyword = $where['keyword'] ?? '';
|
||
$param = $where['param'] ?? [];
|
||
$status = $where['status'] ?? -1;
|
||
$orderList = $where['order'] ?? ['sort' => 'desc'];
|
||
$onlyChild = $where['only_child'] ?? true;
|
||
$whereList = $where['where'] ?? [];
|
||
|
||
$whereMap = [];
|
||
$pageParam = [];
|
||
|
||
if (!empty($whereList)) {
|
||
foreach ($whereList as $w) {
|
||
$whereMap[] = $w;
|
||
}
|
||
}
|
||
|
||
if (is_numeric($categoryId) && $categoryId > 0) {
|
||
$children = Category::getChildrenByParentId($categoryId, $onlyChild);
|
||
if (!empty($children)) {
|
||
$categoryIds = [$categoryId];
|
||
foreach ($children as $child) {
|
||
if ($child['model_id'] == Model::MODEL_ARTICLE) {
|
||
$categoryIds[] = $child['id'];
|
||
}
|
||
}
|
||
$whereMap[] = ['category_id', 'in', $categoryIds];
|
||
} else {
|
||
$whereMap[] = ['category_id', '=', $categoryId];
|
||
}
|
||
$pageParam['category_id'] = $categoryId;
|
||
}
|
||
if (!empty($keyword)) {
|
||
$whereMap[] = ['title', 'like', '%'.$keyword.'%'];
|
||
$pageParam['keyword'] = $keyword;
|
||
}
|
||
if (is_array($param) && count($param) > 0) {
|
||
$pageParam['param'] = $param;
|
||
foreach ($param as $vo) {
|
||
if (in_array($vo, ['top', 'hot', 'recommend', 'is_prev'], true)) {
|
||
$whereMap[] = ["{$vo}", '=', 1];
|
||
}
|
||
}
|
||
}
|
||
$paginate = [
|
||
'list_rows' => $per,
|
||
'query' => $pageParam
|
||
];
|
||
|
||
return self::with(["archivesCategory"])
|
||
->when(count($whereMap) > 0, function ($query) use ($whereMap) {
|
||
$query->where($whereMap);
|
||
})
|
||
->when($status != -1, function ($query) use ($status) {
|
||
$query->where('status', $status);
|
||
})
|
||
->order($orderList)
|
||
->paginate($paginate, false);
|
||
}
|
||
|
||
//获取文章涉及到的图片
|
||
public static function getFilesInUse()
|
||
{
|
||
$items = self::select()->toArray();
|
||
$data = [];
|
||
foreach ($items as $item) {
|
||
$src = trim($item['src']);
|
||
if (!empty($src)) {
|
||
$key = getKeyByPath($src);
|
||
$data[$key] = $src;
|
||
}
|
||
$imgs = getImageUrlFromText($item['content']);
|
||
if (!empty($imgs)) {
|
||
$data = array_merge($data, $imgs);
|
||
}
|
||
$videos = getVideoUrlFromText($item['content']);
|
||
if (!empty($videos)) {
|
||
$data = array_merge($data, $videos);
|
||
}
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
//推荐列表(其他推荐类)
|
||
public static function getRecommendList($categoryId, $recommend = '', $limit = 3, $excludeIds = [], $orderList = ['a.id' => 'desc'])
|
||
{
|
||
if (empty($categoryId) || empty($recommend)) {
|
||
return [];
|
||
}
|
||
|
||
$whereMap = [];
|
||
if (is_numeric($categoryId) && $categoryId > 0) {
|
||
$children = Category::getChildrenByParentId($categoryId);
|
||
if (!empty($children)) {
|
||
$categoryIds = [$categoryId];
|
||
foreach ($children as $child) {
|
||
if ($child['model_id'] == Model::MODEL_ARTICLE) {
|
||
$categoryIds[] = $child['id'];
|
||
}
|
||
}
|
||
$whereMap[] = ['category_id', 'in', $categoryIds];
|
||
} else {
|
||
$whereMap[] = ['category_id', '=', $categoryId];
|
||
}
|
||
}
|
||
if (!empty($excludeIds)) {
|
||
$whereMap[] = ['id', 'not in', $excludeIds];
|
||
}
|
||
|
||
return self::with(["archivesCategory"])
|
||
->when(count($whereMap) > 0, function ($query) use ($whereMap) {
|
||
$query->where($whereMap);
|
||
})
|
||
->whereRaw("FIND_IN_SET(:recommend, `recommend_other`)", ['recommend' => $recommend])
|
||
->where('status', 1)
|
||
->order($orderList)
|
||
->limit($limit)
|
||
->select();
|
||
}
|
||
|
||
// 转换文章的推荐设置
|
||
public static function convertRecommendOther($categoryIds = [], $articles, $isMulti = true)
|
||
{
|
||
if (empty($articles) || count($articles) == 0) {
|
||
return $articles;
|
||
}
|
||
|
||
$attributeList = self::getAttributeList($categoryIds);
|
||
|
||
if ($isMulti) {
|
||
foreach ($articles as &$article) {
|
||
$recommendOtherList = [];
|
||
$recommendOtherStrList = [];
|
||
if (isset($article['recommend_other']) && !empty($article['recommend_other'])) {
|
||
$recommendOtherList = explode(',', $article['recommend_other']);
|
||
foreach ($recommendOtherList as $recommendKey) {
|
||
if (isset($attributeList[$recommendKey]) && !empty($attributeList[$recommendKey])) {
|
||
$recommendOtherStrList[] = $attributeList[$recommendKey];
|
||
}
|
||
}
|
||
}
|
||
$article['recommend_other_list'] = $recommendOtherList;
|
||
$article['recommend_other_str'] = implode(',', $recommendOtherStrList);
|
||
}
|
||
unset($article);
|
||
|
||
} else {
|
||
$recommendOtherList = [];
|
||
$recommendOtherStrList = [];
|
||
if (isset($articles['recommend_other']) && !empty($articles['recommend_other'])) {
|
||
$recommendOtherList = explode(',', $articles['recommend_other']);
|
||
foreach ($recommendOtherList as $recommendKey) {
|
||
if (isset($attributeList[$recommendKey]) && !empty($attributeList[$recommendKey])) {
|
||
$recommendOtherStrList[] = $attributeList[$recommendKey];
|
||
}
|
||
}
|
||
}
|
||
$articles['recommend_other_list'] = $recommendOtherList;
|
||
$articles['recommend_other_str'] = implode(',', $recommendOtherStrList);
|
||
}
|
||
|
||
return $articles;
|
||
}
|
||
|
||
// 获取最新动态
|
||
public static function getLastDynamicsList($categoryId, $withChild = false, $limit = 10)
|
||
{
|
||
$categoryIds = [$categoryId];
|
||
if ($withChild) {
|
||
$childCategories = Category::getChildrenByParentId($categoryId);
|
||
if (!empty($childCategories)) {
|
||
foreach ($childCategories as $category) {
|
||
if ($category['model_id'] == Model::MODEL_ARTICLE) {
|
||
$categoryIds[] = $category['id'];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return self::with(["archivesCategory"])
|
||
->whereIn('category_id', $categoryIds)
|
||
->where('status', 1)
|
||
->order('id', 'desc')
|
||
->limit($limit)
|
||
->select();
|
||
|
||
}
|
||
|
||
|
||
//根据文章ID和栏目IDs,默认按创建时间获取下一篇文章
|
||
public static function getNextArticleByTimeAndCategoryIds(array $where, $sortOrder = ['id' => 'desc'])
|
||
{
|
||
return self::with(["archivesCategory"])
|
||
->where($where)
|
||
->where('status', 1)
|
||
->order($sortOrder)
|
||
->find();
|
||
}
|
||
|
||
//根据文章ID和栏目IDs,默认按创建时间获取上一篇文章
|
||
public static function getPrevArticleByTimeAndCategoryIds(array $where, $sortOrder = ['id' => 'asc'])
|
||
{
|
||
return self::with(["archivesCategory"])
|
||
// ->where('a.id','>',$curId)
|
||
// ->whereIn('a.category_id', $categoryIds)
|
||
->where($where)
|
||
->where('status', 1)
|
||
->order($sortOrder)
|
||
->find();
|
||
}
|
||
|
||
public static function getLastTopList($categoryId, $limit = 3, $excludeIds = [], $orderList = ['recommend_other' => 'desc', 'id' => 'desc'])
|
||
{
|
||
if (empty($categoryId)) {
|
||
return [];
|
||
}
|
||
|
||
$whereMap = [];
|
||
if (is_numeric($categoryId) && $categoryId > 0) {
|
||
$children = Category::getChildrenByParentId($categoryId);
|
||
if (!empty($children)) {
|
||
$categoryIds = [$categoryId];
|
||
foreach ($children as $child) {
|
||
if ($child['model_id'] == Model::MODEL_ARTICLE) {
|
||
$categoryIds[] = $child['id'];
|
||
}
|
||
}
|
||
$whereMap[] = ['category_id', 'in', $categoryIds];
|
||
} else {
|
||
$whereMap[] = ['category_id', '=', $categoryId];
|
||
}
|
||
}
|
||
if (!empty($excludeIds)) {
|
||
$whereMap[] = ['id', 'not in', $excludeIds];
|
||
}
|
||
|
||
$items = self::with(["archivesCategory"])
|
||
->when(count($whereMap) > 0, function ($query) use ($whereMap) {
|
||
$query->where($whereMap);
|
||
})
|
||
->where('status', 1)
|
||
->order($orderList);
|
||
if ($limit > 0) {
|
||
$items = $items->limit($limit);
|
||
}
|
||
$items = $items->limit($limit)
|
||
->select();
|
||
|
||
return $items;
|
||
}
|
||
|
||
// 分页获取最新动态
|
||
public static function getLastDynamicsPageList($categoryId, $withChild = true, $per = 20)
|
||
{
|
||
$categoryIds = [$categoryId];
|
||
if ($withChild) {
|
||
$childCategories = Category::getChildrenByParentId($categoryId);
|
||
if (!empty($childCategories)) {
|
||
foreach ($childCategories as $category) {
|
||
if ($category['model_id'] == Model::MODEL_ARTICLE) {
|
||
$categoryIds[] = $category['id'];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
$paginate = [
|
||
'list_rows' => $per,
|
||
'query' => [
|
||
'category_id' => $categoryId
|
||
]
|
||
];
|
||
|
||
return self::with(["archivesCategory"])
|
||
->whereIn('category_id', $categoryIds)
|
||
->where('status', 1)
|
||
->order('id', 'desc')
|
||
->paginate($paginate, false);
|
||
}
|
||
|
||
// 根据栏目ID进行分组,按sort倒序排列,每组最多获取n条(默认10条)数据
|
||
public static function getGroupListByCategoryIds(array $categoryIds, int $size = 10)
|
||
{
|
||
return self::alias('ca')
|
||
->where($size, '>', function ($q) {
|
||
$q->table('bee_article cb')
|
||
->whereRaw('ca.category_id = cb.category_id and ca.sort < cb.sort')->field('count(*)');
|
||
})
|
||
->whereIn('ca.category_id', $categoryIds)
|
||
->field('ca.*')
|
||
->order(['ca.sort' => 'desc'])
|
||
->select();
|
||
}
|
||
|
||
public static function parseList($items)
|
||
{
|
||
try {
|
||
$tagNameList = [];
|
||
foreach ($items as $ki => $item) {
|
||
$tagStr = trim($item['tag'] ?? '');
|
||
$tagNames = empty($tagStr) ? [] : explode(',', $tagStr);
|
||
$tagNameList = array_merge($tagNameList, $tagNames);
|
||
}
|
||
$tagNameList = array_unique($tagNameList);
|
||
$tagKVs = ArticleTags::findByNames($tagNameList)->column('id', 'name');
|
||
|
||
foreach ($items as $ki => $item) {
|
||
$tagStr = trim($item['tag'] ?? '');
|
||
$tagNames = empty($tagStr) ? [] : explode(',', $tagStr);
|
||
$tagList = [];
|
||
foreach ($tagNames as $tagName) {
|
||
$tagList[] = [
|
||
'name' => $tagName,
|
||
'id' => $tagKVs[$tagName] ?? 0
|
||
];
|
||
}
|
||
$items[$ki]['tag_list'] = $tagList;
|
||
$createTime = is_numeric($item['create_time']) ? $item['create_time'] : strtotime($item['create_time']);
|
||
$items[$ki]['create_date'] = date('Y-m-d', $createTime);
|
||
$item['create_dateTime'] = date('Y-m-d H:i:s', $createTime);
|
||
}
|
||
} catch (\Exception $e) {
|
||
|
||
}
|
||
return $items;
|
||
}
|
||
|
||
public static function parseInfo($item)
|
||
{
|
||
if ($item) {
|
||
$tagStr = trim($item['tag'] ?? '');
|
||
$tagNameList = empty($tagStr) ? [] : explode(',', $tagStr);
|
||
$tagKVs = ArticleTags::findByNames($tagNameList)->column('id', 'name');
|
||
$tagList = [];
|
||
foreach ($tagNameList as $tagName) {
|
||
$tagList[] = [
|
||
'name' => $tagName,
|
||
'id' => $tagKVs[$tagName] ?? 0
|
||
];
|
||
}
|
||
$item['tag_list'] = $tagList;
|
||
$createTime = is_numeric($item['create_time']) ? $item['create_time'] : strtotime($item['create_time']);
|
||
$item['create_date'] = date('Y-m-d', $createTime);
|
||
$item['create_dateTime'] = date('Y-m-d H:i:s', $createTime);
|
||
$item['create_y_m_d'] = date('Y.m.d', $createTime);
|
||
}
|
||
return $item;
|
||
}
|
||
|
||
public static function countList(array $where, callable $call = null)
|
||
{
|
||
$q = new static();
|
||
$q = $q->where($where);
|
||
if ($call) {
|
||
$q = $call($q);
|
||
}
|
||
return $q->count();
|
||
}
|
||
|
||
public static function findListByWhere(array $where, int $page = 1, int $size = 10, callable $call = null, array $sortList = ['sort' => 'desc'])
|
||
{
|
||
$q = new static();
|
||
$q = $q->with(["archivesCategory"])->where($where);
|
||
if ($call) {
|
||
$q = $call($q);
|
||
}
|
||
if ($size > 0) {
|
||
$q = $q->page($page, $size);
|
||
}
|
||
if (count($sortList)) {
|
||
$q = $q->order($sortList);
|
||
}
|
||
return $q->select();
|
||
}
|
||
|
||
public static function getTeam()
|
||
{
|
||
$categoryIds = Category::where('parent_id', Category::CATEGORY_INFO)->order('sort', 'asc')->column('title', 'id');
|
||
$list = self::with(["archivesCategory"])
|
||
->whereIn("category_id", array_keys($categoryIds))
|
||
->order(["sort" => "desc", "id" => "desc"])
|
||
->select();
|
||
$data = [];
|
||
foreach ($categoryIds as $categoryId => $title) {
|
||
if (!isset($data[$categoryId])) {
|
||
$data[$categoryId]['title'] = $title;
|
||
$data[$categoryId]['list'] = [];
|
||
}
|
||
foreach ($list as $item) {
|
||
if ($item['category_id'] == $categoryId) {
|
||
$data[$categoryId]['list'][] = $item;
|
||
}
|
||
}
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
public static function getIndexTop($categoryId)
|
||
{
|
||
return self::with(["archivesCategory"])
|
||
->where("category_id", $categoryId)
|
||
->where("top", 1)
|
||
->order(["sort" => "desc"])
|
||
->find();
|
||
}
|
||
|
||
public static function getIndexList($categoryId, $num)
|
||
{
|
||
return self::with(["archivesCategory"])
|
||
->where("category_id", $categoryId)
|
||
->where("top", "<>", 1)
|
||
->order(['sort' => 'desc', "id" => "desc"])
|
||
->limit($num)
|
||
->select();
|
||
}
|
||
} |