// +---------------------------------------------------------------------- declare (strict_types = 1); namespace addon\articles\controller\backend; use addon\articles\library\ArticleSchema; use addon\articles\model\Article as ArticleModel; use addon\articles\model\ArticleTopic; use addon\articles\model\ArticleTopicArticle; use think\facade\Cache; use think\facade\Request; use think\facade\View; use think\Validate; use ywxapp\controller\BackendBase; /** * 文章专题管理(运营聚合页) */ class Topic extends BackendBase { protected $noNeedVerify = []; protected function initialize() { parent::initialize(); ArticleSchema::ensure(); } public function index() { if (Request::isAjax()) { $page = Request::param('page', 1); $limit = Request::param('limit', 15); $paginator = ArticleTopic::order('sort', 'desc')->order('id', 'desc') ->paginate(['list_rows' => $limit, 'page' => $page]); $rows = []; foreach ($paginator->items() as $t) { $rows[] = [ 'id' => $t->id, 'title' => $t->title, 'alias' => $t->alias, 'sort' => (int) $t->sort, 'status' => $t->status, 'article_count' => ArticleTopicArticle::where('tid', $t->id)->count(), 'create_at' => $t->create_at, 'edit_url' => (string) url('articles/backend/topic/edit', ['id' => $t->id]), ]; } return json(['code' => 0, 'msg' => '', 'count' => $paginator->total(), 'data' => $rows]); } return View::fetch('topic/index'); } public function save() { if (Request::isPost()) { return $this->update(0); } return View::fetch('topic/edit', ['topic' => null, 'picked' => []]); } public function edit($id = null) { $topic = ArticleTopic::find($id); if (!$topic) { return redirect((string) url('articles/backend/topic/index')); } $ids = ArticleTopicArticle::articleIdsOf((int) $topic->id); $picked = $ids ? ArticleModel::whereIn('id', $ids)->field('id,title')->select()->toArray() : []; return View::fetch('topic/edit', ['topic' => $topic, 'picked' => $picked]); } public function update($id = 0) { $data = Request::post(); $id = $id ?: (int) ($data['id'] ?? 0); $data['update_at'] = time(); $data['status'] = isset($data['status']) ? 1 : 0; $validate = new Validate([ 'title|标题' => 'require|max:100', 'alias|别名' => 'require|max:50', ]); if (!$validate->check($data)) { return json(['code' => 0, 'msg' => $validate->getError()]); } // 关联文章:逗号分隔的文章ID(顺序即专题内排序) $articleIds = array_values(array_filter(array_map('intval', explode(',', (string) ($data['article_ids'] ?? ''))))); $allow = ['title', 'alias', 'description', 'cover', 'sort', 'status', 'create_at', 'update_at']; try { if ($id) { $topic = ArticleTopic::find($id); if (!$topic) { return json(['code' => 0, 'msg' => '专题不存在']); } $topic->allowField($allow)->save($data); } else { $data['create_at'] = time(); $topic = ArticleTopic::create($data, $allow); $id = $topic->id; } } catch (\Throwable $e) { // alias 上有唯一键 uk_alias return json(['code' => 0, 'msg' => '保存失败:别名可能已存在']); } ArticleTopicArticle::syncArticles((int) $id, $articleIds); // 前台专题聚合页有缓存,写操作后立即失效 Cache::delete('articles:topics'); return json([ 'code' => 1, 'msg' => '保存成功', 'url' => (string) url('articles/backend/topic/index'), ]); } public function delete($id = 0) { $id = (int) ($id ?: Request::post('id', 0)); $topic = ArticleTopic::find($id); if (!$topic) { return json(['code' => 0, 'msg' => '专题不存在']); } $topic->delete(); ArticleTopicArticle::where('tid', $id)->delete(); Cache::delete('articles:topics'); return json(['code' => 1, 'msg' => '已删除']); } }