diff --git a/app/admin/validate/v1/NavigationItemValidate.php b/app/admin/validate/v1/NavigationItemValidate.php index bf2dbff7..4da9e1bb 100644 --- a/app/admin/validate/v1/NavigationItemValidate.php +++ b/app/admin/validate/v1/NavigationItemValidate.php @@ -3,6 +3,8 @@ declare (strict_types = 1); namespace app\admin\validate\v1; +use app\admin\model\v1\SysNavigationItemModel; +use think\facade\Db; use think\Validate; class NavigationItemValidate extends Validate @@ -16,7 +18,7 @@ class NavigationItemValidate extends Validate protected $rule = [ 'id' => 'require|integer', 'nav_id' => 'require|integer', - 'pid' => 'integer', + 'pid' => 'integer|different:id|checkPidNotBeChildren', 'name' => 'require|max:64', 'icon' => 'max:64', 'link_type' => 'require|integer', @@ -33,23 +35,51 @@ class NavigationItemValidate extends Validate * @var array */ protected $message = [ - 'id.require' => 'ID不能为空', - 'id.integer' => 'ID必须为整数', - 'nav_id.require' => '导航ID不能为空', - 'nav_id.integer' => '导航ID必须为整数', - 'pid.integer' => '父级ID必须为整数', - 'name.require' => '导航名称不能为空', - 'name.max' => '导航名称最多不能超过64个字符', - 'icon.max' => '图标最多不能超过64个字符', - 'link_type.require' => '链接类型不能为空', - 'link_type.integer' => '链接类型必须为整数', - 'link.max' => '链接最多不能超过255个字符', - 'sort.integer' => '排序必须为整数', - 'blank.in' => '是否新窗口打开只能是0或1', - 'status.require' => '状态不能为空', - 'status.in' => '状态只能是1或-1', + 'id.require' => 'ID不能为空', + 'id.integer' => 'ID必须为整数', + 'nav_id.require' => '导航ID不能为空', + 'nav_id.integer' => '导航ID必须为整数', + 'pid.integer' => '父级ID必须为整数', + 'pid.different' => '父级ID不能为自身', + 'pid.checkPidNotBeChildren' => '父级ID不能为自身的子导航', + 'name.require' => '导航名称不能为空', + 'name.max' => '导航名称最多不能超过64个字符', + 'icon.max' => '图标最多不能超过64个字符', + 'link_type.require' => '链接类型不能为空', + 'link_type.integer' => '链接类型必须为整数', + 'link.max' => '链接最多不能超过255个字符', + 'sort.integer' => '排序必须为整数', + 'blank.in' => '是否新窗口打开只能是0或1', + 'status.require' => '状态不能为空', + 'status.in' => '状态只能是1或-1', ]; + // 验证pid + protected function checkPidNotBeChildren($value, $rule, $data = []) + { + if ($value == 0) { + return true; + } + $table_name = (new SysNavigationItemModel)->getTable(); + $children = Db::query( + preg_replace( + '/\s+/u', + ' ', + "WITH RECURSIVE tree_by AS ( + SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']} + UNION ALL + SELECT k.id, k.pid FROM $table_name k INNER JOIN tree_by t ON t.id = k.pid + ) + SELECT id FROM tree_by WHERE id <> {$data['id']};" + ) + ); + if (!empty($children) && in_array($data['pid'], array_column($children, 'id'))) { + return false; + } + + return true; + } + // 定义场景 protected $scene = [ 'add' => ['nav_id', 'pid', 'name', 'icon', 'link_type', 'link', 'sort', 'blank', 'status'],