目录
- 前情回顾与本节目标
- 第一步:页面状态变量准备
- 第二步:编写权限校验自定义方法
- 第三步:页面生命周期绑定
- 第四步:配置组件的"条件展示"
-
- [1. 配置真实业务内容的条件展示](#1. 配置真实业务内容的条件展示)
- [2. 搭建"无权限提示"占位图](#2. 搭建“无权限提示”占位图)
- 最终效果
- 总结
前情回顾与本节目标
在上一讲中,我们成功实现了多角色门户的登录与路由分发。当超级管理员登录后,点击工作台入口,系统会通过 $w.utils.reLaunch 路由到我们的部门管理页面。
但这里存在一个安全漏洞:如果员工把"部门管理"页面的 URL 直接复制发给没有权限的人,或者没有权限的用户手动在浏览器输入了该地址,系统该如何拦截?
本节我们就来解决这个核心问题,为具体的业务页面(以"部门管理"页为例)加上"安全锁"。
本节核心目标:
- 获取鉴权入参:在页面加载时,获取全局对象中的用户标识以及当前页面的标识。
- 数据源鉴权逻辑:通过自定义 JavaScript 方法,查询该用户所属的角色是否被分配了该页面的访问权限。
- 条件渲染拦截:利用微搭组件的"条件展示"属性,有权限则展示业务内容,无权限则展示拦截提示。
第一步:页面状态变量准备
在进入写代码之前,我们需要在部门管理页面中定义两个页面级变量,用来控制 UI 的加载与展示。
在页面设计器右侧的"代码区" -> "当前页面" -> 点击"新建变量":
| 变量名称 | 类型 | 初始值 | 说明 |
|---|---|---|---|
isLoading |
布尔值 | true |
用于控制骨架屏或Loading状态,页面刚进入时正在鉴权,默认为 true |
hasPermission |
布尔值 | false |
用于标记当前用户是否有权限,校验通过后设为 true |
注:设置 isLoading 是为了防止在异步请求未返回时,页面出现短暂的"闪烁"或数据暴露。


第二步:编写权限校验自定义方法
在"代码区" -> "当前页面",点击"新建 JavaScript 方法",命名为 checkPagePermission。

这段代码的核心思路是:从全局状态中获取用户的角色信息,然后根据这些角色从数据库中查询对应的页面权限,检查用户是否拥有访问当前页面的权限。
复制以下代码并粘贴:
javascript
export default async function ({ event, data }) {
try {
// 1. 从全局状态中获取当前登录用户的信息和角色
const currentUser = $w.app.dataset.state.currentUser;
const userRoles = $w.app.dataset.state.userRoles || [];
// 当前页面的唯一标识,与我们在 实战07 中创建的 Pages 表里的 pageId 保持一致
const currentPageId = $w.page.id;
// 如果没有用户信息或用户信息不完整(可能是没登录,或者全局状态丢失)
if (!currentUser || !currentUser._id) {
$w.page.dataset.state.hasPermission = false;
$w.utils.showToast({ title: '未获取到登录信息,请重新登录', icon: 'error' });
// 可选:直接将其踢回登录页
// $w.utils.reLaunch({ pageId: '你的登录页ID' });
return;
}
// 2. 查询用户角色对应的页面权限
let hasAuth = false;
if (userRoles.length > 0) {
// 根据用户角色查询角色信息,获取页面权限
const roleRes = await $w.cloud.callDataSource({
dataSourceName: 'MBA_Roles', // 替换为你的角色表标识
methodName: 'wedaGetRecordsV2',
params: {
filter: {
where: {
code: { $in: userRoles }
}
},
select: {
$master: true,
can_access_pages: true // 角色的页面权限字段
}
}
});
// 检查用户是否有权限访问当前页面
if (roleRes.records && roleRes.records.length > 0) {
for (const role of roleRes.records) {
const authPages = role.can_access_pages || [];
// 检查当前页面是否在角色的权限列表中
const isMatch = authPages.some(page => page.pageId === currentPageId || page._id === currentPageId);
if (isMatch) {
hasAuth = true;
break;
}
}
}
}
// 3. 将鉴权结果写入页面变量
$w.page.dataset.state.hasPermission = hasAuth;
} catch (error) {
console.error('权限校验异常:', error);
$w.page.dataset.state.hasPermission = false;
$w.utils.showToast({ title: '权限校验失败,请联系管理员', icon: 'error' });
} finally {
// 4. 无论鉴权成功与否,结束 Loading 状态
$w.page.dataset.state.isLoading = false;
}
}
第三步:页面生命周期绑定
鉴权方法写好了,我们需要让它在页面刚加载的时候就立即执行。
- 点击左侧大纲树最顶部的 "页面:部门管理" 节点。
- 在右侧属性面板找到 "事件" 配置。
- 找到页面显示 (show)事件。
- 点击添加事件,选择 "自定义 JavaScript 方法" -> 选择我们刚才写好的
checkPagePermission。
注:推荐绑定在 onShow(页面显示)上,这样即使用户通过浏览器的前进后退按钮返回该页面,也会重新触发鉴权,安全性更高。

第四步:配置组件的"条件展示"
这是实现无权限拦截的关键步骤:我们将通过组件的属性,决定给用户看什么。
1. 配置真实业务内容的条件展示
- 在大纲树中,选中包裹你部门管理页面所有核心业务内容的最外层容器网格布局。
- 在右侧属性面板找到 "条件展示"。
- 将默认的开关关闭,点击右侧的
fx(表达式绑定)。 - 输入表达式:
javascript
$w.page.dataset.state.hasPermission
这意味着:只有当鉴权方法跑完,并且结果为 true 时,这块业务内容才会被渲染到页面上。

2. 搭建"无权限提示"占位图
- 在大纲树的最外层(与刚才的业务容器平级),拖入一个新的 "普通容器"。
- 在这个新容器里,放入一个"图标"组件(可以选择一个警告或拦截的 icon)和一个"文本"组件(写上:"抱歉,您暂无权限访问此页面,请联系系统管理员。")。你还可以放一个按钮,点击后调用
$w.utils.navigateBack返回门户页。 - 选中这个无权限提示的容器,在右侧找到 "条件展示"。
- 绑定表达式:
javascript
$w.page.dataset.state.hasPermission === false && $w.page.dataset.state.isLoading === false


这意味着:只有当鉴权结束(加载完成)且结果明确为无权限时,才展示这个提示容器。
(进阶:你还可以为 isLoading === true 单独写一个 Loading 动画容器,逻辑同理)
最终效果
现在,让我们来检验这道"安全锁":
- 正常路径测试:使用配置了管理员角色的账号登录门户,点击"进入管理员工作台"。页面一闪而过极短的 Loading,瞬间展示出完整的左树右表"部门管理"界面。
- 越权路径测试 :退出登录,用一个只有"学员端"权限的普通账号登录。强行在浏览器地址栏输入刚才部门管理页面的 URL 回车。页面加载完成后,核心业务数据完全不可见,屏幕中央仅显示:"抱歉,您暂无权限访问此页面"。
权限隔离完美生效!

总结
本节我们在"微搭"平台上,用极其标准的前端鉴权思路,补齐了整个系统 RBAC (Role-Based Access Control) 的闭环:
- 鉴权时机 :在页面生命周期
onShow时拦截。 - 数据打通 :联动了
Users->RoleUsers->Roles,实现了精准的页面粒度权限验证。 - 前端渲染控制 :利用微搭的条件展示特性,做到数据的物理隔离,防止前端数据泄露。
通过这 8 篇文章的实战,我们的 MBA 培训管理系统已经拥有了一个无比坚固且灵活的底层架构。
下一步,我们将真正深入业务深水区! 我将带大家进入【业务员工作台】,实现核心的 "客户与商机管理(CRM)" 模块,学习如何在微搭中实现复杂的表单联动、线索公海掉落机制。敬请期待!