当前位置: 首页 > news >正文

VFP权限管理怎么做?用户模式vs角色组模式,一看就懂

做VFP项目,权限管理是绕不过的坎。10个用户以内还好,一个个配权限就行。50个用户呢?100个呢?每次来新人都要一个一个菜单勾权限,配置到怀疑人生。

今天我们聊聊VFP权限管理的两种模式——用户模式和角色组模式,从设计到代码一次性讲清楚。


一、核心原理:利用菜单的Skip属性

VFP菜单有个属性叫跳过(Skip),可以控制菜单项是否可用。祺佑框架的权限设计就是基于这个简单而强大的机制。

需要三张表

表名

用途

user_pass

用户表(账号、密码等)

Rights

菜单表(description对应菜单名)

RoleRight

权限表(用户/组 + 菜单ID + 是否启用)

💡 description相当于菜单设计器的提示(菜单名),但可以多个菜单名对应一个description。


二、用户模式:简单直接

思路:每个用户直接配置菜单权限,一人一套。

权限加载代码

TEXT TO lcSQLCmd NOSHOW TEXTMERGE select description, isnull(enabled, 0) enabled, userid from rights left join ( SELECT a1.userid, right_id, enabled FROM RoleRight inner join ( select id userid from user_pass where USER_PASS.id = 1 ) a1 on RoleRight.userid = a1.userid ) b1 on Rights.id = right_id ENDTEXT oDBSQLhelper = Newobject("MSSQLHelper", "MSSQLHelper.prg") If oDBSQLhelper.SQLQuery(lcSQLCmd, "main_menus") < 0 Messagebox(oDBSQLhelper.errmsg) Return.F. Endif

用了左连接是因为菜单表随时会增加,这样查询就会将新增菜单项也全部展现,防止找不到权限。

关键技巧:纵向记录变横向属性

* 表变成对象(纵向记录变横向属性,方便菜单权限控制) Select main_menus oMenus = Createobject("empty") Scan AddProperty(oMenus, Alltrim(description), enabled) Endscan AddProperty(_screen, "oMenus", oMenus) && 挂到_screen全局可用

这样_screen.oMenus.采购入库就是.T..F.,直接控制菜单的Skip属性。

用户模式优点:代码极少,简单高效。
用户模式缺点:人多时配置工作量巨大。


三、角色组模式:人多了就靠它

思路:把权限分配给"组",用户只需选择所属组,自动继承组权限。

数据表改动

user_pass表增加两个字段:

字段

类型

说明

u_lx

逻辑型

.T.=组,.F.=用户(默认.F.)

roleid

整型

所属组ID(默认0=没有所属组)

组和用户在同一个表里,用u_lx字段区分。用户可以设置所属组,但组不可以选所属组。

自联接查询用户和组

Set Multilocks On * 用户列表(自联接,显示用户所属组名) TEXT TO lcSQLCmd noshow select a1.u_name, isnull(b1.u_name, '') rolename, a1.roleid, a1.id, u_lx from user_pass a1 left join ( select id, u_name from user_pass where u_lx = 1 ) b1 on a1.roleid = b1.id ENDTEXT oDBSQLhelper = Newobject("MSSQLHelper", "MSSQLHelper.prg") If oDBSQLhelper.SQLQuery(lcSQLCmd, "user_pass") < 0 Messagebox(oDBSQLhelper.errmsg) Return.F. Endif CursorSetProp("Buffering", 5, "user_pass") && 设置为表缓冲

角色组合框设置

* 角色列表(追加空选项方便选择) TEXT TO lcSQLCmd NOSHOW textm SELECT 0 as id, '' as rolename union all SELECT id, u_name as rolename FROM user_pass WHERE u_lx = 1 ENDTEXT If oDBSQLhelper.SQLQuery(lcSQLCmd, "rolelist") < 0 Messagebox(oDBSQLhelper.errmsg) Return.F. Endif

关键业务逻辑

1. 组合框显示/隐藏

This.Visible = !user_pass.u_lx && 如果是组,组合框隐藏掉

2. 权限列表只读控制

* 用户没有所属组,可以编辑权限列表,否则只读 If user_pass.roleid == 0 IfInlist(Thisform.Opcode, 1, 2) This.ReadOnly = .F. This.column3.Enabled = .T. Else This.ReadOnly = .T. This.column3.Enabled = .F. Endif Else This.ReadOnly = .T. This.column3.Enabled = .F. Endif

3. 保存时更新roleid

Tableupdate(1, .T., "user_pass") && 保存缓冲表 * 与DAL_CA共享链接 oDBSQLhelper = Newobject("MSSQLHelper", "MSSQLHelper.prg", "", Thisform.Oca.Datasource) TEXT TO lcSQLCmd NOSHOW TEXTMERGE UPDATE user_pass SET roleid = ?user_pass.roleid WHERE id = ?user_pass.id ENDTEXT If oDBSQLhelper.ExecuteSQL(lcSQLCmd) < 0 Messagebox(Thisform.Oca.msg) Return Endif

四、前端加载权限:组优先

前端用户获取菜单权限的逻辑非常简单:

* 判定用户的roleid不为空,就使用roleid加载权限 * 否则使用用户id来加载权限 If !Empty(user_pass.roleid) nLoadId = user_pass.roleid && 用组ID加载 Else nLoadId = user_pass.id && 用用户ID加载 Endif

五、进阶:Qiyu_Right权限类

祺佑框架还提供了Qiyu_RightManage权限管理类,支持更精细的权限控制:

属性

说明

isAdd

新增权限

isEdit

编辑权限

isDel

删除权限

isCheck

审核权限

isDee

记账权限

isPrit

打印权限

isGd1/isGd2/isGd3

自定义权限

权限控制两层
1.控制界面控件的开闭— 表单控件的Enabled由权限属性决定
2.控制DAL层方法调用— DAL的Get/Add/Edit/Delete方法受isAdd/isEdit/isDel控制

子类示例

* 由父类派生一个权限操作类 Define Class QX_SJQX As Qiyu_RightManage Of Locfile("Qiyu_RightManager.prg") * 钩子方法 - 用户自定义 Procedure GetRightStatus This.isadd = .f. This.isedit = .f. This.isdel = .f. EndProc EndDefine * 在表单的Init方法中使用 Thisform.oright = Newobject("qx_sjqx", "qx_sjqx.prg") Thisform.RightRefresh() && 权限刷新 Thisform.oright.SetRightStatus(Thisform) && 继承父类方法

六、两种模式怎么选?

维度

用户模式

角色组模式

适合人数

≤10人

10人以上

配置工作量

每人一套权限

配好组,新人选组即可

灵活性

★★★★★ 个性定制

★★★ 组内统一

代码复杂度

简单

稍复杂(自联接+缓冲)

维护成本

人员变动需逐个调整

加组/改组权限即可

我的建议
- 小项目(内部几人用)→ 用户模式,够用就好
- 中大型项目 → 角色组模式,一劳永逸
- 可以先上用户模式,随时平滑升级到角色组模式(数据表结构兼容)


互动时间

你的VFP项目用的哪种权限模式?有没有踩过权限管理的坑?评论区聊聊!

觉得有用,点赞+收藏⭐ 下次开发权限直接抄作业!

http://www.gsyq.cn/news/1378758.html

相关文章:

  • Apache空格解析漏洞CVE-2011-2523原理与复现
  • 别再纠结了!用Unity做独立游戏,2D、2.5D还是3D?看完这篇帮你定方向
  • LangGraph工作流引擎到工程实践的量化分析
  • 网盘下载速度提升300%?这款开源插件让你告别限速烦恼
  • 3分钟掌握罗技鼠标宏:终极PUBG压枪解决方案
  • Switch游戏备份工具NxDumpTool:从零开始完整指南
  • 3分钟学会Avidemux:开源视频编辑器的完整快速入门指南
  • 多智能体协作系统:2026年企业级AI应用的核心架构范式
  • 5分钟搭建原神私服:KCN-GenshinServer图形化服务端完整指南
  • 智能解锁Steam游戏清单:Onekey工具的高效实用指南
  • 温差发电驱动轻型电动车:热电模块与催化燃烧器的系统集成实践
  • 洛雪音乐桌面版:一个开源音乐聚合播放器的现代化体验之旅
  • 别再手动调动画了!用Unity Timeline轻松搞定过场动画(附Cube实例演示)
  • FileSaver.js技术解析:客户端文件保存的跨浏览器解决方案深度剖析
  • Unity UI Toolkit避坑指南:3D世界UI、动画与Shader特效的替代方案
  • 3PEAK思瑞浦 TPA6532-VS1R MSOP8 运算放大器
  • Battery Toolkit 完整指南:掌控 Apple Silicon Mac 电池健康的终极方案
  • 告别手动抢茅台!智能预约系统让你轻松实现茅台自由
  • ESP32语音合成方案:基于云端TTS与I2S音频的智能播报系统
  • UE5 Niagara新手教程:5分钟搞定酷炫的条带拖尾特效(附第三人称角色绑定)
  • 如何免费解锁AMD Ryzen处理器隐藏性能?SMUDebugTool完整使用指南
  • 保姆级教程:用Cesium ClippingPlaneCollection实现3D地形‘开窗’与‘遮罩’效果
  • STM32G431实战:拆解蓝桥杯嵌入式‘分任务’调度核心,让你的代码像RTOS一样清晰
  • 别再用 QThread::terminate 省事了,后面真会炸
  • 一文拆透线阵相机型号:从 MV–CL084–90CM 看懂选型逻辑
  • 论文通关利器!好用的AI写作辅助平台,成稿速度超迅速
  • 3个实用技巧:高效解决音乐歌词获取难题
  • 告别黑屏!Unity VideoPlayer跨平台(Windows到Linux)视频播放的编码‘隐形墙’与ffmpeg一键转换方案
  • ComfyUI-WD14-Tagger:智能图像标签提取工具为AI创作者提供的高效解决方案
  • ZonyLrcToolsX:你的智能歌词管家,一键下载四大平台歌词