引言:校长的困惑——我的数据在哪里?亲爱的校长们,在上一篇教程中,我们一起打好了教务管理系统的数据“地基”,并初步搭建了机构管理员的全局视角。现在,让我们把目光聚焦到每一所教培机构的“心脏”——校区,以及校区的核心管理者——校长。 你可能面临这样的疑问: “我作为校长,只想管理我负责的那个校区的数据,低代码平台怎么知道哪个校区是我的?” “我登录系统后,是不是能看到所有校区的数据,那我怎么分辨哪些是我该管的?” “我的教务老师、招生老师,是不是也只能看到他们校区的数据?” 没错,这些是低代码平台在处理复杂权限和数据隔离时常遇到的“痛点”。由于低代码平台通常没有内置“当前用户所属校区”这种开箱即用的概念,我们需要通过一些巧妙的设计来实现数据的“专属感”。 本篇教程,我们将手把手带你解决这个核心问题,让校长登录后,看到的、管理的,都是他自己校区的专属数据!我们将围绕以下几个关键点展开: - 登录后的“身份识别”:
- 全局变量的妙用:
- 数据过滤的魔法:
让我们开始,为校长打造一个真正属于自己的“专属地盘”! 第一部分:登录后的“身份识别与校区上下文加载”——让系统认识你!低代码平台通常会提供一个内置的用户登录功能,并能在用户登录后获取到该用户的唯一标识(我们称之为 platform_user_id)。但这个ID,仅仅是平台账号,它并不知道你是哪个机构的哪个校区的校长。 为了解决这个问题,我们需要在校长登录后的第一时间,进行一次“身份认证”和“校区上下文加载”。 业务场景: 想象一下,校长登录系统后,系统首先会有一个欢迎页面,上面有一个大大的“进入系统”按钮。当校长点击这个按钮时,系统就开始加载他的专属数据。 1. 为什么需要引导页?登录系统后,我们不能直接跳转到首页。因为首页上需要展示的数据(如学员列表、教师列表)是与校区关联的。如果不知道当前登录的是哪个校区的校长,就无法正确过滤数据。 这个引导页的作用,就是充当一个“中转站”,在进入业务页面前,完成以下核心任务: - 获取平台账号信息:
- 查询校长身份: 根据平台账号,从
Principals 表中找到对应的校长记录。 - 关联校区信息: 根据校长记录,从
Campuses 表中找到他所负责的校区信息。 - 设置全局变量: 将这些关键的校区信息存储起来,供后续所有页面使用。
- 跳转到首页:
2. 引导页设计与核心逻辑2.1 搭建页面布局打开校长应用,点击创建页面的图标
输入页面的名称引导页
删除默认的网格布局,添加普通容器
切换到样式,点击CSS with ai,输入如下样式
:root { width: 100%; height: 100vh; }
这样设置是为了让普通容器占满整个屏幕,然后设置普通容器的布局纵向排列,左对齐、垂直居中
普通容器里边添加文本组件和按钮组件,将文本内容修改为欢迎访问系统,按钮改为进入系统
设置文本组件的字体、行高和外边距
设置按钮的字号、内边距、圆角
2.2 创建全局变量页面布局有了之后,我们需要创建一个全局变量来保存校长的身份信息,点击代码区的全局,创建变量
选择自定义变量
输入变量的名称,选择变量的类型为对象,输入初始的数据结构
{ "principal":{ "id":"P001", "platformUserId":"user_abcxyz", "name":"张校长" }, "campus":{ "id":"C001", "name":"市中心校区" }, "organization":{ "id":"O001", "name":"优学教育集团" } }
2.3 创建API全局变量的加载我们要通过定义一个API来获取数据,点击资源链接,点击+号创建API
选择自定义代码
输入API的名称
输入方法的名称和标识
添加入参
输入如下代码,点击方法测试 module.exports = async function(params, context){ const userId = params.userId; // 获取入参中的 userId
if(!userId){ throw new Error('User ID is required.'); }
let principalInfo = null; let campusInfo = null; let organizationInfo = null;
try { // 1. 根据 userId 查询校长信息 (使用 wedaGetItemV2 获取单条) // 根据截图,校长表的数据模型标识为 'Principals' const principalResult = await context.callModel({ dataSourceName: 'Principals', // 数据模型标识为 Principals methodName: 'wedaGetItemV2', // 获取单条数据 params: { select: {"$master":true}, filter: { // 使用 filter 包裹 where where: { platform_user_id: { $eq: userId // 使用 $eq 比较运算符 } } } }, }); console.log("principalResult",principalResult) if(principalResult && Object.keys(principalResult).length>0){ principalInfo = principalResult; }else{ // 如果没有找到对应的校长信息,则直接返回,表示该用户不是校长 return{ principal: null, campus: null, organization: null, message: 'No principal found for the given user ID.' }; }
// 2. 根据校长信息查询校区信息 (使用 wedaGetItemV2 获取单条) // 根据截图,校区表的数据模型标识为 'Campuses_jw' if(principalInfo._id){ // 确保获取到了 principal_id const campusResult = await context.callModel({ dataSourceName: 'Campuses_jw', // 数据模型标识为 Campuses_jw methodName: 'wedaGetItemV2', // 因为一个校长只负责一个校区,所以用获取单条 params: { select: {"$master":true}, filter: { // 使用 filter 包裹 where where: { principal_id: { $eq: principalInfo._id // 使用 $eq 比较运算符 } } } }, }); console.log("campusResult",campusResult) if(campusResult && Object.keys(campusResult).length>0){ campusInfo = campusResult; } }
// 3. 根据校区信息查询机构信息 (使用 wedaGetItemV2 获取单条) // 假设机构表的数据模型标识为 'Organizations' if(campusInfo && campusInfo.org_id){ // 确保获取到了校区信息和机构ID const organizationResult = await context.callModel({ dataSourceName: 'Organizations', // 假设机构表的数据模型标识 methodName: 'wedaGetItemV2', // 获取单条数据 params: { select: {"$master":true}, filter: { // 使用 filter 包裹 where where: { _id: { $eq: campusInfo.org_id // 使用 $eq 比较运算符 } } } }, });
if(organizationResult && Object.keys(organizationResult).length>0){ organizationInfo = organizationResult; } }
// 封装并返回最终结果 return{ principal: { id: principalInfo._id, platformUserId: principalInfo.platform_user_id, name: principalInfo.full_name, // 假设校长表中的姓名是 full_name phone_number: principalInfo.phone_number, avatar_url: principalInfo.avatar_url, // 从校长表中获取头像URL email: principalInfo.email, // 从校长表中获取邮箱地址 // 根据实际需要添加更多校长属性 }, campus: campusInfo ? { id: campusInfo._id, name: campusInfo.campus_name, address: campusInfo.campus_address, contact_phone: campusInfo.contact_phone, campus_type: campusInfo.campus_type, // 从校区表中获取校区类型 campus_notice: campusInfo.campus_notice, // 从校区表中获取门店公告 campus_images_urls: campusInfo.campus_images_urls, // 从校区表中获取宣传图片URLs campus_video_url: campusInfo.campus_video_url, // 从校区表中获取校区视频URL detailed_intro: campusInfo.detailed_intro, // 从校区表中获取详细介绍 // 根据实际需要添加更多校区属性 }: null, organization: organizationInfo ? { id: organizationInfo._id, name: organizationInfo.org_name, org_logo_url: organizationInfo.org_logo_url, org_features: organizationInfo.org_features, // 根据实际需要添加更多机构属性 }: null };
} catch (error){ console.error('Error in getPrincipalContextByUserId API:', error); throw new Error(`Failed to get principal context: ${error.message}`); } };
输入入参,执行成功后点击出参自动映射
2.4 创建自定义方法API定义好之后,我们需要创建一个自定义方法来调用我们的API。在全局点击+,选择新建javascript方法
输入如下代码 export default async functiongetPrincipalInfo(){ try { $w.utils.showLoading({ title: '加载中', mask: false }); const apiResult = await $w.cloud.callDataSource({ dataSourceName: 'xzgl_tuk3kj4', // API所属的数据源标识,用于后端API的查找和调用。 methodName: 'getPrincipalContextByUserId', // 后端自定义API的名称。 params: { userId: $w.auth.currentUser.userId // 获取当前登录用户的唯一标识符 (平台用户ID)。 }, });
if(apiResult && apiResult.principal){ // 成功获取校长上下文信息:将API返回的数据(包含校长、校区、机构信息)赋值给一个变量。 $w.app.dataset.state.currentPrincipal = apiResult;
// 【调试输出】确认全局变量已成功设置。 console.log("全局校长上下文已设置:", $w.app.dataset.state.currentPrincipal); $w.utils.hideLoading(); $w.utils.navigateTo({ pageId: 'Campuses_jw_iy_list', // 跳转的目标页面ID。 });
}else{ console.warn("当前用户不是校长或未找到相关信息:", apiResult ? apiResult.message :'未知错误'); // 使用Toast提示,告知用户操作失败或没有权限。 $w.utils.showToast({ title: '失败', // 提示标题。 icon: 'error', // 提示图标为错误类型。 duration: 2000 // 提示显示2秒。 }); }
} catch (error){
console.error("获取校长信息失败:", error); // 使用Toast提示,告知用户系统出现问题。 $w.utils.showToast({ title: '失败', // 提示标题。 icon: 'error', // 提示图标为错误类型。 duration: 2000 // 提示显示2秒。 }); } finally { $w.utils.hideLoading(); } }
选中按钮,设置点击事件,调用我们的方法
第二部分:全局变量的应用与数据过滤——让数据为你而动!一旦我们将当前校区的核心信息存储在全局变量中,后续所有涉及数据展示和操作的页面,都可以利用这些全局变量来自动过滤数据,实现“本校区数据隔离”的效果。 业务场景: 校长进入“校区管理”页面,只想查看并编辑他自己负责的校区信息。 选中数据表格组件,设置数据筛选
筛选条件设置为数据标识等于我们全局变量校区的数据标识
总结:掌控核心数据,赋能校区高效运营!通过本篇教程,我们攻克了低代码平台中实现“本校区数据隔离”的核心挑战。我们学习了: - 如何通过登录后的引导页,进行用户身份的识别和校区上下文的加载。
- 如何巧妙地利用全局变量,在整个应用中传递当前校区的关键信息。
- 如何在各个页面中应用数据过滤,确保校长只查看和管理自己校区的专属数据。
现在,你的校长应用已经具备了强大的数据隔离能力,能够让校长更专注于本校区的运营,大大提升管理效率。 在下一篇教程中,我们将继续深入,探讨学员管理模块的搭建,让学员信息、学费、课时等数据也能在你的低代码教务系统中井然有序! 立即动手,让你的校长应用真正“活”起来吧!
|