签入版本
This commit is contained in:
@@ -1,23 +1,23 @@
|
||||
# 6.4 部门管理
|
||||
|
||||
:::tip 概述
|
||||
部门管理维护组织架构数据,支持树形结构,是数据权限(按部门过滤)的基础。继承 BaseTenantLogic 实现租户隔离。
|
||||
部门管理维护组织架构数据,支持树形结构,是数据权限(按部门过滤)的基础。`DeptService` 继承 `BaseTenantService` 实现租户隔离。
|
||||
:::
|
||||
|
||||
## 模块特点
|
||||
|
||||
| 特性 | 说明 |
|
||||
|------|------|
|
||||
| 基类 | BaseTenantLogic(租户隔离) |
|
||||
| 树形结构 | treeParentField='parent_id' |
|
||||
| 唯一校验 | name 全局唯一 |
|
||||
| 删除校验 | beforeDelete 检查是否存在子部门 |
|
||||
| 数据权限 | 被 UserLogic 的 dataScopeDeptField='dept_id' 引用 |
|
||||
| 基类 | `BaseTenantService`(租户隔离) |
|
||||
| 树形结构 | `treeParentField='parent_id'`、`treeLikeField='name'` |
|
||||
| 唯一校验 | `name` 按租户分组唯一(`['name','tenant_id']`) |
|
||||
| 删除校验 | `beforeDelete` 检查子部门与关联用户(均存在时阻止删除) |
|
||||
| 数据权限 | 被 `UserService` 的 `dataScopeDeptField='dept_id'` 引用 |
|
||||
|
||||
## 数据库表结构
|
||||
|
||||
```sql
|
||||
CREATE TABLE `think_dept` (
|
||||
CREATE TABLE `laravel_dept` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`name` varchar(150) NOT NULL COMMENT '部门名称',
|
||||
`type` int DEFAULT 0 COMMENT '部门类型:1-公司 2-子公司 3-部门 4-小组',
|
||||
@@ -37,109 +37,82 @@ CREATE TABLE `think_dept` (
|
||||
|
||||
| 方法 | 路径 | 权限码 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| GET | `/api/dept/list` | sys:dept:page | 树形列表 |
|
||||
| GET | `/api/dept/detail/:id` | sys:dept:detail | 详情 |
|
||||
| GET | `/api/dept/list` | sys:dept:list | 树形列表 |
|
||||
| GET | `/api/dept/detail/{id}` | sys:dept:detail | 详情 |
|
||||
| POST | `/api/dept/add` | sys:dept:add | 新增 |
|
||||
| PUT | `/api/dept/update` | sys:dept:update | 修改 |
|
||||
| DELETE | `/api/dept/delete/:id` | sys:dept:delete | 删除 |
|
||||
| DELETE | `/api/dept/delete/{id}` | sys:dept:delete | 删除 |
|
||||
|
||||
## 核心代码
|
||||
:::tip 树形接口
|
||||
部门使用 `_list()` 而非 `_page()`,返回全量数据后构建树形结构(树形数据需要父子完整链,不适合分页)。
|
||||
:::
|
||||
|
||||
### Logic 配置
|
||||
## Service 配置(来自项目实际代码)
|
||||
|
||||
```php
|
||||
// app/logic/DeptLogic.php
|
||||
|
||||
class DeptLogic extends BaseTenantLogic
|
||||
class DeptService extends BaseTenantService
|
||||
{
|
||||
/**
|
||||
* 关联的模型类
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
use HasCrudOperations, HasQueryScopes, HasUniqueCheck;
|
||||
|
||||
protected string $modelClass = Dept::class;
|
||||
|
||||
/**
|
||||
* LIKE 模糊匹配字段
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $pageLikeFields = ['name'];
|
||||
protected array $pageEqFields = []; // 无精确匹配(列表整体按树返回)
|
||||
protected array $pageOrderBy = ['field' => 'sort', 'type' => 'asc'];
|
||||
|
||||
// name 在同一租户内唯一
|
||||
protected array $uniqueFields = [['name', 'tenant_id']];
|
||||
|
||||
// 树形结构
|
||||
protected string $treeParentField = 'parent_id';
|
||||
protected string $treeLikeField = 'name';
|
||||
|
||||
/**
|
||||
* 精确匹配字段
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $pageEqFields = ['type'];
|
||||
|
||||
/**
|
||||
* 默认排序规则
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $pageOrderBy = [
|
||||
['field' => 'tenant_id', 'type' => 'asc'],
|
||||
['field' => 'sort', 'type' => 'asc'],
|
||||
];
|
||||
|
||||
/**
|
||||
* 唯一性校验字段
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $uniqueFields = ['name'];
|
||||
|
||||
/**
|
||||
* 删除前处理:检查是否存在子部门
|
||||
* 删除前处理:检查子部门与关联用户
|
||||
*
|
||||
* @param int $id 待删除的部门 ID
|
||||
* @return void
|
||||
* @throws \Exception 当存在子部门时抛出
|
||||
* @throws BizException 当存在子部门或关联用户时抛出
|
||||
*/
|
||||
protected function beforeDelete(int $id): void
|
||||
{
|
||||
$childCount = Dept::where('parent_id', $id)->count();
|
||||
if ($childCount > 0) {
|
||||
throw new \Exception('该部门下存在子部门,不可删除');
|
||||
$hasChildren = Dept::where('parent_id', $id)->exists();
|
||||
if ($hasChildren) {
|
||||
throw new BizException('存在子部门,不可删除');
|
||||
}
|
||||
|
||||
$hasUsers = User::where('dept_id', $id)->exists();
|
||||
if ($hasUsers) {
|
||||
throw new BizException('该部门下存在用户,不可删除');
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::tip 树形接口
|
||||
部门使用 `_list()` 而非 `_index()`,返回全量数据后由前端或 Logic 构建树形结构。
|
||||
:::
|
||||
## 删除保护流程
|
||||
|
||||
### Controller 示例
|
||||
|
||||
```php
|
||||
// app/controller/DeptController.php
|
||||
|
||||
class DeptController extends BaseController
|
||||
{
|
||||
protected DeptLogic $logic;
|
||||
|
||||
protected function initialize(): void
|
||||
{
|
||||
$this->logic = new DeptLogic();
|
||||
}
|
||||
|
||||
#[Log('部门管理-查询树形列表', Log::TYPE_QUERY)]
|
||||
#[Permission('sys:dept:page', '部门列表')]
|
||||
public function list(): Json
|
||||
{
|
||||
return parent::_list($this->logic);
|
||||
}
|
||||
|
||||
#[Log('部门管理-新增记录', Log::TYPE_ADD, '新增部门:{name}')]
|
||||
#[Permission('sys:dept:add', '添加部门')]
|
||||
public function add(): Json
|
||||
{
|
||||
return parent::_add($this->logic, $this->getJsonBody());
|
||||
}
|
||||
|
||||
// ... 其他 CRUD 方法
|
||||
}
|
||||
```text
|
||||
DELETE /api/dept/delete/{id}
|
||||
│
|
||||
▼
|
||||
Controller::_delete() → Service::delete()
|
||||
│
|
||||
▼
|
||||
beforeDelete($id)
|
||||
├─ 存在子部门 → throw BizException('存在子部门,不可删除')
|
||||
├─ 存在关联用户 → throw BizException('该部门下存在用户,不可删除')
|
||||
│ → 事务回滚 → {"code":1,"msg":"...不可删除"}
|
||||
▼
|
||||
DB::transaction { 软删除 is_delete=1(树形子节点不级联,需逐级删除) }
|
||||
```
|
||||
|
||||
:::warning 不做级联删除
|
||||
删除父部门不会级联删除子部门(软删除保持数据可恢复)。正确顺序:自叶子节点向上逐级删除;存在子部门时接口直接返回业务错误。
|
||||
:::
|
||||
|
||||
## 与其他模块的关系
|
||||
|
||||
| 关系 | 说明 |
|
||||
|------|------|
|
||||
| 用户 → 部门 | `laravel_user.dept_id` 外键,数据权限按此字段过滤 |
|
||||
| 部门树 → 前端 | 用户表单中以级联选择器回显(`deptName` 由 `afterDetail` 补全) |
|
||||
| 数据权限 | 范围解析为 2(本部门)时查询叠加 `WHERE dept_id = 本部门`(见 [5.9 数据权限](/zh/core/data-scope.html);当前默认解析为 1) |
|
||||
|
||||
Reference in New Issue
Block a user