维普资讯 http://www.cqvip.com
…… C0■P岍硼PROG删MING删U盯E¨_CE……………………………………………… ………………… . 管理伤垂系饶强 仅限矽冬分配钓舒决方 李 曾勇进 摘 要 本文总结了多年实践中常用的操作权限的动态分配问题的解决方案,并给出了 PowerBuilder的开发实例。 关键词操作权限,动态分配 一、问题陈述 在给企业开发MIS系统的过程中,感受颇深的是,公司的 Create-I-able department( dpid _varchar(3) not nul1.%%部门代码 dpname _varchar(20) varchar(3) %%部门名称 .%%本部门的上级部门 管理者对职员的操作权限比较重视。在公司内各个部门的工作 职能都不尽相同,在实现不同部门工作职能,在实现的时候, 往往大都是反映在系统的MD[主窗口的菜单中。如果不对职 员的操作权限做出的话,将会导致职员职责上的混乱和滥 用,不仅不好管理,也难做到各司其职,这一点是管理者最忌 讳的,也是最头痛的,所以必须对职员的操作权限做出。 另外一个问题是,在公司内部,基于各种可能的原因,职员的 dpJevel integer dpparent _not null,%%部门的组织层次 dpmanager varchar(20) _dpnote _.%%本部门的主管 varchar(100) %%本部门说明 varchar(200) ,%%本部门的职责 dptask Primarv Key(dpjd) ): 岗位往往不是固定的,经常会发生转岗或者换岗,显然,其相 应的操作权限亦应该随之发生变化,所以在对职员的权限管理 %%若是总经理的话,可以将dpjoarent的值设为 O %%dpJevel用来记录部门的所在层次,根结点的层次为1,依 次类推 必须戗到动态分配,以可视化的界面提供给管理者使用。这 样,管理者可以根据情况来动态分配职员的操作权限。 %%职员基本情况表 Create Table employee 二、解决方案 对于职员的管理应该按照部门进行管理,在以前的文章 中,曾经探讨过对“客户资料”的管理也是按照部门管理的, 并且给出了解决方案,现在也是按照此思路来实现职员权限的 动态分配。 本方案以SYBASE ASA 6.0为数据库平台,开发工具采用 PowerBuilder8.03。首先,先给出相关对象的数据字典 (WATCOM SQL): (e_code char(3) not nul1.%%职员帐户代码 edeparment varchar(3),%%职员的隶属部门代码 _e_right varchar(600) not null,%%职员的权限代码串 _echeck char(1)default 1 .%%用于可视设计中的 checkbox Primarv Key(e_code) , Foreign Key(e_department)references department(dpid) on delete restrict on update cascade %%部门基本情况表 4- 4- 七 ): 四、结语 ADO数据库连接字符串的动态设置及加密解密极大的方 便了Delphi开发数据库应用软件的安装和部署,数据库连接字 符串中3个重要的参数值,既可以保存在初始文件中,还可以 保存在操作系统的注册表中等。 参考文献 1.陈灿煌著Delphi5彻底研究.中国铁道出版社,2001 2.http://community.csdn.net/ (收稿日期:2007年2月19日) 维普资讯 http://www.cqvip.com
…: …………… ……………… … …… …‘’… … … 实用第一 智慧密集 。 …. . . 。 %%系统菜单描述表 分配CheekBox 菜单项名称ltemCmame %%本表记录MDI系统主菜单上各个将要纳入权限管理的 %%菜单项. 打勾 功能组一 create table menucode( 未打勾 功能组二 itemcode char(3)not null, 打勾 报价 %%菜单项的内部编码,供标识使用 打勾 报表 parentitemcode char(3)not null default 000 , 未打勾 客户资料 %%本菜单项的父菜单 未打勾 单证 itemname varchar(1 2)not nul1. 未打勾 单据 %%本菜单项在PB中的对象名称 itemcname varchar(40)not null,%%本菜单项的中文名称 primary key(itemcode) ): d—right的界面 特别说明一下,假设MDI主窗口的菜单为m_menu,在其 在窗口w_right中定义一个datawindow控件,相对应的 下面有两个子菜单“功能组一” (m_seviceI)和“功能组二” datawindow对象为d right,d_right的SQL数据源为“系统菜 (m_sevice2)。前者下面有三个菜单项,它们分别是“报价” 单表”。在设计它的时候,显示两个数据项,一个是CHECK— (m_quotation)、 “报表” (m_report)和“客户资料” BOX控件,用来表明当前的菜单项对于指定的职员是否可用, (m_customer);后者下面有两个菜单项,它们分别是“单 如果checked=true的话。表明指定的职员可以使用,否则就 证”(m_credit)和“单据”(m_document)。那么关于菜单 不能使用;另外一个数据项是COLUMN,它是“系统菜单表” m_menu的描述反映在表menucode中时如下表所示。 中的字段“itemcname”,其他的字段不予显示,供内部代码使 菜单属性设置 用,但必须将它们选入到SQL的数据源。d_right的界面如上图 ltemeode Parentitemeode ItenmIne It∞cmIl 所示。从界面上看,管理者可以使用点击CheckBox来动态分 (内部编码) (父菜单) (tg单项的对象名) (tg单项中文名称) 配权限,另外几个字段没有显示出来。 ∞l 00o M-MENU ^Ⅱs系统 注:打勾表示选中CheckBox,未打勾表示没有选中 00 ∞l M. ⅥCEl 功能组一 CheckBoxo 00B ∞l M.SEVICE2 功能组二 当管理者点击datawindow控件中的指定一行时,应在该控 004 00 M・QUOTATION 报价 件的itemchanged事件中加入下列代码来收集指定职员的权限 005 00 M.REP0lH 报表 串。 006 00 M.CUSIDMER 客户资料 //一致性处理,比如选了某个菜单项,但没有选中其父菜单, 0 ∞B M.CREDrr 单证 //系统应该能够自动为其选上等 008 加8 M-D0CUMENT 单据 //目前考虑的有两种情况: //(1)父菜单被弃选.这时应将那些有被选的子菜单项弃选 //(2)若某一个子菜单项有被中,这时应将其父菜单选中(假 如父菜单没有被选中) 应该注意到“内部编码”的长度应该统一,都为三位,如 long Inv- n,Invj 编码为‘001’就不能写成‘1’或者‘Ol’,在程序中实现起 string Inv_this,Inv..parent,Inv_checkstatus 来会更方便一些。在“职员基本情况表”里面注意到了字段 if row<=0 then “e_n‘ght”,该字段是用来记录该职员能够使用到菜单中的哪 return row end if 些菜单项,比如,当字段的值为“002004005”表示该职员可 Inv_checkstatus=this.object.itemcheck【row l 以使用“功能组一”下的菜单项“报价”和“报表”,至于其 //此值是变之前的数据,那么很显然,变化后的值是其反码 他的菜单项就不能使用了,这样处理达到了预期目的。 //比如:本来是 0 ,那么变完之后是 1 一个菜单项对应一个功能,或者说对应一个权限,因此, if Inv_checkstatus= 0 then 要想控制职员的权限,只需控制菜单项是否显示在主菜单中即 //检查其父菜单是否有被选,如果没有被选中的话,则自动 //为其补上 可达到目的。需要特别强调的是在设计菜单的时候,所有需要 Inv..parent=this.object.parentitemcode【row l 控制的菜单项的VISIBLE属性都设为false,即不显示。 forInvj=1 toinv_rows 1.权限动态分配窗口 if dw_1.object.itemcode【Invj l=Inv..parent then /M\ ̄-骚2酾007.两4 维普资讯 http://www.cqvip.com
if dw_1.object.itemcheck【Invj】= 0 then dw_1.object.itemcheck【Invj】= 1 endif end if next else Inv_this=this.object.itemcode【row】 forInv_i:1 toinv_rows if dw_1.object.parentitemcode【Invj】:Inv_this then if dw_1.object.itemcheck【Invj】= 1 then dw_1.object.itemcheck【Inv_i】= 0 endif endif next end if 另再增加一个“确认”接纽来将收集到的权限串保存到 指定职员表中,即“职员基本情况表”中的字段e right。该 按纽事件“clicked”中的代码如下: string Invrights= _long Invj |f dw_1.accept-text(1=一1 then messageboxI 错误IA) , 权限分配失败! ) return一1 end if forInv_i=1 to inv_rows if dw_1.object.itemcheck【Invj】= 1 then Invjights=Inv_rights+dw_1.object.itemcode【Invj】 end if next if Invj'ights= then beepI1) messageboxI 提醒您 , 至少授权一个! ,exclamation!) return end if closewithreturn I parent.Inv_rights) 最后返回指定职员的权限串lnv._ifght供保存,具体的代码, 请读者自己来完成。 2.实施动态分配 当职员成功登录到系统的时候,应该首先从“职员基本情况 表”读取该职员的权限串,即e right的值,之后在MDI主窗 口的pfc_postopen事件中解析该权限串,最后将解析结果反映 到系统菜单上去。 //根据系统管理员对其的授权代码串来控制菜单的显示与否 long Inv_nums string Inv_singleright n_cst menu Invn__cst_rnenu //PFC框架内的菜单类 menu Inv_rnenu,Inv_rnenuitem //菜单对象 string Inv_rnenuitemname//对应“系统菜单表”中的 itemname Inv_menu=this.menuid//获取MDI主窗口上的菜单 inv_ds_menucode=create n_ds inv—ds—menucode.dataobject= djight inv_ds_menucode.SetTransObject I SQLCA) inv_ds_menucode.of_setparentwindow(this) setpointer I hourglass!) Inv_rows=inv_ds_menucode.retrieve I) if Invjows<一1 then beepI1) messageboxI 错误IA) , 数据库被非法关闭! ,stopsign Y) this.post event pfc_ctose【) end if if modIlenIinv_employee.is_right),3)<>0 then //在前面,要求该字段的长度都为三位 messageboxI 警告IA)’, 非法的权限代码串! ) return end if //准备按照其权限代码串进行授权 setpointerI hourglass!) InV-nums=len I inv_employee.is right)/3 forInvj:1 toInv』Iums Inv_.singleright=mid I inv employee.is_right,Invj 3—2.3) Inv_searchrow=inv_ds_menucode.find l itemcode= +…+Inv_singleright+…,1.Inv_rows+1) if Inv._searchrow=0 then//异常处理 continue end if Inv_menuitemname=inv_ds_menucode.object.itemname 【Inv_searchrow】 Invncstmenu.of____getmenureferenceI Inv_menu, Inv_menuitemname,Inv_menuitem) //在调试的时候,这个开关暂时不要打开,以免浪费时间 Inv menuitem.visible=true //拥有此权限,显示相应的菜单项 next 通过上面的处理,系统每次启动的时候都会检查当前职员 的权限范围,之后再分配相对应的权限给该职员。 还有一点就是要说明是,那些有快捷键的菜单项在不显示 的情况下,用户按下相应的快捷键会调用相应的功能,这一点 需要另外处理,比较简单就可以完成了,否则会留下后门。 3.“系统菜单表”的维护 一个MIS系统,在开发或者维护的过程中,可能会增加新 的功能,所以对于编程人员来说应该设置一个模块来管理“系 统菜单表”。 三、结语 扩展“系统菜单表”可以管理更多的东西,以上只是简单 的处理思路。内部跟踪菜单项的使用情况和频率等有点像日志 文件,管理者可以调阅该文件来了解系统的运行情况。掌握好 PFC编程会提高编程质量和效率。 (收稿日期:20o7年3月9日)