Files
YwxAppThink/addon/blog/controller/backend/Category.php
T
ywxapp 1d49e6f5ee feat: 公共表更名 common/member 前缀 + 插件命令自动加载 + 版本 1.1.1
- 18 张公共表更名(addon/attachment/configure/links/spider_log/spider_stat/sms/notice/ad/task/prop/medal/help/card -> common_*,member_wallets->member_wallet,score_rule/score_log -> member_*,addon_config->common_addonconf),模型全部对齐新表名,Db 直引用清零
- Attachment 模型补  表名绑定,修复富文本上传查 wxapp_attachment 1146 隐患
- install.sql + 迁移 SQL:backend_admin/backend_role delete_at 默认 0,修复软删除(NULL != 0)误过滤导致后台菜单为空
- AppService::boot() 支持插件 info.php 声明 commands 自动注册插件命令(psr-4 自动加载,坏类名自动跳过)
- 各插件(haonav/mqttbroker/wxchat/articles/blog/forum 等)字段与配置同步调整
- 框架版本 1.1.0 -> 1.1.1
2026-08-20 20:19:15 +08:00

218 lines
7.0 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
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace addon\blog\controller\backend;
use addon\blog\model\BlogCategory as CategoryModel;
use think\facade\Request;
use think\facade\View;
use think\Validate;
use ywxapp\controller\BackendBase;
/**
* Category 类
*
* @author ywxapp <admin@ywxapp.cn>
*/
class Category extends BackendBase
{
protected $noNeedVerify = ['*'];
protected function initialize()
{}
/**
* 分类列表(后台管理全部分类:全局共享 + 各会员自建)
* 以 layui treeTable 所需的扁平结构返回(带 pid / is_parent),由前端 treeTable 自动成树。
*/
public function index()
{
$categories = CategoryModel::withCount('articles')
->order('uid', 'asc')
->order('sort', 'asc')
->select()
->toArray();
// 收集归属会员昵称
$uids = [];
foreach ($categories as $c) {
if (!empty($c['uid'])) {
$uids[] = $c['uid'];
}
}
$owners = [];
if ($uids) {
$owners = \think\facade\Db::name('member_user')
->whereIn('uid', array_unique($uids))
->column('nickname', 'uid');
}
// 计算哪些分类拥有子分类(用于 treeTable 的 is_parent 标记)
$parentIds = array_unique(array_filter(array_column($categories, 'pid')));
$treeData = [];
foreach ($categories as $c) {
$treeData[] = [
'id' => $c['id'],
'pid' => $c['pid'],
'title' => $c['name'], // treeTable 节点显示名称
'name' => $c['name'],
'description' => $c['description'] ?? '',
'sort' => $c['sort'],
'status' => $c['status'],
'is_parent' => in_array($c['id'], $parentIds, true) ? 1 : 0,
'owner' => empty($c['uid']) ? '全局共享' : ($owners[$c['uid']] ?? ('#' . $c['uid'])),
'articles_count' => $c['articles_count'] ?? 0,
];
}
return View::fetch('category/index', [
'treeData' => json_encode($treeData, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG),
]);
}
/**
* 添加分类页面
*/
public function add()
{
$categories = CategoryModel::order('sort', 'asc')->select();
return View::fetch('category/add', ['categories' => $categories]);
}
/**
* 保存分类
*/
public function save()
{
$data = Request::post();
$data['uid'] = 0; // 后台管理的分类为全局共享分类
$data['pid'] = (int) Request::post('pid', 0);
$data['create_at'] = time();
$data['update_at'] = time();
$validate = new Validate([
'name|分类名称' => 'require|unique:BlogCategory,name,0,id,uid,0',
'pid|上级分类' => 'number',
'sort|排序' => 'number|between:0,999',
]);
if (! $validate->check($data)) {
return json(['code' => 0, 'msg' => $validate->getError()]);
}
CategoryModel::create($data);
return json(['code' => 1, 'msg' => '分类添加成功', 'url' => '/blog/backend/category']);
}
/**
* 编辑分类页面
*/
public function edit($id = null)
{
$category = CategoryModel::find($id);
$categories = CategoryModel::order('sort', 'asc')->select();
return View::fetch('category/edit', ['category' => $category, 'categories' => $categories]);
}
/**
* 更新分类
*/
public function update($id)
{
$category = CategoryModel::find($id);
if (! $category) {
return json(['code' => 0, 'msg' => '分类不存在']);
}
if ((int) Request::post('pid', 0) === (int) $id) {
return json(['code' => 0, 'msg' => '上级分类不能选择自己']);
}
$data = Request::post();
$data['pid'] = (int) Request::post('pid', 0);
$data['update_at'] = time();
$validate = new Validate([
'name|分类名称' => 'require|unique:BlogCategory,name,' . $id . ',id,uid,' . $category->uid,
'pid|上级分类' => 'number',
'sort|排序' => 'number|between:0,999',
]);
if (! $validate->check($data)) {
return json(['code' => 0, 'msg' => $validate->getError()]);
}
$category->save($data);
return json(['code' => 1, 'msg' => '分类更新成功', 'url' => '/blog/backend/category']);
}
/**
* 删除分类
*/
public function delete($id)
{
$category = CategoryModel::find($id);
if ($category) {
if ($category->children()->count() > 0) {
return json(['code' => 0, 'msg' => '该分类下有子分类,请先删除子分类']);
}
if ($category->articles()->count() > 0) {
return json(['code' => 0, 'msg' => '该分类下有文章,无法删除']);
}
$category->delete();
return json(['code' => 1, 'msg' => '分类已删除']);
}
return json(['code' => 0, 'msg' => '分类不存在']);
}
/**
* 批量删除分类(前端 treeTable 勾选后调用)
*/
public function batchDelete()
{
$ids = Request::post('ids', '');
$idArr = array_filter(array_map('intval', explode(',', (string) $ids)));
if (empty($idArr)) {
return json(['code' => 0, 'msg' => '请选择要删除的分类']);
}
$deleted = 0;
$skipped = 0;
foreach ($idArr as $id) {
$category = CategoryModel::find($id);
if (! $category) {
continue;
}
if ($category->children()->count() > 0) {
$skipped++;
continue;
}
if ($category->articles()->count() > 0) {
$skipped++;
continue;
}
$category->delete();
$deleted++;
}
if ($deleted === 0) {
return json(['code' => 0, 'msg' => '选中的分类均包含子分类或文章,无法删除']);
}
$msg = '成功删除 ' . $deleted . ' 个分类';
if ($skipped > 0) {
$msg .= '' . $skipped . ' 个因含子分类/文章已跳过';
}
return json(['code' => 1, 'msg' => $msg]);
}
}