应优先通过服务端预检权限再打开弹窗:点击按钮时先 fetch 调用 /api/auth/check 接口校验目标路径权限,allowed 为 true 才调用 layer.open,否则提示原因;需在 layui.use(['layer'], ...) 内执行。

用户点击按钮触发 layer.open 时,需先确认当前角色是否有权访问目标页面,权限不足就中断弹窗打开流程,避免白屏或后端 403 返回后才提示。
服务端预检:打开前用 fetch 获取权限状态
在调用 layer.open() 前,先向后端发起轻量级权限校验请求,成功再打开弹窗,失败则直接提示并终止。
第一步:准备权限校验接口,例如 POST /api/auth/check,请求体携带目标路径(如 {"path":"/admin/user-edit.html"}),后端返回 { "allowed": true, "reason": "" } 或 { "allowed": false, "reason": "无编辑权限" }。
第二步:绑定按钮点击事件,在回调中发起 fetch:
document.getElementById('edit-btn').onclick = function() {<br> fetch('/api/auth/check', {<br> method: 'POST',<br> headers: { 'Content-Type': 'application/json' },<br> body: JSON.stringify({ path: '/admin/user-edit.html' })<br> })<br> .then(res => res.json())<br> .then(data => {<br> if (data.allowed) {<br> layer.open({ type: 2, content: '/admin/user-edit.html' });<br> } else {<br> layer.msg(data.reason || '权限不足,无法打开', { icon: 5 });<br> }<br> })<br> .catch(() => layer.msg('校验失败,请重试', { icon: 2 }));<br>};
这一步必须放在 layui.use(['layer'], function(){}) 内部执行,否则 layer 未定义会报错。
前端缓存权限标识 + 路径白名单快速拦截
适用于权限规则稳定、不频繁变更的后台系统。把用户可访问的 URL 列表存在 localStorage 或全局变量中,点击时同步比对。
方法一:初始化时拉取一次权限列表,存入 window.__PERMS__
layui.use(['layer'], function(){<br> const perms = JSON.parse(localStorage.getItem('user_perms') || '[]');<br> window.__PERMS__ = perms;<br>});
方法二:按钮点击时校验
if (!window.__PERMS__.includes('/admin/user-edit.html')) {<br> layer.msg('您没有访问该功能的权限', { icon: 5 });<br> return;<br>}
【注意】此方式仅作前端体验优化,不可替代后端鉴权。白名单必须由后端下发,禁止前端硬编码或拼接生成。
iframe 加载中实时拦截:onload 后二次鉴权
当弹窗已打开但内容尚未渲染完成时,可在 iframe 加载完毕后检查其响应头或 DOM 特征,判断是否被后端重定向到登录页或 403 页面,立即关闭。
在 layer.open 的 success 回调中监听 iframe 加载完成,并读取其 document.title 或 body 内容特征:
success: function(layero, index) {<br> const iframe = layero.find('iframe')[0];<br> iframe.onload = function() {<br> try {<br> // 跨域时这里会抛 SecurityError,直接跳过<br> const doc = iframe.contentDocument || iframe.contentWindow?.document;<br> if (doc && (<br> doc.title.includes('登录') ||<br> doc.body?.innerText.includes('403') ||<br> doc.querySelector('.forbidden-tip')<br> )) {<br> layer.msg('会话失效或权限不足', { icon: 5 });<br> layer.close(index);<br> }<br> } catch (e) {<br> // 跨域异常,不做处理,依赖服务端预检兜底<br> }<br> };<br>}











