# 6.10 分类管理 :::tip 概述 分类管理支持树形分类数据,可用于文章分类、商品分类等场景。继承 BaseTenantLogic 实现租户隔离。 ::: ## 模块特点 | 特性 | 说明 | |------|------| | 基类 | BaseTenantLogic(租户隔离) | | 唯一校验 | category_name + parent_id 复合唯一(同一父级下名称不可重复) | | 删除校验 | beforeDelete 检查子分类和关联文章 | | 模糊搜索 | category_name | | 精确匹配 | parent_id | ## 数据库表结构 ```sql CREATE TABLE `think_category` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', `category_name` varchar(100) NOT NULL COMMENT '分类名称', `category_code` varchar(100) DEFAULT NULL COMMENT '分类编码', `parent_id` int DEFAULT 0 COMMENT '上级ID', `sort` int DEFAULT 0 COMMENT '排序', `note` varchar(100) DEFAULT NULL COMMENT '分类备注', `create_user` varchar(50) DEFAULT NULL COMMENT '创建人', `create_time` datetime DEFAULT (now()) COMMENT '创建时间', `update_user` varchar(50) DEFAULT NULL COMMENT '更新人', `update_time` datetime DEFAULT (now()) COMMENT '更新时间', `is_delete` int DEFAULT 0 COMMENT '删除标识:0-正常 1-已删除', PRIMARY KEY (`id`) ) COMMENT = '文章分类表'; ``` ## API 接口 | 方法 | 路径 | 权限码 | 说明 | |------|------|--------|------| | GET | `/api/category/page` | sys:category:page | 分页列表 | | GET | `/api/category/list` | sys:category:list | 全量列表 | | GET | `/api/category/detail/:id` | sys:category:detail | 详情 | | POST | `/api/category/add` | sys:category:add | 新增 | | PUT | `/api/category/update` | sys:category:update | 修改 | | DELETE | `/api/category/delete/:id` | sys:category:delete | 删除 | | DELETE | `/api/category/batchDelete` | sys:category:batchDelete | 批量删除 | ## 核心代码 ```php // app/logic/CategoryLogic.php class CategoryLogic extends BaseTenantLogic { protected string $modelClass = Category::class; protected array $pageLikeFields = ['category_name']; protected array $pageEqFields = ['parent_id']; protected array $pageOrderBy = [ ['field' => 'tenant_id', 'type' => 'asc'], ['field' => 'sort', 'type' => 'asc'], ]; /** * 唯一性校验字段 * * 同一父级下分类名称不可重复 * * @var array */ protected array $uniqueFields = [['category_name', 'parent_id']]; /** * 删除前处理:检查子分类和关联文章 * * @param int $id 待删除的分类 ID * @return void * @throws \Exception 当存在子分类或关联文章时抛出 */ protected function beforeDelete(int $id): void { $childCount = Category::where('parent_id', $id)->count(); if ($childCount > 0) { throw new \Exception('该分类下存在子分类,不可删除'); } $articleCount = Article::where('category_id', $id)->count(); if ($articleCount > 0) { throw new \Exception('该分类下存在文章,不可删除'); } } } ``` ### Controller 代码 ```php // app/controller/CategoryController.php class CategoryController extends BaseController { protected CategoryLogic $logic; protected function initialize(): void { $this->logic = new CategoryLogic(); } #[Log('分类管理-查询分页记录', Log::TYPE_QUERY)] #[Permission('sys:category:page', '分类分页')] public function page(): Json { return parent::_index($this->logic); } #[Log('分类管理-查询树形列表', Log::TYPE_QUERY)] #[Permission('sys:category:list', '分类列表')] public function list(): Json { return parent::_list($this->logic); } #[Log('分类管理-新增记录', Log::TYPE_ADD, '新增分类:{category_name}')] #[Permission('sys:category:add', '添加分类')] public function add(): Json { try { $id = $this->logic->add($this->getJsonBody()); return $this->success(['id' => $id], '添加成功'); } catch (\Exception $e) { return $this->fail($e->getMessage()); } } #[Log('分类管理-修改记录', Log::TYPE_UPDATE, '修改分类ID:{id}')] #[Permission('sys:category:update', '修改分类')] public function update(): Json { $data = $this->getJsonBody(); $id = $data['id'] ?? 0; if (empty($id)) return $this->fail('缺少id参数'); try { $this->logic->update($id, $data); return $this->success(null, '修改成功'); } catch (\Exception $e) { return $this->fail($e->getMessage()); } } #[Log('分类管理-删除记录', Log::TYPE_DELETE, '删除分类ID:{id}')] #[Permission('sys:category:delete', '删除分类')] public function delete(int $id): Json { return parent::_remove($this->logic, $id); } #[Log('分类管理-批量删除', Log::TYPE_DELETE)] #[Permission('sys:category:delete', '删除分类')] public function batchDelete(): Json { $ids = $this->getJsonBody()['ids'] ?? []; return parent::_batchRemove($this->logic, $ids); } } ``` :::warning 复合唯一性 分类的唯一性校验使用复合格式 `[['category_name', 'parent_id']]`,表示同一父级下分类名称不可重复,但不同父级下可以有同名分类。 :::