Skip to content

fix: 修复权限/角色表单菜单树不渲染及 flushMenuCache 未定义错误 - #31

Merged
PrintNow merged 2 commits into
2.0from
fix/issue-30-permission-form
Nov 13, 2026
Merged

PrintNow merged 2 commits into
2.0from
fix/issue-30-permission-form

Conversation

@PrintNow

Copy link
Copy Markdown
Owner

Fixes #30

问题

  1. 权限表单中“菜单”树为空,HTTP 路径等字段显示为原生多选框(截图见 issue)。
  2. 修改权限后提交报错 Call to undefined method Dcat\Admin\Models\Permission::flushMenuCache(),但数据已保存。

根因

两处均由近期提交引入:

问题 1(195435ce / af0d4db2):multipleselect.blade.php 新增的脚本写成 $('.{{$selector}}'),而 $selector 本身已是带前缀的 #form-id .field_xxx,渲染后变成:

$('.#form-1 .field_http_method_abc').off('change.select2').on(...)

jQuery 抛出选择器语法错误。Dcat 会把页面内所有 <script> 合并后一次执行,这段报错后其后的 tags、tree 等字段初始化全部中断,于是菜单树为空、HTTP 路径未初始化。此外 off('change.select2') 会误删 select2 自身绑定的内部监听。

问题 2(f676ac3c):Form::saved() 的回调在 HasEvents::makeListener 中会被 bindTo($model) 重新绑定到模型实例,回调里的 $this->flushMenuCache() 实际调用的是 Permission / Role 模型的方法。RoleController 同样受影响。

修改

  • select-script.blade.php:新增 multiple 开关,在同一个 Dcat.init 回调中按 name 查找兄弟隐藏 input,有选中值时禁用,并移除 ?. 以兼容旧浏览器。
  • multipleselect.blade.php:删除独立脚本,改为 @include('admin::form.select-script', ['multiple' => true])。同一选择器不能重复 Dcat.init,否则会被 initialized 标记跳过,所以不能单独注册。
  • HasMenuTreeField:flushMenuCache() 改为 flushMenuCacheOnSaved(Form $form),回调内不依赖 $this。
  • PermissionController / RoleController:改用 flushMenuCacheOnSaved() 注册。

验证

  • php -l 与 PHPStan(--memory-limit=1G)通过,仅剩与本次无关的 Zip.php ignore 规则不匹配提示。
  • 用独立 Blade 编译器渲染 multipleselect 模板,修复前输出 $('.#form-1 .field_...'),修复后生成的脚本经 node --check 语法检查通过。
  • 未运行 Dusk 浏览器测试(需要已安装本包的 Laravel 应用及 MySQL)。建议合并前在实际项目中打开权限/角色的新增与编辑表单做一次人工确认。

问题 1:multipleselect 模板新增的脚本使用 `$('.{{$selector}}')`,而 `$selector`
本身已是 `#form-id .field_xxx`,拼接后变为 `$('.#form-id .field_xxx')`,jQuery 抛出
选择器语法错误,导致同一批合并执行的脚本中断,其后的 tags、tree 等字段全部未初始化
(表现为“菜单”树为空、HTTP 路径显示为原生多选框)。

- 移除该独立脚本,将“有选中值时禁用占位隐藏 input”的逻辑并入 select-script 的
  Dcat.init 回调(通过 `multiple` 参数开启),按 name 查找兄弟隐藏 input,
  不再使用 `?.`,并避免 `off('change.select2')` 误删 select2 内部监听。
- 同一选择器不能重复 Dcat.init,否则会被 `initialized` 标记跳过,故不能单独注册。

问题 2:Form 的 saved 回调会被 `bindTo($model)` 重新绑定到模型实例,
回调内 `$this->flushMenuCache()` 实际调用的是 Permission/Role 模型上的方法,
抛出 `Call to undefined method ...::flushMenuCache()`。

- HasMenuTreeField 改为提供 `flushMenuCacheOnSaved(Form $form)`,回调内不依赖 `$this`。
- PermissionController、RoleController 统一改用该方法注册。
@PrintNow PrintNow mentioned this pull request Oct 20, 2026
- Composer >= 2.10 默认开启 policy.advisories.block,Laravel 10/11 全部版本带安全公告
  被拒绝加载,PHP 8.1 下无可安装版本。仅在 CI 安装前关闭该阻断。
- 新版 PHPStan 不再报告 Zip.php 的 `$folders might not be defined`,
  baseline 条目变为未匹配错误。显式初始化 `$folders = []` 并移除该条目。
@PrintNow

Copy link
Copy Markdown
Owner Author

CI 两处失败均为环境漂移,与本次代码改动无关,已在本 PR 中一并修复并通过全部 PHP 8.1–8.5 矩阵:

  • PHP 8.1:Composer ≥ 2.10 默认开启 policy.advisories.block,Laravel 10/11 所有版本带安全公告被拒绝加载,8.1 下无可安装版本。CI 安装前关闭该阻断(不影响包声明的支持范围)。
  • PHPStan:无 composer.lock,CI 拉到新版 PHPStan 后不再报 Zip.php 的 $folders 未定义,baseline 条目变为未匹配错误。已显式初始化 $folders = [] 并移除该条目。

@PrintNow
PrintNow merged commit a6d2b0b into 2.0 Nov 13, 2026
5 checks passed
PrintNow added a commit that referenced this pull request Nov 13, 2026
fix: 修复权限/角色表单菜单树不渲染及 flushMenuCache 未定义错误
@PrintNow
PrintNow deleted the fix/issue-30-permission-form branch November 13, 2026 11:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

权限功能有问题

1 participant