feat: add community post categories and channels
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace app\adminapi\controller\community;
|
||||
|
||||
use app\adminapi\controller\BaseAdminController;
|
||||
use app\adminapi\lists\community\CommunityCategoryLists;
|
||||
use app\adminapi\logic\community\CommunityCategoryLogic;
|
||||
use app\adminapi\validate\community\CommunityCategoryValidate;
|
||||
|
||||
class CommunityCategoryController extends BaseAdminController
|
||||
{
|
||||
public function lists()
|
||||
{
|
||||
return $this->dataLists(new CommunityCategoryLists());
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
return $this->data(CommunityCategoryLogic::all());
|
||||
}
|
||||
|
||||
public function detail()
|
||||
{
|
||||
$params = (new CommunityCategoryValidate())->goCheck('detail');
|
||||
return $this->data(CommunityCategoryLogic::detail($params));
|
||||
}
|
||||
|
||||
public function add()
|
||||
{
|
||||
$params = (new CommunityCategoryValidate())->post()->goCheck('add');
|
||||
if (CommunityCategoryLogic::add($params)) {
|
||||
return $this->success('添加成功', [], 1, 1);
|
||||
}
|
||||
return $this->fail(CommunityCategoryLogic::getError());
|
||||
}
|
||||
|
||||
public function edit()
|
||||
{
|
||||
$params = (new CommunityCategoryValidate())->post()->goCheck('edit');
|
||||
if (CommunityCategoryLogic::edit($params)) {
|
||||
return $this->success('编辑成功', [], 1, 1);
|
||||
}
|
||||
return $this->fail(CommunityCategoryLogic::getError());
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$params = (new CommunityCategoryValidate())->post()->goCheck('delete');
|
||||
if (CommunityCategoryLogic::delete($params)) {
|
||||
return $this->success('删除成功', [], 1, 1);
|
||||
}
|
||||
return $this->fail(CommunityCategoryLogic::getError());
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,26 @@ class CommunityPostController extends BaseAdminController
|
||||
return $this->fail(CommunityPostLogic::getError());
|
||||
}
|
||||
|
||||
public function setTopic()
|
||||
{
|
||||
$params = (new CommunityPostValidate())->post()->goCheck('topic');
|
||||
$result = CommunityPostLogic::setTopic($params);
|
||||
if (true === $result) {
|
||||
return $this->success('设置成功', [], 1, 1);
|
||||
}
|
||||
return $this->fail(CommunityPostLogic::getError());
|
||||
}
|
||||
|
||||
public function setCategory()
|
||||
{
|
||||
$params = (new CommunityPostValidate())->post()->goCheck('category');
|
||||
$result = CommunityPostLogic::setCategory($params);
|
||||
if (true === $result) {
|
||||
return $this->success('设置成功', [], 1, 1);
|
||||
}
|
||||
return $this->fail(CommunityPostLogic::getError());
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$params = (new CommunityPostValidate())->post()->goCheck('delete');
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace app\adminapi\lists\community;
|
||||
|
||||
use app\adminapi\lists\BaseAdminDataLists;
|
||||
use app\common\lists\ListsSearchInterface;
|
||||
use app\common\model\community\CommunityCategory;
|
||||
|
||||
class CommunityCategoryLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
{
|
||||
public function setSearch(): array
|
||||
{
|
||||
return [
|
||||
'%like%' => ['name'],
|
||||
'=' => ['status'],
|
||||
];
|
||||
}
|
||||
|
||||
public function lists(): array
|
||||
{
|
||||
return CommunityCategory::where($this->searchWhere)
|
||||
->limit($this->limitOffset, $this->limitLength)
|
||||
->order('sort', 'desc')
|
||||
->order('id', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return CommunityCategory::where($this->searchWhere)->count();
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace app\adminapi\lists\community;
|
||||
|
||||
use app\adminapi\lists\BaseAdminDataLists;
|
||||
use app\common\lists\ListsSearchInterface;
|
||||
use app\common\model\community\CommunityCategory;
|
||||
use app\common\model\community\CommunityPost;
|
||||
use app\common\model\user\User;
|
||||
|
||||
@@ -12,7 +13,7 @@ class CommunityPostLists extends BaseAdminDataLists implements ListsSearchInterf
|
||||
public function setSearch(): array
|
||||
{
|
||||
return [
|
||||
'=' => ['status', 'post_type', 'is_top', 'is_hot', 'is_recommend', 'user_id'],
|
||||
'=' => ['status', 'post_type', 'category_id', 'is_top', 'is_hot', 'is_recommend', 'is_topic', 'user_id'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -26,11 +27,16 @@ class CommunityPostLists extends BaseAdminDataLists implements ListsSearchInterf
|
||||
|
||||
$userIds = array_unique(array_column($lists, 'user_id'));
|
||||
$users = User::whereIn('id', $userIds)->column('nickname,avatar', 'id');
|
||||
$categoryIds = array_values(array_filter(array_unique(array_column($lists, 'category_id'))));
|
||||
$categories = $categoryIds
|
||||
? CommunityCategory::whereIn('id', $categoryIds)->column('name', 'id')
|
||||
: [];
|
||||
|
||||
foreach ($lists as &$item) {
|
||||
$user = $users[$item['user_id']] ?? [];
|
||||
$item['nickname'] = $user['nickname'] ?? '-';
|
||||
$item['avatar'] = $user['avatar'] ?? '';
|
||||
$item['category_name'] = $categories[$item['category_id']] ?? '';
|
||||
$item['create_time'] = is_numeric($item['create_time']) ? date('Y-m-d H:i:s', $item['create_time']) : $item['create_time'];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace app\adminapi\logic\community;
|
||||
|
||||
use app\common\logic\BaseLogic;
|
||||
use app\common\model\community\CommunityCategory;
|
||||
use app\common\model\community\CommunityPost;
|
||||
|
||||
class CommunityCategoryLogic extends BaseLogic
|
||||
{
|
||||
public static function add(array $params): bool
|
||||
{
|
||||
try {
|
||||
CommunityCategory::create([
|
||||
'name' => trim($params['name']),
|
||||
'icon' => $params['icon'] ?? '',
|
||||
'sort' => $params['sort'] ?? 0,
|
||||
'status' => $params['status'] ?? 1,
|
||||
]);
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
self::setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function edit(array $params): bool
|
||||
{
|
||||
try {
|
||||
CommunityCategory::update([
|
||||
'id' => $params['id'],
|
||||
'name' => trim($params['name']),
|
||||
'icon' => $params['icon'] ?? '',
|
||||
'sort' => $params['sort'] ?? 0,
|
||||
'status' => $params['status'] ?? 1,
|
||||
]);
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
self::setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function delete(array $params): bool
|
||||
{
|
||||
if (CommunityPost::where('category_id', $params['id'])->count() > 0) {
|
||||
self::setError('该分类下存在帖子,不能删除');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
CommunityCategory::destroy($params['id']);
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
self::setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function detail(array $params): array
|
||||
{
|
||||
return CommunityCategory::findOrEmpty($params['id'])->toArray();
|
||||
}
|
||||
|
||||
public static function all(): array
|
||||
{
|
||||
return CommunityCategory::order('sort', 'desc')
|
||||
->order('id', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,11 @@
|
||||
namespace app\adminapi\logic\community;
|
||||
|
||||
use app\common\logic\BaseLogic;
|
||||
use app\common\model\community\CommunityCategory;
|
||||
use app\common\model\community\CommunityPost;
|
||||
use app\common\service\ai\KbSyncService;
|
||||
use app\common\model\user\User;
|
||||
use app\common\service\ai\KbSyncService;
|
||||
use think\facade\Db;
|
||||
|
||||
class CommunityPostLogic extends BaseLogic
|
||||
{
|
||||
@@ -21,6 +23,9 @@ class CommunityPostLogic extends BaseLogic
|
||||
$user = User::field('nickname,avatar')->findOrEmpty($post['user_id'] ?? 0)->toArray();
|
||||
$post['nickname'] = $user['nickname'] ?? '-';
|
||||
$post['avatar'] = $user['avatar'] ?? '';
|
||||
$post['category_name'] = (int) ($post['category_id'] ?? 0) > 0
|
||||
? (string) CommunityCategory::where('id', $post['category_id'])->value('name')
|
||||
: '';
|
||||
return $post;
|
||||
}
|
||||
|
||||
@@ -87,9 +92,65 @@ class CommunityPostLogic extends BaseLogic
|
||||
}
|
||||
}
|
||||
|
||||
public static function setTopic(array $params): bool
|
||||
{
|
||||
try {
|
||||
CommunityPost::update([
|
||||
'id' => $params['id'],
|
||||
'is_topic' => $params['is_topic'],
|
||||
]);
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
self::setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function setCategory(array $params): bool
|
||||
{
|
||||
$post = CommunityPost::findOrEmpty($params['id']);
|
||||
if ($post->isEmpty()) {
|
||||
self::setError('帖子不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$oldCategoryId = (int) $post->category_id;
|
||||
$newCategoryId = (int) $params['category_id'];
|
||||
if ($oldCategoryId === $newCategoryId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$post->category_id = $newCategoryId;
|
||||
$post->save();
|
||||
self::refreshCategoryCount($oldCategoryId);
|
||||
self::refreshCategoryCount($newCategoryId);
|
||||
Db::commit();
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
self::setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function delete(array $params)
|
||||
{
|
||||
$categoryId = (int) CommunityPost::where('id', $params['id'])->value('category_id');
|
||||
CommunityPost::destroy($params['id']);
|
||||
self::refreshCategoryCount($categoryId);
|
||||
KbSyncService::enqueue('post', 'post', (int) $params['id'], 'delete', 20);
|
||||
}
|
||||
|
||||
private static function refreshCategoryCount(int $categoryId): void
|
||||
{
|
||||
if ($categoryId <= 0) {
|
||||
return;
|
||||
}
|
||||
CommunityCategory::where('id', $categoryId)->update([
|
||||
'post_count' => CommunityPost::where('category_id', $categoryId)->count(),
|
||||
'update_time' => time(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace app\adminapi\validate\community;
|
||||
|
||||
use app\common\model\community\CommunityCategory;
|
||||
use app\common\validate\BaseValidate;
|
||||
|
||||
class CommunityCategoryValidate extends BaseValidate
|
||||
{
|
||||
protected $rule = [
|
||||
'id' => 'require|checkCategory',
|
||||
'name' => 'require|length:1,50|checkNameUnique',
|
||||
'icon' => 'max:500',
|
||||
'sort' => 'integer|egt:0',
|
||||
'status' => 'in:0,1',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'id.require' => '分类id不能为空',
|
||||
'name.require' => '分类名称不能为空',
|
||||
'name.length' => '分类名称长度须在1-50位字符',
|
||||
'icon.max' => '分类图标地址不能超过500个字符',
|
||||
'sort.integer' => '排序值必须为整数',
|
||||
'sort.egt' => '排序值不能小于0',
|
||||
'status.in' => '分类状态值错误',
|
||||
];
|
||||
|
||||
public function sceneAdd()
|
||||
{
|
||||
return $this->remove('id', 'require|checkCategory');
|
||||
}
|
||||
|
||||
public function sceneEdit()
|
||||
{
|
||||
}
|
||||
|
||||
public function sceneDetail()
|
||||
{
|
||||
return $this->only(['id']);
|
||||
}
|
||||
|
||||
public function sceneDelete()
|
||||
{
|
||||
return $this->only(['id']);
|
||||
}
|
||||
|
||||
public function checkCategory($value)
|
||||
{
|
||||
$category = CommunityCategory::findOrEmpty($value);
|
||||
if ($category->isEmpty()) {
|
||||
return '分类不存在';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkNameUnique($value, $rule, $data)
|
||||
{
|
||||
$query = CommunityCategory::where('name', trim((string) $value));
|
||||
if (!empty($data['id'])) {
|
||||
$query->where('id', '<>', (int) $data['id']);
|
||||
}
|
||||
return $query->count() > 0 ? '分类名称已存在' : true;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace app\adminapi\validate\community;
|
||||
|
||||
use app\common\validate\BaseValidate;
|
||||
use app\common\model\community\CommunityCategory;
|
||||
use app\common\model\community\CommunityPost;
|
||||
|
||||
class CommunityPostValidate extends BaseValidate
|
||||
@@ -13,6 +14,8 @@ class CommunityPostValidate extends BaseValidate
|
||||
'is_top' => 'require|in:0,1',
|
||||
'is_hot' => 'require|in:0,1',
|
||||
'is_recommend' => 'require|in:0,1',
|
||||
'is_topic' => 'require|in:0,1',
|
||||
'category_id' => 'require|integer|egt:0|checkCategory',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
@@ -50,6 +53,16 @@ class CommunityPostValidate extends BaseValidate
|
||||
return $this->only(['id', 'is_recommend']);
|
||||
}
|
||||
|
||||
public function sceneTopic()
|
||||
{
|
||||
return $this->only(['id', 'is_topic']);
|
||||
}
|
||||
|
||||
public function sceneCategory()
|
||||
{
|
||||
return $this->only(['id', 'category_id']);
|
||||
}
|
||||
|
||||
public function checkPost($value)
|
||||
{
|
||||
$post = CommunityPost::findOrEmpty($value);
|
||||
@@ -58,4 +71,16 @@ class CommunityPostValidate extends BaseValidate
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkCategory($value)
|
||||
{
|
||||
if ((int) $value === 0) {
|
||||
return true;
|
||||
}
|
||||
$category = CommunityCategory::where('id', $value)->where('status', 1)->findOrEmpty();
|
||||
if ($category->isEmpty()) {
|
||||
return '帖子分类不存在或已禁用';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace app\api\lists\community;
|
||||
|
||||
use app\api\lists\BaseApiDataLists;
|
||||
use app\common\model\community\CommunityCategory;
|
||||
use app\common\model\community\CommunityPost;
|
||||
use app\common\model\community\CommunityFollow;
|
||||
use app\common\model\community\CommunityTag;
|
||||
@@ -61,6 +62,11 @@ class CommunityPostLists extends BaseApiDataLists
|
||||
$where[] = ['id', '=', 0];
|
||||
}
|
||||
}
|
||||
foreach (['is_recommend', 'is_hot', 'is_topic', 'category_id'] as $field) {
|
||||
if (isset($this->params[$field]) && $this->params[$field] !== '') {
|
||||
$where[] = [$field, '=', (int) $this->params[$field]];
|
||||
}
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
|
||||
@@ -88,7 +94,7 @@ class CommunityPostLists extends BaseApiDataLists
|
||||
public function lists(): array
|
||||
{
|
||||
$list = $this->buildQuery()
|
||||
->field('id,origin_id,user_id,content,images,ext,post_type,match_id,is_paid,price_points,paid_count,view_count,like_count,comment_count,share_count,is_top,is_hot,is_recommend,create_time')
|
||||
->field('id,origin_id,user_id,content,images,ext,post_type,category_id,match_id,is_paid,price_points,paid_count,view_count,like_count,comment_count,share_count,is_top,is_hot,is_recommend,is_topic,create_time')
|
||||
->orderRaw('is_top DESC, is_hot DESC, create_time DESC')
|
||||
->limit($this->limitOffset, $this->limitLength)
|
||||
->select()
|
||||
@@ -107,6 +113,11 @@ class CommunityPostLists extends BaseApiDataLists
|
||||
}
|
||||
}
|
||||
|
||||
$categoryIds = array_values(array_filter(array_unique(array_column($list, 'category_id'))));
|
||||
$categoryNames = $categoryIds
|
||||
? CommunityCategory::whereIn('id', $categoryIds)->column('name', 'id')
|
||||
: [];
|
||||
|
||||
// 批量查询帖子标签 → post_id => [tag_name, ...]
|
||||
$tagMap = [];
|
||||
if ($postIds) {
|
||||
@@ -166,6 +177,7 @@ class CommunityPostLists extends BaseApiDataLists
|
||||
|
||||
$item['user'] = $userMap[$item['user_id']] ?? null;
|
||||
$item['tags'] = $tagMap[$item['id']] ?? [];
|
||||
$item['category_name'] = $categoryNames[$item['category_id']] ?? '';
|
||||
$item['source_url'] = $ext['url'] ?? '';
|
||||
$item['is_liked'] = false;
|
||||
if ($this->userId) {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model\community;
|
||||
|
||||
use app\common\model\BaseModel;
|
||||
use app\common\service\FileService;
|
||||
|
||||
class CommunityCategory extends BaseModel
|
||||
{
|
||||
protected $name = 'community_post_category';
|
||||
|
||||
public function getIconAttr($value): string
|
||||
{
|
||||
return trim((string) $value) ? FileService::getFileUrl((string) $value) : '';
|
||||
}
|
||||
|
||||
public function setIconAttr($value): string
|
||||
{
|
||||
return trim((string) $value) ? FileService::setFileUrl($value) : '';
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,9 @@ class CommunityPost extends BaseModel
|
||||
{
|
||||
return $this->belongsToMany(CommunityTag::class, 'la_community_post_tag', 'tag_id', 'post_id');
|
||||
}
|
||||
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(CommunityCategory::class, 'category_id');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user